[ Index ] |
PHP Cross Reference of MyBB |
[Summary view] [Print] [Text view]
1 var autoComplete = Class.create(); 2 3 autoComplete.prototype = { 4 initialize: function(textbox, url, options) 5 { 6 if(!$(textbox)) 7 { 8 return false; 9 } 10 11 this.cache = new Object(); 12 this.lastValue = ''; 13 this.lastKeycode = 0; 14 this.textbox = $(textbox); 15 this.formSubmit = false; 16 this.url = url; 17 18 this.currentIndex = -1; 19 this.valueSpan = options.valueSpan; 20 this.urlParam = options.urlParam; 21 22 if(options.minChars) 23 { 24 this.minChars = options.minChars; 25 } 26 else 27 { 28 this.minChars = 3; 29 } 30 31 if(options.delimChar) 32 { 33 this.delimChar = options.delimChar; 34 } 35 this.menuOpen = false; 36 this.timeout = false; 37 38 Event.observe(document, "dom:loaded", this.init.bindAsEventListener(this)); 39 }, 40 41 init: function() 42 { 43 this.textbox.setAttribute("autocomplete", "off"); 44 this.textbox.autocompletejs = this; 45 Event.observe(this.textbox, "keypress", this.onKeyPress.bindAsEventListener(this)); 46 Event.observe(this.textbox, "keyup", this.onKeyUp.bindAsEventListener(this)); 47 Event.observe(this.textbox, "keydown", this.onKeyDown.bindAsEventListener(this)); 48 49 if(this.textbox.form) 50 { 51 Event.observe(this.textbox.form, "submit", this.onFormSubmit.bindAsEventListener(this)); 52 this.formSubmit = true; 53 } 54 55 this.textbox.onsubmit = this.onFormSubmit.bindAsEventListener(this); 56 this.popup = document.createElement("div"); 57 this.popup.style.position = "absolute"; 58 this.popup.className = "autocomplete"; 59 this.popup.style.display = 'none'; 60 document.body.appendChild(this.popup); 61 62 this.textbox.popup = this; 63 64 Event.observe(document, "unload", this.clearCache.bindAsEventListener(this)); 65 }, 66 67 onFormSubmit: function(e) 68 { 69 if(this.lastKeycode == Event.KEY_RETURN && this.menuOpen == true) 70 { 71 setTimeout(function() { this.textbox.focus() }.bind(this), 10); 72 this.menuOpen = false; 73 this.hidePopup(); 74 Event.stop(e); 75 return false; 76 } 77 else 78 { 79 return true; 80 } 81 //this.textbox.setAttribute("autocomplete", "on"); 82 }, 83 84 onKeyDown: function(e) 85 { 86 this.lastKeycode = e.keyCode; 87 }, 88 89 onKeyUp: function(e) 90 { 91 this.lastKeycode = e.keyCode; 92 }, 93 94 onKeyPress: function(e) 95 { 96 if(this.timeout) 97 { 98 clearTimeout(this.timeout); 99 } 100 101 switch(e.keyCode) 102 { 103 case Event.KEY_LEFT: 104 case Event.KEY_RIGHT: 105 break; 106 case Event.KEY_UP: 107 if(this.popup.visible()) 108 { 109 if(this.currentIndex > 0) 110 { 111 this.scrollToItem(this.currentIndex-1); 112 this.highlightItem(this.currentIndex-1); 113 this.setTypeAhead(this.currentIndex); 114 } 115 else if(this.currentIndex == 0) 116 { 117 this.textbox.value = this.lastValue; 118 this.hidePopup(); 119 } 120 } 121 Event.stop(e); 122 break; 123 case Event.KEY_DOWN: 124 if(this.currentIndex+1 < this.popup.childNodes.length && this.popup.visible()) 125 { 126 this.scrollToItem(this.currentIndex+1); 127 this.highlightItem(this.currentIndex+1); 128 this.setTypeAhead(this.currentIndex); 129 } 130 Event.stop(e); 131 break; 132 case Event.KEY_TAB: 133 if(this.popup.visible() && this.currentIndex > -1) 134 { 135 this.updateValue(this.popup.childNodes[this.currentIndex]); 136 this.hidePopup(); 137 this.currentIndex = -1; 138 139 if(this.delimChar) 140 { 141 Event.stop(e); 142 } 143 return false; 144 } 145 break; 146 case Event.KEY_RETURN: 147 if(this.menuOpen == true) 148 { 149 Event.stop(e); 150 } 151 if(this.currentIndex != -1) 152 { 153 this.updateValue(this.popup.childNodes[this.currentIndex]); 154 this.hidePopup(); 155 this.currentIndex = -1; 156 this.clearSelection(); 157 } 158 //return false; 159 break; 160 case Event.KEY_ESC: 161 this.hidePopup(); 162 break; 163 default: 164 this.currentKeyCode = e.keyCode; 165 this.timeout = setTimeout("$('"+this.textbox.id+"').autocompletejs.doRequest();", 500); 166 break; 167 } 168 return true; 169 }, 170 171 buildURL: function(value) 172 { 173 if(!this.urlParam) 174 { 175 this.urlParam = "query"; 176 } 177 178 var separator = "?"; 179 if(this.url.indexOf("?") >= 0) 180 { 181 separator = "&"; 182 } 183 184 return this.url+separator+this.urlParam+"="+encodeURIComponent(value); 185 }, 186 187 doRequest: function() 188 { 189 if(this.lastValue == this.textbox.value) 190 { 191 return false; 192 } 193 194 this.lastValue = this.textbox.value; 195 this.previousComplete = ''; 196 value = this.textbox.value; 197 cacheValue = this.textbox.length+this.textbox.value; 198 199 if(this.delimChar) 200 { 201 delimIndex = value.lastIndexOf(this.delimChar); 202 if(delimIndex >= -1) 203 { 204 if(value.charAt(delimIndex+1) == " ") 205 { 206 delimIndex += 1; 207 } 208 209 this.previousComplete = value.substr(0, delimIndex+1); 210 value = value.substr(delimIndex+1); 211 } 212 } 213 214 if(value.length >= this.minChars) 215 { 216 if(this.cache[cacheValue]) 217 { 218 this.popup.innerHTML = this.cache[cacheValue]; 219 this.onComplete(); 220 } 221 else 222 { 223 new Ajax.Request(this.buildURL(value), {method: 'get', onComplete: this.onComplete.bindAsEventListener(this)}); 224 } 225 } 226 else 227 { 228 if(this.popup.visible()) 229 { 230 this.hidePopup(); 231 } 232 } 233 }, 234 235 onComplete: function(request) 236 { 237 // Cached results or fresh ones? 238 if(request) 239 { 240 if(request.responseText.charAt(0) != "<") 241 { 242 if(this.popup.visible()) 243 { 244 this.hidePopup(); 245 } 246 return false; 247 } 248 249 cacheValue = this.textbox.length+this.textbox.value; 250 this.popup.innerHTML = request.responseText; 251 this.cache[cacheValue] = this.popup.innerHTML; 252 } 253 254 this.currentIndex = -1; 255 if(this.popup.childNodes.length < 1) 256 { 257 return false; 258 } 259 260 $A(this.popup.childNodes).each(function(node) 261 { 262 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 263 { 264 this.popup.removeChild(node); 265 } 266 }.bind(this)); 267 268 if(this.popup.childNodes.length < 1) 269 { 270 if(this.popup.visible()) 271 { 272 this.hidePopup(); 273 } 274 return false; 275 } 276 277 $A(this.popup.childNodes).each(function(item, i) 278 { 279 item.index = i; 280 item.style.padding = "1px"; 281 item.style.clear = "both"; 282 //item.style.height = "1em"; 283 Event.observe(item, "mouseover", this.itemOver.bindAsEventListener(this)); 284 Event.observe(item, "click", this.itemClick.bindAsEventListener(this)); 285 }.bind(this)); 286 287 // Clone to get offset height (not possible when display=none) 288 var clone = this.popup.cloneNode(true); 289 document.body.appendChild(clone); 290 clone.style.top = "-1000px"; 291 clone.style.display = "block"; 292 offsetHeight = clone.offsetHeight 293 Element.remove(clone); 294 295 var maxHeight = 100; 296 if(offsetHeight > 0 && offsetHeight < maxHeight) 297 { 298 this.popup.style.overflow = "hidden"; 299 } 300 else if(MyBB.browser == "ie") 301 { 302 this.popup.style.height = maxHeight+"px"; 303 this.popup.style.overflowY = "auto"; 304 } 305 else 306 { 307 this.popup.style.maxHeight = maxHeight+"px"; 308 this.popup.style.overflow = "auto"; 309 } 310 311 var offsetTop = 0; 312 var offsetLeft = 0; 313 314 this.popup.style.width = this.textbox.offsetWidth-3+"px"; 315 element = this.textbox; 316 do 317 { 318 offsetTop += element.offsetTop || 0; 319 offsetLeft += element.offsetLeft || 0; 320 element = element.offsetParent; 321 if(element && ($(element).getStyle('position') == 'absolute')) 322 { 323 break; 324 } 325 } while(element); 326 this.popup.style.marginTop = "-1px"; 327 if(MyBB.browser == "ie") 328 { 329 this.popup.style.left = offsetLeft+1+"px"; 330 } 331 else 332 { 333 this.popup.style.left = offsetLeft+"px"; 334 } 335 this.popup.style.top = offsetTop+this.textbox.offsetHeight+"px"; 336 this.popup.scrollTop = 0; 337 Event.observe(this.textbox, "blur", this.hidePopup.bindAsEventListener(this)); 338 Event.observe(this.popup, "mouseover", this.popupOver.bindAsEventListener(this)); 339 Event.observe(this.popup, "mouseout", this.popupOut.bindAsEventListener(this)); 340 this.popup.style.display = ''; 341 this.menuOpen = true; 342 this.overPopup = 0; 343 344 if(this.currentKeyCode != 8 && this.currentKeyCode != 46) 345 { 346 this.highlightItem(0); 347 /*his.setTypeAhead(0, 1);*/ 348 } 349 }, 350 351 hidePopup: function() 352 { 353 this.popup.hide(); 354 this.menuOpen = false; 355 Event.stopObserving(this.textbox, "blur", this.hidePopup.bindAsEventListener(this)); 356 Event.stopObserving(this.popup, "mouseover", this.popupOver.bindAsEventListener(this)); 357 Event.stopObserving(this.popup, "mouseout", this.popupOut.bindAsEventListener(this)); 358 359 if(this.overPopup == 1 && this.currentIndex > -1) 360 { 361 this.updateValue(this.popup.childNodes[this.currentIndex]); 362 this.currentIndex = -1; 363 this.textbox.focus(); 364 } 365 }, 366 367 popupOver: function() 368 { 369 this.overPopup = 1; 370 }, 371 372 popupOut: function() 373 { 374 this.overPopup = 0; 375 }, 376 377 updateValue: function(selectedItem) 378 { 379 if(this.valueSpan && selectedItem.innerHTML) 380 { 381 var items = selectedItem.getElementsByTagName("SPAN"); 382 if(items) 383 { 384 $A(items).each(function(item) { 385 if(item.className == this.valueSpan) 386 { 387 textBoxValue = item.innerHTML; 388 } 389 }.bind(this)); 390 } 391 } 392 else if(!this.valueSpan && selectedItem.innerHTML) 393 { 394 textBoxValue = selectedItem.innerHTML; 395 } 396 else 397 { 398 textBoxValue = selectedItem; 399 } 400 401 this.textbox.value = ""; 402 if(this.delimChar) 403 { 404 if(this.previousComplete) 405 { 406 this.textbox.value = this.previousComplete; 407 } 408 this.textbox.value += textBoxValue+this.delimChar+" "; 409 } 410 else 411 { 412 this.textbox.value = textBoxValue; 413 } 414 return textBoxValue; 415 }, 416 417 itemOver: function(event) 418 { 419 var element = Event.findElement(event, 'DIV'); 420 element.style.cursor = 'pointer'; 421 selectedItem = element.index; 422 this.highlightItem(selectedItem); 423 }, 424 425 itemClick: function(event) 426 { 427 var element = Event.findElement(event, 'DIV'); 428 selectedItem = element.index; 429 this.updateValue(this.popup.childNodes[selectedItem]); 430 this.hidePopup(); 431 this.currentIndex = -1; 432 this.clearSelection(); 433 }, 434 435 highlightItem: function(selectedItem) 436 { 437 if(this.currentIndex != -1) 438 { 439 this.popup.childNodes[this.currentIndex].className = ""; 440 } 441 this.currentIndex = selectedItem; 442 this.popup.childNodes[this.currentIndex].className = "autocomplete_selected"; 443 }, 444 445 scrollToItem: function(selectedItem) 446 { 447 newItem = this.popup.childNodes[selectedItem]; 448 449 if(!newItem) 450 { 451 return false; 452 } 453 454 if(newItem.offsetTop+newItem.offsetHeight > this.popup.scrollTop+this.popup.offsetHeight) 455 { 456 this.popup.scrollTop = (newItem.offsetTop+newItem.offsetHeight) - this.popup.offsetHeight; 457 } 458 else if((newItem.offsetTop+newItem.offsetHeight) < this.popup.scrollTop) 459 { 460 this.popup.scrollTop = newItem.offsetTop; 461 } 462 else if(newItem.offsetTop < this.popup.scrollTop) 463 { 464 this.popup.scrollTop = newItem.offsetTop; 465 } 466 else if(newItem.offsetTop > (this.popup.scrollTop + this.popup.offsetHeight)) 467 { 468 this.popup.scrollTop = (newItem.offsetTop+newItem.offsetHeight)-this.popup.offsetHeight; 469 } 470 }, 471 472 setTypeAhead: function(selectedItem, selectChanges) 473 { 474 selectedItem = this.popup.childNodes[selectedItem]; 475 476 if(!selectedItem || (!this.textbox.setSelectionRange && !this.textbox.createTextRange)) 477 { 478 return false; 479 } 480 481 if(selectChanges) 482 { 483 selectStart = this.textbox.value.length; 484 } 485 486 newValue = this.updateValue(selectedItem); 487 selectEnd = this.textbox.value.length; 488 if(!selectChanges) 489 { 490 selectStart = selectEnd; 491 } 492 493 if(this.textbox.setSelectionRange) 494 { 495 this.textbox.setSelectionRange(selectStart, selectEnd); 496 } 497 else if(this.textbox.createTextRange) 498 { 499 var range = this.textbox.createTextRange(); 500 range.moveStart('character', selectStart); 501 range.moveEnd('character', selectEnd-newValue.length); 502 range.select(); 503 } 504 }, 505 506 clearSelection: function() 507 { 508 selectEnd = this.textbox.value.length; 509 510 if(this.textbox.setSelectionRange) 511 { 512 this.textbox.setSelectionRange(selectEnd, selectEnd); 513 } 514 else if(window.createTextRange) 515 { 516 var range = this.textbox.createTextRange(); 517 range.moveStart('character', selectEnd); 518 range.moveEnd('character', selectEnd); 519 range.select(); 520 } 521 }, 522 523 clearCache: function() 524 { 525 this.cache = ''; 526 } 527 };
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Oct 8 19:19:50 2013 | Cross-referenced by PHPXref 0.7.1 |