[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/misc/ -> autocomplete.js (source)

   1  // $Id: autocomplete.js,v 1.23 2008/01/04 11:53:21 goba Exp $
   2  
   3  /**
   4   * Attaches the autocomplete behavior to all required fields
   5   */
   6  Drupal.behaviors.autocomplete = function (context) {
   7    var acdb = [];
   8    $('input.autocomplete:not(.autocomplete-processed)', context).each(function () {
   9      var uri = this.value;
  10      if (!acdb[uri]) {
  11        acdb[uri] = new Drupal.ACDB(uri);
  12      }
  13      var input = $('#' + this.id.substr(0, this.id.length - 13))
  14        .attr('autocomplete', 'OFF')[0];
  15      $(input.form).submit(Drupal.autocompleteSubmit);
  16      new Drupal.jsAC(input, acdb[uri]);
  17      $(this).addClass('autocomplete-processed');
  18    });
  19  };
  20  
  21  /**
  22   * Prevents the form from submitting if the suggestions popup is open
  23   * and closes the suggestions popup when doing so.
  24   */
  25  Drupal.autocompleteSubmit = function () {
  26    return $('#autocomplete').each(function () {
  27      this.owner.hidePopup();
  28    }).size() == 0;
  29  };
  30  
  31  /**
  32   * An AutoComplete object
  33   */
  34  Drupal.jsAC = function (input, db) {
  35    var ac = this;
  36    this.input = input;
  37    this.db = db;
  38  
  39    $(this.input)
  40      .keydown(function (event) { return ac.onkeydown(this, event); })
  41      .keyup(function (event) { ac.onkeyup(this, event); })
  42      .blur(function () { ac.hidePopup(); ac.db.cancel(); });
  43  
  44  };
  45  
  46  /**
  47   * Handler for the "keydown" event
  48   */
  49  Drupal.jsAC.prototype.onkeydown = function (input, e) {
  50    if (!e) {
  51      e = window.event;
  52    }
  53    switch (e.keyCode) {
  54      case 40: // down arrow
  55        this.selectDown();
  56        return false;
  57      case 38: // up arrow
  58        this.selectUp();
  59        return false;
  60      default: // all other keys
  61        return true;
  62    }
  63  };
  64  
  65  /**
  66   * Handler for the "keyup" event
  67   */
  68  Drupal.jsAC.prototype.onkeyup = function (input, e) {
  69    if (!e) {
  70      e = window.event;
  71    }
  72    switch (e.keyCode) {
  73      case 16: // shift
  74      case 17: // ctrl
  75      case 18: // alt
  76      case 20: // caps lock
  77      case 33: // page up
  78      case 34: // page down
  79      case 35: // end
  80      case 36: // home
  81      case 37: // left arrow
  82      case 38: // up arrow
  83      case 39: // right arrow
  84      case 40: // down arrow
  85        return true;
  86  
  87      case 9:  // tab
  88      case 13: // enter
  89      case 27: // esc
  90        this.hidePopup(e.keyCode);
  91        return true;
  92  
  93      default: // all other keys
  94        if (input.value.length > 0)
  95          this.populatePopup();
  96        else
  97          this.hidePopup(e.keyCode);
  98        return true;
  99    }
 100  };
 101  
 102  /**
 103   * Puts the currently highlighted suggestion into the autocomplete field
 104   */
 105  Drupal.jsAC.prototype.select = function (node) {
 106    this.input.value = node.autocompleteValue;
 107  };
 108  
 109  /**
 110   * Highlights the next suggestion
 111   */
 112  Drupal.jsAC.prototype.selectDown = function () {
 113    if (this.selected && this.selected.nextSibling) {
 114      this.highlight(this.selected.nextSibling);
 115    }
 116    else {
 117      var lis = $('li', this.popup);
 118      if (lis.size() > 0) {
 119        this.highlight(lis.get(0));
 120      }
 121    }
 122  };
 123  
 124  /**
 125   * Highlights the previous suggestion
 126   */
 127  Drupal.jsAC.prototype.selectUp = function () {
 128    if (this.selected && this.selected.previousSibling) {
 129      this.highlight(this.selected.previousSibling);
 130    }
 131  };
 132  
 133  /**
 134   * Highlights a suggestion
 135   */
 136  Drupal.jsAC.prototype.highlight = function (node) {
 137    if (this.selected) {
 138      $(this.selected).removeClass('selected');
 139    }
 140    $(node).addClass('selected');
 141    this.selected = node;
 142  };
 143  
 144  /**
 145   * Unhighlights a suggestion
 146   */
 147  Drupal.jsAC.prototype.unhighlight = function (node) {
 148    $(node).removeClass('selected');
 149    this.selected = false;
 150  };
 151  
 152  /**
 153   * Hides the autocomplete suggestions
 154   */
 155  Drupal.jsAC.prototype.hidePopup = function (keycode) {
 156    // Select item if the right key or mousebutton was pressed
 157    if (this.selected && ((keycode && keycode != 46 && keycode != 8 && keycode != 27) || !keycode)) {
 158      this.input.value = this.selected.autocompleteValue;
 159    }
 160    // Hide popup
 161    var popup = this.popup;
 162    if (popup) {
 163      this.popup = null;
 164      $(popup).fadeOut('fast', function() { $(popup).remove(); });
 165    }
 166    this.selected = false;
 167  };
 168  
 169  /**
 170   * Positions the suggestions popup and starts a search
 171   */
 172  Drupal.jsAC.prototype.populatePopup = function () {
 173    // Show popup
 174    if (this.popup) {
 175      $(this.popup).remove();
 176    }
 177    this.selected = false;
 178    this.popup = document.createElement('div');
 179    this.popup.id = 'autocomplete';
 180    this.popup.owner = this;
 181    $(this.popup).css({
 182      marginTop: this.input.offsetHeight +'px',
 183      width: (this.input.offsetWidth - 4) +'px',
 184      display: 'none'
 185    });
 186    $(this.input).before(this.popup);
 187  
 188    // Do search
 189    this.db.owner = this;
 190    this.db.search(this.input.value);
 191  };
 192  
 193  /**
 194   * Fills the suggestion popup with any matches received
 195   */
 196  Drupal.jsAC.prototype.found = function (matches) {
 197    // If no value in the textfield, do not show the popup.
 198    if (!this.input.value.length) {
 199      return false;
 200    }
 201  
 202    // Prepare matches
 203    var ul = document.createElement('ul');
 204    var ac = this;
 205    for (key in matches) {
 206      var li = document.createElement('li');
 207      $(li)
 208        .html('<div>'+ matches[key] +'</div>')
 209        .mousedown(function () { ac.select(this); })
 210        .mouseover(function () { ac.highlight(this); })
 211        .mouseout(function () { ac.unhighlight(this); });
 212      li.autocompleteValue = key;
 213      $(ul).append(li);
 214    }
 215  
 216    // Show popup with matches, if any
 217    if (this.popup) {
 218      if (ul.childNodes.length > 0) {
 219        $(this.popup).empty().append(ul).show();
 220      }
 221      else {
 222        $(this.popup).css({visibility: 'hidden'});
 223        this.hidePopup();
 224      }
 225    }
 226  };
 227  
 228  Drupal.jsAC.prototype.setStatus = function (status) {
 229    switch (status) {
 230      case 'begin':
 231        $(this.input).addClass('throbbing');
 232        break;
 233      case 'cancel':
 234      case 'error':
 235      case 'found':
 236        $(this.input).removeClass('throbbing');
 237        break;
 238    }
 239  };
 240  
 241  /**
 242   * An AutoComplete DataBase object
 243   */
 244  Drupal.ACDB = function (uri) {
 245    this.uri = uri;
 246    this.delay = 300;
 247    this.cache = {};
 248  };
 249  
 250  /**
 251   * Performs a cached and delayed search
 252   */
 253  Drupal.ACDB.prototype.search = function (searchString) {
 254    var db = this;
 255    this.searchString = searchString;
 256  
 257    // See if this key has been searched for before
 258    if (this.cache[searchString]) {
 259      return this.owner.found(this.cache[searchString]);
 260    }
 261  
 262    // Initiate delayed search
 263    if (this.timer) {
 264      clearTimeout(this.timer);
 265    }
 266    this.timer = setTimeout(function() {
 267      db.owner.setStatus('begin');
 268  
 269      // Ajax GET request for autocompletion
 270      $.ajax({
 271        type: "GET",
 272        url: db.uri +'/'+ Drupal.encodeURIComponent(searchString),
 273        dataType: 'json',
 274        success: function (matches) {
 275          if (typeof matches['status'] == 'undefined' || matches['status'] != 0) {
 276            db.cache[searchString] = matches;
 277            // Verify if these are still the matches the user wants to see
 278            if (db.searchString == searchString) {
 279              db.owner.found(matches);
 280            }
 281            db.owner.setStatus('found');
 282          }
 283        },
 284        error: function (xmlhttp) {
 285          alert(Drupal.ahahError(xmlhttp, db.uri));
 286        }
 287      });
 288    }, this.delay);
 289  };
 290  
 291  /**
 292   * Cancels the current autocomplete request
 293   */
 294  Drupal.ACDB.prototype.cancel = function() {
 295    if (this.owner) this.owner.setStatus('cancel');
 296    if (this.timer) clearTimeout(this.timer);
 297    this.searchString = '';
 298  };


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7