Bug 566746, android asynchronous form autocomplete changes, r=margaret

This commit is contained in:
Neil Deakin 2013-04-11 04:01:49 -04:00
parent f79e9ffda7
commit f088c7b39f
2 changed files with 100 additions and 60 deletions

View File

@ -4530,7 +4530,7 @@ var FormAssistant = {
if (this._showValidationMessage(focused))
break;
this._showAutoCompleteSuggestions(focused);
this._showAutoCompleteSuggestions(focused, function () {});
} else {
// temporarily hide the form assist popup while we're panning or zooming the page
this._hideFormAssistPopup();
@ -4600,8 +4600,14 @@ var FormAssistant = {
// only be available if an invalid form was submitted)
if (this._showValidationMessage(currentElement))
break;
if (!this._showAutoCompleteSuggestions(currentElement))
let checkResultsClick = hasResults => {
if (!hasResults) {
this._hideFormAssistPopup();
}
};
this._showAutoCompleteSuggestions(currentElement, checkResultsClick);
break;
case "input":
@ -4609,13 +4615,18 @@ var FormAssistant = {
// Since we can only show one popup at a time, prioritze autocomplete
// suggestions over a form validation message
if (this._showAutoCompleteSuggestions(currentElement))
break;
if (this._showValidationMessage(currentElement))
break;
let checkResultsInput = hasResults => {
if (hasResults)
return;
if (!this._showValidationMessage(currentElement))
return;
// If we're not showing autocomplete suggestions, hide the form assist popup
this._hideFormAssistPopup();
};
this._showAutoCompleteSuggestions(currentElement, checkResultsInput);
break;
// Reset invalid submit state on each pageshow
@ -4639,14 +4650,14 @@ var FormAssistant = {
},
// Retrieves autocomplete suggestions for an element from the form autocomplete service.
_getAutoCompleteSuggestions: function _getAutoCompleteSuggestions(aSearchString, aElement) {
// aCallback(array_of_suggestions) is called when results are available.
_getAutoCompleteSuggestions: function _getAutoCompleteSuggestions(aSearchString, aElement, aCallback) {
// Cache the form autocomplete service for future use
if (!this._formAutoCompleteService)
this._formAutoCompleteService = Cc["@mozilla.org/satchel/form-autocomplete;1"].
getService(Ci.nsIFormAutoComplete);
let results = this._formAutoCompleteService.autoCompleteSearch(aElement.name || aElement.id,
aSearchString, aElement, null);
let resultsAvailable = function (results) {
let suggestions = [];
for (let i = 0; i < results.matchCount; i++) {
let value = results.getValueAt(i);
@ -4657,9 +4668,13 @@ var FormAssistant = {
// Supply a label and value, since they can differ for datalist suggestions
suggestions.push({ label: value, value: value });
aCallback(suggestions);
}
};
return suggestions;
this._formAutoCompleteService.autoCompleteSearchAsync(aElement.name || aElement.id,
aSearchString, aElement, null,
resultsAvailable);
},
/**
@ -4696,28 +4711,33 @@ var FormAssistant = {
},
// Retrieves autocomplete suggestions for an element from the form autocomplete service
// and sends the suggestions to the Java UI, along with element position data.
// Returns true if there are suggestions to show, false otherwise.
_showAutoCompleteSuggestions: function _showAutoCompleteSuggestions(aElement) {
if (!this._isAutoComplete(aElement))
return false;
// and sends the suggestions to the Java UI, along with element position data. As
// autocomplete queries are asynchronous, calls aCallback when done with a true
// argument if results were found and false if no results were found.
_showAutoCompleteSuggestions: function _showAutoCompleteSuggestions(aElement, aCallback) {
if (!this._isAutoComplete(aElement)) {
aCallback(false);
return;
}
// Don't display the form auto-complete popup after the user starts typing
// to avoid confusing somes IME. See bug 758820 and bug 632744.
if (this._isBlocklisted && aElement.value.length > 0) {
return false;
aCallback(false);
return;
}
let autoCompleteSuggestions = this._getAutoCompleteSuggestions(aElement.value, aElement);
let listSuggestions = this._getListSuggestions(aElement);
let resultsAvailable = autoCompleteSuggestions => {
// On desktop, we show datalist suggestions below autocomplete suggestions,
// without duplicates removed.
let listSuggestions = this._getListSuggestions(aElement);
let suggestions = autoCompleteSuggestions.concat(listSuggestions);
// Return false if there are no suggestions to show
if (!suggestions.length)
return false;
if (!suggestions.length) {
aCallback(false);
return;
}
sendMessageToJava({
type: "FormAssist:AutoComplete",
@ -4728,8 +4748,10 @@ var FormAssistant = {
// Keep track of input element so we can fill it in if the user
// selects an autocomplete suggestion
this._currentInputElement = aElement;
aCallback(true);
};
return true;
this._getAutoCompleteSuggestions(aElement.value, aElement, resultsAvailable);
},
// Only show a validation message if the user submitted an invalid form,

View File

@ -102,7 +102,21 @@ FormAutoComplete.prototype = {
});
},
// This method is obsolete. Use autoCompleteSearchAsync instead.
autoCompleteSearch: function autoCompleteSearch(aName, aQuery, aField, aPrev) {
let result = null;
let listener = function() { result = r; };
this._autoCompleteSearchAsync(aName, aQuery, aField, aPrev, listener);
let thread = Components.classes["@mozilla.org/thread-manager;1"].getService().currentThread;
while (!result) {
thread.processNextEvent(true);
}
return result;
},
autoCompleteSearchAsync: function autoCompleteSearch(aName, aQuery, aField, aPrev, aCallback) {
if (!Services.prefs.getBoolPref("browser.formfill.enable"))
return null;
@ -113,12 +127,12 @@ FormAutoComplete.prototype = {
// Don't allow duplicates get merged into the final results
let dupCheck = {};
// Use the base form autocomplete for non-contact searches
let normal = FAC.autoCompleteSearch(aName, aQuery, aField, aPrev);
if (normal.matchCount > 0) {
for (let i = 0; i < normal.matchCount; i++) {
dupCheck[normal.getValueAt(i)] = true;
result.appendMatch(normal.getValueAt(i), normal.getCommentAt(i), normal.getImageAt(i), normal.getStyleAt(i));
let callback = aNormalResults => {
if (aNormalResults.matchCount > 0) {
for (let i = 0; i < aNormalResults.matchCount; i++) {
dupCheck[aNormalResults.getValueAt(i)] = true;
result.appendMatch(aNormalResults.getValueAt(i), aNormalResults.getCommentAt(i),
aNormalResults.getImageAt(i), aNormalResults.getStyleAt(i));
}
}
@ -129,7 +143,11 @@ FormAutoComplete.prototype = {
let resultCode = result.matchCount ? "RESULT_SUCCESS" : "RESULT_NOMATCH";
result.setSearchResult(Ci.nsIAutoCompleteResult[resultCode]);
return result;
if (aCallback && aCallback.onSearchCompletion)
aCallback.onSearchCompletion(result);
};
FAC.autoCompleteSearchAsync(aName, aQuery, aField, aPrev, callback);
}
};