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:
parent
045cc81b45
commit
9af30a1eda
3 changed files with 52 additions and 70 deletions
|
@ -1,9 +1,6 @@
|
||||||
div.suggestions {
|
div.suggestions {
|
||||||
-moz-box-sizing: border-box;
|
-webkit-appearance: listbox;
|
||||||
box-sizing: border-box;
|
|
||||||
border: 1px solid #cccccc;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background-color: #ffffff;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ function AutoSuggestControl(oTextbox /*:HTMLInputElement*/,
|
||||||
* @param bTypeAhead If the control should provide a type ahead suggestion.
|
* @param bTypeAhead If the control should provide a type ahead suggestion.
|
||||||
*/
|
*/
|
||||||
AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/) {
|
AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/) {
|
||||||
//make sure theres at least one suggestion
|
|
||||||
if (aSuggestions.length > 0) {
|
if (aSuggestions.length > 0) {
|
||||||
this.showSuggestions(aSuggestions);
|
this.showSuggestions(aSuggestions);
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,35 +50,16 @@ AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/) {
|
||||||
* @scope private
|
* @scope private
|
||||||
*/
|
*/
|
||||||
AutoSuggestControl.prototype.createDropDown = function () {
|
AutoSuggestControl.prototype.createDropDown = function () {
|
||||||
var oThis = this;
|
|
||||||
|
|
||||||
var sDiv = document.getElementById("suggestions_box");
|
var sDiv = document.getElementById("suggestions_box");
|
||||||
|
if (sDiv) {
|
||||||
if (sDiv)
|
|
||||||
this.layer = sDiv;
|
this.layer = sDiv;
|
||||||
else
|
return;
|
||||||
{
|
}
|
||||||
this.layer = document.createElement("div");
|
this.layer = document.createElement("div");
|
||||||
this.layer.className = "suggestions";
|
this.layer.className = "suggestions";
|
||||||
this.layer.id = "suggestions_box";
|
this.layer.id = "suggestions_box";
|
||||||
this.layer.style.visibility = "hidden";
|
this.layer.style.visibility = "hidden";
|
||||||
this.layer.style.width = this.textbox.offsetWidth;
|
this.layer.style.width = this.textbox.offsetWidth;
|
||||||
}
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
document.body.appendChild(this.layer);
|
document.body.appendChild(this.layer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,12 +71,10 @@ AutoSuggestControl.prototype.createDropDown = function () {
|
||||||
AutoSuggestControl.prototype.getLeft = function () /*:int*/ {
|
AutoSuggestControl.prototype.getLeft = function () /*:int*/ {
|
||||||
var oNode = this.textbox;
|
var oNode = this.textbox;
|
||||||
var iLeft = 0;
|
var iLeft = 0;
|
||||||
|
while (oNode.tagName != "BODY") {
|
||||||
while(oNode.tagName != "BODY") {
|
|
||||||
iLeft += oNode.offsetLeft;
|
iLeft += oNode.offsetLeft;
|
||||||
oNode = oNode.offsetParent;
|
oNode = oNode.offsetParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return iLeft;
|
return iLeft;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,17 +119,15 @@ AutoSuggestControl.prototype.handleKeyDown = function (oEvent /*:Event*/) {
|
||||||
*/
|
*/
|
||||||
AutoSuggestControl.prototype.handleKeyUp = function (oEvent /*:Event*/) {
|
AutoSuggestControl.prototype.handleKeyUp = function (oEvent /*:Event*/) {
|
||||||
var iKeyCode = oEvent.keyCode;
|
var iKeyCode = oEvent.keyCode;
|
||||||
//for backspace (8) and delete (46), shows suggestions without typeahead
|
|
||||||
if (iKeyCode == 8 || iKeyCode == 46) {
|
if (iKeyCode == 8 || iKeyCode == 46) {
|
||||||
this.provider.requestSuggestions(this);
|
this.provider.requestSuggestions(this);
|
||||||
//make sure not to interfere with non-character keys
|
//make sure not to interfere with non-character keys
|
||||||
} else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123) ) {
|
} else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123) ) {
|
||||||
//ignore
|
//ignore
|
||||||
} else if (oEvent.ctrlKey) {
|
} else if (oEvent.ctrlKey) {
|
||||||
iKeyCode = 0;
|
|
||||||
this.hideSuggestions();
|
this.hideSuggestions();
|
||||||
} else {
|
} else {
|
||||||
//request suggestions from the suggestion provider with typeahead
|
//request suggestions from the suggestion provider
|
||||||
this.provider.requestSuggestions(this);
|
this.provider.requestSuggestions(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -227,11 +203,15 @@ AutoSuggestControl.prototype.init = function () {
|
||||||
AutoSuggestControl.prototype.nextSuggestion = function () {
|
AutoSuggestControl.prototype.nextSuggestion = function () {
|
||||||
var cSuggestionNodes = this.layer.childNodes;
|
var cSuggestionNodes = this.layer.childNodes;
|
||||||
|
|
||||||
if (cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length-1) {
|
if (!cSuggestionNodes.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.cur == cSuggestionNodes.length-1)
|
||||||
|
this.cur = -1;
|
||||||
|
|
||||||
var oNode = cSuggestionNodes[++this.cur];
|
var oNode = cSuggestionNodes[++this.cur];
|
||||||
this.highlightSuggestion(oNode);
|
this.highlightSuggestion(oNode);
|
||||||
this.textbox.value = oNode.firstChild.nodeValue;
|
this.textbox.value = oNode.firstChild.nodeValue;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -242,24 +222,15 @@ AutoSuggestControl.prototype.nextSuggestion = function () {
|
||||||
AutoSuggestControl.prototype.previousSuggestion = function () {
|
AutoSuggestControl.prototype.previousSuggestion = function () {
|
||||||
var cSuggestionNodes = this.layer.childNodes;
|
var cSuggestionNodes = this.layer.childNodes;
|
||||||
|
|
||||||
if (cSuggestionNodes.length > 0 && this.cur > 0) {
|
if (!cSuggestionNodes.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.cur == -1 || this.cur == 0)
|
||||||
|
this.cur = cSuggestionNodes.length;
|
||||||
|
|
||||||
var oNode = cSuggestionNodes[--this.cur];
|
var oNode = cSuggestionNodes[--this.cur];
|
||||||
this.highlightSuggestion(oNode);
|
this.highlightSuggestion(oNode);
|
||||||
this.textbox.value = oNode.firstChild.nodeValue;
|
this.textbox.value = oNode.firstChild.nodeValue;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -269,6 +240,7 @@ AutoSuggestControl.prototype.selectRange = function (iStart /*:int*/, iLength /*
|
||||||
* @param aSuggestions An array of suggestions for the control.
|
* @param aSuggestions An array of suggestions for the control.
|
||||||
*/
|
*/
|
||||||
AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/) {
|
AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/) {
|
||||||
|
var oThis = this;
|
||||||
var oDiv = null;
|
var oDiv = null;
|
||||||
this.layer.innerHTML = ""; //clear contents of the layer
|
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.top = (this.getTop()+this.textbox.offsetHeight) + "px";
|
||||||
this.layer.style.visibility = "visible";
|
this.layer.style.visibility = "visible";
|
||||||
this.layer.style.position = "absolute";
|
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,10 +282,9 @@ FormSuggestions.prototype.requestSuggestions = function (oAutoSuggestControl /*:
|
||||||
|
|
||||||
if (!this.suggestions)
|
if (!this.suggestions)
|
||||||
return;
|
return;
|
||||||
if (!sTextboxValue.length)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//search for matching suggestions
|
//search for matching suggestions
|
||||||
|
if (sTextboxValue.length)
|
||||||
for (var i=0; i < this.suggestions.length; i++) {
|
for (var i=0; i < this.suggestions.length; i++) {
|
||||||
if (this.suggestions[i].toLowerCase().indexOf(sTextboxValue) == 0) {
|
if (this.suggestions[i].toLowerCase().indexOf(sTextboxValue) == 0) {
|
||||||
aSuggestions.push(this.suggestions[i]);
|
aSuggestions.push(this.suggestions[i]);
|
||||||
|
|
|
@ -38,13 +38,13 @@ formhistory_prepare_js ()
|
||||||
|
|
||||||
gchar* data_path = g_build_filename (MDATADIR, PACKAGE_NAME, "res", NULL);
|
gchar* data_path = g_build_filename (MDATADIR, PACKAGE_NAME, "res", NULL);
|
||||||
file = g_build_filename (data_path,"/autosuggestcontrol.js",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;
|
return FALSE;
|
||||||
g_file_get_contents (file, &autosuggest, NULL, NULL);
|
g_file_get_contents (file, &autosuggest, NULL, NULL);
|
||||||
g_strchomp (autosuggest);
|
g_strchomp (autosuggest);
|
||||||
|
|
||||||
file = g_build_filename (data_path,"/autosuggestcontrol.css",NULL);
|
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;
|
return FALSE;
|
||||||
g_file_get_contents (file, &style, NULL, NULL);
|
g_file_get_contents (file, &style, NULL, NULL);
|
||||||
g_strchomp (style);
|
g_strchomp (style);
|
||||||
|
@ -58,7 +58,6 @@ formhistory_prepare_js ()
|
||||||
|
|
||||||
jsforms = g_strdup_printf (
|
jsforms = g_strdup_printf (
|
||||||
"%s"
|
"%s"
|
||||||
"window.addEventListener ('load', function () { initSuggestions (); }, true);"
|
|
||||||
"window.addEventListener ('DOMContentLoaded',"
|
"window.addEventListener ('DOMContentLoaded',"
|
||||||
"function () {"
|
"function () {"
|
||||||
" var styles = document.getElementsByTagName('style');"
|
" var styles = document.getElementsByTagName('style');"
|
||||||
|
@ -66,6 +65,7 @@ formhistory_prepare_js ()
|
||||||
" if (styles[i].getAttribute('title') == 'formhistory')"
|
" if (styles[i].getAttribute('title') == 'formhistory')"
|
||||||
" return;"
|
" return;"
|
||||||
" }"
|
" }"
|
||||||
|
" initSuggestions ();"
|
||||||
" var mystyle = document.createElement('style');"
|
" var mystyle = document.createElement('style');"
|
||||||
" mystyle.setAttribute('type', 'text/css');"
|
" mystyle.setAttribute('type', 'text/css');"
|
||||||
" mystyle.setAttribute('title', 'formhistory');"
|
" mystyle.setAttribute('title', 'formhistory');"
|
||||||
|
@ -215,8 +215,7 @@ formhistory_navigation_decision_cb (WebKitWebView* web_view,
|
||||||
"}"
|
"}"
|
||||||
"dumpForm (document.getElementsByTagName('input'))";
|
"dumpForm (document.getElementsByTagName('input'))";
|
||||||
|
|
||||||
if (webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED
|
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)
|
|
||||||
{
|
{
|
||||||
gchar* value = sokoke_js_script_eval (js_context, script, NULL);
|
gchar* value = sokoke_js_script_eval (js_context, script, NULL);
|
||||||
if (value)
|
if (value)
|
||||||
|
|
Loading…
Reference in a new issue