1jQuery.fn.searchbox = function(delay) { 2 return this.each(function() { 3 if (delay == undefined) { 4 delay = 100; 5 } 6 7 // Grab a jQuery reference to the textbox 8 var textbox = $(this); 9 var boxid = textbox.attr("id"); 10 11 // Look for options in data- attributes on the search box 12 var searchpath = textbox.attr("data-path") || "/_search"; 13 var noPopup = textbox.attr("data-popup") == "false"; 14 var require = textbox.attr("data-require"); 15 16 // Create a div for the search results and append it to the body 17 var resultsdiv = $('<div id="' + boxid + '-results">').attr("class", "search-results"); 18 19 var catname = null; 20 var resultcount = 0; 21 var selected = 0; 22 var latest = -1; 23 var lastqstring = null; 24 var timer = null; 25 var body = $("body"); 26 27 if (!noPopup) { 28 body.mouseup(function (e) { 29 if (e.target !== textbox[0] 30 && $(e.target).closest(resultsdiv).length == 0) { 31 hideResults() 32 } 33 }) 34 } 35 36 var resultsparent = noPopup ? textbox.parent() : body; 37 resultsparent.append(resultsdiv); 38 39 textbox.focus(function() { 40 update(); 41 }).blur(function() { 42 //setTimeout(hideResults, 500); 43 }).keydown(function(e) { 44 var keycode = e.keyCode || window.event.keyCode; 45 var rc = true; 46 47 if (keycode == 13) { 48 // Enter 49 enterClick(); 50 return false; 51 } else if (keycode == 27) { 52 // Escape 53 if (!noPopup) { 54 hideResults(); 55 } 56 return false; 57 } else if (keycode == 38) { 58 // Up key 59 if (selected == 0 || selected == -1) { 60 selected = resultcount - 1; 61 } else { 62 selected--; 63 } 64 updateCss(); 65 rc = false; 66 } else if (keycode == 40) { 67 // Down key 68 if (selected == resultcount - 1) { 69 selected = 0; 70 } else { 71 selected++; 72 } 73 updateCss(); 74 rc = false; 75 } else { 76 if (timer) { 77 clearTimeout(timer); 78 } 79 selected = 0; 80 } 81 82 timer = setTimeout(update, delay); 83 return rc; 84 }); 85 86 function updateCss() { 87 resultsdiv.find(".hit").each(function(i) { 88 if (i == selected) { 89 $(this).addClass("selected"); 90 } else { 91 $(this).removeClass("selected"); 92 } 93 }); 94 } 95 96 function setCategory(name) { 97 catname = name; 98 update(true); 99 } 100 101 function enterClick(e) { 102 if (e) { 103 // User might have clicked an element inside the list item, so 104 // find the closest list item 105 e = $(e).closest(".hit") 106 } else { 107 e = resultsdiv.find(".hit.selected") 108 } 109 110 if (e.hasClass("more")) { 111 setCategory(e.parent().attr("data-name")); 112 } else { 113 var href = e.find("a").attr("href"); 114 if (href) { 115 window.location = href; 116 } 117 } 118 } 119 120 function showResults() { 121 resultsdiv.fadeIn(200); 122 } 123 function hideResults() { 124 resultsdiv.fadeOut(200); 125 } 126 127 function fillResults(html) { 128 html = $(html); 129 var sent = Number(html.attr("data-sent")); 130 if (sent <= latest) return; 131 latest = sent; 132 133 resultsdiv.html(html); 134 135 var hits = html.find(".hit"); 136 resultcount = hits.size(); 137 selected = 0; 138 hits.mouseover(function(e) { 139 var target = $(e.target); 140 while (!target.hasClass("hit")) { 141 target = target.parent(); 142 } 143 hits.each(function(i) { 144 if (this === target[0]) { 145 selected = i; 146 $(this).addClass("selected"); 147 } else { 148 $(this).removeClass("selected"); 149 } 150 }); 151 }).click(function(e) { 152 enterClick(e.target); 153 }); 154 155 var cats = html.find(".cat"); 156 cats.click(function(e) { 157 setCategory($(this).attr("data-name")); 158 }); 159 160 updateCss(); 161 } 162 163 function update(force) { 164 var qstring = textbox.val(); 165 if (qstring === "") { 166 catname = null; 167 } 168 showResults(); 169 if (force || qstring !== lastqstring) { 170 //var startpos = getSelectionStart(box); 171 //var endpos = getSelectionEnd(box); 172 173 //console.log("Running", qstring, catname); 174 $.ajax(searchpath, { 175 data: { 176 q: qstring, 177 category: catname, 178 require: require, 179 permanent: noPopup ? "true" : "false" 180 //startpos: startpos, 181 //endpos: endpos, 182 }, 183 success: function (data) { 184 fillResults(data); 185 }, 186 error: function (data) { 187 console.log("Search error"); 188 } 189 }); 190 lastqstring = qstring; 191 } 192 } 193 194 if (noPopup) { 195 update(); 196 } 197 }); 198}; 199
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.