Bug 628616 - Make sure suggestions from <datalist> are shown in Firefox Mobile UI. r=mbrubeck

This commit is contained in:
Margaret Leibovic 2012-03-06 13:56:16 -08:00
parent e16b9d09cf
commit f018b1d419
2 changed files with 93 additions and 10 deletions

View File

@ -44,7 +44,10 @@ import android.content.Context;
import android.util.Log;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
@ -91,8 +94,10 @@ public class FormAssistPopup extends ListView implements GeckoEventListener {
setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parentView, View view, int position, long id) {
if (mTypeShowing.equals(PopupType.AUTOCOMPLETE)) {
// Use the value stored with the autocomplete view, not the label text,
// since they can be different.
TextView textView = (TextView) view;
String value = textView.getText().toString();
String value = (String) textView.getTag();
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FormAssist:AutoComplete", value));
hide();
}
@ -149,13 +154,8 @@ public class FormAssistPopup extends ListView implements GeckoEventListener {
}
private void showAutoCompleteSuggestions(JSONArray suggestions, JSONArray rect, double zoom) {
ArrayAdapter<String> adapter = new ArrayAdapter<String>(mContext, R.layout.autocomplete_list_item);
try {
for (int i = 0; i < suggestions.length(); i++)
adapter.add(suggestions.get(i).toString());
} catch (JSONException e) {
Log.e(LOGTAG, "JSONException: " + e);
}
AutoCompleteListAdapter adapter = new AutoCompleteListAdapter(mContext, R.layout.autocomplete_list_item);
adapter.populateSuggestionsList(suggestions);
setAdapter(adapter);
if (positionAndShowPopup(rect, zoom))
@ -266,4 +266,48 @@ public class FormAssistPopup extends ListView implements GeckoEventListener {
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FormAssist:Hidden", null));
}
}
private class AutoCompleteListAdapter extends ArrayAdapter<Pair<String, String>> {
private LayoutInflater mInflater;
private int mTextViewResourceId;
public AutoCompleteListAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mTextViewResourceId = textViewResourceId;
}
// This method takes an array of autocomplete suggestions with label/value properties
// and adds label/value Pair objects to the array that backs the adapter.
public void populateSuggestionsList(JSONArray suggestions) {
try {
for (int i = 0; i < suggestions.length(); i++) {
JSONObject suggestion = (JSONObject) suggestions.get(i);
String label = suggestion.getString("label");
String value = suggestion.getString("value");
add(new Pair<String, String>(label, value));
}
} catch (JSONException e) {
Log.e(LOGTAG, "JSONException: " + e);
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = mInflater.inflate(mTextViewResourceId, null);
Pair<String, String> item = getItem(position);
TextView itemView = (TextView) convertView;
// Set the text with the suggestion label
itemView.setText(item.first);
// Set a tag with the suggestion value
itemView.setTag(item.second);
return convertView;
}
}
}

View File

@ -2952,7 +2952,41 @@ var FormAssistant = {
if (value == aSearchString)
continue;
suggestions.push(value);
// Supply a label and value, since they can differ for datalist suggestions
suggestions.push({ label: value, value: value });
}
return suggestions;
},
/**
* (Copied from mobile/xul/chrome/content/forms.js)
* This function is similar to getListSuggestions from
* components/satchel/src/nsInputListAutoComplete.js but sadly this one is
* used by the autocomplete.xml binding which is not in used in fennec
*/
_getListSuggestions: function _getListSuggestions(aElement) {
if (!(aElement instanceof HTMLInputElement) || !aElement.list)
return [];
let suggestions = [];
let filter = !aElement.hasAttribute("mozNoFilter");
let lowerFieldValue = aElement.value.toLowerCase();
let options = aElement.list.options;
let length = options.length;
for (let i = 0; i < length; i++) {
let item = options.item(i);
let label = item.value;
if (item.label)
label = item.label;
else if (item.text)
label = item.text;
if (filter && label.toLowerCase().indexOf(lowerFieldValue) == -1)
continue;
suggestions.push({ label: label, value: item.value });
}
return suggestions;
@ -2977,7 +3011,12 @@ var FormAssistant = {
if (!this._isAutoComplete(aElement))
return false;
let suggestions = this._getAutoCompleteSuggestions(aElement.value, aElement);
let autoCompleteSuggestions = this._getAutoCompleteSuggestions(aElement.value, aElement);
let listSuggestions = this._getListSuggestions(aElement);
// On desktop, we show datalist suggestions below autocomplete suggestions,
// without duplicates removed.
let suggestions = autoCompleteSuggestions.concat(listSuggestions);
// Return false if there are no suggestions to show
if (!suggestions.length)