diff --git a/public_html/static/js/jquery-autocomplete.js b/public_html/static/js/jquery-autocomplete.js index 5ed76d0..4f8b5ae 100644 --- a/public_html/static/js/jquery-autocomplete.js +++ b/public_html/static/js/jquery-autocomplete.js @@ -74,7 +74,14 @@ AutoCompleterInstance.prototype._handleKeyUp = function(event) { switch(event.keyCode) { case 9: // Tab + /* This is now handled in the keydown event, to be able to + * implement passthrough behaviour when no autocompletion + * occurs... */ + break; case 13: // Enter/Return + /* We need slightly different behaviour for the Enter key; + * even if no autocompletion has happened, we still want to + * block potential accidental form submits. */ if(this.visible == true && this.total_items > 0) { this._selectCurrent(); @@ -89,6 +96,15 @@ AutoCompleterInstance.prototype._handleKeyDown = function(event) { switch(event.keyCode) { case 9: // Tab + if(this.visible == true && this.total_items > 0) + { + if(this._selectCurrent()) + { + event.stopPropagation(); + event.preventDefault(); + } + } + break; case 13: // Enter/Return /* We don't want this to do anything. */ if(this.visible == true && this.total_items > 0) @@ -165,16 +181,31 @@ AutoCompleterInstance.prototype._moveNext = function() { AutoCompleterInstance.prototype._selectCurrent = function() { var item = this.source.getItem(this.current_selection); - if(typeof this.callback !== "undefined") + /* We only want to autocomplete if the currently selected item still matches + * the original query; this is to deal with race conditions where the user + * has changed his query to no longer be accurate, but the new results have + * not yet been fetched. */ + if(this.source.matchesItem(this.current_selection, this.target.val())) { - this.callback.call(this, item); + if(typeof this.callback !== "undefined") + { + this.callback.call(this, item); + } + else + { + this.target.val(item.value); + } + + var has_autocompleted = true; } else { - this.target.val(item.value); + var has_autocompleted = false; } this.remove(); + + return has_autocompleted; } AutoCompleterInstance.prototype._updateItems = function() { diff --git a/public_html/static/js/openng.js b/public_html/static/js/openng.js index 0458bd8..30ffee1 100644 --- a/public_html/static/js/openng.js +++ b/public_html/static/js/openng.js @@ -212,6 +212,22 @@ SearchCompletionSource.prototype.updateItems = function(query, callback) { }); } +SearchCompletionSource.prototype.isInItems = function(query) { + for(i in this.results) + { + if(this.results[i].indexOf(query) > 0) + { + return true; + } + } + + return false; +} + +SearchCompletionSource.prototype.matchesItem = function(index, query) { + return (this.results[index].name.toLowerCase().indexOf(query.toLowerCase()) > -1); +} + function PropertyNameCompletionSource(element) { this.element = element; @@ -243,6 +259,26 @@ PropertyNameCompletionSource.prototype.updateItems = function(query, callback) { }); } +PropertyNameCompletionSource.prototype.isInItems = function(query) { + for(i in this.results) + { + if(this.results[i].indexOf(query) > 0) + { + return true; + } + } + + return false; +} + + +PropertyNameCompletionSource.prototype.matchesItem = function(index, query) { + console.log("item", this.results[index].value.toLowerCase()); + console.log("query", query.toLowerCase()); + console.log("result", this.results[index].value.toLowerCase().indexOf(query.toLowerCase())); + return (this.results[index].value.toLowerCase().indexOf(query.toLowerCase()) > -1); +} + $(function(){ hookSubmitEvent($("#form_search"));