1/* 2 jQuery autoComplete v1.0.7 3 Copyright (c) 2014 Simon Steinberger / Pixabay 4 GitHub: https://github.com/Pixabay/jQuery-autoComplete 5 License: http://www.opensource.org/licenses/mit-license.php 6*/ 7 8(function ($) { 9 $.fn.autoComplete = function (options) { 10 var o = $.extend({}, $.fn.autoComplete.defaults, options); 11 12 // public methods 13 if (typeof options == 'string') { 14 this.each(function () { 15 var that = $(this); 16 if (options == 'destroy') { 17 $(window).off('resize.autocomplete', that.updateSC); 18 that.off('blur.autocomplete focus.autocomplete keydown.autocomplete keyup.autocomplete'); 19 if (that.data('autocomplete')) 20 that.attr('autocomplete', that.data('autocomplete')); 21 else 22 that.removeAttr('autocomplete'); 23 $(that.data('sc')).remove(); 24 that.removeData('sc').removeData('autocomplete'); 25 } 26 }); 27 return this; 28 } 29 30 return this.each(function () { 31 var that = $(this); 32 // sc = 'suggestions container' 33 that.sc = $('<div class="autocomplete-suggestions ' + o.menuClass + '"></div>'); 34 that.data('sc', that.sc).data('autocomplete', that.attr('autocomplete')); 35 that.attr('autocomplete', 'off'); 36 that.cache = {}; 37 that.last_val = ''; 38 39 that.updateSC = function (resize, next) { 40 that.sc.css({ 41 top: that.offset().top + that.outerHeight() - (that.sc.css("position") == "fixed" ? $(window).scrollTop() : 0), 42 left: that.offset().left, 43 width: that.outerWidth() 44 }); 45 if (!resize) { 46 that.sc.show(); 47 if (!that.sc.maxHeight) that.sc.maxHeight = parseInt(that.sc.css('max-height')); 48 if (!that.sc.suggestionHeight) that.sc.suggestionHeight = $('.autocomplete-suggestion', that.sc).first().outerHeight(); 49 if (that.sc.suggestionHeight) 50 if (!next) that.sc.scrollTop(0); 51 else { 52 var scrTop = that.sc.scrollTop(), selTop = next.offset().top - that.sc.offset().top; 53 if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0) 54 that.sc.scrollTop(selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight); 55 else if (selTop < 0) 56 that.sc.scrollTop(selTop + scrTop); 57 } 58 } 59 } 60 $(window).on('resize.autocomplete', that.updateSC); 61 62 that.sc.appendTo('body'); 63 64 that.on('click', function () { 65 if ($(this).val().length > 0 && that.sc.is(":hidden")) { 66 setTimeout(function () { 67 that.sc.show(); 68 }, 100); 69 } 70 }); 71 72 that.sc.on('mouseleave', '.autocomplete-suggestion', function () { 73 $('.autocomplete-suggestion.selected').removeClass('selected'); 74 }); 75 76 that.sc.on('mouseenter', '.autocomplete-suggestion', function () { 77 $('.autocomplete-suggestion.selected').removeClass('selected'); 78 $(this).addClass('selected'); 79 }); 80 81 that.sc.on('mousedown click', '.autocomplete-suggestion', function (e) { 82 var item = $(this), v = item.data('val'); 83 if (v || item.hasClass('autocomplete-suggestion')) { // else outside click 84 that.val(v); 85 o.onSelect(e, v, item); 86 that.sc.hide(); 87 } 88 return false; 89 }); 90 91 that.on('blur.autocomplete', function () { 92 try { 93 over_sb = $('.autocomplete-suggestions:hover').length; 94 } catch (e) { 95 over_sb = 0; 96 } // IE7 fix :hover 97 if (!over_sb) { 98 that.last_val = that.val(); 99 that.sc.hide(); 100 setTimeout(function () { 101 that.sc.hide(); 102 }, 350); // hide suggestions on fast input 103 } else if (!that.is(':focus')) setTimeout(function () { 104 that.focus(); 105 }, 20); 106 }); 107 108 if (!o.minChars) that.on('focus.autocomplete', function () { 109 that.last_val = '\n'; 110 that.trigger('keyup.autocomplete'); 111 }); 112 113 function suggest(data) { 114 var val = that.val(); 115 that.cache[val] = data; 116 if (data.length && val.length >= o.minChars) { 117 var s = ''; 118 if (data.length > 0) { 119 s += typeof o.header === 'function' ? o.header.call(data, o, that) : o.header; 120 for (var i = 0; i < data.length; i++) s += o.renderItem(data[i], val); 121 s += typeof o.footer === 'function' ? o.footer.call(data, o, that) : o.footer; 122 } 123 that.sc.html(s); 124 that.updateSC(0); 125 } else 126 that.sc.hide(); 127 } 128 129 that.on('keydown.autocomplete', function (e) { 130 // down (40), up (38) 131 if ((e.which == 40 || e.which == 38) && that.sc.html()) { 132 var next, sel = $('.autocomplete-suggestion.selected', that.sc); 133 if (!sel.length) { 134 next = (e.which == 40) ? $('.autocomplete-suggestion', that.sc).first() : $('.autocomplete-suggestion', that.sc).last(
134); 135 that.val(next.addClass('selected').data('val')); 136 } else { 137 next = (e.which == 40) ? sel.next('.autocomplete-suggestion') : sel.prev('.autocomplete-suggestion'); 138 if (next.length) { 139 sel.removeClass('selected'); 140 that.val(next.addClass('selected').data('val')); 141 } else { 142 sel.removeClass('selected'); 143 that.val(that.last_val); 144 next = 0; 145 } 146 } 147 that.updateSC(0, next); 148 return false; 149 } 150 // esc 151 else if (e.which == 27) that.val(that.last_val).sc.hide(); 152 // enter or tab 153 else if (e.which == 13 || e.which == 9) { 154 var sel = $('.autocomplete-suggestion.selected', that.sc); 155 if (sel.length && that.sc.is(':visible')) { 156 o.onSelect(e, sel.data('val'), sel); 157 setTimeout(function () { 158 that.sc.hide(); 159 }, 20); 160 } 161 } 162 }); 163 164 that.on('keyup.autocomplete', function (e) { 165 if (!~$.inArray(e.which, [13, 27, 35, 36, 37, 38, 39, 40])) { 166 var val = that.val(); 167 if (val.length >= o.minChars) { 168 if (val != that.last_val) { 169 that.last_val = val; 170 clearTimeout(that.timer); 171 if (o.cache) { 172 if (val in that.cache) { 173 suggest(that.cache[val]); 174 return; 175 } 176 // no requests if previous suggestions were empty 177 for (var i = 1; i < val.length - o.minChars; i++) { 178 var part = val.slice(0, val.length - i); 179 if (part in that.cache && !that.cache[part].length) { 180 suggest([]); 181 return; 182 } 183 } 184 } 185 that.timer = setTimeout(function () { 186 o.source(val, suggest) 187 }, o.delay); 188 } 189 } else { 190 that.last_val = val; 191 that.sc.hide(); 192 } 193 } 194 }); 195 }); 196 } 197 198 $.fn.autoComplete.defaults = { 199 source: 0, 200 minChars: 3, 201 delay: 150, 202 cache: 1, 203 menuClass: '', 204 header: '', 205 footer: '', 206 renderItem: function (item, search) { 207 // escape special characters 208 search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); 209 var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi"); 210 return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item.replace(re, "<b>$1</b>") + '</div>'; 211 }, 212 onSelect: function (e, term, item) { 213 } 214 }; 215}(jQuery));
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.