diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 070045d16ab..1a38814569a 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -17,7 +17,8 @@ $.widget( "ui.autocomplete", { options: { minLength: 1, - delay: 300 + delay: 300, + separator: false }, _create: function() { var self = this, @@ -108,14 +109,26 @@ $.widget( "ui.autocomplete", { if ( false !== self._trigger( "focus", null, { item: item } ) ) { // use value to match what will end up in the input, if it was a key event if ( /^key/.test(event.originalEvent.type) ) { - self.element.val( item.value ); + if(self.options.separator){ + var val = self._insertValue(item.value); + self.element.val( val ); + $.ui.autocomplete.caret( self.element, val.length - self.valEndLength ); + } else { + self.element.val( item.value ); + } } } }, selected: function( event, ui ) { var item = ui.item.data( "item.autocomplete" ); if ( false !== self._trigger( "select", event, { item: item } ) ) { - self.element.val( item.value ); + if(self.options.separator){ + var val = self._insertValue(item.value); + self.element.val( val ); + $.ui.autocomplete.caret( self.element, val.length - self.valEndLength ); + } else { + self.element.val( item.value ); + } } self.close( event ); // only trigger when focus was lost (click on menu) @@ -198,7 +211,51 @@ $.widget( "ui.autocomplete", { // always save the actual value, not the one passed as an argument .val(); - this.source( { term: value }, this.response ); + if( this.options.separator ){ + var caretPos = $.ui.autocomplete.caret(this.element).end; + value = this._getValue( value, caretPos ); + this._storeTermBits( caretPos ); + } + if( value ){ + this.source( { term: value }, this.response ); + } + }, + + _getValue: function( value, caretPos ){ + /* + * Cut the string in half at the caret, split at the separators, + * and then concat the outter array values so that editing the + * middle of a string still correctly triggers the autocomplete + */ + var begin = value.substr( 0, caretPos ).split( this.options.separator ), + end = value.substr( caretPos ); + this.valEndLength = end.length; + + return begin[ begin.length-1 ] + end.split( this.options.separator )[0]; + }, + + _storeTermBits: function( caretPos ){ + /* + * Store the beginning and end of the original term so that + * the values can quickly be swapped in and out in _insertValue + */ + this.termBegin = this.term.substr( 0, caretPos ).split( this.options.separator ); + this.termEnd = this.term.substr( caretPos ).split( this.options.separator ); + //clean the arrays of empty entries + this.termBegin.pop(); + this.termEnd.shift(); + }, + + _insertValue: function( value ){ + var result = ''; + if( this.termBegin.length ){ + result = this.termBegin.join( this.options.separator ) + this.options.separator; + } + result += value; + if( this.termEnd.length ){ + result += this.options.separator + this.termEnd.join( this.options.separator ); + } + return result; }, _response: function( content ) { @@ -310,6 +367,34 @@ $.extend( $.ui.autocomplete, { return $.grep( array, function(value) { return matcher.test( value.label || value.value || value ); }); + }, + caret: function(element, begin, end) { //Helper Function for Caret positioning taken from http://dev.jqueryui.com/browser/branches/dev/mask/ui/ui.mask.js?rev=2371 + var input = element[0]; + if (typeof begin == 'number') { + end = (typeof end == 'number') ? end : begin; + if (input.setSelectionRange) { + input.focus(); + input.setSelectionRange(begin, end); + } else if (input.createTextRange) { + var range = input.createTextRange(); + range.collapse(true); + range.moveEnd('character', end); + range.moveStart('character', begin); + range.select(); + } + return element; + } else { + if (input.setSelectionRange) { + begin = input.selectionStart; + end = input.selectionEnd; + } + else if (document.selection && document.selection.createRange) { + var range = document.selection.createRange(); + begin = 0 - range.duplicate().moveStart('character', -100000); + end = begin + range.text.length; + } + return { begin: begin, end: end }; + } } });