diff --git a/jquery-ui.triggeredAutocomplete.js b/jquery-ui.triggeredAutocomplete.js index 5628762..dfd886e 100644 --- a/jquery-ui.triggeredAutocomplete.js +++ b/jquery-ui.triggeredAutocomplete.js @@ -2,6 +2,7 @@ /* * triggeredAutocomplete (jQuery UI autocomplete widget) * 2012 by Hawkee.com (hawkee@gmail.com) + * 2013 by Augusto Destrero (a.destrero@gmail.com) * * Version 1.4.5 * @@ -46,10 +47,15 @@ } }); - // Check for the id_map as an attribute. This is for editing. - - var id_map_string = this.element.attr('id_map'); - if(id_map_string) this.id_map = jQuery.parseJSON(id_map_string); + // Check for the id_map as a data attribute. This is for editing. + try { + var id_map_string = this.element.data(self.options.data); + if (id_map_string && id_map_string != '') { + this.id_map = jQuery.parseJSON(id_map_string); + } + } catch(err) { + this.id_map = new Object(); + } this.ac = $.ui.autocomplete.prototype; this.ac._create.apply(this, arguments); @@ -71,7 +77,13 @@ start = start.substring(0, start.lastIndexOf(self.options.trigger)); var top = self.element.scrollTop(); - this.value = start + self.options.trigger+ui.item.label+' ' + end; + var newvalue = start + self.options.trigger + ui.item.label; + if (end.charAt(0) != ' ') { + newvalue += ' '; + } + var newcaretposition = newvalue.length + 1; + newvalue += end; + this.value = newvalue; self.element.scrollTop(top); // Create an id map so we can create a hidden version of this string with id's instead of labels. @@ -80,13 +92,12 @@ self.updateHidden(); /** Places the caret right after the inserted item. */ - var index = start.length + self.options.trigger.length + ui.item.label.length + 2; if (this.createTextRange) { var range = this.createTextRange(); - range.move('character', index); + range.move('character', newcaretposition); range.select(); } else if (this.setSelectionRange) { - this.setSelectionRange(index, index); + this.setSelectionRange(newcaretposition, newcaretposition); } return false; @@ -125,9 +136,9 @@ this.search( null, event ); return; } - if ( this.menu.first() && /^previous/.test(direction) || - this.menu.last() && /^next/.test(direction) ) { - this.menu.deactivate(); + if ( this.menu.isFirstItem() && /^previous/.test(direction) || + this.menu.isLastItem() && /^next/.test(direction) ) { + this.menu.disable(); return; } this.menu[ direction ]( event ); @@ -140,18 +151,26 @@ this.contents = contents; this.cursorPos = cursorPos; + // cut contents at cursor position + contents = contents.substring(0, cursorPos); + // Include the character before the trigger and check that the trigger is not in the middle of a word // This avoids trying to match in the middle of email addresses when '@' is used as the trigger var check_contents = contents.substring(contents.lastIndexOf(this.options.trigger) - 1, cursorPos); var regex = new RegExp('\\B\\'+this.options.trigger+'([\\w\\-]+)'); + var only_trigger_regex = new RegExp('\\B\\' + this.options.trigger); + + // Close the suggestion list if there's only the trigger + if (check_contents.match(only_trigger_regex)) { + this.close(); + } if (contents.indexOf(this.options.trigger) >= 0 && check_contents.match(regex)) { // Get the characters following the trigger and before the cursor position. // Get the contents up to the cursortPos first then get the lastIndexOf the trigger to find the search term. - contents = contents.substring(0, cursorPos); var term = contents.substring(contents.lastIndexOf(this.options.trigger) + 1, contents.length); // Only query the server if we have a term and we haven't received a null response. @@ -258,7 +277,12 @@ contents = contents.replace(regex, trigger+'['+this.id_map[key]+']'); if(old_contents == contents) delete this.id_map[key]; } - $(this.options.hidden).val(contents); + if (typeof this.options.hidden != 'undefined') { + $(this.options.hidden).val(contents); + } + if (typeof this.options.data != 'undefined') { + this.element.data(this.options.data, this.id_map); + } this.element.scrollTop(top); }