1 /* 2 * AutoSuggest 3 * Copyright 2009-2010 Drew Wilson 4 * www.drewwilson.com 5 * code.drewwilson.com/entry/autosuggest-jquery-plugin 6 * 7 * Version 1.4 - Updated: Mar. 23, 2010 8 * 9 * This Plug-In will auto-complete or auto-suggest completed search queries 10 * for you as you type. You can add multiple selections and remove them on 11 * the fly. It supports keybord navigation (UP + DOWN + RETURN), as well 12 * as multiple AutoSuggest fields on the same page. 13 * 14 * Inspied by the Autocomplete plugin by: J?rn Zaefferer 15 * and the Facelist plugin by: Ian Tearle (iantearle.com) 16 * 17 * This AutoSuggest jQuery plug-in is dual licensed under the MIT and GPL licenses: 18 * http://www.opensource.org/licenses/mit-license.php 19 * http://www.gnu.org/licenses/gpl.html 20 */ 21 22(function($){ 23 $.fn.autoSuggest = function(data, options) { 24 var originKeyword = $('#inputQu').val(); 25 var defaults = { 26 startText: "", //Enter Name Here 27 emptyText: "No Results Found", 28 preFill: {}, 29 limitText: "No More Selections Are Allowed", 30 selectedItemProp: "keyword", //value //name of object property 31 selectedValuesProp: "keyword", //value //name of object property 32 searchObjProps: "keyword", //value //comma separated list of object property names 33 queryParam: "keywords", // q 34 retrieveLimit: 10, //false //number for 'limit' param on ajax request 35 extraParams: "", 36 matchCase: false, 37 matchGlobal: false, 38 minChars: 1, 39 keyDelay: 200, 40 resultsMargin: "0", 41 resultsHighlight: true, 42 neverSubmit: false, 43 selectionLimit: false, 44 showResultList: true, 45 start: function(){}, 46 wrapStyle: "", 47 selectionClick: function(elem){}, 48 selectionAdded: function(elem){}, 49 selectionRemoved: function(elem){ elem.remove(); }, 50 beforeRetrieve: function(string){ return string; }, 51 retrieveComplete: function(data){ return data; }, 52 resultClick: function(data){}, 53 formatList: function(this_data, formatted) { 54 return formatted.html('<span style="float: left">' + this_data['keyword'] + '</span><span style="font-size: 11px; color: #1f83cf; float: right">' + this_data['cntString'] + 'ê²°ê³¼</span>'); 55 }, 56 recomBookList: null, 57 recomDocList: null, 58 resultsComplete: function(results_holder) { 59 $(results_holder).prepend("<p>ê²ìì´ ì¶ì²</p>"); 60 }, 61 newDesign: false 62 }; 63 var opts = $.extend(defaults, options); 64 var d_type = "object"; 65 var d_count = 0; 66 var lastKeyPressCode = 0; 67 var isSubmit = false; 68 var isMainPage = false; 69 70 if($('#mainIndex').length > 0) { // ë©ì¸íì´ì§ ì ì© 71 isMainPage = true; 72 } 73 74 if(typeof data == "string") { 75 d_type = "string"; 76 var req_string = data; 77 } else { 78 var org_data = data; 79 for (k in data) if (data.hasOwnProperty(k)) d_count++; 80 } 81 82 if((d_type == "object" && d_count > 0) || d_type == "string"){ 83 return this.each(function(x){ 84 var input = $(this); 85 var input_focus = false; 86 87 opts.start.call(this); 88 input.attr("autocomplete","off").addClass("as-input"); 89 if (opts.startText) input.val(opts.startText); 90 91 // Setup basic elements and render them to the DOM 92 input.wrap('<div style="position:relative;z-index:100;' + opts.wrapStyle + '"></div>').wrap('<ul class="as-selections" id="as-selections-'+x+'"></ul>').wrap('<li class="as-original" id="as-original-'+x+'"></li>'); 93 var selections_holder = $("#as-selections-"+x); 94 var org_li = $("#as-original-"+x); 95 96 if(isMainPage){ 97 var results_holder = $('<div class="autokeyword_v4 as-results" id="as-results-'+x+'"></div>').hide(); 98 } else if(opts.newDesign) { 99 var results_holder = $('<div class="autokeyword as-results" id="as-results-'+x+'"></div>').hide(); 100 } else{ 101 var results_holder = $('<div class="as-results" id="as-results-'+x+'"></div>').hide(); 102 } 103 104 var results_ul = $('<ul class="as-list"></ul>'); 105 var values_input = ""; 106 var prefill_value = ""; 107 results_ul.css({"width": selections_holder.outerWidth()+opts.browserGap}); 108 109 results_holder.css({"margin": opts.resultsMargin}); 110 111 opts.divWidth = parseInt(opts.divWidth); 112 if(!isNaN(opts.divWidth) && opts.divWidth > 0) { 113 results_holder.css({"width":opts.divWidth}); 114 } 115 opts.divTop = parseInt(opts.divTop); 116 if(!isNaN(opts.divTop) && opts.divTop > 0) { 117 results_holder.css({"top":opts.divTop}); 118 } 119 120 if(typeof opts.preFill == "string"){ 121 var vals = opts.preFill.split(","); 122 for(var i=0; i < vals.length; i++){ 123 var v_data = {}; 124 v_data[opts.selectedValuesProp] = vals[i]; 125 if(vals[i] != ""){ 126 add_selected_item(v_data, "000"+i); 127 } 128 } 129 prefill_value = opts.preFill; 130 } else { 131 prefill_value = ""; 132 var prefill_count = 0; 133 for (k in opts.preFill) if (opts.preFill.hasOwnProperty(k)) prefill_count++; 134 if(prefill_count > 0){ 135 for(var i=0; i < prefill_count; i++){ 136 var new_v = opts.preFill[i][opts.selectedValuesProp]; 137 if(new_v == undefined){ new_v = ""; } 138 prefill_value = prefill_value+new_v+","; 139 if(new_v != ""){ 140 add_selected_item(opts.preFill[i], "000"+i); 141 } 142 } 143 } 144 } 145 146 if(prefill_value != ""){ 147 input.val(""); 148 var lastChar = prefill_value.substring(prefill_value.length-1); 149 if(lastChar != ","){ prefill_value = prefill_value+","; } 150 values_input = ","+prefill_value; 151 $("li.as-selection-item", selections_holder).addClass("blur").removeClass("selected"); 152 } 153 154 selections_holder.click(function(){ 155 input_focus = true; 156 input.focus(); 157 }).mousedown(function(){ input_focus = false; }).after(results_holder); 158 159 var timeout = null; 160 var prev = ""; 161 var totalSelections = 0; 162 var tab_press = false;
163 164 // Handle input field events 165 input.focus(function(){ 166 if($(this).val() == opts.startText && values_input == ""){ 167 $(this).val(""); 168 } else if(input_focus){ 169 $("li.as-selection-item", selections_holder).removeClass("blur"); 170 if($(this).val() != ""){ 171 if ($("li:first", results_holder).text() == opts.emptyText) { 172 results_holder.hide(); 173 } else { 174 if (input.val() != values_input) { 175 if (!isSubmit) keyChange(); 176 } else { 177 results_holder.show(); 178 } 179 } 180 } 181 } 182 input_focus = true; 183 return true; 184 }).blur(function(){ 185 if($(this).val() == "" && values_input == "" && prefill_value == ""){ 186 if (opts.startText) $(this).val(opts.startText); 187 } else if(input_focus){ 188 $("li.as-selection-item", selections_holder).addClass("blur").removeClass("selected"); 189 results_holder.hide(); 190 } 191 }).keydown(function(e) { 192 // track last key pressed 193 lastKeyPressCode = e.keyCode; 194 first_focus = false; 195 switch(e.keyCode) { 196 case 37: // left 197 break; 198 case 39: // right 199 break; 200 case 38: // up 201 e.preventDefault(); 202 e.stopPropagation(); 203 // ìì±ì¤ì¸ íê¸ ë¬¸ì ë문ì íì¬ ê°ì ë¤ìíë² ê¸°ë¡ì í´ì¤ë¤. 204 $('#inputQu').val($('#inputQu').val()); 205 moveSelection("up"); 206 break; 207 case 40: // down 208 e.preventDefault(); 209 e.stopPropagation(); 210 // ìì±ì¤ì¸ íê¸ ë¬¸ì ë문ì íì¬ ê°ì ë¤ìíë² ê¸°ë¡ì í´ì¤ë¤. 211 $('#inputQu').val($('#inputQu').val()); 212 moveSelection("down"); 213 break; 214 case 8: // delete 215 if(input.val() == ""){ 216 var last = values_input.split(","); 217 last = last[last.length - 2]; 218 selections_holder.children().not(org_li.prev()).removeClass("selected"); 219 if(org_li.prev().hasClass("selected")){ 220 values_input = values_input.val().replace(","+last+",",","); 221 opts.selectionRemoved.call(this, org_li.prev()); 222 } else { 223 opts.selectionClick.call(this, org_li.prev()); 224 org_li.prev().addClass("selected"); 225 } 226 } 227 if(input.val().length <= 1){ 228 results_holder.hide(); 229 prev = ""; 230 } 231 else { 232 if (timeout){ clearTimeout(timeout); } 233 timeout = setTimeout(function(){ keyChange(); }, opts.keyDelay); 234 } 235 break; 236 case 13: // return 237 tab_press = false; 238 var active = $("li.active:first", results_holder); 239 if(active.length > 0){ 240 // active.click(); 241 results_holder.hide(); 242 } 243 244 if(false && (opts.neverSubmit || active.length > 0)){ 245 e.preventDefault(); 246 } 247 break; 248 default: 249 if(opts.showResultList){ 250 if(opts.selectionLimit && $("li.as-selection-item", selections_holder).length >= opts.selectionLimit){ 251 results_ul.html('<li class="as-message">'+opts.limitText+'</li>'); 252 if ($("li:first", results_holder).text() == opts.emptyText) { 253 results_holder.hide(); 254 } else { 255 results_holder.show(); 256 } 257 } else { 258 if (timeout){ clearTimeout(timeout); } 259 timeout = setTimeout(function(){ keyChange(); }, opts.keyDelay); 260 } 261 } 262 263 originKeyword = $('#inputQu').val(); 264 break; 265 } 266 }); 267 268 function keyChange() { 269 // ignore if the following keys are pressed: [del] [shift] [capslock] 270 if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ){ return results_holder.hide(); } 271 var string = convertHangul(input.val().replace(/[\\]+|[\/]+/g,"")); 272 273 if (string == prev) return; 274 prev = string; 275 if (string.length >= opts.minChars) { 276 if(d_type == "string"){ 277 var limit = ""; 278 if(opts.retrieveLimit){ 279 limit = "&limit="+encodeURIComponent(opts.retrieveLimit); 280 } 281 if(opts.beforeRetrieve){ 282 string = opts.beforeRetrieve.call(this, string); 283 } 284 string = $.trim(string); 285 values_input = string; 286 287 if (string.length > 0) { 288 $.getJSON(req_string+"?"+opts.queryParam+"="+encodeURIComponent(string)+limit+opts.extraParams, function(data){ 289 d_count = 0; 290 var new_data = opts.retrieveComplete.call(this, data.list); 291 for (k in new_data) if (new_data.hasOwnProperty(k)) d_count++; 292 processData(new_data, string); 293 }); 294 } 295 } else { 296 if(opts.beforeRetrieve){ 297 string = opts.beforeRetrieve.call(this, string); 298 } 299 processData(org_data, string); 300 } 301 } else { 302 results_holder.hide(); 303 } 304 } 305 306 var num_count = 0; 307 function processData(data, query, recommendBook, recommendDocs){ 308 if (!opts.matchCase){ query = query.toLowerCase(); } 309 var matchCount = 0; 310 results_holder.html(results_ul.html("")).hide(); 311 results_holder.prepend('<p style="border:none" class="as-list-title">ì¶ì²ê²ìì´</p>'); 312 for(var i=0;i<d_count;i++){ 313 var num = i; 314 num_count++; 315 var forward = false;
316 if(opts.searchObjProps == "value") { 317 var str = data[num].value; 318 } 319 else { 320 var str = ""; 321 var names = opts.searchObjProps.split(","); 322 for(var y=0;y<names.length;y++){ 323 var name = $.trim(names[y]); 324 str = str+data[num][name]+" "; 325 } 326 } 327 if(str){ 328 if (!opts.matchCase){ str = str.toLowerCase(); } 329 forward = true; 330 } 331 if(forward){ 332 var formatted = $('<li class="as-result-item" id="as-result-item-'+num+'" data-text="' + data[num].keyword + '"></li>').click(function(){ 333 var raw_data = $(this).data("data"); 334 var number = raw_data.num; 335 if($("#as-selection-"+number, selections_holder).length <= 0 && !tab_press){ 336 var data = raw_data.attributes; 337 prev = ""; 338 add_selected_item(data, number); 339 opts.resultClick.call(this, raw_data); 340 results_holder.hide(); 341 } 342 tab_press = false; 343 }).mousedown(function(){ input_focus = false; }).mouseover(function(){ 344 $("li", results_ul).removeClass("active"); 345 $(this).addClass("active"); 346 }).data("data",{attributes: data[num], num: num_count}); 347 var this_data = $.extend({},data[num]); 348 var regx = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + query + ")(?![^<>]*>)(?![^&;]+;)", ((opts.matchCase)? "" : "i") + ((opts.matchGlobal)? "g" : "")); 349 350 if(opts.resultsHighlight){ 351 var highlightTag = "<em>$1</em>"; 352 if(opts.newDesign){ 353 highlightTag = "<strong>$1</strong>"; 354 } 355 this_data[opts.selectedItemProp] = this_data[opts.selectedItemProp].replace(regx,highlightTag); 356 } 357 if(!opts.formatList){ 358 formatted = formatted.html(this_data[opts.selectedItemProp]); 359 } else { 360 formatted = opts.formatList.call(this, this_data, formatted); 361 } 362 results_ul.append(formatted); 363 delete this_data; 364 matchCount++; 365 if(opts.retrieveLimit && opts.retrieveLimit == matchCount ){ break; } 366 } 367 } 368 369 if(matchCount <= 0){ 370 results_ul.html('<li class="as-message">'+opts.emptyText+'</li>'); 371 } 372 results_ul.css("width", selections_holder.outerWidth()+opts.browserGap); 373 if(isMainPage) { 374 results_ul.css("width", 647); 375 } 376 377 if ( 378 ($("li:first", results_holder).text() == opts.emptyText) 379 && matchCount <= 0 380 ) { 381 results_holder.hide(); 382 } else { 383 if (matchCount <= 0) { 384 results_holder.find('.as-list-title').hide(); 385 results_ul.hide(); 386 } 387 results_holder.show(); 388 opts.resultsComplete.call(this, results_holder); 389 } 390 // if ($("li:first", results_holder).text() == opts.emptyText || matchCount <= 0) { 391 // results_holder.hide(); 392 // } else { 393 // results_holder.show(); 394 // opts.resultsComplete.call(this, results_holder); 395 // } 396 } 397 398 function add_selected_item(data, num){ 399 isSubmit = true; 400 input.val(data[opts.selectedValuesProp]); 401 $("form[name='search']").submit(); 402 } 403 404 function moveSelection(direction){ 405 if($(":visible",results_holder).length > 0){ 406 var lis = $("li[id^='as-result-item']", results_holder); 407 if(direction == "down"){ 408 var start = lis.eq(0); 409 } else { 410 var start = lis.filter(":last"); 411 } 412 var active = $("li.active:first", results_holder); 413 if(active.length > 0){ 414 if(direction == "down"){ 415 start = active.next(); 416 } else { 417 start = active.prev(); 418 } 419 } 420 lis.removeClass("active"); 421 start.addClass("active"); 422 423 if (!$("li.active > span:first", results_holder).text()) { 424 input.val(values_input); 425 } 426 else { 427 if (timeout){ clearTimeout(timeout); } 428 input.val($("li.active > span:first", results_holder).text()); 429 results_holder.show(); 430 } 431 var selected = $('.as-list>li.active:eq(0)'); 432 if(selected.length > 0) { 433 var _text = selected.attr('data-text'); 434 $('#inputQu').val(_text); 435 } else { 436 $('#inputQu').val(originKeyword); 437 } 438 } 439 } 440 441 function convertHangul(str) { 442 var initial = "rRseEfaqQtTdwWczxvg"; 443 var regInitial = "[" + initial + "]"; 444 var medial = {k:0,o:1,i:2,O:3,j:4,p:5,u:6,P:7,h:8,hk:9,ho:10,hl:11,y:12,n:13,nj:14,np:15,nl:16,b:1
4447,m:18,ml:19,l:20} 445 var regMedial = "hk|ho|hl|nj|np|nl|ml|k|o|i|O|j|p|u|P|h|y|n|b|m|l"; 446 var final = {"":0,r:1,R:2,rt:3,s:4,sw:5,sg:6,e:7,f:8,fr:9,fa:10,fq:11,ft:12,fx:13,fv:14,fg:15,a:16,q:17,qt:18,t:19,T:20,d:21,w:22,c:23,z:24,x:25,v:26,g:27} 447 var regFinal = "rt|sw|sg|fr|fa|fq|ft|fx|fv|fg|qt|r|R|s|e|f|a|q|t|T|d|w|c|z|x|v|g|"; 448 449 var reg_exp = new RegExp("("+regInitial+")("+regMedial+")((?:"+regFinal+")(?=(?:"+regInitial+")(?:"+regMedial+"))|(?:"+regFinal+"))", "g"); 450 451 var regAlpha =/^[a-zA-Z]+$/; 452 var regHangul =/^[ê°-í£]+$/; 453 454 temp = str.replace(reg_exp, function replace(str, h, b, f) { return String.fromCharCode(initial.indexOf(h)*21*28 + medial[b]*28 + final[f] + 44032); }); 455 456 if(temp && regHangul.test(temp) && !regAlpha.test(temp)) { 457 str = temp; 458 } 459 460 return str; 461 } 462 }); 463 } 464 } 465})(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.