1 2 /* 3 * jquery.suggest 1.1 - 2007-08-06 4 * 5 * Uses code and techniques from following libraries: 6 * 1. http://www.dyve.net/jquery/?autocomplete 7 * 2. http://dev.jquery.com/browser/trunk/plugins/interface/iautocompleter.js 8 * 9 * All the new stuff written by Peter Vulgaris (www.vulgarisoip.com) 10 * Feel free to do whatever you want with this file 11 * 12 */ 13 14 (function($) { 15 16 $.suggest = function(input, options) { 17 18 var $input = $(input).attr("autocomplete", "off"); 19 var $results = $(document.createElement("ul")); 20 21 var timeout = false; // hold timeout ID for suggestion results to appear 22 var prevLength = 0; // last recorded length of $input.val() 23 var cache = []; // cache MRU list 24 var cacheSize = 0; // size of cache in chars (bytes?) 25 26 $results.addClass(options.resultsClass).appendTo('body'); 27 28 29 resetPosition(); 30 $(window).resize(resetPosition); 31 $(window).on("load", resetPosition); //ersetzt $(window).load(resetPosition) // just in case user is changing size of page while loading 32 33 34 $input.blur(function() { 35 setTimeout(function() { $results.hide() }, 200); 36 }); 37 38 39 // help IE users if possible 40 try { 41 $results.bgiframe(); 42 } catch(e) { } 43 44 45 // I really hate browser detection, but I don't see any other way 46 if ($.browser.mozilla) 47 $input.keypress(processKey); // onkeypress repeats arrow keys in Mozilla/Opera 48 else 49 $input.keydown(processKey); // onkeydown repeats arrow keys in IE/Safari 50 51 52 53 54 function resetPosition() { 55 // requires jquery.dimension plugin 56 var offset = $input.offset(); 57 $results.css({ 58 top: (offset.top + input.offsetHeight) + 'px', 59 left: offset.left + 'px' 60 }); 61 } 62 63 64 function processKey(e) { 65 66 // handling up/down/escape requires results to be visible 67 // handling enter/tab requires that AND a result to be selected 68 if ((/27$|38$|40$/.test(e.keyCode) && $results.is(':visible')) || 69 (/^13$|^9$/.test(e.keyCode) && getCurrentResult())) { 70 71 if (e.preventDefault) 72 e.preventDefault(); 73 if (e.stopPropagation) 74 e.stopPropagation(); 75 76 e.cancelBubble = true; 77 e.returnValue = false; 78 79 switch(e.keyCode) { 80 81 case 38: // up 82 prevResult(); 83 break; 84 85 case 40: // down 86 nextResult(); 87 break; 88 89 case 9: // tab 90 case 13: // return 91 selectCurrentResult(); 92 break; 93 94 case 27: // escape 95 $results.hide(); 96 break; 97 98 } 99 100 } else if ($input.val().length != prevLength) { 101 102 if (timeout) 103 clearTimeout(timeout); 104 timeout = setTimeout(suggest, options.delay); 105 prevLength = $input.val().length; 106 107 } 108 109 110 } 111 112 113 function suggest() { 114 115 // Update: Kategorie hinzufügen 2011-04-07 116 var cat = $('input[name="data[search_cat]"]:checked').val(); 117 if (typeof cat == 'undefined') cat = 0; 118 119 var q = $.trim($input.val())+'#'+cat; 120 121 if (q.length >= options.minchars) { 122 123 cached = checkCache(q); 124 125 if (cached) { 126 127 displayItems(cached['items']); 128 129 } else { 130 131 $.get(options.source, {q: q}, function(txt) { 132 133 $results.hide(); 134 135 var items = parseTxt(txt, q); 136 137 displayItems(items); 138 addToCache(q, items, txt.length); 139 140 }); 141 142 } 143 144 } else { 145 146 $results.hide(); 147 148 } 149 150 } 151 152 153 function checkCache(q) { 154 155 for (var i = 0; i < cache.length; i++) 156 if (cache[i]['q'] == q) { 157 cache.unshift(cache.splice(i, 1)[0]); 158 return cache[0]; 159 } 160 161 return false; 162 163 } 164 165 function addToCache(q, items, size) { 166 167 while (cache.length && (cacheSize + size > options.maxCacheSize)) { 168 var cached = cache.pop();
169 cacheSize -= cached['size']; 170 } 171 172 cache.push({ 173 q: q, 174 size: size, 175 items: items 176 }); 177 178 cacheSize += size; 179 180 } 181 182 function displayItems(items) { 183 184 if (!items) 185 return; 186 187 if (!items.length) { 188 $results.hide(); 189 return; 190 } 191 192 var html = ''; 193 for (var i = 0; i < items.length; i++) 194 html += '<li>' + items[i] + '</li>'; 195 196 $results.html(html).show(); 197 198 $results 199 .children('li') 200 .mouseover(function() { 201 $results.children('li').removeClass(options.selectClass); 202 $(this).addClass(options.selectClass); 203 }) 204 .click(function(e) { 205 e.preventDefault(); 206 e.stopPropagation(); 207 selectCurrentResult(); 208 }); 209 210 } 211 212 function parseTxt(txt, q) { 213 214 var items = []; 215 var tokens = txt.split(options.delimiter); 216 217 // parse returned data for non-empty items 218 for (var i = 0; i < tokens.length; i++) { 219 var token = $.trim(tokens[i]); 220 if (token) { 221 token = token.replace( 222 new RegExp(q, 'ig'), 223 function(q) { return '<span class="' + options.matchClass + '">' + q + '</span>' } 224 ); 225 items[items.length] = token; 226 } 227 } 228 229 return items; 230 } 231 232 function getCurrentResult() { 233 234 if (!$results.is(':visible')) 235 return false; 236 237 var $currentResult = $results.children('li.' + options.selectClass); 238 239 if (!$currentResult.length) 240 $currentResult = false; 241 242 return $currentResult; 243 244 } 245 246 function selectCurrentResult() { 247 248 $currentResult = getCurrentResult(); 249 250 if ($currentResult) { 251 $input.val($currentResult.text()); 252 $results.hide(); 253 254 if (options.onSelect) 255 options.onSelect.apply($currentResult); // edit, ti: options.onSelect.apply($input[0]) Zur Auswertung das gesamte Objekt übergeben 256 257 } 258 259 } 260 261 function nextResult() { 262 263 $currentResult = getCurrentResult(); 264 265 if ($currentResult) 266 $currentResult 267 .removeClass(options.selectClass) 268 .next() 269 .addClass(options.selectClass); 270 else 271 $results.children('li:first-child').addClass(options.selectClass); 272 273 } 274 275 function prevResult() { 276 277 $currentResult = getCurrentResult(); 278 279 if ($currentResult) 280 $currentResult 281 .removeClass(options.selectClass) 282 .prev() 283 .addClass(options.selectClass); 284 else 285 $results.children('li:last-child').addClass(options.selectClass); 286 287 } 288 289 } 290 291 $.fn.suggest = function(source, options) { 292 293 if (!source) 294 return; 295 296 options = options || {}; 297 options.source = source; 298 options.delay = options.delay || 300; 299 options.resultsClass = options.resultsClass || 'ac_results'; 300 options.selectClass = options.selectClass || 'ac_over'; 301 options.matchClass = options.matchClass || 'ac_match'; 302 options.minchars = options.minchars || 2; 303 options.delimiter = options.delimiter || '\n'; 304 options.onSelect = options.onSelect || false; 305 options.maxCacheSize = options.maxCacheSize || 65536; 306 307 this.each(function() { 308 new $.suggest(this, options); 309 }); 310 311 return this; 312 313 }; 314 315 })(jQuery); 316
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.