[ Index ]

PHP Cross Reference of MyBB

title

Body

[close]

/jscripts/ -> autocomplete.js (source)

   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  };


Generated: Tue Oct 8 19:19:50 2013 Cross-referenced by PHPXref 0.7.1