📄 zpautocomplete-core.js
字号:
/** * @fileoverview Zapatec Auto Complete widget. * * <pre> * Copyright (c) 2004-2007 by Zapatec, Inc. * http://www.zapatec.com * 1700 MLK Way, Berkeley, California, * 94709, U.S.A. * All rights reserved. * </pre> *//* $Id: zpautocomplete-core.js 7545 2007-07-13 09:39:03Z alex $ *//** * Zapatec Auto Complete widget class. Extends base Zapatec Widget class * (utils/zpwidget.js). * * <pre> * <strong>In addition to config options defined in base Zapatec.Widget class * provides following config options:</strong> * * <b>keywordLength</b> [number] Length of keyword that is passed to the server. * Until a user inputs number of characters defined here, nothing happens. Once * a user inputs number of characters defined using this config option, request * is sent to the server side script. On further input request is not sent to * the server any more. Only previously received response is filtered. * Default: 3. * * <b>fields</b> [object] Array of input element objects or their ids. * AutoComplete object will be attached to all elements passed in this array and * shared among them. When one of input fields receives focus, AutoComplete * appears next to it. When field looses focus, AutoComplete disappears * automatically. Default: empty array. * * Passing several elements gives ability to reuse the same AutoComplete object * among several input fields. * * If this option is not defined, initially AutoComplete object is not attached * to any input field. Later, after intialization it can be attached and * detached dynamically using {@link Zapatec.AutoComplete#addField} and * {@link Zapatec.AutoComplete#removeField} methods. * * <b>dataOnDemand</b> [boolean] Must be always true because currently this is * the only way for AutoComplete to get data. It makes sence to use this option * together with <b>callbackSource</b> config option defined in * {@link Zapatec.Widget} class. In this case AutoComplete passes to * <b>callbackSource</b> function following object: * { * keyword: [string] entered keyword of constant length defined using * keywordLength config option * } * and lets it to form the source, e.g. server URL, where tips are received * then. * * Entered keyword length is constant and defined using <b>keywordLength</b> * config option. This means server side script always receive keywords of the * same predefined length. It must return all possible results that are filtered * later on the client side depending on the further input. * * Currently AutoComplete accepts only JSON source. This means that * <b>callbackSource</b> must return either "json/url" or "json" sourceType. * * <b>convertTip</b> [function] Callback function that converts tips into * strings. Useful for complex tips. If not defined, tips are converted using * default conversion. * * <b>selectTip</b> [function] Callback function that must set selected value. * * <b>width</b> [string] CSS value of tips box width or "auto" to adjust it to * the field width. Default: content width. * * <b>height</b> [string] CSS value of tips box height. Default: content height. * * <b>overflow</b> [string] CSS value of tips box overflow. Default: "hidden". * * <b>customEvents</b> [boolean] If true, field events (focus, keydown, keyup, * keypress, blur) will not trigger AutoComplete selection. Instead you can * use your custom events. Do not use this option unless you know exactly what * you are doing. Default: false. * </pre> * * @constructor * @extends Zapatec.Widget * @param {object} oArg User configuration */Zapatec.AutoComplete = function(oArg) { // Call constructor of superclass Zapatec.AutoComplete.SUPERconstructor.call(this, oArg);};// Inherit WidgetZapatec.inherit(Zapatec.AutoComplete, Zapatec.Widget);/** * Initializes object. * * @param {object} oArg User configuration */Zapatec.AutoComplete.prototype.init = function(oArg) { // Call init method of superclass Zapatec.AutoComplete.SUPERclass.init.call(this, oArg);};/** * Reconfigures the widget with new config options after it was initialized. * May be used to change look or behavior of the widget after it has loaded * the data. In the argument pass only values for changed config options. * There is no need to pass config options that were not changed. * * @param {object} oArg Changes to user configuration */Zapatec.AutoComplete.prototype.reconfigure = function(oArg) { // Remove old fields var aFields = this.config.fields; if (typeof oArg.fields != 'undefined' && (aFields instanceof Array)) { var iFields = aFields.length; var iField; for (iField = 0; iField < iFields; iField++) { this.removeField(aFields[iField]); } } // Call parent method Zapatec.AutoComplete.SUPERclass.reconfigure.call(this, oArg);};/** * Configures the widget. Gets called from init and reconfigure methods of * superclass. * * @private * @param {object} oArg User configuration */Zapatec.AutoComplete.prototype.configure = function(oArg) { // Overwrite default config options if needed // Define new config options this.defineConfigOption('keywordLength', 3); this.defineConfigOption('fields', []); this.defineConfigOption('dataOnDemand', false); this.defineConfigOption('convertTip'); this.defineConfigOption('selectTip'); this.defineConfigOption('width'); this.defineConfigOption('height'); this.defineConfigOption('overflow', 'hidden'); // Call parent method Zapatec.AutoComplete.SUPERclass.configure.call(this, oArg); // Check passed config options and correct them if needed var oConfig = this.config; oConfig.keywordLength = parseInt(oConfig.keywordLength); if (isNaN(oConfig.keywordLength) || oConfig.keywordLength < 1) { oConfig.keywordLength = 3; } // By default dimensions are in pixels if (oConfig.width && oConfig.width == parseInt(oConfig.width)) { oConfig.width += 'px'; } if (oConfig.height && oConfig.height == parseInt(oConfig.height)) { oConfig.height += 'px'; } // Add fields if (oConfig.fields instanceof Array) { var aFields = oConfig.fields; var iFields = aFields.length; var iField; for (iField = 0; iField < iFields; iField++) { this.addField(aFields[iField]); } } // Current field this.field = null; // Active tip id this.activeTipId = null; // Selected tip this.tip = null; // Current set of tips this.data = null; // Tips cache this.cache = {};};/** * Attaches this AutoComplete object to the specified text field. * * @param {object} oField Input element object or id */Zapatec.AutoComplete.prototype.addField = function(oField) { // Get field object oField = Zapatec.Widget.getElementById(oField); if (!oField || typeof oField.value == 'undefined') { return; } // Attach oField.zpAutoCompleteId = this.id; // Turn browser autocomplete feature off oField.zpAutocompleteOrig = oField.getAttribute('autocomplete'); oField.setAttribute('autocomplete', 'off'); // Add event listeners if (!this.config.customEvents) { var oUtils = Zapatec.Utils; var oAutoComplete = Zapatec.AutoComplete; oUtils.addEvent(oField, 'focus', oAutoComplete.onFocus); oUtils.addEvent(oField, 'keydown', oAutoComplete.onKeydown); oUtils.addEvent(oField, 'keyup', oAutoComplete.onKeyup); oUtils.addEvent(oField, 'keypress', oAutoComplete.onKeypress); oUtils.addEvent(oField, 'blur', oAutoComplete.onBlur); }};/** * Detaches this AutoComplete object from the specified text field. * * @param {object} oField Input element object or id */Zapatec.AutoComplete.prototype.removeField = function(oField) { // Get field object oField = Zapatec.Widget.getElementById(oField); if (!oField) { return; } // Detach var undef; oField.zpAutoCompleteId = undef; // Turn browser autocomplete feature on oField.setAttribute('autocomplete', oField.zpAutocompleteOrig); oField.zpAutocompleteOrig = null; // Remove event listeners if (!this.config.customEvents) { var oUtils = Zapatec.Utils; var oAutoComplete = Zapatec.AutoComplete; oUtils.removeEvent(oField, 'focus', oAutoComplete.onFocus); oUtils.removeEvent(oField, 'keydown',oAutoComplete.onKeydown); oUtils.removeEvent(oField, 'keyup', oAutoComplete.onKeyup); oUtils.removeEvent(oField, 'keypress', oAutoComplete.onKeypress); oUtils.removeEvent(oField, 'blur', oAutoComplete.onBlur); }};/** * Field onfocus event listener. * * @private * @param {object} oEvent Event object */Zapatec.AutoComplete.onFocus = function(oEvent) { // Get target element var oField = Zapatec.Utils.getTargetElement(oEvent); if (oField) { // Call method of attached AutoComplete object Zapatec.Widget.callMethod(oField.zpAutoCompleteId, 'onFocus', { field: oField }); }};/** * Switches AutoComplete to the specified field when it is focused. Field must * be previously added using {@link Zapatec.AutoComplete#addField} method. * * <pre> * Arguments format: * { * field: [object] Input field element * } * </pre> * * @private * @param {object} oArg Arguments */Zapatec.AutoComplete.prototype.onFocus = function(oArg) { // Unset current field this.field = null; // Get field if (!oArg) { return; } var oField = oArg.field; // Field must be previously attached if (!oField || oField.zpAutoCompleteId != this.id) { return; } // Set current field this.field = oField;};/** * Field onblur event listener. * * @private * @param {object} oEvent Event object */Zapatec.AutoComplete.onBlur = function(oEvent) { // Get target element var oField = Zapatec.Utils.getTargetElement(oEvent); if (oField) { // Prevent loosing of focus when scrollbar is clicked in Opera and Safari // Blur event occurs before click. Let the click event occur before closing // the selection. setTimeout(function() { // Call method of attached AutoComplete object Zapatec.Widget.callMethod(oField.zpAutoCompleteId, 'onBlur', { field: oField }); }, 0); }};/** * Selects first tip and hides tips on field blur. * * <pre> * Arguments format: * { * field: [object] Input field element * } * </pre> * * @private * @param {object} oArg Arguments */Zapatec.AutoComplete.prototype.onBlur = function(oArg) { // Get field if (!oArg) { return; } var oField = oArg.field; if (!oField) { return; } // Prevent loosing of focus when scrollbar is clicked in Opera and Safari // If scrollbar was clicked, return focus to the input field // this.content may be undefined at this point var oContent = this.content; if (oContent && oContent.zpACClicked) { oContent.zpACClicked = null; oField.focus(); return; } // Select active tip if tip was not selected if (!this.tip) { this.selectTip({ field: oField, i: this.activeTipId * 1 }); }};/** * Field keydown event listener. * * @private * @param {object} oEvent Event object */Zapatec.AutoComplete.onKeydown = function(oEvent) { // Get target element var oField = Zapatec.Utils.getTargetElement(oEvent); if (oField) { // Call method of attached AutoComplete object Zapatec.Widget.callMethod(oField.zpAutoCompleteId, 'onKeydown', { event: oEvent }); }};/** * Hides tips on Esc, porvides keyboard navigation. * * <pre> * Arguments format: * { * event: [object] Event object * } * </pre> * * @private * @param {object} oArg Arguments */Zapatec.AutoComplete.prototype.onKeydown = function(oArg) { // Get event if (!oArg) { return; } var oEvent = oArg.event; if (!oEvent) { return; } // Process key switch (oEvent.keyCode) { case 27: // Esc this.hide(); // Prevent entered value from erasing Zapatec.Utils.stopEvent(oEvent); break; case 38: // Up arrow this.gotoPrevTip(); // Prevent movement of cursor inside the field Zapatec.Utils.stopEvent(oEvent); break; case 40: // Down arrow this.gotoNextTip(); // Prevent movement of cursor inside the field Zapatec.Utils.stopEvent(oEvent); break; }};/** * Field keyup event listener. * * @private * @param {object} oEvent Event object */Zapatec.AutoComplete.onKeyup = function(oEvent) { // Get target element var oField = Zapatec.Utils.getTargetElement(oEvent); if (oField) { // Call method of attached AutoComplete object Zapatec.Widget.callMethod(oField.zpAutoCompleteId, 'onKeyup', { field: oField, event: oEvent }); }};/** * Shows tips when there are at least keywordLength chars entered in the field. * * <pre> * Arguments format: * { * field: [object] Input field element, * event: [object] Event object * } * </pre>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -