Optimize and clean-up form history

Switch from g_file_test() to g_access()

Initialize suggestions once the DOM is ready and only once

No need to handle WEBKIT_WEB_NAVIGATION_REASON_FORM_RESUBMITTED

[JS] Hide suggestions if search pattern was cleared

[JS] Human usable up/ down navigation in the suggestion window

Reusing a single suggestion window introduced a regression.
Suggestions were filling into the wrong editbox if there was more
than 1 on the page.

Some comments fixed and style clean-ups

Removed dead code
This commit is contained in:
Alexander Butenko 2009-12-19 10:45:39 +01:00 committed by Christian Dywan
parent 045cc81b45
commit 9af30a1eda
3 changed files with 52 additions and 70 deletions

View File

@ -1,9 +1,6 @@
div.suggestions {
-moz-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid #cccccc;
-webkit-appearance: listbox;
text-align: left;
background-color: #ffffff;
position: absolute;
z-index: 999;
}

View File

@ -38,7 +38,6 @@ function AutoSuggestControl(oTextbox /*:HTMLInputElement*/,
* @param bTypeAhead If the control should provide a type ahead suggestion.
*/
AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/) {
//make sure theres at least one suggestion
if (aSuggestions.length > 0) {
this.showSuggestions(aSuggestions);
} else {
@ -51,35 +50,16 @@ AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/) {
* @scope private
*/
AutoSuggestControl.prototype.createDropDown = function () {
var oThis = this;
var sDiv = document.getElementById("suggestions_box");
if (sDiv)
if (sDiv) {
this.layer = sDiv;
else
{
this.layer = document.createElement("div");
this.layer.className = "suggestions";
this.layer.id = "suggestions_box";
this.layer.style.visibility = "hidden";
this.layer.style.width = this.textbox.offsetWidth;
return;
}
this.layer.onmousedown =
this.layer.onmouseup =
this.layer.onmouseover = function (oEvent) {
oEvent = oEvent || window.event;
oTarget = oEvent.target || oEvent.srcElement;
if (oEvent.type == "mousedown") {
oThis.textbox.value = oTarget.firstChild.nodeValue;
oThis.hideSuggestions();
} else if (oEvent.type == "mouseover") {
oThis.highlightSuggestion(oTarget);
} else {
oThis.textbox.focus();
}
};
this.layer = document.createElement("div");
this.layer.className = "suggestions";
this.layer.id = "suggestions_box";
this.layer.style.visibility = "hidden";
this.layer.style.width = this.textbox.offsetWidth;
document.body.appendChild(this.layer);
};
@ -91,12 +71,10 @@ AutoSuggestControl.prototype.createDropDown = function () {
AutoSuggestControl.prototype.getLeft = function () /*:int*/ {
var oNode = this.textbox;
var iLeft = 0;
while(oNode.tagName != "BODY") {
while (oNode.tagName != "BODY") {
iLeft += oNode.offsetLeft;
oNode = oNode.offsetParent;
}
return iLeft;
};
@ -141,17 +119,15 @@ AutoSuggestControl.prototype.handleKeyDown = function (oEvent /*:Event*/) {
*/
AutoSuggestControl.prototype.handleKeyUp = function (oEvent /*:Event*/) {
var iKeyCode = oEvent.keyCode;
//for backspace (8) and delete (46), shows suggestions without typeahead
if (iKeyCode == 8 || iKeyCode == 46) {
this.provider.requestSuggestions(this);
//make sure not to interfere with non-character keys
} else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123) ) {
//ignore
} else if (oEvent.ctrlKey) {
iKeyCode = 0;
this.hideSuggestions();
} else {
//request suggestions from the suggestion provider with typeahead
//request suggestions from the suggestion provider
this.provider.requestSuggestions(this);
}
};
@ -227,11 +203,15 @@ AutoSuggestControl.prototype.init = function () {
AutoSuggestControl.prototype.nextSuggestion = function () {
var cSuggestionNodes = this.layer.childNodes;
if (cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length-1) {
var oNode = cSuggestionNodes[++this.cur];
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue;
}
if (!cSuggestionNodes.length)
return;
if (this.cur == cSuggestionNodes.length-1)
this.cur = -1;
var oNode = cSuggestionNodes[++this.cur];
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue;
};
/**
@ -242,24 +222,15 @@ AutoSuggestControl.prototype.nextSuggestion = function () {
AutoSuggestControl.prototype.previousSuggestion = function () {
var cSuggestionNodes = this.layer.childNodes;
if (cSuggestionNodes.length > 0 && this.cur > 0) {
var oNode = cSuggestionNodes[--this.cur];
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue;
}
};
if (!cSuggestionNodes.length)
return;
/**
* Selects a range of text in the textbox.
* @scope public
* @param iStart The start index (base 0) of the selection.
* @param iLength The number of characters to select.
*/
AutoSuggestControl.prototype.selectRange = function (iStart /*:int*/, iLength /*:int*/) {
if (this.textbox.setSelectionRange) {
this.textbox.setSelectionRange(iStart, iLength);
}
this.textbox.focus();
if (this.cur == -1 || this.cur == 0)
this.cur = cSuggestionNodes.length;
var oNode = cSuggestionNodes[--this.cur];
this.highlightSuggestion(oNode);
this.textbox.value = oNode.firstChild.nodeValue;
};
/**
@ -269,6 +240,7 @@ AutoSuggestControl.prototype.selectRange = function (iStart /*:int*/, iLength /*
* @param aSuggestions An array of suggestions for the control.
*/
AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/) {
var oThis = this;
var oDiv = null;
this.layer.innerHTML = ""; //clear contents of the layer
@ -282,6 +254,21 @@ AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/
this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + "px";
this.layer.style.visibility = "visible";
this.layer.style.position = "absolute";
this.layer.onmousedown =
this.layer.onmouseup =
this.layer.onmouseover = function (oEvent) {
var oEvent = oEvent || window.event;
var oTarget = oEvent.target || oEvent.srcElement;
if (oEvent.type == "mousedown") {
oThis.textbox.value = oTarget.firstChild.nodeValue;
oThis.hideSuggestions();
} else if (oEvent.type == "mouseover") {
oThis.highlightSuggestion(oTarget);
} else {
oThis.textbox.focus();
}
};
};
/**
@ -295,14 +282,13 @@ FormSuggestions.prototype.requestSuggestions = function (oAutoSuggestControl /*:
if (!this.suggestions)
return;
if (!sTextboxValue.length)
return;
//search for matching suggestions
for (var i=0; i < this.suggestions.length; i++) {
if (this.suggestions[i].toLowerCase().indexOf(sTextboxValue) == 0) {
aSuggestions.push(this.suggestions[i]);
}
if (sTextboxValue.length)
for (var i=0; i < this.suggestions.length; i++) {
if (this.suggestions[i].toLowerCase().indexOf(sTextboxValue) == 0) {
aSuggestions.push(this.suggestions[i]);
}
}
//provide suggestions to the control
oAutoSuggestControl.autosuggest(aSuggestions);

View File

@ -38,13 +38,13 @@ formhistory_prepare_js ()
gchar* data_path = g_build_filename (MDATADIR, PACKAGE_NAME, "res", NULL);
file = g_build_filename (data_path,"/autosuggestcontrol.js",NULL);
if (!g_file_test (file, G_FILE_TEST_EXISTS))
if (g_access (file, F_OK) != 0)
return FALSE;
g_file_get_contents (file, &autosuggest, NULL, NULL);
g_strchomp (autosuggest);
file = g_build_filename (data_path,"/autosuggestcontrol.css",NULL);
if (!g_file_test (file, G_FILE_TEST_EXISTS))
if (g_access (file, F_OK) != 0)
return FALSE;
g_file_get_contents (file, &style, NULL, NULL);
g_strchomp (style);
@ -58,7 +58,6 @@ formhistory_prepare_js ()
jsforms = g_strdup_printf (
"%s"
"window.addEventListener ('load', function () { initSuggestions (); }, true);"
"window.addEventListener ('DOMContentLoaded',"
"function () {"
" var styles = document.getElementsByTagName('style');"
@ -66,6 +65,7 @@ formhistory_prepare_js ()
" if (styles[i].getAttribute('title') == 'formhistory')"
" return;"
" }"
" initSuggestions ();"
" var mystyle = document.createElement('style');"
" mystyle.setAttribute('type', 'text/css');"
" mystyle.setAttribute('title', 'formhistory');"
@ -215,8 +215,7 @@ formhistory_navigation_decision_cb (WebKitWebView* web_view,
"}"
"dumpForm (document.getElementsByTagName('input'))";
if (webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED
|| webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_RESUBMITTED)
if (webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED)
{
gchar* value = sokoke_js_script_eval (js_context, script, NULL);
if (value)