Bug 466770 - fix content autocomplete [r=vingtetun]

This commit is contained in:
Mark Finkle 2010-03-09 22:42:04 -05:00
parent 5acb099c05
commit d43ef37bda
8 changed files with 180 additions and 36 deletions

View File

@ -1086,6 +1086,11 @@ var FormHelper = {
return this._selectContainer = document.getElementById("select-container");
},
get _autofillContainer() {
delete this._autofillContainer;
return this._autofillContainer = document.getElementById("form-helper-autofill");
},
_getRectForElement: function formHelper_getRectForElement(aElement) {
const kDistanceMax = 100;
let elRect = Browser.getBoundingContentRect(aElement);
@ -1109,6 +1114,14 @@ var FormHelper = {
_update: function(aPreviousElement, aNewElement) {
this._updateSelect(aPreviousElement, aNewElement);
// Setup autofill UI
if (aNewElement instanceof HTMLInputElement && aNewElement.type == "text") {
let suggestions = this._getSuggestions();
this._setSuggestions(suggestions);
} else {
this._autofillContainer.hidden = true;
}
let height = Math.floor(this._container.getBoundingClientRect().height);
this._container.top = window.innerHeight - height;
@ -1216,6 +1229,44 @@ var FormHelper = {
return (index != -1 ? this._nodes[++index] : null);
},
_fac: Cc["@mozilla.org/satchel/form-autocomplete;1"].getService(Ci.nsIFormAutoComplete),
_getSuggestions: function() {
let suggestions = [];
let currentValue = this._currentElement.value;
let results = this._fac.autoCompleteSearch(this._currentElement.name, currentValue, this._currentElement, null);
if (results.matchCount > 0) {
for (let i = 0; i < results.matchCount; i++) {
let value = results.getValueAt(i);
suggestions.push(value);
}
}
return suggestions;
},
_setSuggestions: function(aSuggestions) {
let autofill = this._autofillContainer;
while (autofill.hasChildNodes())
autofill.removeChild(autofill.lastChild);
let fragment = document.createDocumentFragment();
for (let i = 0; i < aSuggestions.length; i++) {
let value = aSuggestions[i];
let button = document.createElement("label");
button.setAttribute("value", value);
fragment.appendChild(button);
}
autofill.appendChild(fragment);
autofill.hidden = !aSuggestions.length;
},
doAutoFill: function formHelperDoAutoFill(aElement) {
if (!this._currentElement)
return;
this._currentElement.value = aElement.value;
},
getLabelsFor: function(aElement) {
let associatedLabels = [];
if (this._isValidElement(aElement)) {
@ -1268,7 +1319,6 @@ var FormHelper = {
return false;
this._open = true;
window.addEventListener("keypress", this, true);
window.addEventListener("keyup", this, false);
let bv = Browser._browserView;
bv.ignorePageScroll(true);
@ -1288,6 +1338,7 @@ var FormHelper = {
this._updateSelect(this._currentElement, null);
this._helperSpacer.hidden = true;
// give the form spacer area back to the content
let bv = Browser._browserView;
Browser.forceChromeReflow();
@ -1296,7 +1347,6 @@ var FormHelper = {
bv.ignorePageScroll(false);
window.removeEventListener("keypress", this, true);
window.removeEventListener("keyup", this, false);
this._container.hidden = true;
this._currentElement = null;
@ -1309,41 +1359,55 @@ var FormHelper = {
return;
let currentElement = this.getCurrentElement();
if (aEvent.type == "keypress") {
switch (aEvent.keyCode) {
case aEvent.DOM_VK_DOWN:
if (currentElement instanceof HTMLTextAreaElement) {
let existSelection = currentElement.selectionEnd - currentElement.selectionStart;
let isEnd = (currentElement.textLength == currentElement.selectionEnd);
if (!isEnd || existSelection)
return;
switch (aEvent.keyCode) {
case aEvent.DOM_VK_DOWN:
if (currentElement instanceof HTMLTextAreaElement) {
let existSelection = currentElement.selectionEnd - currentElement.selectionStart;
let isEnd = (currentElement.textLength == currentElement.selectionEnd);
if (!isEnd || existSelection)
return;
}
this.goToNext();
break;
case aEvent.DOM_VK_UP:
if (currentElement instanceof HTMLTextAreaElement) {
let existSelection = currentElement.selectionEnd - currentElement.selectionStart;
let isStart = (currentElement.selectionEnd == 0);
if (!isStart || existSelection)
return;
}
this.goToPrevious();
break;
case aEvent.DOM_VK_RETURN:
break;
default:
let target = aEvent.target;
if (currentElement instanceof HTMLInputElement && currentElement.type == "text") {
let suggestions = this._getSuggestions();
this._setSuggestions(suggestions);
let height = Math.floor(this._container.getBoundingClientRect().height);
this._container.top = window.innerHeight - height;
this._helperSpacer.setAttribute("height", height);
// XXX if we are at the bottom of the page we need to give back the content
// area by refreshing it
if (suggestions.length == 0) {
let bv = Browser._browserView;
Browser.forceChromeReflow();
Browser.contentScrollboxScroller.scrollBy(0, 0);
bv.onAfterVisibleMove();
}
this.goToNext();
aEvent.preventDefault();
aEvent.stopPropagation();
break;
case aEvent.DOM_VK_UP:
if (currentElement instanceof HTMLTextAreaElement) {
let existSelection = currentElement.selectionEnd - currentElement.selectionStart;
let isStart = (currentElement.selectionEnd == 0);
if (!isStart || existSelection)
return;
}
this.goToPrevious();
aEvent.preventDefault();
aEvent.stopPropagation();
break;
}
}
else if (aEvent.type == "keyup") {
let target = aEvent.target;
if (currentElement == target && this._isValidSelectElement(target)) {
SelectHelper.unselectAll();
SelectHelper.selectByIndex(target.selectedIndex);
}
} else if (currentElement == target && this._isValidSelectElement(target)) {
SelectHelper.unselectAll();
SelectHelper.selectByIndex(target.selectedIndex);
}
break;
}
},

View File

@ -274,6 +274,8 @@
<!-- popup for form helper -->
<vbox id="form-helper-container" class="window-width" hidden="true" top="0" pack="end">
<arrowscrollbox id="form-helper-autofill" hidden="true" align="center" flex="1" orient="horizontal"
onclick="FormHelper.doAutoFill(event.target);"/>
<hbox id="form-buttons" class="panel-dark" pack="center">
<button id="form-helper-previous" class="button-dark" label="&formHelper.previous;" command="cmd_formPrevious"/>
<button id="form-helper-next" class="button-dark" label="&formHelper.next;" command="cmd_formNext"/>

View File

@ -946,6 +946,44 @@ box[type="documenttab"]:only-child .documenttab-close {
-moz-user-select: none;
}
#form-helper-autofill {
padding: 4px 0; /* half core spacing & none (autorepeat arrows compensate) */
border-top: 4px solid #36373b;
background-color: white;
}
#form-helper-autofill .autorepeatbutton-down {
list-style-image: url(images/arrowright-16.png);
}
#form-helper-autofill .autorepeatbutton-up {
list-style-image: url(images/arrowleft-16.png);
}
/* force the autorepeat buttons to create a 'padding' when collapsed */
#form-helper-autofill autorepeatbutton[collapsed="true"],
#form-helper-autofill autorepeatbutton[disabled="true"] {
visibility: hidden;
}
#form-helper-autofill > label {
padding: 12px 8px; /* 12px helps get row size for the labels */
margin: 0;
border-right: 1px solid gray;
}
#form-helper-autofill > label:first-child {
padding-left: -moz-initial; /* the arrowscrollbox creates enough left padding */
}
#form-helper-autofill > label:last-child {
border-right: none;
}
#form-helper-autofill > label:active {
background-color: #8db8d8;
}
#form-helper-container #select-buttons {
display: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

View File

@ -16,6 +16,7 @@ chrome.jar:
images/weave.png (images/weave.png)
images/aboutBackground.png (images/aboutBackground.png)
images/panel-shadow.png (images/panel-shadow.png)
images/arrowleft-16.png (images/arrowleft-16.png)
images/arrowright-16.png (images/arrowright-16.png)
images/arrowup-16.png (images/arrowup-16.png)
images/arrowdown-16.png (images/arrowdown-16.png)

View File

@ -625,6 +625,44 @@ box[type="documenttab"]:only-child .documenttab-close {
border-top: 0;
}
#form-helper-autofill {
padding: 0.25mm 0; /* half core spacing & none (autorepeat arrows compensate) */
border-top: 0.25mm solid #36373b;
background-color: white;
}
#form-helper-autofill .autorepeatbutton-down {
list-style-image: url(images/arrowright-16.png);
}
#form-helper-autofill .autorepeatbutton-up {
list-style-image: url(images/arrowleft-16.png);
}
/* force the autorepeat buttons to create a 'padding' when collapsed */
#form-helper-autofill autorepeatbutton[collapsed="true"],
#form-helper-autofill autorepeatbutton[disabled="true"] {
visibility: hidden;
}
#form-helper-autofill > label {
padding: 0.75mm 0.5mm; /* 0.75 helps get row size for the labels */
margin: 0;
border-right: 1px solid gray;
}
#form-helper-autofill > label:first-child {
padding-left: -moz-initial; /* the arrowscrollbox creates enough left padding */
}
#form-helper-autofill > label:last-child {
border-right: none;
}
#form-helper-autofill > label:active {
background-color: #8db8d8;
}
/* select popup ------------------------------------------------------------ */
#stack > #select-container {
padding: 1.5mm;

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

View File

@ -16,6 +16,7 @@ chrome.jar:
images/weave.png (images/weave.png)
images/panel-shadow.png (images/panel-shadow.png)
images/aboutBackground.png (images/aboutBackground.png)
images/arrowleft-16.png (images/arrowleft-16.png)
images/arrowright-16.png (images/arrowright-16.png)
images/arrowup-16.png (images/arrowup-16.png)
images/arrowdown-16.png (images/arrowdown-16.png)