1function initAutocomplete (field, multiple, url, data, separator){ 2 3 separator = separator || ', '; 4 5 var cache = {}; 6 var min_length = data ? 1 : 2; 7 8 var term_template = "<b class='ui-autocomplete-term'>$1</b>"; 9 10 var loadSource = function (term, response){ 11 if(data){ 12 return loadData(term, response); 13 } else { 14 return loadJson(term, response); 15 } 16 }; 17 var loadData = function (term, response){ 18 var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex(term), "i" ); 19 response( $.grep(data, function( item ){ 20 return matcher.test(item); 21 })); 22 }; 23 var loadJson = function (term, response){ 24 $.getJSON(url, { 25 term: term 26 }, function(r, status, xhr) { 27 cache[term] = r; 28 response(r); 29 }); 30 }; 31 32 var getTerm = function (request_term){ 33 return request_term.substring(0, getCaretPosition('#'+field)).split(separator).pop().trim(); 34 }; 35 36 var highlightTerm = function (e,ui) { 37 var autocomplete = $(this).data('ui-autocomplete'); 38 autocomplete.menu.element.find('li').each(function() { 39 var me = $(this).find('div'); 40 if(me.length === 0){ me = $(this); } 41 var keywords = autocomplete.term.split(' ').join('|'); 42 me.html(me.text().replace(new RegExp("(" + keywords + ")", "gi"), term_template)); 43 }); 44 }; 45 46 if(multiple){ 47 $('#'+field).bind('keydown', function( event ) { 48 if ( event.keyCode === $.ui.keyCode.TAB && 49 $(this).data('ui-autocomplete').menu.active ) { 50 event.preventDefault(); 51 } 52 }).autocomplete({ 53 minLength: min_length, 54 source: function(request, response) { 55 var term = getTerm(request.term); 56 if (term.length < min_length) { 57 return false; 58 } 59 if (term in cache) { 60 response(cache[term]); 61 return; 62 } 63 loadSource(term, response); 64 }, 65 focus: function() { 66 return false; 67 }, 68 select: function( event, ui ) { 69 var value = $(this).val(); 70 var terms = []; 71 var new_string = ''; 72 var is_last = true; 73 var position = 0; 74 if(value.length > 0){ 75 76 terms = value.split(separator); 77 78 var position_terms = value.substring(0, getCaretPosition('#'+field)).split(separator); 79 80 var terms_count = terms.length; 81 var position_terms_count = position_terms.length; 82 83 if(position_terms_count !== terms_count){ 84 is_last = false; 85 } 86 87 if(terms_count === 1){ 88 position = ui.item.value.length; 89 } else { 90 position_terms.pop(); 91 position_terms.push(ui.item.value); 92 position = position_terms.join(separator).length; 93 } 94 95 terms[position_terms_count-1] = ui.item.value; 96 97 } else { 98 terms = [ui.item.value]; 99 position = ui.item.value.length; 100 } 101 new_string = terms.join(separator); 102 if(is_last){ 103 new_string = new_string+separator; 104 position += separator.length; 105 } 106 $(this).val(new_string); 107 setCaretPosition('#'+field, position); 108 icms.events.run('autocomplete_select', ui); 109 return false; 110 }, 111 open: highlightTerm 112 }); 113 } else { 114 $('#'+field).autocomplete({ 115 minLength: min_length, 116 delay: 500, 117 source: function( request, response ) { 118 var term = request.term; 119 if ( term in cache ) { 120 response( cache[ term ] ); 121 return; 122 } 123 loadSource(term, response); 124 }, 125 select: function( event, ui ) { 126 icms.events.run('autocomplete_select', ui); 127 }, 128 open: highlightTerm 129 }); 130 } 131}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.