1 2 3/** 4 * An autosuggest textbox control. 5 * @class 6 * @scope public 7 */ 8function AutoSuggestControl(oTextbox /*:HTMLInputElement*/, 9 oProvider /*:SuggestionProvider*/) { 10 11 /** 12 * The currently selected suggestions. 13 * @scope private 14 */ 15 this.cur /*:int*/ = -1; 16 17 /** 18 * The dropdown list layer. 19 * @scope private 20 */ 21 this.layer = null; 22 23 /** 24 * Suggestion provider for the autosuggest feature. 25 * @scope private. 26 */ 27 this.provider /*:SuggestionProvider*/ = oProvider; 28 29 /** 30 * The textbox to capture. 31 * @scope private 32 */ 33 this.textbox /*:HTMLInputElement*/ = oTextbox; 34 35 //initialize the control 36 this.init(); 37 38} 39 40/** 41 * Autosuggests one or more suggestions for what the user has typed. 42 * If no suggestions are passed in, then no autosuggest occurs. 43 * @scope private 44 * @param aSuggestions An array of suggestion strings. 45 * @param bTypeAhead If the control should provide a type ahead suggestion. 46 */ 47AutoSuggestControl.prototype.autosuggest = function (aSuggestions /*:Array*/, 48 bTypeAhead /*:boolean*/) { 49 //make sure there's at least one suggestion 50 if (aSuggestions.length > 0) { 51 if (bTypeAhead) { 52 this.typeAhead(aSuggestions[0]); 53 } 54 55 this.showSuggestions(aSuggestions); 56 } else { 57 this.hideSuggestions(); 58 } 59}; 60 61/** 62 * Creates the dropdown layer to display multiple suggestions. 63 * @scope private 64 */ 65AutoSuggestControl.prototype.createDropDown = function () { 66 var oThis = this; 67 68 //create the layer and assign styles 69 this.layer = document.createElement("div"); 70 this.layer.className = "suggestions"; 71 this.layer.style.visibility = "hidden"; 72 this.layer.style.width ='300px'; 73 74 //when the user clicks on the a suggestion, get the text (innerHTML) 75 //and place it into a textbox 76 this.layer.onmousedown = 77 this.layer.onmouseup = 78 this.layer.onmouseover = function (oEvent) { 79 oEvent = oEvent || window.event; 80 oTarget = oEvent.target || oEvent.srcElement; 81 82 if (oEvent.type == "mousedown") { 83 oThis.textbox.value = oTarget.firstChild.nodeValue; 84 oThis.hideSuggestions(); 85 } else if (oEvent.type == "mouseover") { 86 oThis.highlightSuggestion(oTarget); 87 } else { 88 oThis.textbox.focus(); 89 } 90 }; 91 92 93 document.body.appendChild(this.layer); 94}; 95 96/** 97 * Gets the left coordinate of the textbox. 98 * @scope private 99 * @return The left coordinate of the textbox in pixels. 100 */ 101AutoSuggestControl.prototype.getLeft = function () /*:int*/ { 102 103 var oNode = this.textbox; 104 var iLeft = 0; 105 106 while(oNode.tagName != "BODY") { 107 iLeft += oNode.offsetLeft; 108 oNode = oNode.offsetParent; 109 } 110 111 return iLeft; 112}; 113 114/** 115 * Gets the top coordinate of the textbox. 116 * @scope private 117 * @return The top coordinate of the textbox in pixels. 118 */ 119AutoSuggestControl.prototype.getTop = function () /*:int*/ { 120 var oNode = this.textbox; 121 var iTop = 0; 122 123 while(oNode.tagName != "BODY") { 124 iTop += oNode.offsetTop; 125 oNode = oNode.offsetParent; 126 } 127 128 return iTop; 129}; 130 131/** 132 * Handles three keydown events. 133 * @scope private 134 * @param oEvent The event object for the keydown event. 135 */ 136AutoSuggestControl.prototype.handleKeyDown = function (oEvent /*:Event*/) { 137 switch(oEvent.keyCode) { 138 case 38: //up arrow 139 this.previousSuggestion(); 140 break; 141 case 40: //down arrow 142 this.nextSuggestion(); 143 break; 144 case 13: //enter 145 this.hideSuggestions(); 146 break; 147 } 148 149}; 150 151/** 152 * Handles keyup events. 153 * @scope private 154 * @param oEvent The event object for the keyup event. 155 */ 156AutoSuggestControl.prototype.handleKeyUp = function (oEvent /*:Event*/) { 157 var iKeyCode = oEvent.keyCode; 158 159 //for backspace (8) and delete (46), shows suggestions without typeahead 160 161 if (iKeyCode == 8 || iKeyCode == 46 ) { 162 163 this.provider.requestSuggestions(this, false); 164 165 //make sure not to interfere with non-character keys 166 } else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123)) { 167 168 //ignore 169 } else { 170 171 //request suggestions from the suggestion provider with typeahead 172 this.provider.requestSuggestions(this, true); 173 174 } 175}; 176 177/** 178 * Hides the suggestion dropdown. 179 * @scope private 180 */ 181AutoSuggestControl.prototype.hideSuggestions = function () { 182 this.layer.style.visibility = "hidden"; 183}; 184 185/** 186 * Highlights the given node in the suggestions dropdown. 187 * @scope private 188 * @param oSuggestionNode The node representing a suggestion in the dropdown. 189 */ 190AutoSuggestControl.prototype.highlightSuggestion = function (oSuggestionNode) { 191 for (var i=0; i < this.layer.childNodes.length; i++) { 192 var oNode = this.layer.childNodes[i];
193 if (oNode == oSuggestionNode) { 194 oNode.className = "current" 195 } else if (oNode.className == "current") { 196 oNode.className = ""; 197 } 198 } 199}; 200 201/** 202 * Initializes the textbox with event handlers for 203 * auto suggest functionality. 204 * @scope private 205 */ 206AutoSuggestControl.prototype.init = function () { 207 //save a reference to this object 208 var oThis = this; 209 210 //assign the onkeyup event handler 211 this.textbox.onkeyup = function (oEvent) { 212 213 //check for the proper location of the event object 214 if (!oEvent) { 215 216 oEvent = window.event; 217 } 218 219 //call the handleKeyUp() method with the event object 220 221 oThis.handleKeyUp(oEvent); 222 }; 223 224 //assign onkeydown event handler 225 this.textbox.onkeydown = function (oEvent) { 226 227 //check for the proper location of the event object 228 if (!oEvent) { 229 oEvent = window.event; 230 } 231 232 //call the handleKeyDown() method with the event object 233 oThis.handleKeyDown(oEvent); 234 }; 235 236 //assign onblur event handler (hides suggestions) 237 this.textbox.onblur = function () { 238 oThis.hideSuggestions(); 239 //checkValid(); 240 241 //getNubApp(); 242 243 //getMaterialId(); 244 }; 245 246 //create the suggestions dropdown 247 this.createDropDown(); 248}; 249 250/** 251 * Highlights the next suggestion in the dropdown and 252 * places the suggestion into the textbox. 253 * @scope private 254 */ 255AutoSuggestControl.prototype.nextSuggestion = function () { 256 var cSuggestionNodes = this.layer.childNodes; 257 258 if (cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length-1) { 259 var oNode = cSuggestionNodes[++this.cur]; 260 this.highlightSuggestion(oNode); 261 this.textbox.value = oNode.firstChild.nodeValue; 262 } 263}; 264 265/** 266 * Highlights the previous suggestion in the dropdown and 267 * places the suggestion into the textbox. 268 * @scope private 269 */ 270AutoSuggestControl.prototype.previousSuggestion = function () { 271 var cSuggestionNodes = this.layer.childNodes; 272 273 if (cSuggestionNodes.length > 0 && this.cur > 0) { 274 var oNode = cSuggestionNodes[--this.cur]; 275 this.highlightSuggestion(oNode); 276 this.textbox.value = oNode.firstChild.nodeValue; 277 } 278}; 279 280/** 281 * Selects a range of text in the textbox. 282 * @scope public 283 * @param iStart The start index (base 0) of the selection. 284 * @param iLength The number of characters to select. 285 */ 286AutoSuggestControl.prototype.selectRange = function (iStart /*:int*/, iLength /*:int*/) { 287 //use text ranges for Internet Explorer 288 if (this.textbox.createTextRange) { 289 var oRange = this.textbox.createTextRange(); 290 oRange.moveStart("character", iStart); 291 oRange.moveEnd("character", iLength - this.textbox.value.length); 292 oRange.select(); 293 294 //use setSelectionRange() for Mozilla 295 } else if (this.textbox.setSelectionRange) { 296 this.textbox.setSelectionRange(iStart, iLength); 297 } 298 299 //set focus back to the textbox 300 this.textbox.focus(); 301}; 302 303/** 304 * Builds the suggestion layer contents, moves it into position, 305 * and displays the layer. 306 * @scope private 307 * @param aSuggestions An array of suggestions for the control. 308 */ 309AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/) { 310 var oDiv = null; 311 this.layer.innerHTML = ""; //clear contents of the layer 312 313 for (var i=0; i < aSuggestions.length; i++) { 314 oDiv = document.createElement("div"); 315 oDiv.appendChild(document.createTextNode(aSuggestions[i])); 316 this.layer.appendChild(oDiv); 317 } 318 319 this.layer.style.left = this.getLeft() + "px"; 320 321 this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + "px"; 322 this.layer.style.visibility = "visible"; 323 324}; 325 326/** 327 * Inserts a suggestion into the textbox, highlighting the 328 * suggested part of the text. 329 * @scope private 330 * @param sSuggestion The suggestion for the textbox. 331 */ 332AutoSuggestControl.prototype.typeAhead = function (sSuggestion /*:String*/) { 333 //check for support of typeahead functionality 334 if (this.textbox.createTextRange || this.textbox.setSelectionRange){ 335 var iLen = this.textbox.value.length; 336 this.textbox.value = sSuggestion; 337 this.selectRange(iLen, sSuggestion.length); 338 } 339};
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.