home *** CD-ROM | disk | FTP | other *** search
- // $Id: autocomplete.js,v 1.23 2008/01/04 11:53:21 goba Exp $
-
- /**
- * Attaches the autocomplete behavior to all required fields
- */
- Drupal.behaviors.autocomplete = function (context) {
- var acdb = [];
- $('input.autocomplete:not(.autocomplete-processed)', context).each(function () {
- var uri = this.value;
- if (!acdb[uri]) {
- acdb[uri] = new Drupal.ACDB(uri);
- }
- var input = $('#' + this.id.substr(0, this.id.length - 13))
- .attr('autocomplete', 'OFF')[0];
- $(input.form).submit(Drupal.autocompleteSubmit);
- new Drupal.jsAC(input, acdb[uri]);
- $(this).addClass('autocomplete-processed');
- });
- };
-
- /**
- * Prevents the form from submitting if the suggestions popup is open
- * and closes the suggestions popup when doing so.
- */
- Drupal.autocompleteSubmit = function () {
- return $('#autocomplete').each(function () {
- this.owner.hidePopup();
- }).size() == 0;
- };
-
- /**
- * An AutoComplete object
- */
- Drupal.jsAC = function (input, db) {
- var ac = this;
- this.input = input;
- this.db = db;
-
- $(this.input)
- .keydown(function (event) { return ac.onkeydown(this, event); })
- .keyup(function (event) { ac.onkeyup(this, event); })
- .blur(function () { ac.hidePopup(); ac.db.cancel(); });
-
- };
-
- /**
- * Handler for the "keydown" event
- */
- Drupal.jsAC.prototype.onkeydown = function (input, e) {
- if (!e) {
- e = window.event;
- }
- switch (e.keyCode) {
- case 40: // down arrow
- this.selectDown();
- return false;
- case 38: // up arrow
- this.selectUp();
- return false;
- default: // all other keys
- return true;
- }
- };
-
- /**
- * Handler for the "keyup" event
- */
- Drupal.jsAC.prototype.onkeyup = function (input, e) {
- if (!e) {
- e = window.event;
- }
- switch (e.keyCode) {
- case 16: // shift
- case 17: // ctrl
- case 18: // alt
- case 20: // caps lock
- case 33: // page up
- case 34: // page down
- case 35: // end
- case 36: // home
- case 37: // left arrow
- case 38: // up arrow
- case 39: // right arrow
- case 40: // down arrow
- return true;
-
- case 9: // tab
- case 13: // enter
- case 27: // esc
- this.hidePopup(e.keyCode);
- return true;
-
- default: // all other keys
- if (input.value.length > 0)
- this.populatePopup();
- else
- this.hidePopup(e.keyCode);
- return true;
- }
- };
-
- /**
- * Puts the currently highlighted suggestion into the autocomplete field
- */
- Drupal.jsAC.prototype.select = function (node) {
- this.input.value = node.autocompleteValue;
- };
-
- /**
- * Highlights the next suggestion
- */
- Drupal.jsAC.prototype.selectDown = function () {
- if (this.selected && this.selected.nextSibling) {
- this.highlight(this.selected.nextSibling);
- }
- else {
- var lis = $('li', this.popup);
- if (lis.size() > 0) {
- this.highlight(lis.get(0));
- }
- }
- };
-
- /**
- * Highlights the previous suggestion
- */
- Drupal.jsAC.prototype.selectUp = function () {
- if (this.selected && this.selected.previousSibling) {
- this.highlight(this.selected.previousSibling);
- }
- };
-
- /**
- * Highlights a suggestion
- */
- Drupal.jsAC.prototype.highlight = function (node) {
- if (this.selected) {
- $(this.selected).removeClass('selected');
- }
- $(node).addClass('selected');
- this.selected = node;
- };
-
- /**
- * Unhighlights a suggestion
- */
- Drupal.jsAC.prototype.unhighlight = function (node) {
- $(node).removeClass('selected');
- this.selected = false;
- };
-
- /**
- * Hides the autocomplete suggestions
- */
- Drupal.jsAC.prototype.hidePopup = function (keycode) {
- // Select item if the right key or mousebutton was pressed
- if (this.selected && ((keycode && keycode != 46 && keycode != 8 && keycode != 27) || !keycode)) {
- this.input.value = this.selected.autocompleteValue;
- }
- // Hide popup
- var popup = this.popup;
- if (popup) {
- this.popup = null;
- $(popup).fadeOut('fast', function() { $(popup).remove(); });
- }
- this.selected = false;
- };
-
- /**
- * Positions the suggestions popup and starts a search
- */
- Drupal.jsAC.prototype.populatePopup = function () {
- // Show popup
- if (this.popup) {
- $(this.popup).remove();
- }
- this.selected = false;
- this.popup = document.createElement('div');
- this.popup.id = 'autocomplete';
- this.popup.owner = this;
- $(this.popup).css({
- marginTop: this.input.offsetHeight +'px',
- width: (this.input.offsetWidth - 4) +'px',
- display: 'none'
- });
- $(this.input).before(this.popup);
-
- // Do search
- this.db.owner = this;
- this.db.search(this.input.value);
- };
-
- /**
- * Fills the suggestion popup with any matches received
- */
- Drupal.jsAC.prototype.found = function (matches) {
- // If no value in the textfield, do not show the popup.
- if (!this.input.value.length) {
- return false;
- }
-
- // Prepare matches
- var ul = document.createElement('ul');
- var ac = this;
- for (key in matches) {
- var li = document.createElement('li');
- $(li)
- .html('<div>'+ matches[key] +'</div>')
- .mousedown(function () { ac.select(this); })
- .mouseover(function () { ac.highlight(this); })
- .mouseout(function () { ac.unhighlight(this); });
- li.autocompleteValue = key;
- $(ul).append(li);
- }
-
- // Show popup with matches, if any
- if (this.popup) {
- if (ul.childNodes.length > 0) {
- $(this.popup).empty().append(ul).show();
- }
- else {
- $(this.popup).css({visibility: 'hidden'});
- this.hidePopup();
- }
- }
- };
-
- Drupal.jsAC.prototype.setStatus = function (status) {
- switch (status) {
- case 'begin':
- $(this.input).addClass('throbbing');
- break;
- case 'cancel':
- case 'error':
- case 'found':
- $(this.input).removeClass('throbbing');
- break;
- }
- };
-
- /**
- * An AutoComplete DataBase object
- */
- Drupal.ACDB = function (uri) {
- this.uri = uri;
- this.delay = 300;
- this.cache = {};
- };
-
- /**
- * Performs a cached and delayed search
- */
- Drupal.ACDB.prototype.search = function (searchString) {
- var db = this;
- this.searchString = searchString;
-
- // See if this key has been searched for before
- if (this.cache[searchString]) {
- return this.owner.found(this.cache[searchString]);
- }
-
- // Initiate delayed search
- if (this.timer) {
- clearTimeout(this.timer);
- }
- this.timer = setTimeout(function() {
- db.owner.setStatus('begin');
-
- // Ajax GET request for autocompletion
- $.ajax({
- type: "GET",
- url: db.uri +'/'+ Drupal.encodeURIComponent(searchString),
- dataType: 'json',
- success: function (matches) {
- if (typeof matches['status'] == 'undefined' || matches['status'] != 0) {
- db.cache[searchString] = matches;
- // Verify if these are still the matches the user wants to see
- if (db.searchString == searchString) {
- db.owner.found(matches);
- }
- db.owner.setStatus('found');
- }
- },
- error: function (xmlhttp) {
- alert(Drupal.ahahError(xmlhttp, db.uri));
- }
- });
- }, this.delay);
- };
-
- /**
- * Cancels the current autocomplete request
- */
- Drupal.ACDB.prototype.cancel = function() {
- if (this.owner) this.owner.setStatus('cancel');
- if (this.timer) clearTimeout(this.timer);
- this.searchString = '';
- };
-