1 |
efrain |
1 |
YUI.add('yui2-autocomplete', function(Y) {
|
|
|
2 |
var YAHOO = Y.YUI2;
|
|
|
3 |
/*
|
|
|
4 |
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
|
|
|
5 |
Code licensed under the BSD License:
|
|
|
6 |
http://developer.yahoo.com/yui/license.html
|
|
|
7 |
version: 2.9.0
|
|
|
8 |
*/
|
|
|
9 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
10 |
//
|
|
|
11 |
// YAHOO.widget.DataSource Backwards Compatibility
|
|
|
12 |
//
|
|
|
13 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
14 |
|
|
|
15 |
YAHOO.widget.DS_JSArray = YAHOO.util.LocalDataSource;
|
|
|
16 |
|
|
|
17 |
YAHOO.widget.DS_JSFunction = YAHOO.util.FunctionDataSource;
|
|
|
18 |
|
|
|
19 |
YAHOO.widget.DS_XHR = function(sScriptURI, aSchema, oConfigs) {
|
|
|
20 |
var DS = new YAHOO.util.XHRDataSource(sScriptURI, oConfigs);
|
|
|
21 |
DS._aDeprecatedSchema = aSchema;
|
|
|
22 |
return DS;
|
|
|
23 |
};
|
|
|
24 |
|
|
|
25 |
YAHOO.widget.DS_ScriptNode = function(sScriptURI, aSchema, oConfigs) {
|
|
|
26 |
var DS = new YAHOO.util.ScriptNodeDataSource(sScriptURI, oConfigs);
|
|
|
27 |
DS._aDeprecatedSchema = aSchema;
|
|
|
28 |
return DS;
|
|
|
29 |
};
|
|
|
30 |
|
|
|
31 |
YAHOO.widget.DS_XHR.TYPE_JSON = YAHOO.util.DataSourceBase.TYPE_JSON;
|
|
|
32 |
YAHOO.widget.DS_XHR.TYPE_XML = YAHOO.util.DataSourceBase.TYPE_XML;
|
|
|
33 |
YAHOO.widget.DS_XHR.TYPE_FLAT = YAHOO.util.DataSourceBase.TYPE_TEXT;
|
|
|
34 |
|
|
|
35 |
// TODO: widget.DS_ScriptNode.scriptCallbackParam
|
|
|
36 |
|
|
|
37 |
|
|
|
38 |
|
|
|
39 |
/**
|
|
|
40 |
* The AutoComplete control provides the front-end logic for text-entry suggestion and
|
|
|
41 |
* completion functionality.
|
|
|
42 |
*
|
|
|
43 |
* @module autocomplete
|
|
|
44 |
* @requires yahoo, dom, event, datasource
|
|
|
45 |
* @optional animation
|
|
|
46 |
* @namespace YAHOO.widget
|
|
|
47 |
* @title AutoComplete Widget
|
|
|
48 |
*/
|
|
|
49 |
|
|
|
50 |
/****************************************************************************/
|
|
|
51 |
/****************************************************************************/
|
|
|
52 |
/****************************************************************************/
|
|
|
53 |
|
|
|
54 |
/**
|
|
|
55 |
* The AutoComplete class provides the customizable functionality of a plug-and-play DHTML
|
|
|
56 |
* auto completion widget. Some key features:
|
|
|
57 |
* <ul>
|
|
|
58 |
* <li>Navigate with up/down arrow keys and/or mouse to pick a selection</li>
|
|
|
59 |
* <li>The drop down container can "roll down" or "fly out" via configurable
|
|
|
60 |
* animation</li>
|
|
|
61 |
* <li>UI look-and-feel customizable through CSS, including container
|
|
|
62 |
* attributes, borders, position, fonts, etc</li>
|
|
|
63 |
* </ul>
|
|
|
64 |
*
|
|
|
65 |
* @class AutoComplete
|
|
|
66 |
* @constructor
|
|
|
67 |
* @param elInput {HTMLElement} DOM element reference of an input field.
|
|
|
68 |
* @param elInput {String} String ID of an input field.
|
|
|
69 |
* @param elContainer {HTMLElement} DOM element reference of an existing DIV.
|
|
|
70 |
* @param elContainer {String} String ID of an existing DIV.
|
|
|
71 |
* @param oDataSource {YAHOO.widget.DataSource} DataSource instance.
|
|
|
72 |
* @param oConfigs {Object} (optional) Object literal of configuration params.
|
|
|
73 |
*/
|
|
|
74 |
YAHOO.widget.AutoComplete = function(elInput,elContainer,oDataSource,oConfigs) {
|
|
|
75 |
if(elInput && elContainer && oDataSource) {
|
|
|
76 |
// Validate DataSource
|
|
|
77 |
if(oDataSource && YAHOO.lang.isFunction(oDataSource.sendRequest)) {
|
|
|
78 |
this.dataSource = oDataSource;
|
|
|
79 |
}
|
|
|
80 |
else {
|
|
|
81 |
YAHOO.log("Could not instantiate AutoComplete due to an invalid DataSource", "error", this.toString());
|
|
|
82 |
return;
|
|
|
83 |
}
|
|
|
84 |
|
|
|
85 |
// YAHOO.widget.DataSource schema backwards compatibility
|
|
|
86 |
// Converted deprecated schema into supported schema
|
|
|
87 |
// First assume key data is held in position 0 of results array
|
|
|
88 |
this.key = 0;
|
|
|
89 |
var schema = oDataSource.responseSchema;
|
|
|
90 |
// An old school schema has been defined in the deprecated DataSource constructor
|
|
|
91 |
if(oDataSource._aDeprecatedSchema) {
|
|
|
92 |
var aDeprecatedSchema = oDataSource._aDeprecatedSchema;
|
|
|
93 |
if(YAHOO.lang.isArray(aDeprecatedSchema)) {
|
|
|
94 |
|
|
|
95 |
if((oDataSource.responseType === YAHOO.util.DataSourceBase.TYPE_JSON) ||
|
|
|
96 |
(oDataSource.responseType === YAHOO.util.DataSourceBase.TYPE_UNKNOWN)) { // Used to default to unknown
|
|
|
97 |
// Store the resultsList
|
|
|
98 |
schema.resultsList = aDeprecatedSchema[0];
|
|
|
99 |
// Store the key
|
|
|
100 |
this.key = aDeprecatedSchema[1];
|
|
|
101 |
// Only resultsList and key are defined, so grab all the data
|
|
|
102 |
schema.fields = (aDeprecatedSchema.length < 3) ? null : aDeprecatedSchema.slice(1);
|
|
|
103 |
}
|
|
|
104 |
else if(oDataSource.responseType === YAHOO.util.DataSourceBase.TYPE_XML) {
|
|
|
105 |
schema.resultNode = aDeprecatedSchema[0];
|
|
|
106 |
this.key = aDeprecatedSchema[1];
|
|
|
107 |
schema.fields = aDeprecatedSchema.slice(1);
|
|
|
108 |
}
|
|
|
109 |
else if(oDataSource.responseType === YAHOO.util.DataSourceBase.TYPE_TEXT) {
|
|
|
110 |
schema.recordDelim = aDeprecatedSchema[0];
|
|
|
111 |
schema.fieldDelim = aDeprecatedSchema[1];
|
|
|
112 |
}
|
|
|
113 |
oDataSource.responseSchema = schema;
|
|
|
114 |
}
|
|
|
115 |
}
|
|
|
116 |
|
|
|
117 |
// Validate input element
|
|
|
118 |
if(YAHOO.util.Dom.inDocument(elInput)) {
|
|
|
119 |
if(YAHOO.lang.isString(elInput)) {
|
|
|
120 |
this._sName = "instance" + YAHOO.widget.AutoComplete._nIndex + " " + elInput;
|
|
|
121 |
this._elTextbox = document.getElementById(elInput);
|
|
|
122 |
}
|
|
|
123 |
else {
|
|
|
124 |
this._sName = (elInput.id) ?
|
|
|
125 |
"instance" + YAHOO.widget.AutoComplete._nIndex + " " + elInput.id:
|
|
|
126 |
"instance" + YAHOO.widget.AutoComplete._nIndex;
|
|
|
127 |
this._elTextbox = elInput;
|
|
|
128 |
}
|
|
|
129 |
YAHOO.util.Dom.addClass(this._elTextbox, "yui-ac-input");
|
|
|
130 |
}
|
|
|
131 |
else {
|
|
|
132 |
YAHOO.log("Could not instantiate AutoComplete due to an invalid input element", "error", this.toString());
|
|
|
133 |
return;
|
|
|
134 |
}
|
|
|
135 |
|
|
|
136 |
// Validate container element
|
|
|
137 |
if(YAHOO.util.Dom.inDocument(elContainer)) {
|
|
|
138 |
if(YAHOO.lang.isString(elContainer)) {
|
|
|
139 |
this._elContainer = document.getElementById(elContainer);
|
|
|
140 |
}
|
|
|
141 |
else {
|
|
|
142 |
this._elContainer = elContainer;
|
|
|
143 |
}
|
|
|
144 |
if(this._elContainer.style.display == "none") {
|
|
|
145 |
YAHOO.log("The container may not display properly if display is set to \"none\" in CSS", "warn", this.toString());
|
|
|
146 |
}
|
|
|
147 |
|
|
|
148 |
// For skinning
|
|
|
149 |
var elParent = this._elContainer.parentNode;
|
|
|
150 |
var elTag = elParent.tagName.toLowerCase();
|
|
|
151 |
if(elTag == "div") {
|
|
|
152 |
YAHOO.util.Dom.addClass(elParent, "yui-ac");
|
|
|
153 |
}
|
|
|
154 |
else {
|
|
|
155 |
YAHOO.log("Could not find the wrapper element for skinning", "warn", this.toString());
|
|
|
156 |
}
|
|
|
157 |
}
|
|
|
158 |
else {
|
|
|
159 |
YAHOO.log("Could not instantiate AutoComplete due to an invalid container element", "error", this.toString());
|
|
|
160 |
return;
|
|
|
161 |
}
|
|
|
162 |
|
|
|
163 |
// Default applyLocalFilter setting is to enable for local sources
|
|
|
164 |
if(this.dataSource.dataType === YAHOO.util.DataSourceBase.TYPE_LOCAL) {
|
|
|
165 |
this.applyLocalFilter = true;
|
|
|
166 |
}
|
|
|
167 |
|
|
|
168 |
// Set any config params passed in to override defaults
|
|
|
169 |
if(oConfigs && (oConfigs.constructor == Object)) {
|
|
|
170 |
for(var sConfig in oConfigs) {
|
|
|
171 |
if(sConfig) {
|
|
|
172 |
this[sConfig] = oConfigs[sConfig];
|
|
|
173 |
}
|
|
|
174 |
}
|
|
|
175 |
}
|
|
|
176 |
|
|
|
177 |
// Initialization sequence
|
|
|
178 |
this._initContainerEl();
|
|
|
179 |
this._initProps();
|
|
|
180 |
this._initListEl();
|
|
|
181 |
this._initContainerHelperEls();
|
|
|
182 |
|
|
|
183 |
// Set up events
|
|
|
184 |
var oSelf = this;
|
|
|
185 |
var elTextbox = this._elTextbox;
|
|
|
186 |
|
|
|
187 |
// Dom events
|
|
|
188 |
YAHOO.util.Event.addListener(elTextbox,"keyup",oSelf._onTextboxKeyUp,oSelf);
|
|
|
189 |
YAHOO.util.Event.addListener(elTextbox,"keydown",oSelf._onTextboxKeyDown,oSelf);
|
|
|
190 |
YAHOO.util.Event.addListener(elTextbox,"focus",oSelf._onTextboxFocus,oSelf);
|
|
|
191 |
YAHOO.util.Event.addListener(elTextbox,"blur",oSelf._onTextboxBlur,oSelf);
|
|
|
192 |
YAHOO.util.Event.addListener(elContainer,"mouseover",oSelf._onContainerMouseover,oSelf);
|
|
|
193 |
YAHOO.util.Event.addListener(elContainer,"mouseout",oSelf._onContainerMouseout,oSelf);
|
|
|
194 |
YAHOO.util.Event.addListener(elContainer,"click",oSelf._onContainerClick,oSelf);
|
|
|
195 |
YAHOO.util.Event.addListener(elContainer,"scroll",oSelf._onContainerScroll,oSelf);
|
|
|
196 |
YAHOO.util.Event.addListener(elContainer,"resize",oSelf._onContainerResize,oSelf);
|
|
|
197 |
YAHOO.util.Event.addListener(elTextbox,"keypress",oSelf._onTextboxKeyPress,oSelf);
|
|
|
198 |
YAHOO.util.Event.addListener(window,"unload",oSelf._onWindowUnload,oSelf);
|
|
|
199 |
|
|
|
200 |
// Custom events
|
|
|
201 |
this.textboxFocusEvent = new YAHOO.util.CustomEvent("textboxFocus", this);
|
|
|
202 |
this.textboxKeyEvent = new YAHOO.util.CustomEvent("textboxKey", this);
|
|
|
203 |
this.dataRequestEvent = new YAHOO.util.CustomEvent("dataRequest", this);
|
|
|
204 |
this.dataRequestCancelEvent = new YAHOO.util.CustomEvent("dataRequestCancel", this);
|
|
|
205 |
this.dataReturnEvent = new YAHOO.util.CustomEvent("dataReturn", this);
|
|
|
206 |
this.dataErrorEvent = new YAHOO.util.CustomEvent("dataError", this);
|
|
|
207 |
this.containerPopulateEvent = new YAHOO.util.CustomEvent("containerPopulate", this);
|
|
|
208 |
this.containerExpandEvent = new YAHOO.util.CustomEvent("containerExpand", this);
|
|
|
209 |
this.typeAheadEvent = new YAHOO.util.CustomEvent("typeAhead", this);
|
|
|
210 |
this.itemMouseOverEvent = new YAHOO.util.CustomEvent("itemMouseOver", this);
|
|
|
211 |
this.itemMouseOutEvent = new YAHOO.util.CustomEvent("itemMouseOut", this);
|
|
|
212 |
this.itemArrowToEvent = new YAHOO.util.CustomEvent("itemArrowTo", this);
|
|
|
213 |
this.itemArrowFromEvent = new YAHOO.util.CustomEvent("itemArrowFrom", this);
|
|
|
214 |
this.itemSelectEvent = new YAHOO.util.CustomEvent("itemSelect", this);
|
|
|
215 |
this.unmatchedItemSelectEvent = new YAHOO.util.CustomEvent("unmatchedItemSelect", this);
|
|
|
216 |
this.selectionEnforceEvent = new YAHOO.util.CustomEvent("selectionEnforce", this);
|
|
|
217 |
this.containerCollapseEvent = new YAHOO.util.CustomEvent("containerCollapse", this);
|
|
|
218 |
this.textboxBlurEvent = new YAHOO.util.CustomEvent("textboxBlur", this);
|
|
|
219 |
this.textboxChangeEvent = new YAHOO.util.CustomEvent("textboxChange", this);
|
|
|
220 |
|
|
|
221 |
// Finish up
|
|
|
222 |
elTextbox.setAttribute("autocomplete","off");
|
|
|
223 |
YAHOO.widget.AutoComplete._nIndex++;
|
|
|
224 |
YAHOO.log("AutoComplete initialized","info",this.toString());
|
|
|
225 |
}
|
|
|
226 |
// Required arguments were not found
|
|
|
227 |
else {
|
|
|
228 |
YAHOO.log("Could not instantiate AutoComplete due invalid arguments", "error", this.toString());
|
|
|
229 |
}
|
|
|
230 |
};
|
|
|
231 |
|
|
|
232 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
233 |
//
|
|
|
234 |
// Public member variables
|
|
|
235 |
//
|
|
|
236 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
237 |
|
|
|
238 |
/**
|
|
|
239 |
* The DataSource object that encapsulates the data used for auto completion.
|
|
|
240 |
* This object should be an inherited object from YAHOO.widget.DataSource.
|
|
|
241 |
*
|
|
|
242 |
* @property dataSource
|
|
|
243 |
* @type YAHOO.widget.DataSource
|
|
|
244 |
*/
|
|
|
245 |
YAHOO.widget.AutoComplete.prototype.dataSource = null;
|
|
|
246 |
|
|
|
247 |
/**
|
|
|
248 |
* By default, results from local DataSources will pass through the filterResults
|
|
|
249 |
* method to apply a client-side matching algorithm.
|
|
|
250 |
*
|
|
|
251 |
* @property applyLocalFilter
|
|
|
252 |
* @type Boolean
|
|
|
253 |
* @default true for local arrays and json, otherwise false
|
|
|
254 |
*/
|
|
|
255 |
YAHOO.widget.AutoComplete.prototype.applyLocalFilter = null;
|
|
|
256 |
|
|
|
257 |
/**
|
|
|
258 |
* When applyLocalFilter is true, the local filtering algorthim can have case sensitivity
|
|
|
259 |
* enabled.
|
|
|
260 |
*
|
|
|
261 |
* @property queryMatchCase
|
|
|
262 |
* @type Boolean
|
|
|
263 |
* @default false
|
|
|
264 |
*/
|
|
|
265 |
YAHOO.widget.AutoComplete.prototype.queryMatchCase = false;
|
|
|
266 |
|
|
|
267 |
/**
|
|
|
268 |
* When applyLocalFilter is true, results can be locally filtered to return
|
|
|
269 |
* matching strings that "contain" the query string rather than simply "start with"
|
|
|
270 |
* the query string.
|
|
|
271 |
*
|
|
|
272 |
* @property queryMatchContains
|
|
|
273 |
* @type Boolean
|
|
|
274 |
* @default false
|
|
|
275 |
*/
|
|
|
276 |
YAHOO.widget.AutoComplete.prototype.queryMatchContains = false;
|
|
|
277 |
|
|
|
278 |
/**
|
|
|
279 |
* Enables query subset matching. When the DataSource's cache is enabled and queryMatchSubset is
|
|
|
280 |
* true, substrings of queries will return matching cached results. For
|
|
|
281 |
* instance, if the first query is for "abc" susequent queries that start with
|
|
|
282 |
* "abc", like "abcd", will be queried against the cache, and not the live data
|
|
|
283 |
* source. Recommended only for DataSources that return comprehensive results
|
|
|
284 |
* for queries with very few characters.
|
|
|
285 |
*
|
|
|
286 |
* @property queryMatchSubset
|
|
|
287 |
* @type Boolean
|
|
|
288 |
* @default false
|
|
|
289 |
*
|
|
|
290 |
*/
|
|
|
291 |
YAHOO.widget.AutoComplete.prototype.queryMatchSubset = false;
|
|
|
292 |
|
|
|
293 |
/**
|
|
|
294 |
* Number of characters that must be entered before querying for results. A negative value
|
|
|
295 |
* effectively turns off the widget. A value of 0 allows queries of null or empty string
|
|
|
296 |
* values.
|
|
|
297 |
*
|
|
|
298 |
* @property minQueryLength
|
|
|
299 |
* @type Number
|
|
|
300 |
* @default 1
|
|
|
301 |
*/
|
|
|
302 |
YAHOO.widget.AutoComplete.prototype.minQueryLength = 1;
|
|
|
303 |
|
|
|
304 |
/**
|
|
|
305 |
* Maximum number of results to display in results container.
|
|
|
306 |
*
|
|
|
307 |
* @property maxResultsDisplayed
|
|
|
308 |
* @type Number
|
|
|
309 |
* @default 10
|
|
|
310 |
*/
|
|
|
311 |
YAHOO.widget.AutoComplete.prototype.maxResultsDisplayed = 10;
|
|
|
312 |
|
|
|
313 |
/**
|
|
|
314 |
* Number of seconds to delay before submitting a query request. If a query
|
|
|
315 |
* request is received before a previous one has completed its delay, the
|
|
|
316 |
* previous request is cancelled and the new request is set to the delay. If
|
|
|
317 |
* typeAhead is also enabled, this value must always be less than the typeAheadDelay
|
|
|
318 |
* in order to avoid certain race conditions.
|
|
|
319 |
*
|
|
|
320 |
* @property queryDelay
|
|
|
321 |
* @type Number
|
|
|
322 |
* @default 0.2
|
|
|
323 |
*/
|
|
|
324 |
YAHOO.widget.AutoComplete.prototype.queryDelay = 0.2;
|
|
|
325 |
|
|
|
326 |
/**
|
|
|
327 |
* If typeAhead is true, number of seconds to delay before updating input with
|
|
|
328 |
* typeAhead value. In order to prevent certain race conditions, this value must
|
|
|
329 |
* always be greater than the queryDelay.
|
|
|
330 |
*
|
|
|
331 |
* @property typeAheadDelay
|
|
|
332 |
* @type Number
|
|
|
333 |
* @default 0.5
|
|
|
334 |
*/
|
|
|
335 |
YAHOO.widget.AutoComplete.prototype.typeAheadDelay = 0.5;
|
|
|
336 |
|
|
|
337 |
/**
|
|
|
338 |
* When IME usage is detected or interval detection is explicitly enabled,
|
|
|
339 |
* AutoComplete will detect the input value at the given interval and send a
|
|
|
340 |
* query if the value has changed.
|
|
|
341 |
*
|
|
|
342 |
* @property queryInterval
|
|
|
343 |
* @type Number
|
|
|
344 |
* @default 500
|
|
|
345 |
*/
|
|
|
346 |
YAHOO.widget.AutoComplete.prototype.queryInterval = 500;
|
|
|
347 |
|
|
|
348 |
/**
|
|
|
349 |
* Class name of a highlighted item within results container.
|
|
|
350 |
*
|
|
|
351 |
* @property highlightClassName
|
|
|
352 |
* @type String
|
|
|
353 |
* @default "yui-ac-highlight"
|
|
|
354 |
*/
|
|
|
355 |
YAHOO.widget.AutoComplete.prototype.highlightClassName = "yui-ac-highlight";
|
|
|
356 |
|
|
|
357 |
/**
|
|
|
358 |
* Class name of a pre-highlighted item within results container.
|
|
|
359 |
*
|
|
|
360 |
* @property prehighlightClassName
|
|
|
361 |
* @type String
|
|
|
362 |
*/
|
|
|
363 |
YAHOO.widget.AutoComplete.prototype.prehighlightClassName = null;
|
|
|
364 |
|
|
|
365 |
/**
|
|
|
366 |
* Query delimiter. A single character separator for multiple delimited
|
|
|
367 |
* selections. Multiple delimiter characteres may be defined as an array of
|
|
|
368 |
* strings. A null value or empty string indicates that query results cannot
|
|
|
369 |
* be delimited. This feature is not recommended if you need forceSelection to
|
|
|
370 |
* be true.
|
|
|
371 |
*
|
|
|
372 |
* @property delimChar
|
|
|
373 |
* @type String | String[]
|
|
|
374 |
*/
|
|
|
375 |
YAHOO.widget.AutoComplete.prototype.delimChar = null;
|
|
|
376 |
|
|
|
377 |
/**
|
|
|
378 |
* Whether or not the first item in results container should be automatically highlighted
|
|
|
379 |
* on expand.
|
|
|
380 |
*
|
|
|
381 |
* @property autoHighlight
|
|
|
382 |
* @type Boolean
|
|
|
383 |
* @default true
|
|
|
384 |
*/
|
|
|
385 |
YAHOO.widget.AutoComplete.prototype.autoHighlight = true;
|
|
|
386 |
|
|
|
387 |
/**
|
|
|
388 |
* If autohighlight is enabled, whether or not the input field should be automatically updated
|
|
|
389 |
* with the first query result as the user types, auto-selecting the substring portion
|
|
|
390 |
* of the first result that the user has not yet typed.
|
|
|
391 |
*
|
|
|
392 |
* @property typeAhead
|
|
|
393 |
* @type Boolean
|
|
|
394 |
* @default false
|
|
|
395 |
*/
|
|
|
396 |
YAHOO.widget.AutoComplete.prototype.typeAhead = false;
|
|
|
397 |
|
|
|
398 |
/**
|
|
|
399 |
* Whether or not to animate the expansion/collapse of the results container in the
|
|
|
400 |
* horizontal direction.
|
|
|
401 |
*
|
|
|
402 |
* @property animHoriz
|
|
|
403 |
* @type Boolean
|
|
|
404 |
* @default false
|
|
|
405 |
*/
|
|
|
406 |
YAHOO.widget.AutoComplete.prototype.animHoriz = false;
|
|
|
407 |
|
|
|
408 |
/**
|
|
|
409 |
* Whether or not to animate the expansion/collapse of the results container in the
|
|
|
410 |
* vertical direction.
|
|
|
411 |
*
|
|
|
412 |
* @property animVert
|
|
|
413 |
* @type Boolean
|
|
|
414 |
* @default true
|
|
|
415 |
*/
|
|
|
416 |
YAHOO.widget.AutoComplete.prototype.animVert = true;
|
|
|
417 |
|
|
|
418 |
/**
|
|
|
419 |
* Speed of container expand/collapse animation, in seconds..
|
|
|
420 |
*
|
|
|
421 |
* @property animSpeed
|
|
|
422 |
* @type Number
|
|
|
423 |
* @default 0.3
|
|
|
424 |
*/
|
|
|
425 |
YAHOO.widget.AutoComplete.prototype.animSpeed = 0.3;
|
|
|
426 |
|
|
|
427 |
/**
|
|
|
428 |
* Whether or not to force the user's selection to match one of the query
|
|
|
429 |
* results. Enabling this feature essentially transforms the input field into a
|
|
|
430 |
* <select> field. This feature is not recommended with delimiter character(s)
|
|
|
431 |
* defined.
|
|
|
432 |
*
|
|
|
433 |
* @property forceSelection
|
|
|
434 |
* @type Boolean
|
|
|
435 |
* @default false
|
|
|
436 |
*/
|
|
|
437 |
YAHOO.widget.AutoComplete.prototype.forceSelection = false;
|
|
|
438 |
|
|
|
439 |
/**
|
|
|
440 |
* Whether or not to allow browsers to cache user-typed input in the input
|
|
|
441 |
* field. Disabling this feature will prevent the widget from setting the
|
|
|
442 |
* autocomplete="off" on the input field. When autocomplete="off"
|
|
|
443 |
* and users click the back button after form submission, user-typed input can
|
|
|
444 |
* be prefilled by the browser from its cache. This caching of user input may
|
|
|
445 |
* not be desired for sensitive data, such as credit card numbers, in which
|
|
|
446 |
* case, implementers should consider setting allowBrowserAutocomplete to false.
|
|
|
447 |
*
|
|
|
448 |
* @property allowBrowserAutocomplete
|
|
|
449 |
* @type Boolean
|
|
|
450 |
* @default true
|
|
|
451 |
*/
|
|
|
452 |
YAHOO.widget.AutoComplete.prototype.allowBrowserAutocomplete = true;
|
|
|
453 |
|
|
|
454 |
/**
|
|
|
455 |
* Enabling this feature prevents the toggling of the container to a collapsed state.
|
|
|
456 |
* Setting to true does not automatically trigger the opening of the container.
|
|
|
457 |
* Implementers are advised to pre-load the container with an explicit "sendQuery()" call.
|
|
|
458 |
*
|
|
|
459 |
* @property alwaysShowContainer
|
|
|
460 |
* @type Boolean
|
|
|
461 |
* @default false
|
|
|
462 |
*/
|
|
|
463 |
YAHOO.widget.AutoComplete.prototype.alwaysShowContainer = false;
|
|
|
464 |
|
|
|
465 |
/**
|
|
|
466 |
* Whether or not to use an iFrame to layer over Windows form elements in
|
|
|
467 |
* IE. Set to true only when the results container will be on top of a
|
|
|
468 |
* <select> field in IE and thus exposed to the IE z-index bug (i.e.,
|
|
|
469 |
* 5.5 < IE < 7).
|
|
|
470 |
*
|
|
|
471 |
* @property useIFrame
|
|
|
472 |
* @type Boolean
|
|
|
473 |
* @default false
|
|
|
474 |
*/
|
|
|
475 |
YAHOO.widget.AutoComplete.prototype.useIFrame = false;
|
|
|
476 |
|
|
|
477 |
/**
|
|
|
478 |
* Whether or not the results container should have a shadow.
|
|
|
479 |
*
|
|
|
480 |
* @property useShadow
|
|
|
481 |
* @type Boolean
|
|
|
482 |
* @default false
|
|
|
483 |
*/
|
|
|
484 |
YAHOO.widget.AutoComplete.prototype.useShadow = false;
|
|
|
485 |
|
|
|
486 |
/**
|
|
|
487 |
* Whether or not the input field should be updated with selections.
|
|
|
488 |
*
|
|
|
489 |
* @property suppressInputUpdate
|
|
|
490 |
* @type Boolean
|
|
|
491 |
* @default false
|
|
|
492 |
*/
|
|
|
493 |
YAHOO.widget.AutoComplete.prototype.suppressInputUpdate = false;
|
|
|
494 |
|
|
|
495 |
/**
|
|
|
496 |
* For backward compatibility to pre-2.6.0 formatResults() signatures, setting
|
|
|
497 |
* resultsTypeList to true will take each object literal result returned by
|
|
|
498 |
* DataSource and flatten into an array.
|
|
|
499 |
*
|
|
|
500 |
* @property resultTypeList
|
|
|
501 |
* @type Boolean
|
|
|
502 |
* @default true
|
|
|
503 |
*/
|
|
|
504 |
YAHOO.widget.AutoComplete.prototype.resultTypeList = true;
|
|
|
505 |
|
|
|
506 |
/**
|
|
|
507 |
* For XHR DataSources, AutoComplete will automatically insert a "?" between the server URI and
|
|
|
508 |
* the "query" param/value pair. To prevent this behavior, implementers should
|
|
|
509 |
* set this value to false. To more fully customize the query syntax, implementers
|
|
|
510 |
* should override the generateRequest() method.
|
|
|
511 |
*
|
|
|
512 |
* @property queryQuestionMark
|
|
|
513 |
* @type Boolean
|
|
|
514 |
* @default true
|
|
|
515 |
*/
|
|
|
516 |
YAHOO.widget.AutoComplete.prototype.queryQuestionMark = true;
|
|
|
517 |
|
|
|
518 |
/**
|
|
|
519 |
* If true, before each time the container expands, the container element will be
|
|
|
520 |
* positioned to snap to the bottom-left corner of the input element. If
|
|
|
521 |
* autoSnapContainer is set to false, this positioning will not be done.
|
|
|
522 |
*
|
|
|
523 |
* @property autoSnapContainer
|
|
|
524 |
* @type Boolean
|
|
|
525 |
* @default true
|
|
|
526 |
*/
|
|
|
527 |
YAHOO.widget.AutoComplete.prototype.autoSnapContainer = true;
|
|
|
528 |
|
|
|
529 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
530 |
//
|
|
|
531 |
// Public methods
|
|
|
532 |
//
|
|
|
533 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
534 |
|
|
|
535 |
/**
|
|
|
536 |
* Public accessor to the unique name of the AutoComplete instance.
|
|
|
537 |
*
|
|
|
538 |
* @method toString
|
|
|
539 |
* @return {String} Unique name of the AutoComplete instance.
|
|
|
540 |
*/
|
|
|
541 |
YAHOO.widget.AutoComplete.prototype.toString = function() {
|
|
|
542 |
return "AutoComplete " + this._sName;
|
|
|
543 |
};
|
|
|
544 |
|
|
|
545 |
/**
|
|
|
546 |
* Returns DOM reference to input element.
|
|
|
547 |
*
|
|
|
548 |
* @method getInputEl
|
|
|
549 |
* @return {HTMLELement} DOM reference to input element.
|
|
|
550 |
*/
|
|
|
551 |
YAHOO.widget.AutoComplete.prototype.getInputEl = function() {
|
|
|
552 |
return this._elTextbox;
|
|
|
553 |
};
|
|
|
554 |
|
|
|
555 |
/**
|
|
|
556 |
* Returns DOM reference to container element.
|
|
|
557 |
*
|
|
|
558 |
* @method getContainerEl
|
|
|
559 |
* @return {HTMLELement} DOM reference to container element.
|
|
|
560 |
*/
|
|
|
561 |
YAHOO.widget.AutoComplete.prototype.getContainerEl = function() {
|
|
|
562 |
return this._elContainer;
|
|
|
563 |
};
|
|
|
564 |
|
|
|
565 |
/**
|
|
|
566 |
* Returns true if widget instance is currently active.
|
|
|
567 |
*
|
|
|
568 |
* @method isFocused
|
|
|
569 |
* @return {Boolean} Returns true if widget instance is currently active.
|
|
|
570 |
*/
|
|
|
571 |
YAHOO.widget.AutoComplete.prototype.isFocused = function() {
|
|
|
572 |
return this._bFocused;
|
|
|
573 |
};
|
|
|
574 |
|
|
|
575 |
/**
|
|
|
576 |
* Returns true if container is in an expanded state, false otherwise.
|
|
|
577 |
*
|
|
|
578 |
* @method isContainerOpen
|
|
|
579 |
* @return {Boolean} Returns true if container is in an expanded state, false otherwise.
|
|
|
580 |
*/
|
|
|
581 |
YAHOO.widget.AutoComplete.prototype.isContainerOpen = function() {
|
|
|
582 |
return this._bContainerOpen;
|
|
|
583 |
};
|
|
|
584 |
|
|
|
585 |
/**
|
|
|
586 |
* Public accessor to the <ul> element that displays query results within the results container.
|
|
|
587 |
*
|
|
|
588 |
* @method getListEl
|
|
|
589 |
* @return {HTMLElement[]} Reference to <ul> element within the results container.
|
|
|
590 |
*/
|
|
|
591 |
YAHOO.widget.AutoComplete.prototype.getListEl = function() {
|
|
|
592 |
return this._elList;
|
|
|
593 |
};
|
|
|
594 |
|
|
|
595 |
/**
|
|
|
596 |
* Public accessor to the matching string associated with a given <li> result.
|
|
|
597 |
*
|
|
|
598 |
* @method getListItemMatch
|
|
|
599 |
* @param elListItem {HTMLElement} Reference to <LI> element.
|
|
|
600 |
* @return {String} Matching string.
|
|
|
601 |
*/
|
|
|
602 |
YAHOO.widget.AutoComplete.prototype.getListItemMatch = function(elListItem) {
|
|
|
603 |
if(elListItem._sResultMatch) {
|
|
|
604 |
return elListItem._sResultMatch;
|
|
|
605 |
}
|
|
|
606 |
else {
|
|
|
607 |
return null;
|
|
|
608 |
}
|
|
|
609 |
};
|
|
|
610 |
|
|
|
611 |
/**
|
|
|
612 |
* Public accessor to the result data associated with a given <li> result.
|
|
|
613 |
*
|
|
|
614 |
* @method getListItemData
|
|
|
615 |
* @param elListItem {HTMLElement} Reference to <LI> element.
|
|
|
616 |
* @return {Object} Result data.
|
|
|
617 |
*/
|
|
|
618 |
YAHOO.widget.AutoComplete.prototype.getListItemData = function(elListItem) {
|
|
|
619 |
if(elListItem._oResultData) {
|
|
|
620 |
return elListItem._oResultData;
|
|
|
621 |
}
|
|
|
622 |
else {
|
|
|
623 |
return null;
|
|
|
624 |
}
|
|
|
625 |
};
|
|
|
626 |
|
|
|
627 |
/**
|
|
|
628 |
* Public accessor to the index of the associated with a given <li> result.
|
|
|
629 |
*
|
|
|
630 |
* @method getListItemIndex
|
|
|
631 |
* @param elListItem {HTMLElement} Reference to <LI> element.
|
|
|
632 |
* @return {Number} Index.
|
|
|
633 |
*/
|
|
|
634 |
YAHOO.widget.AutoComplete.prototype.getListItemIndex = function(elListItem) {
|
|
|
635 |
if(YAHOO.lang.isNumber(elListItem._nItemIndex)) {
|
|
|
636 |
return elListItem._nItemIndex;
|
|
|
637 |
}
|
|
|
638 |
else {
|
|
|
639 |
return null;
|
|
|
640 |
}
|
|
|
641 |
};
|
|
|
642 |
|
|
|
643 |
/**
|
|
|
644 |
* Sets HTML markup for the results container header. This markup will be
|
|
|
645 |
* inserted within a <div> tag with a class of "yui-ac-hd".
|
|
|
646 |
*
|
|
|
647 |
* @method setHeader
|
|
|
648 |
* @param sHeader {HTML} HTML markup for results container header.
|
|
|
649 |
*/
|
|
|
650 |
YAHOO.widget.AutoComplete.prototype.setHeader = function(sHeader) {
|
|
|
651 |
if(this._elHeader) {
|
|
|
652 |
var elHeader = this._elHeader;
|
|
|
653 |
if(sHeader) {
|
|
|
654 |
elHeader.innerHTML = sHeader;
|
|
|
655 |
elHeader.style.display = "";
|
|
|
656 |
}
|
|
|
657 |
else {
|
|
|
658 |
elHeader.innerHTML = "";
|
|
|
659 |
elHeader.style.display = "none";
|
|
|
660 |
}
|
|
|
661 |
}
|
|
|
662 |
};
|
|
|
663 |
|
|
|
664 |
/**
|
|
|
665 |
* Sets HTML markup for the results container footer. This markup will be
|
|
|
666 |
* inserted within a <div> tag with a class of "yui-ac-ft".
|
|
|
667 |
*
|
|
|
668 |
* @method setFooter
|
|
|
669 |
* @param sFooter {HTML} HTML markup for results container footer.
|
|
|
670 |
*/
|
|
|
671 |
YAHOO.widget.AutoComplete.prototype.setFooter = function(sFooter) {
|
|
|
672 |
if(this._elFooter) {
|
|
|
673 |
var elFooter = this._elFooter;
|
|
|
674 |
if(sFooter) {
|
|
|
675 |
elFooter.innerHTML = sFooter;
|
|
|
676 |
elFooter.style.display = "";
|
|
|
677 |
}
|
|
|
678 |
else {
|
|
|
679 |
elFooter.innerHTML = "";
|
|
|
680 |
elFooter.style.display = "none";
|
|
|
681 |
}
|
|
|
682 |
}
|
|
|
683 |
};
|
|
|
684 |
|
|
|
685 |
/**
|
|
|
686 |
* Sets HTML markup for the results container body. This markup will be
|
|
|
687 |
* inserted within a <div> tag with a class of "yui-ac-bd".
|
|
|
688 |
*
|
|
|
689 |
* @method setBody
|
|
|
690 |
* @param sBody {HTML} HTML markup for results container body.
|
|
|
691 |
*/
|
|
|
692 |
YAHOO.widget.AutoComplete.prototype.setBody = function(sBody) {
|
|
|
693 |
if(this._elBody) {
|
|
|
694 |
var elBody = this._elBody;
|
|
|
695 |
YAHOO.util.Event.purgeElement(elBody, true);
|
|
|
696 |
if(sBody) {
|
|
|
697 |
elBody.innerHTML = sBody;
|
|
|
698 |
elBody.style.display = "";
|
|
|
699 |
}
|
|
|
700 |
else {
|
|
|
701 |
elBody.innerHTML = "";
|
|
|
702 |
elBody.style.display = "none";
|
|
|
703 |
}
|
|
|
704 |
this._elList = null;
|
|
|
705 |
}
|
|
|
706 |
};
|
|
|
707 |
|
|
|
708 |
/**
|
|
|
709 |
* A function that converts an AutoComplete query into a request value which is then
|
|
|
710 |
* passed to the DataSource's sendRequest method in order to retrieve data for
|
|
|
711 |
* the query. By default, returns a String with the syntax: "query={query}"
|
|
|
712 |
* Implementers can customize this method for custom request syntaxes.
|
|
|
713 |
*
|
|
|
714 |
* @method generateRequest
|
|
|
715 |
* @param sQuery {String} Query string
|
|
|
716 |
* @return {MIXED} Request
|
|
|
717 |
*/
|
|
|
718 |
YAHOO.widget.AutoComplete.prototype.generateRequest = function(sQuery) {
|
|
|
719 |
var dataType = this.dataSource.dataType;
|
|
|
720 |
|
|
|
721 |
// Transform query string in to a request for remote data
|
|
|
722 |
// By default, local data doesn't need a transformation, just passes along the query as is.
|
|
|
723 |
if(dataType === YAHOO.util.DataSourceBase.TYPE_XHR) {
|
|
|
724 |
// By default, XHR GET requests look like "{scriptURI}?{scriptQueryParam}={sQuery}&{scriptQueryAppend}"
|
|
|
725 |
if(!this.dataSource.connMethodPost) {
|
|
|
726 |
sQuery = (this.queryQuestionMark ? "?" : "") + (this.dataSource.scriptQueryParam || "query") + "=" + sQuery +
|
|
|
727 |
(this.dataSource.scriptQueryAppend ? ("&" + this.dataSource.scriptQueryAppend) : "");
|
|
|
728 |
}
|
|
|
729 |
// By default, XHR POST bodies are sent to the {scriptURI} like "{scriptQueryParam}={sQuery}&{scriptQueryAppend}"
|
|
|
730 |
else {
|
|
|
731 |
sQuery = (this.dataSource.scriptQueryParam || "query") + "=" + sQuery +
|
|
|
732 |
(this.dataSource.scriptQueryAppend ? ("&" + this.dataSource.scriptQueryAppend) : "");
|
|
|
733 |
}
|
|
|
734 |
}
|
|
|
735 |
// By default, remote script node requests look like "{scriptURI}&{scriptCallbackParam}={callbackString}&{scriptQueryParam}={sQuery}&{scriptQueryAppend}"
|
|
|
736 |
else if(dataType === YAHOO.util.DataSourceBase.TYPE_SCRIPTNODE) {
|
|
|
737 |
sQuery = "&" + (this.dataSource.scriptQueryParam || "query") + "=" + sQuery +
|
|
|
738 |
(this.dataSource.scriptQueryAppend ? ("&" + this.dataSource.scriptQueryAppend) : "");
|
|
|
739 |
}
|
|
|
740 |
|
|
|
741 |
return sQuery;
|
|
|
742 |
};
|
|
|
743 |
|
|
|
744 |
/**
|
|
|
745 |
* Makes query request to the DataSource.
|
|
|
746 |
*
|
|
|
747 |
* @method sendQuery
|
|
|
748 |
* @param sQuery {String} Query string.
|
|
|
749 |
*/
|
|
|
750 |
YAHOO.widget.AutoComplete.prototype.sendQuery = function(sQuery) {
|
|
|
751 |
// Activate focus for a new interaction
|
|
|
752 |
this._bFocused = true;
|
|
|
753 |
|
|
|
754 |
// Adjust programatically sent queries to look like they were input by user
|
|
|
755 |
// when delimiters are enabled
|
|
|
756 |
var newQuery = (this.delimChar) ? this._elTextbox.value + sQuery : sQuery;
|
|
|
757 |
this._sendQuery(newQuery);
|
|
|
758 |
};
|
|
|
759 |
|
|
|
760 |
/**
|
|
|
761 |
* Snaps container to bottom-left corner of input element
|
|
|
762 |
*
|
|
|
763 |
* @method snapContainer
|
|
|
764 |
*/
|
|
|
765 |
YAHOO.widget.AutoComplete.prototype.snapContainer = function() {
|
|
|
766 |
var oTextbox = this._elTextbox,
|
|
|
767 |
pos = YAHOO.util.Dom.getXY(oTextbox);
|
|
|
768 |
pos[1] += YAHOO.util.Dom.get(oTextbox).offsetHeight + 2;
|
|
|
769 |
YAHOO.util.Dom.setXY(this._elContainer,pos);
|
|
|
770 |
};
|
|
|
771 |
|
|
|
772 |
/**
|
|
|
773 |
* Expands container.
|
|
|
774 |
*
|
|
|
775 |
* @method expandContainer
|
|
|
776 |
*/
|
|
|
777 |
YAHOO.widget.AutoComplete.prototype.expandContainer = function() {
|
|
|
778 |
this._toggleContainer(true);
|
|
|
779 |
};
|
|
|
780 |
|
|
|
781 |
/**
|
|
|
782 |
* Collapses container.
|
|
|
783 |
*
|
|
|
784 |
* @method collapseContainer
|
|
|
785 |
*/
|
|
|
786 |
YAHOO.widget.AutoComplete.prototype.collapseContainer = function() {
|
|
|
787 |
this._toggleContainer(false);
|
|
|
788 |
};
|
|
|
789 |
|
|
|
790 |
/**
|
|
|
791 |
* Clears entire list of suggestions.
|
|
|
792 |
*
|
|
|
793 |
* @method clearList
|
|
|
794 |
*/
|
|
|
795 |
YAHOO.widget.AutoComplete.prototype.clearList = function() {
|
|
|
796 |
var allItems = this._elList.childNodes,
|
|
|
797 |
i=allItems.length-1;
|
|
|
798 |
for(; i>-1; i--) {
|
|
|
799 |
allItems[i].style.display = "none";
|
|
|
800 |
}
|
|
|
801 |
};
|
|
|
802 |
|
|
|
803 |
/**
|
|
|
804 |
* Handles subset matching for when queryMatchSubset is enabled.
|
|
|
805 |
*
|
|
|
806 |
* @method getSubsetMatches
|
|
|
807 |
* @param sQuery {String} Query string.
|
|
|
808 |
* @return {Object} oParsedResponse or null.
|
|
|
809 |
*/
|
|
|
810 |
YAHOO.widget.AutoComplete.prototype.getSubsetMatches = function(sQuery) {
|
|
|
811 |
var subQuery, oCachedResponse, subRequest;
|
|
|
812 |
// Loop through substrings of each cached element's query property...
|
|
|
813 |
for(var i = sQuery.length; i >= this.minQueryLength ; i--) {
|
|
|
814 |
subRequest = this.generateRequest(sQuery.substr(0,i));
|
|
|
815 |
this.dataRequestEvent.fire(this, subQuery, subRequest);
|
|
|
816 |
YAHOO.log("Searching for query subset \"" + subQuery + "\" in cache", "info", this.toString());
|
|
|
817 |
|
|
|
818 |
// If a substring of the query is found in the cache
|
|
|
819 |
oCachedResponse = this.dataSource.getCachedResponse(subRequest);
|
|
|
820 |
if(oCachedResponse) {
|
|
|
821 |
YAHOO.log("Found match for query subset \"" + subQuery + "\": " + YAHOO.lang.dump(oCachedResponse), "info", this.toString());
|
|
|
822 |
return this.filterResults.apply(this.dataSource, [sQuery, oCachedResponse, oCachedResponse, {scope:this}]);
|
|
|
823 |
}
|
|
|
824 |
}
|
|
|
825 |
YAHOO.log("Did not find subset match for query subset \"" + sQuery + "\"" , "info", this.toString());
|
|
|
826 |
return null;
|
|
|
827 |
};
|
|
|
828 |
|
|
|
829 |
/**
|
|
|
830 |
* Executed by DataSource (within DataSource scope via doBeforeParseData()) to
|
|
|
831 |
* handle responseStripAfter cleanup.
|
|
|
832 |
*
|
|
|
833 |
* @method preparseRawResponse
|
|
|
834 |
* @param sQuery {String} Query string.
|
|
|
835 |
* @return {Object} oParsedResponse or null.
|
|
|
836 |
*/
|
|
|
837 |
YAHOO.widget.AutoComplete.prototype.preparseRawResponse = function(oRequest, oFullResponse, oCallback) {
|
|
|
838 |
var nEnd = ((this.responseStripAfter !== "") && (oFullResponse.indexOf)) ?
|
|
|
839 |
oFullResponse.indexOf(this.responseStripAfter) : -1;
|
|
|
840 |
if(nEnd != -1) {
|
|
|
841 |
oFullResponse = oFullResponse.substring(0,nEnd);
|
|
|
842 |
}
|
|
|
843 |
return oFullResponse;
|
|
|
844 |
};
|
|
|
845 |
|
|
|
846 |
/**
|
|
|
847 |
* Executed by DataSource (within DataSource scope via doBeforeCallback()) to
|
|
|
848 |
* filter results through a simple client-side matching algorithm.
|
|
|
849 |
*
|
|
|
850 |
* @method filterResults
|
|
|
851 |
* @param sQuery {String} Original request.
|
|
|
852 |
* @param oFullResponse {Object} Full response object.
|
|
|
853 |
* @param oParsedResponse {Object} Parsed response object.
|
|
|
854 |
* @param oCallback {Object} Callback object.
|
|
|
855 |
* @return {Object} Filtered response object.
|
|
|
856 |
*/
|
|
|
857 |
|
|
|
858 |
YAHOO.widget.AutoComplete.prototype.filterResults = function(sQuery, oFullResponse, oParsedResponse, oCallback) {
|
|
|
859 |
// If AC has passed a query string value back to itself, grab it
|
|
|
860 |
if(oCallback && oCallback.argument && YAHOO.lang.isValue(oCallback.argument.query)) {
|
|
|
861 |
sQuery = oCallback.argument.query;
|
|
|
862 |
}
|
|
|
863 |
|
|
|
864 |
// Only if a query string is available to match against
|
|
|
865 |
if(sQuery && sQuery !== "") {
|
|
|
866 |
// First make a copy of the oParseResponse
|
|
|
867 |
oParsedResponse = YAHOO.widget.AutoComplete._cloneObject(oParsedResponse);
|
|
|
868 |
|
|
|
869 |
var oAC = oCallback.scope,
|
|
|
870 |
oDS = this,
|
|
|
871 |
allResults = oParsedResponse.results, // the array of results
|
|
|
872 |
filteredResults = [], // container for filtered results,
|
|
|
873 |
nMax = oAC.maxResultsDisplayed, // max to find
|
|
|
874 |
bMatchCase = (oDS.queryMatchCase || oAC.queryMatchCase), // backward compat
|
|
|
875 |
bMatchContains = (oDS.queryMatchContains || oAC.queryMatchContains); // backward compat
|
|
|
876 |
|
|
|
877 |
// Loop through each result object...
|
|
|
878 |
for(var i=0, len=allResults.length; i<len; i++) {
|
|
|
879 |
var oResult = allResults[i];
|
|
|
880 |
|
|
|
881 |
// Grab the data to match against from the result object...
|
|
|
882 |
var sResult = null;
|
|
|
883 |
|
|
|
884 |
// Result object is a simple string already
|
|
|
885 |
if(YAHOO.lang.isString(oResult)) {
|
|
|
886 |
sResult = oResult;
|
|
|
887 |
}
|
|
|
888 |
// Result object is an array of strings
|
|
|
889 |
else if(YAHOO.lang.isArray(oResult)) {
|
|
|
890 |
sResult = oResult[0];
|
|
|
891 |
|
|
|
892 |
}
|
|
|
893 |
// Result object is an object literal of strings
|
|
|
894 |
else if(this.responseSchema.fields) {
|
|
|
895 |
var key = this.responseSchema.fields[0].key || this.responseSchema.fields[0];
|
|
|
896 |
sResult = oResult[key];
|
|
|
897 |
}
|
|
|
898 |
// Backwards compatibility
|
|
|
899 |
else if(this.key) {
|
|
|
900 |
sResult = oResult[this.key];
|
|
|
901 |
}
|
|
|
902 |
|
|
|
903 |
if(YAHOO.lang.isString(sResult)) {
|
|
|
904 |
|
|
|
905 |
var sKeyIndex = (bMatchCase) ?
|
|
|
906 |
sResult.indexOf(decodeURIComponent(sQuery)) :
|
|
|
907 |
sResult.toLowerCase().indexOf(decodeURIComponent(sQuery).toLowerCase());
|
|
|
908 |
|
|
|
909 |
// A STARTSWITH match is when the query is found at the beginning of the key string...
|
|
|
910 |
if((!bMatchContains && (sKeyIndex === 0)) ||
|
|
|
911 |
// A CONTAINS match is when the query is found anywhere within the key string...
|
|
|
912 |
(bMatchContains && (sKeyIndex > -1))) {
|
|
|
913 |
// Stash the match
|
|
|
914 |
filteredResults.push(oResult);
|
|
|
915 |
}
|
|
|
916 |
}
|
|
|
917 |
|
|
|
918 |
// Filter no more if maxResultsDisplayed is reached
|
|
|
919 |
if(len>nMax && filteredResults.length===nMax) {
|
|
|
920 |
break;
|
|
|
921 |
}
|
|
|
922 |
}
|
|
|
923 |
oParsedResponse.results = filteredResults;
|
|
|
924 |
YAHOO.log("Filtered " + filteredResults.length + " results against query \"" + sQuery + "\": " + YAHOO.lang.dump(filteredResults), "info", this.toString());
|
|
|
925 |
}
|
|
|
926 |
else {
|
|
|
927 |
YAHOO.log("Did not filter results against query", "info", this.toString());
|
|
|
928 |
}
|
|
|
929 |
|
|
|
930 |
return oParsedResponse;
|
|
|
931 |
};
|
|
|
932 |
|
|
|
933 |
/**
|
|
|
934 |
* Handles response for display. This is the callback function method passed to
|
|
|
935 |
* YAHOO.util.DataSourceBase#sendRequest so results from the DataSource are
|
|
|
936 |
* returned to the AutoComplete instance.
|
|
|
937 |
*
|
|
|
938 |
* @method handleResponse
|
|
|
939 |
* @param sQuery {String} Original request.
|
|
|
940 |
* @param oResponse {Object} <a href="http://developer.yahoo.com/yui/datasource/#ds_oParsedResponse">Response object</a>.
|
|
|
941 |
* @param oPayload {MIXED} (optional) Additional argument(s)
|
|
|
942 |
*/
|
|
|
943 |
YAHOO.widget.AutoComplete.prototype.handleResponse = function(sQuery, oResponse, oPayload) {
|
|
|
944 |
if((this instanceof YAHOO.widget.AutoComplete) && this._sName) {
|
|
|
945 |
this._populateList(sQuery, oResponse, oPayload);
|
|
|
946 |
}
|
|
|
947 |
};
|
|
|
948 |
|
|
|
949 |
/**
|
|
|
950 |
* Overridable method called before container is loaded with result data.
|
|
|
951 |
*
|
|
|
952 |
* @method doBeforeLoadData
|
|
|
953 |
* @param sQuery {String} Original request.
|
|
|
954 |
* @param oResponse {Object} <a href="http://developer.yahoo.com/yui/datasource/#ds_oParsedResponse">Response object</a>.
|
|
|
955 |
* @param oPayload {MIXED} (optional) Additional argument(s)
|
|
|
956 |
* @return {Boolean} Return true to continue loading data, false to cancel.
|
|
|
957 |
*/
|
|
|
958 |
YAHOO.widget.AutoComplete.prototype.doBeforeLoadData = function(sQuery, oResponse, oPayload) {
|
|
|
959 |
return true;
|
|
|
960 |
};
|
|
|
961 |
|
|
|
962 |
/**
|
|
|
963 |
* Overridable method that returns HTML markup for one result to be populated
|
|
|
964 |
* as innerHTML of an <LI> element.
|
|
|
965 |
*
|
|
|
966 |
* @method formatResult
|
|
|
967 |
* @param oResultData {Object} Result data object.
|
|
|
968 |
* @param sQuery {String} The corresponding query string.
|
|
|
969 |
* @param sResultMatch {HTMLElement} The current query string.
|
|
|
970 |
* @return {HTML} HTML markup of formatted result data.
|
|
|
971 |
*/
|
|
|
972 |
YAHOO.widget.AutoComplete.prototype.formatResult = function(oResultData, sQuery, sResultMatch) {
|
|
|
973 |
var sMarkup = (sResultMatch) ? sResultMatch : "";
|
|
|
974 |
return sMarkup;
|
|
|
975 |
};
|
|
|
976 |
|
|
|
977 |
/**
|
|
|
978 |
* An alternative to the formatResult() method, escapes the result data before
|
|
|
979 |
* inserting into DOM. Implementers should point to this method when accessing
|
|
|
980 |
* data from third-party sources, from user input, or from otherwise
|
|
|
981 |
* untrustworthy sources:
|
|
|
982 |
* myAutoComplete.formatResult = myAutoComplete.formatEscapedResult;
|
|
|
983 |
*
|
|
|
984 |
* @method formatEscapedResult
|
|
|
985 |
* @param oResultData {Object} Result data object.
|
|
|
986 |
* @param sQuery {String} The corresponding query string.
|
|
|
987 |
* @param sResultMatch {HTMLElement} The current query string.
|
|
|
988 |
* @return {String} Formatted result data.
|
|
|
989 |
*/
|
|
|
990 |
YAHOO.widget.AutoComplete.prototype.formatEscapedResult = function(oResultData, sQuery, sResultMatch) {
|
|
|
991 |
var sResult = (sResultMatch) ? sResultMatch : "";
|
|
|
992 |
return YAHOO.lang.escapeHTML(sResult);
|
|
|
993 |
};
|
|
|
994 |
|
|
|
995 |
/**
|
|
|
996 |
* Overridable method called before container expands allows implementers to access data
|
|
|
997 |
* and DOM elements.
|
|
|
998 |
*
|
|
|
999 |
* @method doBeforeExpandContainer
|
|
|
1000 |
* @param elTextbox {HTMLElement} The text input box.
|
|
|
1001 |
* @param elContainer {HTMLElement} The container element.
|
|
|
1002 |
* @param sQuery {String} The query string.
|
|
|
1003 |
* @param aResults {Object[]} An array of query results.
|
|
|
1004 |
* @return {Boolean} Return true to continue expanding container, false to cancel the expand.
|
|
|
1005 |
*/
|
|
|
1006 |
YAHOO.widget.AutoComplete.prototype.doBeforeExpandContainer = function(elTextbox, elContainer, sQuery, aResults) {
|
|
|
1007 |
return true;
|
|
|
1008 |
};
|
|
|
1009 |
|
|
|
1010 |
|
|
|
1011 |
/**
|
|
|
1012 |
* Nulls out the entire AutoComplete instance and related objects, removes attached
|
|
|
1013 |
* event listeners, and clears out DOM elements inside the container. After
|
|
|
1014 |
* calling this method, the instance reference should be expliclitly nulled by
|
|
|
1015 |
* implementer, as in myAutoComplete = null. Use with caution!
|
|
|
1016 |
*
|
|
|
1017 |
* @method destroy
|
|
|
1018 |
*/
|
|
|
1019 |
YAHOO.widget.AutoComplete.prototype.destroy = function() {
|
|
|
1020 |
var instanceName = this.toString();
|
|
|
1021 |
var elInput = this._elTextbox;
|
|
|
1022 |
var elContainer = this._elContainer;
|
|
|
1023 |
|
|
|
1024 |
// Unhook custom events
|
|
|
1025 |
this.textboxFocusEvent.unsubscribeAll();
|
|
|
1026 |
this.textboxKeyEvent.unsubscribeAll();
|
|
|
1027 |
this.dataRequestEvent.unsubscribeAll();
|
|
|
1028 |
this.dataReturnEvent.unsubscribeAll();
|
|
|
1029 |
this.dataErrorEvent.unsubscribeAll();
|
|
|
1030 |
this.containerPopulateEvent.unsubscribeAll();
|
|
|
1031 |
this.containerExpandEvent.unsubscribeAll();
|
|
|
1032 |
this.typeAheadEvent.unsubscribeAll();
|
|
|
1033 |
this.itemMouseOverEvent.unsubscribeAll();
|
|
|
1034 |
this.itemMouseOutEvent.unsubscribeAll();
|
|
|
1035 |
this.itemArrowToEvent.unsubscribeAll();
|
|
|
1036 |
this.itemArrowFromEvent.unsubscribeAll();
|
|
|
1037 |
this.itemSelectEvent.unsubscribeAll();
|
|
|
1038 |
this.unmatchedItemSelectEvent.unsubscribeAll();
|
|
|
1039 |
this.selectionEnforceEvent.unsubscribeAll();
|
|
|
1040 |
this.containerCollapseEvent.unsubscribeAll();
|
|
|
1041 |
this.textboxBlurEvent.unsubscribeAll();
|
|
|
1042 |
this.textboxChangeEvent.unsubscribeAll();
|
|
|
1043 |
|
|
|
1044 |
// Unhook DOM events
|
|
|
1045 |
YAHOO.util.Event.purgeElement(elInput, true);
|
|
|
1046 |
YAHOO.util.Event.purgeElement(elContainer, true);
|
|
|
1047 |
|
|
|
1048 |
// Remove DOM elements
|
|
|
1049 |
elContainer.innerHTML = "";
|
|
|
1050 |
|
|
|
1051 |
// Null out objects
|
|
|
1052 |
for(var key in this) {
|
|
|
1053 |
if(YAHOO.lang.hasOwnProperty(this, key)) {
|
|
|
1054 |
this[key] = null;
|
|
|
1055 |
}
|
|
|
1056 |
}
|
|
|
1057 |
|
|
|
1058 |
YAHOO.log("AutoComplete instance destroyed: " + instanceName);
|
|
|
1059 |
};
|
|
|
1060 |
|
|
|
1061 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
1062 |
//
|
|
|
1063 |
// Public events
|
|
|
1064 |
//
|
|
|
1065 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
1066 |
|
|
|
1067 |
/**
|
|
|
1068 |
* Fired when the input field receives focus.
|
|
|
1069 |
*
|
|
|
1070 |
* @event textboxFocusEvent
|
|
|
1071 |
* @param type {String} Name of the event.
|
|
|
1072 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1073 |
*/
|
|
|
1074 |
YAHOO.widget.AutoComplete.prototype.textboxFocusEvent = null;
|
|
|
1075 |
|
|
|
1076 |
/**
|
|
|
1077 |
* Fired when the input field receives key input.
|
|
|
1078 |
*
|
|
|
1079 |
* @event textboxKeyEvent
|
|
|
1080 |
* @param type {String} Name of the event.
|
|
|
1081 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1082 |
* @param args[1] {Number} The keycode number.
|
|
|
1083 |
*/
|
|
|
1084 |
YAHOO.widget.AutoComplete.prototype.textboxKeyEvent = null;
|
|
|
1085 |
|
|
|
1086 |
/**
|
|
|
1087 |
* Fired when the AutoComplete instance makes a request to the DataSource.
|
|
|
1088 |
*
|
|
|
1089 |
* @event dataRequestEvent
|
|
|
1090 |
* @param type {String} Name of the event.
|
|
|
1091 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1092 |
* @param args[1] {String} The query string.
|
|
|
1093 |
* @param args[2] {Object} The request.
|
|
|
1094 |
*/
|
|
|
1095 |
YAHOO.widget.AutoComplete.prototype.dataRequestEvent = null;
|
|
|
1096 |
|
|
|
1097 |
/**
|
|
|
1098 |
* Fired when the AutoComplete request to the DataSource is canceled.
|
|
|
1099 |
*
|
|
|
1100 |
* @event dataRequestCancelEvent
|
|
|
1101 |
* @param type {String} Name of the event.
|
|
|
1102 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1103 |
* @param args[1] {String} The query string.
|
|
|
1104 |
*/
|
|
|
1105 |
YAHOO.widget.AutoComplete.prototype.dataRequestCancelEvent = null;
|
|
|
1106 |
|
|
|
1107 |
/**
|
|
|
1108 |
* Fired when the AutoComplete instance receives query results from the data
|
|
|
1109 |
* source.
|
|
|
1110 |
*
|
|
|
1111 |
* @event dataReturnEvent
|
|
|
1112 |
* @param type {String} Name of the event.
|
|
|
1113 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1114 |
* @param args[1] {String} The query string.
|
|
|
1115 |
* @param args[2] {Object[]} Results array.
|
|
|
1116 |
*/
|
|
|
1117 |
YAHOO.widget.AutoComplete.prototype.dataReturnEvent = null;
|
|
|
1118 |
|
|
|
1119 |
/**
|
|
|
1120 |
* Fired when the AutoComplete instance does not receive query results from the
|
|
|
1121 |
* DataSource due to an error.
|
|
|
1122 |
*
|
|
|
1123 |
* @event dataErrorEvent
|
|
|
1124 |
* @param type {String} Name of the event.
|
|
|
1125 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1126 |
* @param args[1] {String} The query string.
|
|
|
1127 |
* @param args[2] {Object} The response object, if available.
|
|
|
1128 |
*/
|
|
|
1129 |
YAHOO.widget.AutoComplete.prototype.dataErrorEvent = null;
|
|
|
1130 |
|
|
|
1131 |
/**
|
|
|
1132 |
* Fired when the results container is populated.
|
|
|
1133 |
*
|
|
|
1134 |
* @event containerPopulateEvent
|
|
|
1135 |
* @param type {String} Name of the event.
|
|
|
1136 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1137 |
*/
|
|
|
1138 |
YAHOO.widget.AutoComplete.prototype.containerPopulateEvent = null;
|
|
|
1139 |
|
|
|
1140 |
/**
|
|
|
1141 |
* Fired when the results container is expanded.
|
|
|
1142 |
*
|
|
|
1143 |
* @event containerExpandEvent
|
|
|
1144 |
* @param type {String} Name of the event.
|
|
|
1145 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1146 |
*/
|
|
|
1147 |
YAHOO.widget.AutoComplete.prototype.containerExpandEvent = null;
|
|
|
1148 |
|
|
|
1149 |
/**
|
|
|
1150 |
* Fired when the input field has been prefilled by the type-ahead
|
|
|
1151 |
* feature.
|
|
|
1152 |
*
|
|
|
1153 |
* @event typeAheadEvent
|
|
|
1154 |
* @param type {String} Name of the event.
|
|
|
1155 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1156 |
* @param args[1] {String} The query string.
|
|
|
1157 |
* @param args[2] {String} The prefill string.
|
|
|
1158 |
*/
|
|
|
1159 |
YAHOO.widget.AutoComplete.prototype.typeAheadEvent = null;
|
|
|
1160 |
|
|
|
1161 |
/**
|
|
|
1162 |
* Fired when result item has been moused over.
|
|
|
1163 |
*
|
|
|
1164 |
* @event itemMouseOverEvent
|
|
|
1165 |
* @param type {String} Name of the event.
|
|
|
1166 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1167 |
* @param args[1] {HTMLElement} The <li> element item moused to.
|
|
|
1168 |
*/
|
|
|
1169 |
YAHOO.widget.AutoComplete.prototype.itemMouseOverEvent = null;
|
|
|
1170 |
|
|
|
1171 |
/**
|
|
|
1172 |
* Fired when result item has been moused out.
|
|
|
1173 |
*
|
|
|
1174 |
* @event itemMouseOutEvent
|
|
|
1175 |
* @param type {String} Name of the event.
|
|
|
1176 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1177 |
* @param args[1] {HTMLElement} The <li> element item moused from.
|
|
|
1178 |
*/
|
|
|
1179 |
YAHOO.widget.AutoComplete.prototype.itemMouseOutEvent = null;
|
|
|
1180 |
|
|
|
1181 |
/**
|
|
|
1182 |
* Fired when result item has been arrowed to.
|
|
|
1183 |
*
|
|
|
1184 |
* @event itemArrowToEvent
|
|
|
1185 |
* @param type {String} Name of the event.
|
|
|
1186 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1187 |
* @param args[1] {HTMLElement} The <li> element item arrowed to.
|
|
|
1188 |
*/
|
|
|
1189 |
YAHOO.widget.AutoComplete.prototype.itemArrowToEvent = null;
|
|
|
1190 |
|
|
|
1191 |
/**
|
|
|
1192 |
* Fired when result item has been arrowed away from.
|
|
|
1193 |
*
|
|
|
1194 |
* @event itemArrowFromEvent
|
|
|
1195 |
* @param type {String} Name of the event.
|
|
|
1196 |
* @param args[0[ {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1197 |
* @param args[1] {HTMLElement} The <li> element item arrowed from.
|
|
|
1198 |
*/
|
|
|
1199 |
YAHOO.widget.AutoComplete.prototype.itemArrowFromEvent = null;
|
|
|
1200 |
|
|
|
1201 |
/**
|
|
|
1202 |
* Fired when an item is selected via mouse click, ENTER key, or TAB key.
|
|
|
1203 |
*
|
|
|
1204 |
* @event itemSelectEvent
|
|
|
1205 |
* @param type {String} Name of the event.
|
|
|
1206 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1207 |
* @param args[1] {HTMLElement} The selected <li> element item.
|
|
|
1208 |
* @param args[2] {Object} The data returned for the item, either as an object,
|
|
|
1209 |
* or mapped from the schema into an array.
|
|
|
1210 |
*/
|
|
|
1211 |
YAHOO.widget.AutoComplete.prototype.itemSelectEvent = null;
|
|
|
1212 |
|
|
|
1213 |
/**
|
|
|
1214 |
* Fired when a user selection does not match any of the displayed result items.
|
|
|
1215 |
*
|
|
|
1216 |
* @event unmatchedItemSelectEvent
|
|
|
1217 |
* @param type {String} Name of the event.
|
|
|
1218 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1219 |
* @param args[1] {String} The selected string.
|
|
|
1220 |
*/
|
|
|
1221 |
YAHOO.widget.AutoComplete.prototype.unmatchedItemSelectEvent = null;
|
|
|
1222 |
|
|
|
1223 |
/**
|
|
|
1224 |
* Fired if forceSelection is enabled and the user's input has been cleared
|
|
|
1225 |
* because it did not match one of the returned query results.
|
|
|
1226 |
*
|
|
|
1227 |
* @event selectionEnforceEvent
|
|
|
1228 |
* @param type {String} Name of the event.
|
|
|
1229 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1230 |
* @param args[1] {String} The cleared value (including delimiters if applicable).
|
|
|
1231 |
*/
|
|
|
1232 |
YAHOO.widget.AutoComplete.prototype.selectionEnforceEvent = null;
|
|
|
1233 |
|
|
|
1234 |
/**
|
|
|
1235 |
* Fired when the results container is collapsed.
|
|
|
1236 |
*
|
|
|
1237 |
* @event containerCollapseEvent
|
|
|
1238 |
* @param type {String} Name of the event.
|
|
|
1239 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1240 |
*/
|
|
|
1241 |
YAHOO.widget.AutoComplete.prototype.containerCollapseEvent = null;
|
|
|
1242 |
|
|
|
1243 |
/**
|
|
|
1244 |
* Fired when the input field loses focus.
|
|
|
1245 |
*
|
|
|
1246 |
* @event textboxBlurEvent
|
|
|
1247 |
* @param type {String} Name of the event.
|
|
|
1248 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1249 |
*/
|
|
|
1250 |
YAHOO.widget.AutoComplete.prototype.textboxBlurEvent = null;
|
|
|
1251 |
|
|
|
1252 |
/**
|
|
|
1253 |
* Fired when the input field value has changed when it loses focus.
|
|
|
1254 |
*
|
|
|
1255 |
* @event textboxChangeEvent
|
|
|
1256 |
* @param type {String} Name of the event.
|
|
|
1257 |
* @param args[0] {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1258 |
*/
|
|
|
1259 |
YAHOO.widget.AutoComplete.prototype.textboxChangeEvent = null;
|
|
|
1260 |
|
|
|
1261 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
1262 |
//
|
|
|
1263 |
// Private member variables
|
|
|
1264 |
//
|
|
|
1265 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
1266 |
|
|
|
1267 |
/**
|
|
|
1268 |
* Internal class variable to index multiple AutoComplete instances.
|
|
|
1269 |
*
|
|
|
1270 |
* @property _nIndex
|
|
|
1271 |
* @type Number
|
|
|
1272 |
* @default 0
|
|
|
1273 |
* @private
|
|
|
1274 |
*/
|
|
|
1275 |
YAHOO.widget.AutoComplete._nIndex = 0;
|
|
|
1276 |
|
|
|
1277 |
/**
|
|
|
1278 |
* Name of AutoComplete instance.
|
|
|
1279 |
*
|
|
|
1280 |
* @property _sName
|
|
|
1281 |
* @type String
|
|
|
1282 |
* @private
|
|
|
1283 |
*/
|
|
|
1284 |
YAHOO.widget.AutoComplete.prototype._sName = null;
|
|
|
1285 |
|
|
|
1286 |
/**
|
|
|
1287 |
* Text input field DOM element.
|
|
|
1288 |
*
|
|
|
1289 |
* @property _elTextbox
|
|
|
1290 |
* @type HTMLElement
|
|
|
1291 |
* @private
|
|
|
1292 |
*/
|
|
|
1293 |
YAHOO.widget.AutoComplete.prototype._elTextbox = null;
|
|
|
1294 |
|
|
|
1295 |
/**
|
|
|
1296 |
* Container DOM element.
|
|
|
1297 |
*
|
|
|
1298 |
* @property _elContainer
|
|
|
1299 |
* @type HTMLElement
|
|
|
1300 |
* @private
|
|
|
1301 |
*/
|
|
|
1302 |
YAHOO.widget.AutoComplete.prototype._elContainer = null;
|
|
|
1303 |
|
|
|
1304 |
/**
|
|
|
1305 |
* Reference to content element within container element.
|
|
|
1306 |
*
|
|
|
1307 |
* @property _elContent
|
|
|
1308 |
* @type HTMLElement
|
|
|
1309 |
* @private
|
|
|
1310 |
*/
|
|
|
1311 |
YAHOO.widget.AutoComplete.prototype._elContent = null;
|
|
|
1312 |
|
|
|
1313 |
/**
|
|
|
1314 |
* Reference to header element within content element.
|
|
|
1315 |
*
|
|
|
1316 |
* @property _elHeader
|
|
|
1317 |
* @type HTMLElement
|
|
|
1318 |
* @private
|
|
|
1319 |
*/
|
|
|
1320 |
YAHOO.widget.AutoComplete.prototype._elHeader = null;
|
|
|
1321 |
|
|
|
1322 |
/**
|
|
|
1323 |
* Reference to body element within content element.
|
|
|
1324 |
*
|
|
|
1325 |
* @property _elBody
|
|
|
1326 |
* @type HTMLElement
|
|
|
1327 |
* @private
|
|
|
1328 |
*/
|
|
|
1329 |
YAHOO.widget.AutoComplete.prototype._elBody = null;
|
|
|
1330 |
|
|
|
1331 |
/**
|
|
|
1332 |
* Reference to footer element within content element.
|
|
|
1333 |
*
|
|
|
1334 |
* @property _elFooter
|
|
|
1335 |
* @type HTMLElement
|
|
|
1336 |
* @private
|
|
|
1337 |
*/
|
|
|
1338 |
YAHOO.widget.AutoComplete.prototype._elFooter = null;
|
|
|
1339 |
|
|
|
1340 |
/**
|
|
|
1341 |
* Reference to shadow element within container element.
|
|
|
1342 |
*
|
|
|
1343 |
* @property _elShadow
|
|
|
1344 |
* @type HTMLElement
|
|
|
1345 |
* @private
|
|
|
1346 |
*/
|
|
|
1347 |
YAHOO.widget.AutoComplete.prototype._elShadow = null;
|
|
|
1348 |
|
|
|
1349 |
/**
|
|
|
1350 |
* Reference to iframe element within container element.
|
|
|
1351 |
*
|
|
|
1352 |
* @property _elIFrame
|
|
|
1353 |
* @type HTMLElement
|
|
|
1354 |
* @private
|
|
|
1355 |
*/
|
|
|
1356 |
YAHOO.widget.AutoComplete.prototype._elIFrame = null;
|
|
|
1357 |
|
|
|
1358 |
/**
|
|
|
1359 |
* Whether or not the widget instance is currently active. If query results come back
|
|
|
1360 |
* but the user has already moved on, do not proceed with auto complete behavior.
|
|
|
1361 |
*
|
|
|
1362 |
* @property _bFocused
|
|
|
1363 |
* @type Boolean
|
|
|
1364 |
* @private
|
|
|
1365 |
*/
|
|
|
1366 |
YAHOO.widget.AutoComplete.prototype._bFocused = false;
|
|
|
1367 |
|
|
|
1368 |
/**
|
|
|
1369 |
* Animation instance for container expand/collapse.
|
|
|
1370 |
*
|
|
|
1371 |
* @property _oAnim
|
|
|
1372 |
* @type Boolean
|
|
|
1373 |
* @private
|
|
|
1374 |
*/
|
|
|
1375 |
YAHOO.widget.AutoComplete.prototype._oAnim = null;
|
|
|
1376 |
|
|
|
1377 |
/**
|
|
|
1378 |
* Whether or not the results container is currently open.
|
|
|
1379 |
*
|
|
|
1380 |
* @property _bContainerOpen
|
|
|
1381 |
* @type Boolean
|
|
|
1382 |
* @private
|
|
|
1383 |
*/
|
|
|
1384 |
YAHOO.widget.AutoComplete.prototype._bContainerOpen = false;
|
|
|
1385 |
|
|
|
1386 |
/**
|
|
|
1387 |
* Whether or not the mouse is currently over the results
|
|
|
1388 |
* container. This is necessary in order to prevent clicks on container items
|
|
|
1389 |
* from being text input field blur events.
|
|
|
1390 |
*
|
|
|
1391 |
* @property _bOverContainer
|
|
|
1392 |
* @type Boolean
|
|
|
1393 |
* @private
|
|
|
1394 |
*/
|
|
|
1395 |
YAHOO.widget.AutoComplete.prototype._bOverContainer = false;
|
|
|
1396 |
|
|
|
1397 |
/**
|
|
|
1398 |
* Internal reference to <ul> elements that contains query results within the
|
|
|
1399 |
* results container.
|
|
|
1400 |
*
|
|
|
1401 |
* @property _elList
|
|
|
1402 |
* @type HTMLElement
|
|
|
1403 |
* @private
|
|
|
1404 |
*/
|
|
|
1405 |
YAHOO.widget.AutoComplete.prototype._elList = null;
|
|
|
1406 |
|
|
|
1407 |
/*
|
|
|
1408 |
* Array of <li> elements references that contain query results within the
|
|
|
1409 |
* results container.
|
|
|
1410 |
*
|
|
|
1411 |
* @property _aListItemEls
|
|
|
1412 |
* @type HTMLElement[]
|
|
|
1413 |
* @private
|
|
|
1414 |
*/
|
|
|
1415 |
//YAHOO.widget.AutoComplete.prototype._aListItemEls = null;
|
|
|
1416 |
|
|
|
1417 |
/**
|
|
|
1418 |
* Number of <li> elements currently displayed in results container.
|
|
|
1419 |
*
|
|
|
1420 |
* @property _nDisplayedItems
|
|
|
1421 |
* @type Number
|
|
|
1422 |
* @private
|
|
|
1423 |
*/
|
|
|
1424 |
YAHOO.widget.AutoComplete.prototype._nDisplayedItems = 0;
|
|
|
1425 |
|
|
|
1426 |
/*
|
|
|
1427 |
* Internal count of <li> elements displayed and hidden in results container.
|
|
|
1428 |
*
|
|
|
1429 |
* @property _maxResultsDisplayed
|
|
|
1430 |
* @type Number
|
|
|
1431 |
* @private
|
|
|
1432 |
*/
|
|
|
1433 |
//YAHOO.widget.AutoComplete.prototype._maxResultsDisplayed = 0;
|
|
|
1434 |
|
|
|
1435 |
/**
|
|
|
1436 |
* Current query string
|
|
|
1437 |
*
|
|
|
1438 |
* @property _sCurQuery
|
|
|
1439 |
* @type String
|
|
|
1440 |
* @private
|
|
|
1441 |
*/
|
|
|
1442 |
YAHOO.widget.AutoComplete.prototype._sCurQuery = null;
|
|
|
1443 |
|
|
|
1444 |
/**
|
|
|
1445 |
* Selections from previous queries (for saving delimited queries).
|
|
|
1446 |
*
|
|
|
1447 |
* @property _sPastSelections
|
|
|
1448 |
* @type String
|
|
|
1449 |
* @default ""
|
|
|
1450 |
* @private
|
|
|
1451 |
*/
|
|
|
1452 |
YAHOO.widget.AutoComplete.prototype._sPastSelections = "";
|
|
|
1453 |
|
|
|
1454 |
/**
|
|
|
1455 |
* Stores initial input value used to determine if textboxChangeEvent should be fired.
|
|
|
1456 |
*
|
|
|
1457 |
* @property _sInitInputValue
|
|
|
1458 |
* @type String
|
|
|
1459 |
* @private
|
|
|
1460 |
*/
|
|
|
1461 |
YAHOO.widget.AutoComplete.prototype._sInitInputValue = null;
|
|
|
1462 |
|
|
|
1463 |
/**
|
|
|
1464 |
* Pointer to the currently highlighted <li> element in the container.
|
|
|
1465 |
*
|
|
|
1466 |
* @property _elCurListItem
|
|
|
1467 |
* @type HTMLElement
|
|
|
1468 |
* @private
|
|
|
1469 |
*/
|
|
|
1470 |
YAHOO.widget.AutoComplete.prototype._elCurListItem = null;
|
|
|
1471 |
|
|
|
1472 |
/**
|
|
|
1473 |
* Pointer to the currently pre-highlighted <li> element in the container.
|
|
|
1474 |
*
|
|
|
1475 |
* @property _elCurPrehighlightItem
|
|
|
1476 |
* @type HTMLElement
|
|
|
1477 |
* @private
|
|
|
1478 |
*/
|
|
|
1479 |
YAHOO.widget.AutoComplete.prototype._elCurPrehighlightItem = null;
|
|
|
1480 |
|
|
|
1481 |
/**
|
|
|
1482 |
* Whether or not an item has been selected since the container was populated
|
|
|
1483 |
* with results. Reset to false by _populateList, and set to true when item is
|
|
|
1484 |
* selected.
|
|
|
1485 |
*
|
|
|
1486 |
* @property _bItemSelected
|
|
|
1487 |
* @type Boolean
|
|
|
1488 |
* @private
|
|
|
1489 |
*/
|
|
|
1490 |
YAHOO.widget.AutoComplete.prototype._bItemSelected = false;
|
|
|
1491 |
|
|
|
1492 |
/**
|
|
|
1493 |
* Key code of the last key pressed in textbox.
|
|
|
1494 |
*
|
|
|
1495 |
* @property _nKeyCode
|
|
|
1496 |
* @type Number
|
|
|
1497 |
* @private
|
|
|
1498 |
*/
|
|
|
1499 |
YAHOO.widget.AutoComplete.prototype._nKeyCode = null;
|
|
|
1500 |
|
|
|
1501 |
/**
|
|
|
1502 |
* Delay timeout ID.
|
|
|
1503 |
*
|
|
|
1504 |
* @property _nDelayID
|
|
|
1505 |
* @type Number
|
|
|
1506 |
* @private
|
|
|
1507 |
*/
|
|
|
1508 |
YAHOO.widget.AutoComplete.prototype._nDelayID = -1;
|
|
|
1509 |
|
|
|
1510 |
/**
|
|
|
1511 |
* TypeAhead delay timeout ID.
|
|
|
1512 |
*
|
|
|
1513 |
* @property _nTypeAheadDelayID
|
|
|
1514 |
* @type Number
|
|
|
1515 |
* @private
|
|
|
1516 |
*/
|
|
|
1517 |
YAHOO.widget.AutoComplete.prototype._nTypeAheadDelayID = -1;
|
|
|
1518 |
|
|
|
1519 |
/**
|
|
|
1520 |
* Src to iFrame used when useIFrame = true. Supports implementations over SSL
|
|
|
1521 |
* as well.
|
|
|
1522 |
*
|
|
|
1523 |
* @property _iFrameSrc
|
|
|
1524 |
* @type String
|
|
|
1525 |
* @private
|
|
|
1526 |
*/
|
|
|
1527 |
YAHOO.widget.AutoComplete.prototype._iFrameSrc = "javascript:false;";
|
|
|
1528 |
|
|
|
1529 |
/**
|
|
|
1530 |
* For users typing via certain IMEs, queries must be triggered by intervals,
|
|
|
1531 |
* since key events yet supported across all browsers for all IMEs.
|
|
|
1532 |
*
|
|
|
1533 |
* @property _queryInterval
|
|
|
1534 |
* @type Object
|
|
|
1535 |
* @private
|
|
|
1536 |
*/
|
|
|
1537 |
YAHOO.widget.AutoComplete.prototype._queryInterval = null;
|
|
|
1538 |
|
|
|
1539 |
/**
|
|
|
1540 |
* Internal tracker to last known textbox value, used to determine whether or not
|
|
|
1541 |
* to trigger a query via interval for certain IME users.
|
|
|
1542 |
*
|
|
|
1543 |
* @event _sLastTextboxValue
|
|
|
1544 |
* @type String
|
|
|
1545 |
* @private
|
|
|
1546 |
*/
|
|
|
1547 |
YAHOO.widget.AutoComplete.prototype._sLastTextboxValue = null;
|
|
|
1548 |
|
|
|
1549 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
1550 |
//
|
|
|
1551 |
// Private methods
|
|
|
1552 |
//
|
|
|
1553 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
1554 |
|
|
|
1555 |
/**
|
|
|
1556 |
* Updates and validates latest public config properties.
|
|
|
1557 |
*
|
|
|
1558 |
* @method __initProps
|
|
|
1559 |
* @private
|
|
|
1560 |
*/
|
|
|
1561 |
YAHOO.widget.AutoComplete.prototype._initProps = function() {
|
|
|
1562 |
// Correct any invalid values
|
|
|
1563 |
var minQueryLength = this.minQueryLength;
|
|
|
1564 |
if(!YAHOO.lang.isNumber(minQueryLength)) {
|
|
|
1565 |
this.minQueryLength = 1;
|
|
|
1566 |
}
|
|
|
1567 |
var maxResultsDisplayed = this.maxResultsDisplayed;
|
|
|
1568 |
if(!YAHOO.lang.isNumber(maxResultsDisplayed) || (maxResultsDisplayed < 1)) {
|
|
|
1569 |
this.maxResultsDisplayed = 10;
|
|
|
1570 |
}
|
|
|
1571 |
var queryDelay = this.queryDelay;
|
|
|
1572 |
if(!YAHOO.lang.isNumber(queryDelay) || (queryDelay < 0)) {
|
|
|
1573 |
this.queryDelay = 0.2;
|
|
|
1574 |
}
|
|
|
1575 |
var typeAheadDelay = this.typeAheadDelay;
|
|
|
1576 |
if(!YAHOO.lang.isNumber(typeAheadDelay) || (typeAheadDelay < 0)) {
|
|
|
1577 |
this.typeAheadDelay = 0.2;
|
|
|
1578 |
}
|
|
|
1579 |
var delimChar = this.delimChar;
|
|
|
1580 |
if(YAHOO.lang.isString(delimChar) && (delimChar.length > 0)) {
|
|
|
1581 |
this.delimChar = [delimChar];
|
|
|
1582 |
}
|
|
|
1583 |
else if(!YAHOO.lang.isArray(delimChar)) {
|
|
|
1584 |
this.delimChar = null;
|
|
|
1585 |
}
|
|
|
1586 |
var animSpeed = this.animSpeed;
|
|
|
1587 |
if((this.animHoriz || this.animVert) && YAHOO.util.Anim) {
|
|
|
1588 |
if(!YAHOO.lang.isNumber(animSpeed) || (animSpeed < 0)) {
|
|
|
1589 |
this.animSpeed = 0.3;
|
|
|
1590 |
}
|
|
|
1591 |
if(!this._oAnim ) {
|
|
|
1592 |
this._oAnim = new YAHOO.util.Anim(this._elContent, {}, this.animSpeed);
|
|
|
1593 |
}
|
|
|
1594 |
else {
|
|
|
1595 |
this._oAnim.duration = this.animSpeed;
|
|
|
1596 |
}
|
|
|
1597 |
}
|
|
|
1598 |
if(this.forceSelection && delimChar) {
|
|
|
1599 |
YAHOO.log("The forceSelection feature has been enabled with delimChar defined.","warn", this.toString());
|
|
|
1600 |
}
|
|
|
1601 |
};
|
|
|
1602 |
|
|
|
1603 |
/**
|
|
|
1604 |
* Initializes the results container helpers if they are enabled and do
|
|
|
1605 |
* not exist
|
|
|
1606 |
*
|
|
|
1607 |
* @method _initContainerHelperEls
|
|
|
1608 |
* @private
|
|
|
1609 |
*/
|
|
|
1610 |
YAHOO.widget.AutoComplete.prototype._initContainerHelperEls = function() {
|
|
|
1611 |
if(this.useShadow && !this._elShadow) {
|
|
|
1612 |
var elShadow = document.createElement("div");
|
|
|
1613 |
elShadow.className = "yui-ac-shadow";
|
|
|
1614 |
elShadow.style.width = 0;
|
|
|
1615 |
elShadow.style.height = 0;
|
|
|
1616 |
this._elShadow = this._elContainer.appendChild(elShadow);
|
|
|
1617 |
}
|
|
|
1618 |
if(this.useIFrame && !this._elIFrame) {
|
|
|
1619 |
var elIFrame = document.createElement("iframe");
|
|
|
1620 |
elIFrame.src = this._iFrameSrc;
|
|
|
1621 |
elIFrame.frameBorder = 0;
|
|
|
1622 |
elIFrame.scrolling = "no";
|
|
|
1623 |
elIFrame.style.position = "absolute";
|
|
|
1624 |
elIFrame.style.width = 0;
|
|
|
1625 |
elIFrame.style.height = 0;
|
|
|
1626 |
elIFrame.style.padding = 0;
|
|
|
1627 |
elIFrame.tabIndex = -1;
|
|
|
1628 |
elIFrame.role = "presentation";
|
|
|
1629 |
elIFrame.title = "Presentational iframe shim";
|
|
|
1630 |
this._elIFrame = this._elContainer.appendChild(elIFrame);
|
|
|
1631 |
}
|
|
|
1632 |
};
|
|
|
1633 |
|
|
|
1634 |
/**
|
|
|
1635 |
* Initializes the results container once at object creation
|
|
|
1636 |
*
|
|
|
1637 |
* @method _initContainerEl
|
|
|
1638 |
* @private
|
|
|
1639 |
*/
|
|
|
1640 |
YAHOO.widget.AutoComplete.prototype._initContainerEl = function() {
|
|
|
1641 |
YAHOO.util.Dom.addClass(this._elContainer, "yui-ac-container");
|
|
|
1642 |
|
|
|
1643 |
if(!this._elContent) {
|
|
|
1644 |
// The elContent div is assigned DOM listeners and
|
|
|
1645 |
// helps size the iframe and shadow properly
|
|
|
1646 |
var elContent = document.createElement("div");
|
|
|
1647 |
elContent.className = "yui-ac-content";
|
|
|
1648 |
elContent.style.display = "none";
|
|
|
1649 |
|
|
|
1650 |
this._elContent = this._elContainer.appendChild(elContent);
|
|
|
1651 |
|
|
|
1652 |
var elHeader = document.createElement("div");
|
|
|
1653 |
elHeader.className = "yui-ac-hd";
|
|
|
1654 |
elHeader.style.display = "none";
|
|
|
1655 |
this._elHeader = this._elContent.appendChild(elHeader);
|
|
|
1656 |
|
|
|
1657 |
var elBody = document.createElement("div");
|
|
|
1658 |
elBody.className = "yui-ac-bd";
|
|
|
1659 |
this._elBody = this._elContent.appendChild(elBody);
|
|
|
1660 |
|
|
|
1661 |
var elFooter = document.createElement("div");
|
|
|
1662 |
elFooter.className = "yui-ac-ft";
|
|
|
1663 |
elFooter.style.display = "none";
|
|
|
1664 |
this._elFooter = this._elContent.appendChild(elFooter);
|
|
|
1665 |
}
|
|
|
1666 |
else {
|
|
|
1667 |
YAHOO.log("Could not initialize the container","warn",this.toString());
|
|
|
1668 |
}
|
|
|
1669 |
};
|
|
|
1670 |
|
|
|
1671 |
/**
|
|
|
1672 |
* Clears out contents of container body and creates up to
|
|
|
1673 |
* YAHOO.widget.AutoComplete#maxResultsDisplayed <li> elements in an
|
|
|
1674 |
* <ul> element.
|
|
|
1675 |
*
|
|
|
1676 |
* @method _initListEl
|
|
|
1677 |
* @private
|
|
|
1678 |
*/
|
|
|
1679 |
YAHOO.widget.AutoComplete.prototype._initListEl = function() {
|
|
|
1680 |
var nListLength = this.maxResultsDisplayed,
|
|
|
1681 |
elList = this._elList || document.createElement("ul"),
|
|
|
1682 |
elListItem;
|
|
|
1683 |
|
|
|
1684 |
while(elList.childNodes.length < nListLength) {
|
|
|
1685 |
elListItem = document.createElement("li");
|
|
|
1686 |
elListItem.style.display = "none";
|
|
|
1687 |
elListItem._nItemIndex = elList.childNodes.length;
|
|
|
1688 |
elList.appendChild(elListItem);
|
|
|
1689 |
}
|
|
|
1690 |
if(!this._elList) {
|
|
|
1691 |
var elBody = this._elBody;
|
|
|
1692 |
YAHOO.util.Event.purgeElement(elBody, true);
|
|
|
1693 |
elBody.innerHTML = "";
|
|
|
1694 |
this._elList = elBody.appendChild(elList);
|
|
|
1695 |
}
|
|
|
1696 |
|
|
|
1697 |
this._elBody.style.display = "";
|
|
|
1698 |
};
|
|
|
1699 |
|
|
|
1700 |
/**
|
|
|
1701 |
* Focuses input field.
|
|
|
1702 |
*
|
|
|
1703 |
* @method _focus
|
|
|
1704 |
* @private
|
|
|
1705 |
*/
|
|
|
1706 |
YAHOO.widget.AutoComplete.prototype._focus = function() {
|
|
|
1707 |
// http://developer.mozilla.org/en/docs/index.php?title=Key-navigable_custom_DHTML_widgets
|
|
|
1708 |
var oSelf = this;
|
|
|
1709 |
setTimeout(function() {
|
|
|
1710 |
try {
|
|
|
1711 |
oSelf._elTextbox.focus();
|
|
|
1712 |
}
|
|
|
1713 |
catch(e) {
|
|
|
1714 |
}
|
|
|
1715 |
},0);
|
|
|
1716 |
};
|
|
|
1717 |
|
|
|
1718 |
/**
|
|
|
1719 |
* Enables interval detection for IME support.
|
|
|
1720 |
*
|
|
|
1721 |
* @method _enableIntervalDetection
|
|
|
1722 |
* @private
|
|
|
1723 |
*/
|
|
|
1724 |
YAHOO.widget.AutoComplete.prototype._enableIntervalDetection = function() {
|
|
|
1725 |
var oSelf = this;
|
|
|
1726 |
if(!oSelf._queryInterval && oSelf.queryInterval) {
|
|
|
1727 |
oSelf._queryInterval = setInterval(function() { oSelf._onInterval(); }, oSelf.queryInterval);
|
|
|
1728 |
YAHOO.log("Interval set", "info", this.toString());
|
|
|
1729 |
}
|
|
|
1730 |
};
|
|
|
1731 |
|
|
|
1732 |
/**
|
|
|
1733 |
* Enables interval detection for a less performant but brute force mechanism to
|
|
|
1734 |
* detect input values at an interval set by queryInterval and send queries if
|
|
|
1735 |
* input value has changed. Needed to support right-click+paste or shift+insert
|
|
|
1736 |
* edge cases. Please note that intervals are cleared at the end of each interaction,
|
|
|
1737 |
* so enableIntervalDetection must be called for each new interaction. The
|
|
|
1738 |
* recommended approach is to call it in response to textboxFocusEvent.
|
|
|
1739 |
*
|
|
|
1740 |
* @method enableIntervalDetection
|
|
|
1741 |
*/
|
|
|
1742 |
YAHOO.widget.AutoComplete.prototype.enableIntervalDetection =
|
|
|
1743 |
YAHOO.widget.AutoComplete.prototype._enableIntervalDetection;
|
|
|
1744 |
|
|
|
1745 |
/**
|
|
|
1746 |
* Enables query triggers based on text input detection by intervals (rather
|
|
|
1747 |
* than by key events).
|
|
|
1748 |
*
|
|
|
1749 |
* @method _onInterval
|
|
|
1750 |
* @private
|
|
|
1751 |
*/
|
|
|
1752 |
YAHOO.widget.AutoComplete.prototype._onInterval = function() {
|
|
|
1753 |
var currValue = this._elTextbox.value;
|
|
|
1754 |
var lastValue = this._sLastTextboxValue;
|
|
|
1755 |
if(currValue != lastValue) {
|
|
|
1756 |
this._sLastTextboxValue = currValue;
|
|
|
1757 |
this._sendQuery(currValue);
|
|
|
1758 |
}
|
|
|
1759 |
};
|
|
|
1760 |
|
|
|
1761 |
/**
|
|
|
1762 |
* Cancels text input detection by intervals.
|
|
|
1763 |
*
|
|
|
1764 |
* @method _clearInterval
|
|
|
1765 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
1766 |
* @private
|
|
|
1767 |
*/
|
|
|
1768 |
YAHOO.widget.AutoComplete.prototype._clearInterval = function() {
|
|
|
1769 |
if(this._queryInterval) {
|
|
|
1770 |
clearInterval(this._queryInterval);
|
|
|
1771 |
this._queryInterval = null;
|
|
|
1772 |
YAHOO.log("Interval cleared", "info", this.toString());
|
|
|
1773 |
}
|
|
|
1774 |
};
|
|
|
1775 |
|
|
|
1776 |
/**
|
|
|
1777 |
* Whether or not key is functional or should be ignored. Note that the right
|
|
|
1778 |
* arrow key is NOT an ignored key since it triggers queries for certain intl
|
|
|
1779 |
* charsets.
|
|
|
1780 |
*
|
|
|
1781 |
* @method _isIgnoreKey
|
|
|
1782 |
* @param nKeycode {Number} Code of key pressed.
|
|
|
1783 |
* @return {Boolean} True if key should be ignored, false otherwise.
|
|
|
1784 |
* @private
|
|
|
1785 |
*/
|
|
|
1786 |
YAHOO.widget.AutoComplete.prototype._isIgnoreKey = function(nKeyCode) {
|
|
|
1787 |
if((nKeyCode == 9) || (nKeyCode == 13) || // tab, enter
|
|
|
1788 |
(nKeyCode == 16) || (nKeyCode == 17) || // shift, ctl
|
|
|
1789 |
(nKeyCode >= 18 && nKeyCode <= 20) || // alt, pause/break,caps lock
|
|
|
1790 |
(nKeyCode == 27) || // esc
|
|
|
1791 |
(nKeyCode >= 33 && nKeyCode <= 35) || // page up,page down,end
|
|
|
1792 |
/*(nKeyCode >= 36 && nKeyCode <= 38) || // home,left,up
|
|
|
1793 |
(nKeyCode == 40) || // down*/
|
|
|
1794 |
(nKeyCode >= 36 && nKeyCode <= 40) || // home,left,up, right, down
|
|
|
1795 |
(nKeyCode >= 44 && nKeyCode <= 45) || // print screen,insert
|
|
|
1796 |
(nKeyCode == 229) // Bug 2041973: Korean XP fires 2 keyup events, the key and 229
|
|
|
1797 |
) {
|
|
|
1798 |
return true;
|
|
|
1799 |
}
|
|
|
1800 |
return false;
|
|
|
1801 |
};
|
|
|
1802 |
|
|
|
1803 |
/**
|
|
|
1804 |
* Makes query request to the DataSource.
|
|
|
1805 |
*
|
|
|
1806 |
* @method _sendQuery
|
|
|
1807 |
* @param sQuery {String} Query string.
|
|
|
1808 |
* @private
|
|
|
1809 |
*/
|
|
|
1810 |
YAHOO.widget.AutoComplete.prototype._sendQuery = function(sQuery) {
|
|
|
1811 |
// Widget has been effectively turned off
|
|
|
1812 |
if(this.minQueryLength < 0) {
|
|
|
1813 |
this._toggleContainer(false);
|
|
|
1814 |
YAHOO.log("Property minQueryLength is less than 0", "info", this.toString());
|
|
|
1815 |
return;
|
|
|
1816 |
}
|
|
|
1817 |
// Delimiter has been enabled
|
|
|
1818 |
if(this.delimChar) {
|
|
|
1819 |
var extraction = this._extractQuery(sQuery);
|
|
|
1820 |
// Here is the query itself
|
|
|
1821 |
sQuery = extraction.query;
|
|
|
1822 |
// ...and save the rest of the string for later
|
|
|
1823 |
this._sPastSelections = extraction.previous;
|
|
|
1824 |
}
|
|
|
1825 |
|
|
|
1826 |
// Don't search queries that are too short
|
|
|
1827 |
if((sQuery && (sQuery.length < this.minQueryLength)) || (!sQuery && this.minQueryLength > 0)) {
|
|
|
1828 |
if(this._nDelayID != -1) {
|
|
|
1829 |
clearTimeout(this._nDelayID);
|
|
|
1830 |
}
|
|
|
1831 |
this._toggleContainer(false);
|
|
|
1832 |
YAHOO.log("Query \"" + sQuery + "\" is too short", "info", this.toString());
|
|
|
1833 |
return;
|
|
|
1834 |
}
|
|
|
1835 |
|
|
|
1836 |
sQuery = encodeURIComponent(sQuery);
|
|
|
1837 |
this._nDelayID = -1; // Reset timeout ID because request is being made
|
|
|
1838 |
|
|
|
1839 |
// Subset matching
|
|
|
1840 |
if(this.dataSource.queryMatchSubset || this.queryMatchSubset) { // backward compat
|
|
|
1841 |
var oResponse = this.getSubsetMatches(sQuery);
|
|
|
1842 |
if(oResponse) {
|
|
|
1843 |
this.handleResponse(sQuery, oResponse, {query: sQuery});
|
|
|
1844 |
return;
|
|
|
1845 |
}
|
|
|
1846 |
}
|
|
|
1847 |
|
|
|
1848 |
if(this.dataSource.responseStripAfter) {
|
|
|
1849 |
this.dataSource.doBeforeParseData = this.preparseRawResponse;
|
|
|
1850 |
}
|
|
|
1851 |
if(this.applyLocalFilter) {
|
|
|
1852 |
this.dataSource.doBeforeCallback = this.filterResults;
|
|
|
1853 |
}
|
|
|
1854 |
|
|
|
1855 |
var sRequest = this.generateRequest(sQuery);
|
|
|
1856 |
|
|
|
1857 |
if(sRequest !== undefined) {
|
|
|
1858 |
this.dataRequestEvent.fire(this, sQuery, sRequest);
|
|
|
1859 |
YAHOO.log("Sending query \"" + sRequest + "\"", "info", this.toString());
|
|
|
1860 |
|
|
|
1861 |
this.dataSource.sendRequest(sRequest, {
|
|
|
1862 |
success : this.handleResponse,
|
|
|
1863 |
failure : this.handleResponse,
|
|
|
1864 |
scope : this,
|
|
|
1865 |
argument: {
|
|
|
1866 |
query: sQuery
|
|
|
1867 |
}
|
|
|
1868 |
});
|
|
|
1869 |
}
|
|
|
1870 |
else {
|
|
|
1871 |
this.dataRequestCancelEvent.fire(this, sQuery);
|
|
|
1872 |
YAHOO.log("Canceled query \"" + sQuery + "\"", "info", this.toString());
|
|
|
1873 |
}
|
|
|
1874 |
};
|
|
|
1875 |
|
|
|
1876 |
/**
|
|
|
1877 |
* Populates the given <li> element with return value from formatResult().
|
|
|
1878 |
*
|
|
|
1879 |
* @method _populateListItem
|
|
|
1880 |
* @param elListItem {HTMLElement} The LI element.
|
|
|
1881 |
* @param oResult {Object} The result object.
|
|
|
1882 |
* @param sCurQuery {String} The query string.
|
|
|
1883 |
* @private
|
|
|
1884 |
*/
|
|
|
1885 |
YAHOO.widget.AutoComplete.prototype._populateListItem = function(elListItem, oResult, sQuery) {
|
|
|
1886 |
elListItem.innerHTML = this.formatResult(oResult, sQuery, elListItem._sResultMatch);
|
|
|
1887 |
};
|
|
|
1888 |
|
|
|
1889 |
/**
|
|
|
1890 |
* Populates the array of <li> elements in the container with query
|
|
|
1891 |
* results.
|
|
|
1892 |
*
|
|
|
1893 |
* @method _populateList
|
|
|
1894 |
* @param sQuery {String} Original request.
|
|
|
1895 |
* @param oResponse {Object} <a href="http://developer.yahoo.com/yui/datasource/#ds_oParsedResponse">Response object</a>.
|
|
|
1896 |
* @param oPayload {MIXED} (optional) Additional argument(s)
|
|
|
1897 |
* @private
|
|
|
1898 |
*/
|
|
|
1899 |
YAHOO.widget.AutoComplete.prototype._populateList = function(sQuery, oResponse, oPayload) {
|
|
|
1900 |
// Clear previous timeout
|
|
|
1901 |
if(this._nTypeAheadDelayID != -1) {
|
|
|
1902 |
clearTimeout(this._nTypeAheadDelayID);
|
|
|
1903 |
}
|
|
|
1904 |
|
|
|
1905 |
sQuery = (oPayload && oPayload.query) ? oPayload.query : sQuery;
|
|
|
1906 |
|
|
|
1907 |
// Pass data through abstract method for any transformations
|
|
|
1908 |
var ok = this.doBeforeLoadData(sQuery, oResponse, oPayload);
|
|
|
1909 |
|
|
|
1910 |
// Data is ok
|
|
|
1911 |
if(ok && !oResponse.error) {
|
|
|
1912 |
this.dataReturnEvent.fire(this, sQuery, oResponse.results);
|
|
|
1913 |
|
|
|
1914 |
// Continue only if instance is still active (i.e., user hasn't already moved on)
|
|
|
1915 |
if(this._bFocused) {
|
|
|
1916 |
// Store state for this interaction
|
|
|
1917 |
var sCurQuery = decodeURIComponent(sQuery);
|
|
|
1918 |
this._sCurQuery = sCurQuery;
|
|
|
1919 |
this._bItemSelected = false;
|
|
|
1920 |
|
|
|
1921 |
var allResults = oResponse.results,
|
|
|
1922 |
nItemsToShow = Math.min(allResults.length,this.maxResultsDisplayed),
|
|
|
1923 |
sMatchKey = (this.dataSource.responseSchema.fields) ?
|
|
|
1924 |
(this.dataSource.responseSchema.fields[0].key || this.dataSource.responseSchema.fields[0]) : 0;
|
|
|
1925 |
|
|
|
1926 |
if(nItemsToShow > 0) {
|
|
|
1927 |
// Make sure container and helpers are ready to go
|
|
|
1928 |
if(!this._elList || (this._elList.childNodes.length < nItemsToShow)) {
|
|
|
1929 |
this._initListEl();
|
|
|
1930 |
}
|
|
|
1931 |
this._initContainerHelperEls();
|
|
|
1932 |
|
|
|
1933 |
var allListItemEls = this._elList.childNodes;
|
|
|
1934 |
// Fill items with data from the bottom up
|
|
|
1935 |
for(var i = nItemsToShow-1; i >= 0; i--) {
|
|
|
1936 |
var elListItem = allListItemEls[i],
|
|
|
1937 |
oResult = allResults[i];
|
|
|
1938 |
|
|
|
1939 |
// Backward compatibility
|
|
|
1940 |
if(this.resultTypeList) {
|
|
|
1941 |
// Results need to be converted back to an array
|
|
|
1942 |
var aResult = [];
|
|
|
1943 |
// Match key is first
|
|
|
1944 |
aResult[0] = (YAHOO.lang.isString(oResult)) ? oResult : oResult[sMatchKey] || oResult[this.key];
|
|
|
1945 |
// Add additional data to the result array
|
|
|
1946 |
var fields = this.dataSource.responseSchema.fields;
|
|
|
1947 |
if(YAHOO.lang.isArray(fields) && (fields.length > 1)) {
|
|
|
1948 |
for(var k=1, len=fields.length; k<len; k++) {
|
|
|
1949 |
aResult[aResult.length] = oResult[fields[k].key || fields[k]];
|
|
|
1950 |
}
|
|
|
1951 |
}
|
|
|
1952 |
// No specific fields defined, so pass along entire data object
|
|
|
1953 |
else {
|
|
|
1954 |
// Already an array
|
|
|
1955 |
if(YAHOO.lang.isArray(oResult)) {
|
|
|
1956 |
aResult = oResult;
|
|
|
1957 |
}
|
|
|
1958 |
// Simple string
|
|
|
1959 |
else if(YAHOO.lang.isString(oResult)) {
|
|
|
1960 |
aResult = [oResult];
|
|
|
1961 |
}
|
|
|
1962 |
// Object
|
|
|
1963 |
else {
|
|
|
1964 |
aResult[1] = oResult;
|
|
|
1965 |
}
|
|
|
1966 |
}
|
|
|
1967 |
oResult = aResult;
|
|
|
1968 |
}
|
|
|
1969 |
|
|
|
1970 |
// The matching value, including backward compatibility for array format and safety net
|
|
|
1971 |
elListItem._sResultMatch = (YAHOO.lang.isString(oResult)) ? oResult : (YAHOO.lang.isArray(oResult)) ? oResult[0] : (oResult[sMatchKey] || "");
|
|
|
1972 |
elListItem._oResultData = oResult; // Additional data
|
|
|
1973 |
this._populateListItem(elListItem, oResult, sCurQuery);
|
|
|
1974 |
elListItem.style.display = "";
|
|
|
1975 |
}
|
|
|
1976 |
|
|
|
1977 |
// Clear out extraneous items
|
|
|
1978 |
if(nItemsToShow < allListItemEls.length) {
|
|
|
1979 |
var extraListItem;
|
|
|
1980 |
for(var j = allListItemEls.length-1; j >= nItemsToShow; j--) {
|
|
|
1981 |
extraListItem = allListItemEls[j];
|
|
|
1982 |
extraListItem.style.display = "none";
|
|
|
1983 |
}
|
|
|
1984 |
}
|
|
|
1985 |
|
|
|
1986 |
this._nDisplayedItems = nItemsToShow;
|
|
|
1987 |
|
|
|
1988 |
this.containerPopulateEvent.fire(this, sQuery, allResults);
|
|
|
1989 |
|
|
|
1990 |
// Highlight the first item
|
|
|
1991 |
if(this.autoHighlight) {
|
|
|
1992 |
var elFirstListItem = this._elList.firstChild;
|
|
|
1993 |
this._toggleHighlight(elFirstListItem,"to");
|
|
|
1994 |
this.itemArrowToEvent.fire(this, elFirstListItem);
|
|
|
1995 |
YAHOO.log("Arrowed to first item", "info", this.toString());
|
|
|
1996 |
this._typeAhead(elFirstListItem,sQuery);
|
|
|
1997 |
}
|
|
|
1998 |
// Unhighlight any previous time
|
|
|
1999 |
else {
|
|
|
2000 |
this._toggleHighlight(this._elCurListItem,"from");
|
|
|
2001 |
}
|
|
|
2002 |
|
|
|
2003 |
// Pre-expansion stuff
|
|
|
2004 |
ok = this._doBeforeExpandContainer(this._elTextbox, this._elContainer, sQuery, allResults);
|
|
|
2005 |
|
|
|
2006 |
// Expand the container
|
|
|
2007 |
this._toggleContainer(ok);
|
|
|
2008 |
}
|
|
|
2009 |
else {
|
|
|
2010 |
this._toggleContainer(false);
|
|
|
2011 |
}
|
|
|
2012 |
|
|
|
2013 |
YAHOO.log("Container populated with " + nItemsToShow + " list items", "info", this.toString());
|
|
|
2014 |
return;
|
|
|
2015 |
}
|
|
|
2016 |
}
|
|
|
2017 |
// Error
|
|
|
2018 |
else {
|
|
|
2019 |
this.dataErrorEvent.fire(this, sQuery, oResponse);
|
|
|
2020 |
}
|
|
|
2021 |
|
|
|
2022 |
YAHOO.log("Could not populate list", "info", this.toString());
|
|
|
2023 |
};
|
|
|
2024 |
|
|
|
2025 |
/**
|
|
|
2026 |
* Called before container expands, by default snaps container to the
|
|
|
2027 |
* bottom-left corner of the input element, then calls public overrideable method.
|
|
|
2028 |
*
|
|
|
2029 |
* @method _doBeforeExpandContainer
|
|
|
2030 |
* @param elTextbox {HTMLElement} The text input box.
|
|
|
2031 |
* @param elContainer {HTMLElement} The container element.
|
|
|
2032 |
* @param sQuery {String} The query string.
|
|
|
2033 |
* @param aResults {Object[]} An array of query results.
|
|
|
2034 |
* @return {Boolean} Return true to continue expanding container, false to cancel the expand.
|
|
|
2035 |
* @private
|
|
|
2036 |
*/
|
|
|
2037 |
YAHOO.widget.AutoComplete.prototype._doBeforeExpandContainer = function(elTextbox, elContainer, sQuery, aResults) {
|
|
|
2038 |
if(this.autoSnapContainer) {
|
|
|
2039 |
this.snapContainer();
|
|
|
2040 |
}
|
|
|
2041 |
|
|
|
2042 |
return this.doBeforeExpandContainer(elTextbox, elContainer, sQuery, aResults);
|
|
|
2043 |
};
|
|
|
2044 |
|
|
|
2045 |
/**
|
|
|
2046 |
* When forceSelection is true and the user attempts
|
|
|
2047 |
* leave the text input box without selecting an item from the query results,
|
|
|
2048 |
* the user selection is cleared.
|
|
|
2049 |
*
|
|
|
2050 |
* @method _clearSelection
|
|
|
2051 |
* @private
|
|
|
2052 |
*/
|
|
|
2053 |
YAHOO.widget.AutoComplete.prototype._clearSelection = function() {
|
|
|
2054 |
var extraction = (this.delimChar) ? this._extractQuery(this._elTextbox.value) :
|
|
|
2055 |
{previous:"",query:this._elTextbox.value};
|
|
|
2056 |
this._elTextbox.value = extraction.previous;
|
|
|
2057 |
this.selectionEnforceEvent.fire(this, extraction.query);
|
|
|
2058 |
YAHOO.log("Selection enforced", "info", this.toString());
|
|
|
2059 |
};
|
|
|
2060 |
|
|
|
2061 |
/**
|
|
|
2062 |
* Whether or not user-typed value in the text input box matches any of the
|
|
|
2063 |
* query results.
|
|
|
2064 |
*
|
|
|
2065 |
* @method _textMatchesOption
|
|
|
2066 |
* @return {HTMLElement} Matching list item element if user-input text matches
|
|
|
2067 |
* a result, null otherwise.
|
|
|
2068 |
* @private
|
|
|
2069 |
*/
|
|
|
2070 |
YAHOO.widget.AutoComplete.prototype._textMatchesOption = function() {
|
|
|
2071 |
var elMatch = null;
|
|
|
2072 |
|
|
|
2073 |
for(var i=0; i<this._nDisplayedItems; i++) {
|
|
|
2074 |
var elListItem = this._elList.childNodes[i];
|
|
|
2075 |
var sMatch = ("" + elListItem._sResultMatch).toLowerCase();
|
|
|
2076 |
if(sMatch == this._sCurQuery.toLowerCase()) {
|
|
|
2077 |
elMatch = elListItem;
|
|
|
2078 |
break;
|
|
|
2079 |
}
|
|
|
2080 |
}
|
|
|
2081 |
return(elMatch);
|
|
|
2082 |
};
|
|
|
2083 |
|
|
|
2084 |
/**
|
|
|
2085 |
* Updates in the text input box with the first query result as the user types,
|
|
|
2086 |
* selecting the substring that the user has not typed.
|
|
|
2087 |
*
|
|
|
2088 |
* @method _typeAhead
|
|
|
2089 |
* @param elListItem {HTMLElement} The <li> element item whose data populates the input field.
|
|
|
2090 |
* @param sQuery {String} Query string.
|
|
|
2091 |
* @private
|
|
|
2092 |
*/
|
|
|
2093 |
YAHOO.widget.AutoComplete.prototype._typeAhead = function(elListItem, sQuery) {
|
|
|
2094 |
// Don't typeAhead if turned off or is backspace
|
|
|
2095 |
if(!this.typeAhead || (this._nKeyCode == 8)) {
|
|
|
2096 |
return;
|
|
|
2097 |
}
|
|
|
2098 |
|
|
|
2099 |
var oSelf = this,
|
|
|
2100 |
elTextbox = this._elTextbox;
|
|
|
2101 |
|
|
|
2102 |
// Only if text selection is supported
|
|
|
2103 |
if(elTextbox.setSelectionRange || elTextbox.createTextRange) {
|
|
|
2104 |
// Set and store timeout for this typeahead
|
|
|
2105 |
this._nTypeAheadDelayID = setTimeout(function() {
|
|
|
2106 |
// Select the portion of text that the user has not typed
|
|
|
2107 |
var nStart = elTextbox.value.length; // any saved queries plus what user has typed
|
|
|
2108 |
oSelf._updateValue(elListItem);
|
|
|
2109 |
var nEnd = elTextbox.value.length;
|
|
|
2110 |
oSelf._selectText(elTextbox,nStart,nEnd);
|
|
|
2111 |
var sPrefill = elTextbox.value.substr(nStart,nEnd);
|
|
|
2112 |
// Bug 2528552: Store as a selection
|
|
|
2113 |
oSelf._sCurQuery = elListItem._sResultMatch;
|
|
|
2114 |
oSelf.typeAheadEvent.fire(oSelf,sQuery,sPrefill);
|
|
|
2115 |
YAHOO.log("Typeahead occured with prefill string \"" + sPrefill + "\"", "info", oSelf.toString());
|
|
|
2116 |
},(this.typeAheadDelay*1000));
|
|
|
2117 |
}
|
|
|
2118 |
};
|
|
|
2119 |
|
|
|
2120 |
/**
|
|
|
2121 |
* Selects text in the input field.
|
|
|
2122 |
*
|
|
|
2123 |
* @method _selectText
|
|
|
2124 |
* @param elTextbox {HTMLElement} Text input box element in which to select text.
|
|
|
2125 |
* @param nStart {Number} Starting index of text string to select.
|
|
|
2126 |
* @param nEnd {Number} Ending index of text selection.
|
|
|
2127 |
* @private
|
|
|
2128 |
*/
|
|
|
2129 |
YAHOO.widget.AutoComplete.prototype._selectText = function(elTextbox, nStart, nEnd) {
|
|
|
2130 |
if(elTextbox.setSelectionRange) { // For Mozilla
|
|
|
2131 |
elTextbox.setSelectionRange(nStart,nEnd);
|
|
|
2132 |
}
|
|
|
2133 |
else if(elTextbox.createTextRange) { // For IE
|
|
|
2134 |
var oTextRange = elTextbox.createTextRange();
|
|
|
2135 |
oTextRange.moveStart("character", nStart);
|
|
|
2136 |
oTextRange.moveEnd("character", nEnd-elTextbox.value.length);
|
|
|
2137 |
oTextRange.select();
|
|
|
2138 |
}
|
|
|
2139 |
else {
|
|
|
2140 |
elTextbox.select();
|
|
|
2141 |
}
|
|
|
2142 |
};
|
|
|
2143 |
|
|
|
2144 |
/**
|
|
|
2145 |
* Extracts rightmost query from delimited string.
|
|
|
2146 |
*
|
|
|
2147 |
* @method _extractQuery
|
|
|
2148 |
* @param sQuery {String} String to parse
|
|
|
2149 |
* @return {Object} Object literal containing properties "query" and "previous".
|
|
|
2150 |
* @private
|
|
|
2151 |
*/
|
|
|
2152 |
YAHOO.widget.AutoComplete.prototype._extractQuery = function(sQuery) {
|
|
|
2153 |
var aDelimChar = this.delimChar,
|
|
|
2154 |
nDelimIndex = -1,
|
|
|
2155 |
nNewIndex, nQueryStart,
|
|
|
2156 |
i = aDelimChar.length-1,
|
|
|
2157 |
sPrevious;
|
|
|
2158 |
|
|
|
2159 |
// Loop through all possible delimiters and find the rightmost one in the query
|
|
|
2160 |
// A " " may be a false positive if they are defined as delimiters AND
|
|
|
2161 |
// are used to separate delimited queries
|
|
|
2162 |
for(; i >= 0; i--) {
|
|
|
2163 |
nNewIndex = sQuery.lastIndexOf(aDelimChar[i]);
|
|
|
2164 |
if(nNewIndex > nDelimIndex) {
|
|
|
2165 |
nDelimIndex = nNewIndex;
|
|
|
2166 |
}
|
|
|
2167 |
}
|
|
|
2168 |
// If we think the last delimiter is a space (" "), make sure it is NOT
|
|
|
2169 |
// a false positive by also checking the char directly before it
|
|
|
2170 |
if(aDelimChar[i] == " ") {
|
|
|
2171 |
for (var j = aDelimChar.length-1; j >= 0; j--) {
|
|
|
2172 |
if(sQuery[nDelimIndex - 1] == aDelimChar[j]) {
|
|
|
2173 |
nDelimIndex--;
|
|
|
2174 |
break;
|
|
|
2175 |
}
|
|
|
2176 |
}
|
|
|
2177 |
}
|
|
|
2178 |
// A delimiter has been found in the query so extract the latest query from past selections
|
|
|
2179 |
if(nDelimIndex > -1) {
|
|
|
2180 |
nQueryStart = nDelimIndex + 1;
|
|
|
2181 |
// Trim any white space from the beginning...
|
|
|
2182 |
while(sQuery.charAt(nQueryStart) == " ") {
|
|
|
2183 |
nQueryStart += 1;
|
|
|
2184 |
}
|
|
|
2185 |
// ...and save the rest of the string for later
|
|
|
2186 |
sPrevious = sQuery.substring(0,nQueryStart);
|
|
|
2187 |
// Here is the query itself
|
|
|
2188 |
sQuery = sQuery.substr(nQueryStart);
|
|
|
2189 |
}
|
|
|
2190 |
// No delimiter found in the query, so there are no selections from past queries
|
|
|
2191 |
else {
|
|
|
2192 |
sPrevious = "";
|
|
|
2193 |
}
|
|
|
2194 |
|
|
|
2195 |
return {
|
|
|
2196 |
previous: sPrevious,
|
|
|
2197 |
query: sQuery
|
|
|
2198 |
};
|
|
|
2199 |
};
|
|
|
2200 |
|
|
|
2201 |
/**
|
|
|
2202 |
* Syncs results container with its helpers.
|
|
|
2203 |
*
|
|
|
2204 |
* @method _toggleContainerHelpers
|
|
|
2205 |
* @param bShow {Boolean} True if container is expanded, false if collapsed
|
|
|
2206 |
* @private
|
|
|
2207 |
*/
|
|
|
2208 |
YAHOO.widget.AutoComplete.prototype._toggleContainerHelpers = function(bShow) {
|
|
|
2209 |
var width = this._elContent.offsetWidth + "px";
|
|
|
2210 |
var height = this._elContent.offsetHeight + "px";
|
|
|
2211 |
|
|
|
2212 |
if(this.useIFrame && this._elIFrame) {
|
|
|
2213 |
var elIFrame = this._elIFrame;
|
|
|
2214 |
if(bShow) {
|
|
|
2215 |
elIFrame.style.width = width;
|
|
|
2216 |
elIFrame.style.height = height;
|
|
|
2217 |
elIFrame.style.padding = "";
|
|
|
2218 |
YAHOO.log("Iframe expanded", "info", this.toString());
|
|
|
2219 |
}
|
|
|
2220 |
else {
|
|
|
2221 |
elIFrame.style.width = 0;
|
|
|
2222 |
elIFrame.style.height = 0;
|
|
|
2223 |
elIFrame.style.padding = 0;
|
|
|
2224 |
YAHOO.log("Iframe collapsed", "info", this.toString());
|
|
|
2225 |
}
|
|
|
2226 |
}
|
|
|
2227 |
if(this.useShadow && this._elShadow) {
|
|
|
2228 |
var elShadow = this._elShadow;
|
|
|
2229 |
if(bShow) {
|
|
|
2230 |
elShadow.style.width = width;
|
|
|
2231 |
elShadow.style.height = height;
|
|
|
2232 |
YAHOO.log("Shadow expanded", "info", this.toString());
|
|
|
2233 |
}
|
|
|
2234 |
else {
|
|
|
2235 |
elShadow.style.width = 0;
|
|
|
2236 |
elShadow.style.height = 0;
|
|
|
2237 |
YAHOO.log("Shadow collapsed", "info", this.toString());
|
|
|
2238 |
}
|
|
|
2239 |
}
|
|
|
2240 |
};
|
|
|
2241 |
|
|
|
2242 |
/**
|
|
|
2243 |
* Animates expansion or collapse of the container.
|
|
|
2244 |
*
|
|
|
2245 |
* @method _toggleContainer
|
|
|
2246 |
* @param bShow {Boolean} True if container should be expanded, false if container should be collapsed
|
|
|
2247 |
* @private
|
|
|
2248 |
*/
|
|
|
2249 |
YAHOO.widget.AutoComplete.prototype._toggleContainer = function(bShow) {
|
|
|
2250 |
YAHOO.log("Toggling container " + ((bShow) ? "open" : "closed"), "info", this.toString());
|
|
|
2251 |
|
|
|
2252 |
var elContainer = this._elContainer;
|
|
|
2253 |
|
|
|
2254 |
// If implementer has container always open and it's already open, don't mess with it
|
|
|
2255 |
// Container is initialized with display "none" so it may need to be shown first time through
|
|
|
2256 |
if(this.alwaysShowContainer && this._bContainerOpen) {
|
|
|
2257 |
return;
|
|
|
2258 |
}
|
|
|
2259 |
|
|
|
2260 |
// Reset states
|
|
|
2261 |
if(!bShow) {
|
|
|
2262 |
this._toggleHighlight(this._elCurListItem,"from");
|
|
|
2263 |
this._nDisplayedItems = 0;
|
|
|
2264 |
this._sCurQuery = null;
|
|
|
2265 |
|
|
|
2266 |
// Container is already closed, so don't bother with changing the UI
|
|
|
2267 |
if(this._elContent.style.display == "none") {
|
|
|
2268 |
return;
|
|
|
2269 |
}
|
|
|
2270 |
}
|
|
|
2271 |
|
|
|
2272 |
// If animation is enabled...
|
|
|
2273 |
var oAnim = this._oAnim;
|
|
|
2274 |
if(oAnim && oAnim.getEl() && (this.animHoriz || this.animVert)) {
|
|
|
2275 |
if(oAnim.isAnimated()) {
|
|
|
2276 |
oAnim.stop(true);
|
|
|
2277 |
}
|
|
|
2278 |
|
|
|
2279 |
// Clone container to grab current size offscreen
|
|
|
2280 |
var oClone = this._elContent.cloneNode(true);
|
|
|
2281 |
elContainer.appendChild(oClone);
|
|
|
2282 |
oClone.style.top = "-9000px";
|
|
|
2283 |
oClone.style.width = "";
|
|
|
2284 |
oClone.style.height = "";
|
|
|
2285 |
oClone.style.display = "";
|
|
|
2286 |
|
|
|
2287 |
// Current size of the container is the EXPANDED size
|
|
|
2288 |
var wExp = oClone.offsetWidth;
|
|
|
2289 |
var hExp = oClone.offsetHeight;
|
|
|
2290 |
|
|
|
2291 |
// Calculate COLLAPSED sizes based on horiz and vert anim
|
|
|
2292 |
var wColl = (this.animHoriz) ? 0 : wExp;
|
|
|
2293 |
var hColl = (this.animVert) ? 0 : hExp;
|
|
|
2294 |
|
|
|
2295 |
// Set animation sizes
|
|
|
2296 |
oAnim.attributes = (bShow) ?
|
|
|
2297 |
{width: { to: wExp }, height: { to: hExp }} :
|
|
|
2298 |
{width: { to: wColl}, height: { to: hColl }};
|
|
|
2299 |
|
|
|
2300 |
// If opening anew, set to a collapsed size...
|
|
|
2301 |
if(bShow && !this._bContainerOpen) {
|
|
|
2302 |
this._elContent.style.width = wColl+"px";
|
|
|
2303 |
this._elContent.style.height = hColl+"px";
|
|
|
2304 |
}
|
|
|
2305 |
// Else, set it to its last known size.
|
|
|
2306 |
else {
|
|
|
2307 |
this._elContent.style.width = wExp+"px";
|
|
|
2308 |
this._elContent.style.height = hExp+"px";
|
|
|
2309 |
}
|
|
|
2310 |
|
|
|
2311 |
elContainer.removeChild(oClone);
|
|
|
2312 |
oClone = null;
|
|
|
2313 |
|
|
|
2314 |
var oSelf = this;
|
|
|
2315 |
var onAnimComplete = function() {
|
|
|
2316 |
// Finish the collapse
|
|
|
2317 |
oAnim.onComplete.unsubscribeAll();
|
|
|
2318 |
|
|
|
2319 |
if(bShow) {
|
|
|
2320 |
oSelf._toggleContainerHelpers(true);
|
|
|
2321 |
oSelf._bContainerOpen = bShow;
|
|
|
2322 |
oSelf.containerExpandEvent.fire(oSelf);
|
|
|
2323 |
YAHOO.log("Container expanded", "info", oSelf.toString());
|
|
|
2324 |
}
|
|
|
2325 |
else {
|
|
|
2326 |
oSelf._elContent.style.display = "none";
|
|
|
2327 |
oSelf._bContainerOpen = bShow;
|
|
|
2328 |
oSelf.containerCollapseEvent.fire(oSelf);
|
|
|
2329 |
YAHOO.log("Container collapsed", "info", oSelf.toString());
|
|
|
2330 |
}
|
|
|
2331 |
};
|
|
|
2332 |
|
|
|
2333 |
// Display container and animate it
|
|
|
2334 |
this._toggleContainerHelpers(false); // Bug 1424486: Be early to hide, late to show;
|
|
|
2335 |
this._elContent.style.display = "";
|
|
|
2336 |
oAnim.onComplete.subscribe(onAnimComplete);
|
|
|
2337 |
oAnim.animate();
|
|
|
2338 |
}
|
|
|
2339 |
// Else don't animate, just show or hide
|
|
|
2340 |
else {
|
|
|
2341 |
if(bShow) {
|
|
|
2342 |
this._elContent.style.display = "";
|
|
|
2343 |
this._toggleContainerHelpers(true);
|
|
|
2344 |
this._bContainerOpen = bShow;
|
|
|
2345 |
this.containerExpandEvent.fire(this);
|
|
|
2346 |
YAHOO.log("Container expanded", "info", this.toString());
|
|
|
2347 |
}
|
|
|
2348 |
else {
|
|
|
2349 |
this._toggleContainerHelpers(false);
|
|
|
2350 |
this._elContent.style.display = "none";
|
|
|
2351 |
this._bContainerOpen = bShow;
|
|
|
2352 |
this.containerCollapseEvent.fire(this);
|
|
|
2353 |
YAHOO.log("Container collapsed", "info", this.toString());
|
|
|
2354 |
}
|
|
|
2355 |
}
|
|
|
2356 |
|
|
|
2357 |
};
|
|
|
2358 |
|
|
|
2359 |
/**
|
|
|
2360 |
* Toggles the highlight on or off for an item in the container, and also cleans
|
|
|
2361 |
* up highlighting of any previous item.
|
|
|
2362 |
*
|
|
|
2363 |
* @method _toggleHighlight
|
|
|
2364 |
* @param elNewListItem {HTMLElement} The <li> element item to receive highlight behavior.
|
|
|
2365 |
* @param sType {String} Type "mouseover" will toggle highlight on, and "mouseout" will toggle highlight off.
|
|
|
2366 |
* @private
|
|
|
2367 |
*/
|
|
|
2368 |
YAHOO.widget.AutoComplete.prototype._toggleHighlight = function(elNewListItem, sType) {
|
|
|
2369 |
if(elNewListItem) {
|
|
|
2370 |
var sHighlight = this.highlightClassName;
|
|
|
2371 |
if(this._elCurListItem) {
|
|
|
2372 |
// Remove highlight from old item
|
|
|
2373 |
YAHOO.util.Dom.removeClass(this._elCurListItem, sHighlight);
|
|
|
2374 |
this._elCurListItem = null;
|
|
|
2375 |
}
|
|
|
2376 |
|
|
|
2377 |
if((sType == "to") && sHighlight) {
|
|
|
2378 |
// Apply highlight to new item
|
|
|
2379 |
YAHOO.util.Dom.addClass(elNewListItem, sHighlight);
|
|
|
2380 |
this._elCurListItem = elNewListItem;
|
|
|
2381 |
}
|
|
|
2382 |
}
|
|
|
2383 |
};
|
|
|
2384 |
|
|
|
2385 |
/**
|
|
|
2386 |
* Toggles the pre-highlight on or off for an item in the container, and also cleans
|
|
|
2387 |
* up pre-highlighting of any previous item.
|
|
|
2388 |
*
|
|
|
2389 |
* @method _togglePrehighlight
|
|
|
2390 |
* @param elNewListItem {HTMLElement} The <li> element item to receive highlight behavior.
|
|
|
2391 |
* @param sType {String} Type "mouseover" will toggle highlight on, and "mouseout" will toggle highlight off.
|
|
|
2392 |
* @private
|
|
|
2393 |
*/
|
|
|
2394 |
YAHOO.widget.AutoComplete.prototype._togglePrehighlight = function(elNewListItem, sType) {
|
|
|
2395 |
var sPrehighlight = this.prehighlightClassName;
|
|
|
2396 |
|
|
|
2397 |
if(this._elCurPrehighlightItem) {
|
|
|
2398 |
YAHOO.util.Dom.removeClass(this._elCurPrehighlightItem, sPrehighlight);
|
|
|
2399 |
}
|
|
|
2400 |
if(elNewListItem == this._elCurListItem) {
|
|
|
2401 |
return;
|
|
|
2402 |
}
|
|
|
2403 |
|
|
|
2404 |
if((sType == "mouseover") && sPrehighlight) {
|
|
|
2405 |
// Apply prehighlight to new item
|
|
|
2406 |
YAHOO.util.Dom.addClass(elNewListItem, sPrehighlight);
|
|
|
2407 |
this._elCurPrehighlightItem = elNewListItem;
|
|
|
2408 |
}
|
|
|
2409 |
else {
|
|
|
2410 |
// Remove prehighlight from old item
|
|
|
2411 |
YAHOO.util.Dom.removeClass(elNewListItem, sPrehighlight);
|
|
|
2412 |
}
|
|
|
2413 |
};
|
|
|
2414 |
|
|
|
2415 |
/**
|
|
|
2416 |
* Updates the text input box value with selected query result. If a delimiter
|
|
|
2417 |
* has been defined, then the value gets appended with the delimiter.
|
|
|
2418 |
*
|
|
|
2419 |
* @method _updateValue
|
|
|
2420 |
* @param elListItem {HTMLElement} The <li> element item with which to update the value.
|
|
|
2421 |
* @private
|
|
|
2422 |
*/
|
|
|
2423 |
YAHOO.widget.AutoComplete.prototype._updateValue = function(elListItem) {
|
|
|
2424 |
if(!this.suppressInputUpdate) {
|
|
|
2425 |
var elTextbox = this._elTextbox;
|
|
|
2426 |
var sDelimChar = (this.delimChar) ? (this.delimChar[0] || this.delimChar) : null;
|
|
|
2427 |
var sResultMatch = elListItem._sResultMatch;
|
|
|
2428 |
|
|
|
2429 |
// Calculate the new value
|
|
|
2430 |
var sNewValue = "";
|
|
|
2431 |
if(sDelimChar) {
|
|
|
2432 |
// Preserve selections from past queries
|
|
|
2433 |
sNewValue = this._sPastSelections;
|
|
|
2434 |
// Add new selection plus delimiter
|
|
|
2435 |
sNewValue += sResultMatch + sDelimChar;
|
|
|
2436 |
if(sDelimChar != " ") {
|
|
|
2437 |
sNewValue += " ";
|
|
|
2438 |
}
|
|
|
2439 |
}
|
|
|
2440 |
else {
|
|
|
2441 |
sNewValue = sResultMatch;
|
|
|
2442 |
}
|
|
|
2443 |
|
|
|
2444 |
// Update input field
|
|
|
2445 |
elTextbox.value = sNewValue;
|
|
|
2446 |
|
|
|
2447 |
// Scroll to bottom of textarea if necessary
|
|
|
2448 |
if(elTextbox.type == "textarea") {
|
|
|
2449 |
elTextbox.scrollTop = elTextbox.scrollHeight;
|
|
|
2450 |
}
|
|
|
2451 |
|
|
|
2452 |
// Move cursor to end
|
|
|
2453 |
var end = elTextbox.value.length;
|
|
|
2454 |
this._selectText(elTextbox,end,end);
|
|
|
2455 |
|
|
|
2456 |
this._elCurListItem = elListItem;
|
|
|
2457 |
}
|
|
|
2458 |
};
|
|
|
2459 |
|
|
|
2460 |
/**
|
|
|
2461 |
* Selects a result item from the container
|
|
|
2462 |
*
|
|
|
2463 |
* @method _selectItem
|
|
|
2464 |
* @param elListItem {HTMLElement} The selected <li> element item.
|
|
|
2465 |
* @private
|
|
|
2466 |
*/
|
|
|
2467 |
YAHOO.widget.AutoComplete.prototype._selectItem = function(elListItem) {
|
|
|
2468 |
this._bItemSelected = true;
|
|
|
2469 |
this._updateValue(elListItem);
|
|
|
2470 |
this._sPastSelections = this._elTextbox.value;
|
|
|
2471 |
this._clearInterval();
|
|
|
2472 |
this.itemSelectEvent.fire(this, elListItem, elListItem._oResultData);
|
|
|
2473 |
YAHOO.log("Item selected: " + YAHOO.lang.dump(elListItem._oResultData), "info", this.toString());
|
|
|
2474 |
this._toggleContainer(false);
|
|
|
2475 |
};
|
|
|
2476 |
|
|
|
2477 |
/**
|
|
|
2478 |
* If an item is highlighted in the container, the right arrow key jumps to the
|
|
|
2479 |
* end of the textbox and selects the highlighted item, otherwise the container
|
|
|
2480 |
* is closed.
|
|
|
2481 |
*
|
|
|
2482 |
* @method _jumpSelection
|
|
|
2483 |
* @private
|
|
|
2484 |
*/
|
|
|
2485 |
YAHOO.widget.AutoComplete.prototype._jumpSelection = function() {
|
|
|
2486 |
if(this._elCurListItem) {
|
|
|
2487 |
this._selectItem(this._elCurListItem);
|
|
|
2488 |
}
|
|
|
2489 |
else {
|
|
|
2490 |
this._toggleContainer(false);
|
|
|
2491 |
}
|
|
|
2492 |
};
|
|
|
2493 |
|
|
|
2494 |
/**
|
|
|
2495 |
* Triggered by up and down arrow keys, changes the current highlighted
|
|
|
2496 |
* <li> element item. Scrolls container if necessary.
|
|
|
2497 |
*
|
|
|
2498 |
* @method _moveSelection
|
|
|
2499 |
* @param nKeyCode {Number} Code of key pressed.
|
|
|
2500 |
* @private
|
|
|
2501 |
*/
|
|
|
2502 |
YAHOO.widget.AutoComplete.prototype._moveSelection = function(nKeyCode) {
|
|
|
2503 |
if(this._bContainerOpen) {
|
|
|
2504 |
// Determine current item's id number
|
|
|
2505 |
var elCurListItem = this._elCurListItem,
|
|
|
2506 |
nCurItemIndex = -1;
|
|
|
2507 |
|
|
|
2508 |
if(elCurListItem) {
|
|
|
2509 |
nCurItemIndex = elCurListItem._nItemIndex;
|
|
|
2510 |
}
|
|
|
2511 |
|
|
|
2512 |
var nNewItemIndex = (nKeyCode == 40) ?
|
|
|
2513 |
(nCurItemIndex + 1) : (nCurItemIndex - 1);
|
|
|
2514 |
|
|
|
2515 |
// Out of bounds
|
|
|
2516 |
if(nNewItemIndex < -2 || nNewItemIndex >= this._nDisplayedItems) {
|
|
|
2517 |
return;
|
|
|
2518 |
}
|
|
|
2519 |
|
|
|
2520 |
if(elCurListItem) {
|
|
|
2521 |
// Unhighlight current item
|
|
|
2522 |
this._toggleHighlight(elCurListItem, "from");
|
|
|
2523 |
this.itemArrowFromEvent.fire(this, elCurListItem);
|
|
|
2524 |
YAHOO.log("Item arrowed from: " + elCurListItem._nItemIndex, "info", this.toString());
|
|
|
2525 |
}
|
|
|
2526 |
if(nNewItemIndex == -1) {
|
|
|
2527 |
// Go back to query (remove type-ahead string)
|
|
|
2528 |
if(this.delimChar) {
|
|
|
2529 |
this._elTextbox.value = this._sPastSelections + this._sCurQuery;
|
|
|
2530 |
}
|
|
|
2531 |
else {
|
|
|
2532 |
this._elTextbox.value = this._sCurQuery;
|
|
|
2533 |
}
|
|
|
2534 |
return;
|
|
|
2535 |
}
|
|
|
2536 |
if(nNewItemIndex == -2) {
|
|
|
2537 |
// Close container
|
|
|
2538 |
this._toggleContainer(false);
|
|
|
2539 |
return;
|
|
|
2540 |
}
|
|
|
2541 |
|
|
|
2542 |
var elNewListItem = this._elList.childNodes[nNewItemIndex],
|
|
|
2543 |
|
|
|
2544 |
// Scroll the container if necessary
|
|
|
2545 |
elContent = this._elContent,
|
|
|
2546 |
sOF = YAHOO.util.Dom.getStyle(elContent,"overflow"),
|
|
|
2547 |
sOFY = YAHOO.util.Dom.getStyle(elContent,"overflowY"),
|
|
|
2548 |
scrollOn = ((sOF == "auto") || (sOF == "scroll") || (sOFY == "auto") || (sOFY == "scroll"));
|
|
|
2549 |
if(scrollOn && (nNewItemIndex > -1) &&
|
|
|
2550 |
(nNewItemIndex < this._nDisplayedItems)) {
|
|
|
2551 |
// User is keying down
|
|
|
2552 |
if(nKeyCode == 40) {
|
|
|
2553 |
// Bottom of selected item is below scroll area...
|
|
|
2554 |
if((elNewListItem.offsetTop+elNewListItem.offsetHeight) > (elContent.scrollTop + elContent.offsetHeight)) {
|
|
|
2555 |
// Set bottom of scroll area to bottom of selected item
|
|
|
2556 |
elContent.scrollTop = (elNewListItem.offsetTop+elNewListItem.offsetHeight) - elContent.offsetHeight;
|
|
|
2557 |
}
|
|
|
2558 |
// Bottom of selected item is above scroll area...
|
|
|
2559 |
else if((elNewListItem.offsetTop+elNewListItem.offsetHeight) < elContent.scrollTop) {
|
|
|
2560 |
// Set top of selected item to top of scroll area
|
|
|
2561 |
elContent.scrollTop = elNewListItem.offsetTop;
|
|
|
2562 |
|
|
|
2563 |
}
|
|
|
2564 |
}
|
|
|
2565 |
// User is keying up
|
|
|
2566 |
else {
|
|
|
2567 |
// Top of selected item is above scroll area
|
|
|
2568 |
if(elNewListItem.offsetTop < elContent.scrollTop) {
|
|
|
2569 |
// Set top of scroll area to top of selected item
|
|
|
2570 |
this._elContent.scrollTop = elNewListItem.offsetTop;
|
|
|
2571 |
}
|
|
|
2572 |
// Top of selected item is below scroll area
|
|
|
2573 |
else if(elNewListItem.offsetTop > (elContent.scrollTop + elContent.offsetHeight)) {
|
|
|
2574 |
// Set bottom of selected item to bottom of scroll area
|
|
|
2575 |
this._elContent.scrollTop = (elNewListItem.offsetTop+elNewListItem.offsetHeight) - elContent.offsetHeight;
|
|
|
2576 |
}
|
|
|
2577 |
}
|
|
|
2578 |
}
|
|
|
2579 |
|
|
|
2580 |
this._toggleHighlight(elNewListItem, "to");
|
|
|
2581 |
this.itemArrowToEvent.fire(this, elNewListItem);
|
|
|
2582 |
YAHOO.log("Item arrowed to " + elNewListItem._nItemIndex, "info", this.toString());
|
|
|
2583 |
if(this.typeAhead) {
|
|
|
2584 |
this._updateValue(elNewListItem);
|
|
|
2585 |
// Bug 2528552: Store as a selection
|
|
|
2586 |
this._sCurQuery = elNewListItem._sResultMatch;
|
|
|
2587 |
}
|
|
|
2588 |
}
|
|
|
2589 |
};
|
|
|
2590 |
|
|
|
2591 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
2592 |
//
|
|
|
2593 |
// Private event handlers
|
|
|
2594 |
//
|
|
|
2595 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
2596 |
|
|
|
2597 |
/**
|
|
|
2598 |
* Handles container mouseover events.
|
|
|
2599 |
*
|
|
|
2600 |
* @method _onContainerMouseover
|
|
|
2601 |
* @param v {HTMLEvent} The mouseover event.
|
|
|
2602 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2603 |
* @private
|
|
|
2604 |
*/
|
|
|
2605 |
YAHOO.widget.AutoComplete.prototype._onContainerMouseover = function(v,oSelf) {
|
|
|
2606 |
var elTarget = YAHOO.util.Event.getTarget(v);
|
|
|
2607 |
var elTag = elTarget.nodeName.toLowerCase();
|
|
|
2608 |
while(elTarget && (elTag != "table")) {
|
|
|
2609 |
switch(elTag) {
|
|
|
2610 |
case "body":
|
|
|
2611 |
return;
|
|
|
2612 |
case "li":
|
|
|
2613 |
if(oSelf.prehighlightClassName) {
|
|
|
2614 |
oSelf._togglePrehighlight(elTarget,"mouseover");
|
|
|
2615 |
}
|
|
|
2616 |
else {
|
|
|
2617 |
oSelf._toggleHighlight(elTarget,"to");
|
|
|
2618 |
}
|
|
|
2619 |
|
|
|
2620 |
oSelf.itemMouseOverEvent.fire(oSelf, elTarget);
|
|
|
2621 |
YAHOO.log("Item moused over " + elTarget._nItemIndex, "info", oSelf.toString());
|
|
|
2622 |
break;
|
|
|
2623 |
case "div":
|
|
|
2624 |
if(YAHOO.util.Dom.hasClass(elTarget,"yui-ac-container")) {
|
|
|
2625 |
oSelf._bOverContainer = true;
|
|
|
2626 |
return;
|
|
|
2627 |
}
|
|
|
2628 |
break;
|
|
|
2629 |
default:
|
|
|
2630 |
break;
|
|
|
2631 |
}
|
|
|
2632 |
|
|
|
2633 |
elTarget = elTarget.parentNode;
|
|
|
2634 |
if(elTarget) {
|
|
|
2635 |
elTag = elTarget.nodeName.toLowerCase();
|
|
|
2636 |
}
|
|
|
2637 |
}
|
|
|
2638 |
};
|
|
|
2639 |
|
|
|
2640 |
/**
|
|
|
2641 |
* Handles container mouseout events.
|
|
|
2642 |
*
|
|
|
2643 |
* @method _onContainerMouseout
|
|
|
2644 |
* @param v {HTMLEvent} The mouseout event.
|
|
|
2645 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2646 |
* @private
|
|
|
2647 |
*/
|
|
|
2648 |
YAHOO.widget.AutoComplete.prototype._onContainerMouseout = function(v,oSelf) {
|
|
|
2649 |
var elTarget = YAHOO.util.Event.getTarget(v);
|
|
|
2650 |
var elTag = elTarget.nodeName.toLowerCase();
|
|
|
2651 |
while(elTarget && (elTag != "table")) {
|
|
|
2652 |
switch(elTag) {
|
|
|
2653 |
case "body":
|
|
|
2654 |
return;
|
|
|
2655 |
case "li":
|
|
|
2656 |
if(oSelf.prehighlightClassName) {
|
|
|
2657 |
oSelf._togglePrehighlight(elTarget,"mouseout");
|
|
|
2658 |
}
|
|
|
2659 |
else {
|
|
|
2660 |
oSelf._toggleHighlight(elTarget,"from");
|
|
|
2661 |
}
|
|
|
2662 |
|
|
|
2663 |
oSelf.itemMouseOutEvent.fire(oSelf, elTarget);
|
|
|
2664 |
YAHOO.log("Item moused out " + elTarget._nItemIndex, "info", oSelf.toString());
|
|
|
2665 |
break;
|
|
|
2666 |
case "ul":
|
|
|
2667 |
oSelf._toggleHighlight(oSelf._elCurListItem,"to");
|
|
|
2668 |
break;
|
|
|
2669 |
case "div":
|
|
|
2670 |
if(YAHOO.util.Dom.hasClass(elTarget,"yui-ac-container")) {
|
|
|
2671 |
oSelf._bOverContainer = false;
|
|
|
2672 |
return;
|
|
|
2673 |
}
|
|
|
2674 |
break;
|
|
|
2675 |
default:
|
|
|
2676 |
break;
|
|
|
2677 |
}
|
|
|
2678 |
|
|
|
2679 |
elTarget = elTarget.parentNode;
|
|
|
2680 |
if(elTarget) {
|
|
|
2681 |
elTag = elTarget.nodeName.toLowerCase();
|
|
|
2682 |
}
|
|
|
2683 |
}
|
|
|
2684 |
};
|
|
|
2685 |
|
|
|
2686 |
/**
|
|
|
2687 |
* Handles container click events.
|
|
|
2688 |
*
|
|
|
2689 |
* @method _onContainerClick
|
|
|
2690 |
* @param v {HTMLEvent} The click event.
|
|
|
2691 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2692 |
* @private
|
|
|
2693 |
*/
|
|
|
2694 |
YAHOO.widget.AutoComplete.prototype._onContainerClick = function(v,oSelf) {
|
|
|
2695 |
var elTarget = YAHOO.util.Event.getTarget(v);
|
|
|
2696 |
var elTag = elTarget.nodeName.toLowerCase();
|
|
|
2697 |
while(elTarget && (elTag != "table")) {
|
|
|
2698 |
switch(elTag) {
|
|
|
2699 |
case "body":
|
|
|
2700 |
return;
|
|
|
2701 |
case "li":
|
|
|
2702 |
// In case item has not been moused over
|
|
|
2703 |
oSelf._toggleHighlight(elTarget,"to");
|
|
|
2704 |
oSelf._selectItem(elTarget);
|
|
|
2705 |
return;
|
|
|
2706 |
default:
|
|
|
2707 |
break;
|
|
|
2708 |
}
|
|
|
2709 |
|
|
|
2710 |
elTarget = elTarget.parentNode;
|
|
|
2711 |
if(elTarget) {
|
|
|
2712 |
elTag = elTarget.nodeName.toLowerCase();
|
|
|
2713 |
}
|
|
|
2714 |
}
|
|
|
2715 |
};
|
|
|
2716 |
|
|
|
2717 |
|
|
|
2718 |
/**
|
|
|
2719 |
* Handles container scroll events.
|
|
|
2720 |
*
|
|
|
2721 |
* @method _onContainerScroll
|
|
|
2722 |
* @param v {HTMLEvent} The scroll event.
|
|
|
2723 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2724 |
* @private
|
|
|
2725 |
*/
|
|
|
2726 |
YAHOO.widget.AutoComplete.prototype._onContainerScroll = function(v,oSelf) {
|
|
|
2727 |
oSelf._focus();
|
|
|
2728 |
};
|
|
|
2729 |
|
|
|
2730 |
/**
|
|
|
2731 |
* Handles container resize events.
|
|
|
2732 |
*
|
|
|
2733 |
* @method _onContainerResize
|
|
|
2734 |
* @param v {HTMLEvent} The resize event.
|
|
|
2735 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2736 |
* @private
|
|
|
2737 |
*/
|
|
|
2738 |
YAHOO.widget.AutoComplete.prototype._onContainerResize = function(v,oSelf) {
|
|
|
2739 |
oSelf._toggleContainerHelpers(oSelf._bContainerOpen);
|
|
|
2740 |
};
|
|
|
2741 |
|
|
|
2742 |
|
|
|
2743 |
/**
|
|
|
2744 |
* Handles textbox keydown events of functional keys, mainly for UI behavior.
|
|
|
2745 |
*
|
|
|
2746 |
* @method _onTextboxKeyDown
|
|
|
2747 |
* @param v {HTMLEvent} The keydown event.
|
|
|
2748 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2749 |
* @private
|
|
|
2750 |
*/
|
|
|
2751 |
YAHOO.widget.AutoComplete.prototype._onTextboxKeyDown = function(v,oSelf) {
|
|
|
2752 |
var nKeyCode = v.keyCode;
|
|
|
2753 |
|
|
|
2754 |
// Clear timeout
|
|
|
2755 |
if(oSelf._nTypeAheadDelayID != -1) {
|
|
|
2756 |
clearTimeout(oSelf._nTypeAheadDelayID);
|
|
|
2757 |
}
|
|
|
2758 |
|
|
|
2759 |
switch (nKeyCode) {
|
|
|
2760 |
case 9: // tab
|
|
|
2761 |
if(!YAHOO.env.ua.opera && (navigator.userAgent.toLowerCase().indexOf("mac") == -1) || (YAHOO.env.ua.webkit>420)) {
|
|
|
2762 |
// select an item or clear out
|
|
|
2763 |
if(oSelf._elCurListItem) {
|
|
|
2764 |
if(oSelf.delimChar && (oSelf._nKeyCode != nKeyCode)) {
|
|
|
2765 |
if(oSelf._bContainerOpen) {
|
|
|
2766 |
YAHOO.util.Event.stopEvent(v);
|
|
|
2767 |
}
|
|
|
2768 |
}
|
|
|
2769 |
oSelf._selectItem(oSelf._elCurListItem);
|
|
|
2770 |
}
|
|
|
2771 |
else {
|
|
|
2772 |
oSelf._toggleContainer(false);
|
|
|
2773 |
}
|
|
|
2774 |
}
|
|
|
2775 |
break;
|
|
|
2776 |
case 13: // enter
|
|
|
2777 |
if(!YAHOO.env.ua.opera && (navigator.userAgent.toLowerCase().indexOf("mac") == -1) || (YAHOO.env.ua.webkit>420)) {
|
|
|
2778 |
if(oSelf._elCurListItem) {
|
|
|
2779 |
if(oSelf._nKeyCode != nKeyCode) {
|
|
|
2780 |
if(oSelf._bContainerOpen) {
|
|
|
2781 |
YAHOO.util.Event.stopEvent(v);
|
|
|
2782 |
}
|
|
|
2783 |
}
|
|
|
2784 |
oSelf._selectItem(oSelf._elCurListItem);
|
|
|
2785 |
}
|
|
|
2786 |
else {
|
|
|
2787 |
oSelf._toggleContainer(false);
|
|
|
2788 |
}
|
|
|
2789 |
}
|
|
|
2790 |
break;
|
|
|
2791 |
case 27: // esc
|
|
|
2792 |
oSelf._toggleContainer(false);
|
|
|
2793 |
return;
|
|
|
2794 |
case 39: // right
|
|
|
2795 |
oSelf._jumpSelection();
|
|
|
2796 |
break;
|
|
|
2797 |
case 38: // up
|
|
|
2798 |
if(oSelf._bContainerOpen) {
|
|
|
2799 |
YAHOO.util.Event.stopEvent(v);
|
|
|
2800 |
oSelf._moveSelection(nKeyCode);
|
|
|
2801 |
}
|
|
|
2802 |
break;
|
|
|
2803 |
case 40: // down
|
|
|
2804 |
if(oSelf._bContainerOpen) {
|
|
|
2805 |
YAHOO.util.Event.stopEvent(v);
|
|
|
2806 |
oSelf._moveSelection(nKeyCode);
|
|
|
2807 |
}
|
|
|
2808 |
break;
|
|
|
2809 |
default:
|
|
|
2810 |
oSelf._bItemSelected = false;
|
|
|
2811 |
oSelf._toggleHighlight(oSelf._elCurListItem, "from");
|
|
|
2812 |
|
|
|
2813 |
oSelf.textboxKeyEvent.fire(oSelf, nKeyCode);
|
|
|
2814 |
YAHOO.log("Textbox keyed", "info", oSelf.toString());
|
|
|
2815 |
break;
|
|
|
2816 |
}
|
|
|
2817 |
|
|
|
2818 |
if(nKeyCode === 18){
|
|
|
2819 |
oSelf._enableIntervalDetection();
|
|
|
2820 |
}
|
|
|
2821 |
oSelf._nKeyCode = nKeyCode;
|
|
|
2822 |
};
|
|
|
2823 |
|
|
|
2824 |
/**
|
|
|
2825 |
* Handles textbox keypress events.
|
|
|
2826 |
* @method _onTextboxKeyPress
|
|
|
2827 |
* @param v {HTMLEvent} The keypress event.
|
|
|
2828 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2829 |
* @private
|
|
|
2830 |
*/
|
|
|
2831 |
YAHOO.widget.AutoComplete.prototype._onTextboxKeyPress = function(v,oSelf) {
|
|
|
2832 |
var nKeyCode = v.keyCode;
|
|
|
2833 |
|
|
|
2834 |
// Expose only to non SF3 (bug 1978549) Mac browsers (bug 790337) and Opera browsers (bug 583531),
|
|
|
2835 |
// where stopEvent is ineffective on keydown events
|
|
|
2836 |
if(YAHOO.env.ua.opera || (navigator.userAgent.toLowerCase().indexOf("mac") != -1) && (YAHOO.env.ua.webkit < 420)) {
|
|
|
2837 |
switch (nKeyCode) {
|
|
|
2838 |
case 9: // tab
|
|
|
2839 |
// select an item or clear out
|
|
|
2840 |
if(oSelf._bContainerOpen) {
|
|
|
2841 |
if(oSelf.delimChar) {
|
|
|
2842 |
YAHOO.util.Event.stopEvent(v);
|
|
|
2843 |
}
|
|
|
2844 |
if(oSelf._elCurListItem) {
|
|
|
2845 |
oSelf._selectItem(oSelf._elCurListItem);
|
|
|
2846 |
}
|
|
|
2847 |
else {
|
|
|
2848 |
oSelf._toggleContainer(false);
|
|
|
2849 |
}
|
|
|
2850 |
}
|
|
|
2851 |
break;
|
|
|
2852 |
case 13: // enter
|
|
|
2853 |
if(oSelf._bContainerOpen) {
|
|
|
2854 |
YAHOO.util.Event.stopEvent(v);
|
|
|
2855 |
if(oSelf._elCurListItem) {
|
|
|
2856 |
oSelf._selectItem(oSelf._elCurListItem);
|
|
|
2857 |
}
|
|
|
2858 |
else {
|
|
|
2859 |
oSelf._toggleContainer(false);
|
|
|
2860 |
}
|
|
|
2861 |
}
|
|
|
2862 |
break;
|
|
|
2863 |
default:
|
|
|
2864 |
break;
|
|
|
2865 |
}
|
|
|
2866 |
}
|
|
|
2867 |
|
|
|
2868 |
//TODO: (?) limit only to non-IE, non-Mac-FF for Korean IME support (bug 811948)
|
|
|
2869 |
// Korean IME detected
|
|
|
2870 |
else if(nKeyCode == 229) {
|
|
|
2871 |
oSelf._enableIntervalDetection();
|
|
|
2872 |
}
|
|
|
2873 |
};
|
|
|
2874 |
|
|
|
2875 |
/**
|
|
|
2876 |
* Handles textbox keyup events to trigger queries.
|
|
|
2877 |
*
|
|
|
2878 |
* @method _onTextboxKeyUp
|
|
|
2879 |
* @param v {HTMLEvent} The keyup event.
|
|
|
2880 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2881 |
* @private
|
|
|
2882 |
*/
|
|
|
2883 |
YAHOO.widget.AutoComplete.prototype._onTextboxKeyUp = function(v,oSelf) {
|
|
|
2884 |
var sText = this.value; //string in textbox
|
|
|
2885 |
|
|
|
2886 |
// Check to see if any of the public properties have been updated
|
|
|
2887 |
oSelf._initProps();
|
|
|
2888 |
|
|
|
2889 |
// Filter out chars that don't trigger queries
|
|
|
2890 |
var nKeyCode = v.keyCode;
|
|
|
2891 |
if(oSelf._isIgnoreKey(nKeyCode)) {
|
|
|
2892 |
return;
|
|
|
2893 |
}
|
|
|
2894 |
|
|
|
2895 |
// Clear previous timeout
|
|
|
2896 |
if(oSelf._nDelayID != -1) {
|
|
|
2897 |
clearTimeout(oSelf._nDelayID);
|
|
|
2898 |
}
|
|
|
2899 |
|
|
|
2900 |
// Set new timeout
|
|
|
2901 |
oSelf._nDelayID = setTimeout(function(){
|
|
|
2902 |
oSelf._sendQuery(sText);
|
|
|
2903 |
},(oSelf.queryDelay * 1000));
|
|
|
2904 |
};
|
|
|
2905 |
|
|
|
2906 |
/**
|
|
|
2907 |
* Handles text input box receiving focus.
|
|
|
2908 |
*
|
|
|
2909 |
* @method _onTextboxFocus
|
|
|
2910 |
* @param v {HTMLEvent} The focus event.
|
|
|
2911 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2912 |
* @private
|
|
|
2913 |
*/
|
|
|
2914 |
YAHOO.widget.AutoComplete.prototype._onTextboxFocus = function (v,oSelf) {
|
|
|
2915 |
// Start of a new interaction
|
|
|
2916 |
if(!oSelf._bFocused) {
|
|
|
2917 |
oSelf._elTextbox.setAttribute("autocomplete","off");
|
|
|
2918 |
oSelf._bFocused = true;
|
|
|
2919 |
oSelf._sInitInputValue = oSelf._elTextbox.value;
|
|
|
2920 |
oSelf.textboxFocusEvent.fire(oSelf);
|
|
|
2921 |
YAHOO.log("Textbox focused", "info", oSelf.toString());
|
|
|
2922 |
}
|
|
|
2923 |
};
|
|
|
2924 |
|
|
|
2925 |
/**
|
|
|
2926 |
* Handles text input box losing focus.
|
|
|
2927 |
*
|
|
|
2928 |
* @method _onTextboxBlur
|
|
|
2929 |
* @param v {HTMLEvent} The focus event.
|
|
|
2930 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2931 |
* @private
|
|
|
2932 |
*/
|
|
|
2933 |
YAHOO.widget.AutoComplete.prototype._onTextboxBlur = function (v,oSelf) {
|
|
|
2934 |
// Is a true blur
|
|
|
2935 |
if(!oSelf._bOverContainer || (oSelf._nKeyCode == 9)) {
|
|
|
2936 |
// Current query needs to be validated as a selection
|
|
|
2937 |
if(!oSelf._bItemSelected) {
|
|
|
2938 |
var elMatchListItem = oSelf._textMatchesOption();
|
|
|
2939 |
// Container is closed or current query doesn't match any result
|
|
|
2940 |
if(!oSelf._bContainerOpen || (oSelf._bContainerOpen && (elMatchListItem === null))) {
|
|
|
2941 |
// Force selection is enabled so clear the current query
|
|
|
2942 |
if(oSelf.forceSelection) {
|
|
|
2943 |
oSelf._clearSelection();
|
|
|
2944 |
}
|
|
|
2945 |
// Treat current query as a valid selection
|
|
|
2946 |
else {
|
|
|
2947 |
oSelf.unmatchedItemSelectEvent.fire(oSelf, oSelf._sCurQuery);
|
|
|
2948 |
YAHOO.log("Unmatched item selected: " + oSelf._sCurQuery, "info", oSelf.toString());
|
|
|
2949 |
}
|
|
|
2950 |
}
|
|
|
2951 |
// Container is open and current query matches a result
|
|
|
2952 |
else {
|
|
|
2953 |
// Force a selection when textbox is blurred with a match
|
|
|
2954 |
if(oSelf.forceSelection) {
|
|
|
2955 |
oSelf._selectItem(elMatchListItem);
|
|
|
2956 |
}
|
|
|
2957 |
}
|
|
|
2958 |
}
|
|
|
2959 |
|
|
|
2960 |
oSelf._clearInterval();
|
|
|
2961 |
oSelf._bFocused = false;
|
|
|
2962 |
if(oSelf._sInitInputValue !== oSelf._elTextbox.value) {
|
|
|
2963 |
oSelf.textboxChangeEvent.fire(oSelf);
|
|
|
2964 |
}
|
|
|
2965 |
oSelf.textboxBlurEvent.fire(oSelf);
|
|
|
2966 |
YAHOO.log("Textbox blurred", "info", oSelf.toString());
|
|
|
2967 |
|
|
|
2968 |
oSelf._toggleContainer(false);
|
|
|
2969 |
}
|
|
|
2970 |
// Not a true blur if it was a selection via mouse click
|
|
|
2971 |
else {
|
|
|
2972 |
oSelf._focus();
|
|
|
2973 |
}
|
|
|
2974 |
};
|
|
|
2975 |
|
|
|
2976 |
/**
|
|
|
2977 |
* Handles window unload event.
|
|
|
2978 |
*
|
|
|
2979 |
* @method _onWindowUnload
|
|
|
2980 |
* @param v {HTMLEvent} The unload event.
|
|
|
2981 |
* @param oSelf {YAHOO.widget.AutoComplete} The AutoComplete instance.
|
|
|
2982 |
* @private
|
|
|
2983 |
*/
|
|
|
2984 |
YAHOO.widget.AutoComplete.prototype._onWindowUnload = function(v,oSelf) {
|
|
|
2985 |
if(oSelf && oSelf._elTextbox && oSelf.allowBrowserAutocomplete) {
|
|
|
2986 |
oSelf._elTextbox.setAttribute("autocomplete","on");
|
|
|
2987 |
}
|
|
|
2988 |
};
|
|
|
2989 |
|
|
|
2990 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
2991 |
//
|
|
|
2992 |
// Deprecated for Backwards Compatibility
|
|
|
2993 |
//
|
|
|
2994 |
/////////////////////////////////////////////////////////////////////////////
|
|
|
2995 |
/**
|
|
|
2996 |
* @method doBeforeSendQuery
|
|
|
2997 |
* @deprecated Use generateRequest.
|
|
|
2998 |
*/
|
|
|
2999 |
YAHOO.widget.AutoComplete.prototype.doBeforeSendQuery = function(sQuery) {
|
|
|
3000 |
return this.generateRequest(sQuery);
|
|
|
3001 |
};
|
|
|
3002 |
|
|
|
3003 |
/**
|
|
|
3004 |
* @method getListItems
|
|
|
3005 |
* @deprecated Use getListEl().childNodes.
|
|
|
3006 |
*/
|
|
|
3007 |
YAHOO.widget.AutoComplete.prototype.getListItems = function() {
|
|
|
3008 |
var allListItemEls = [],
|
|
|
3009 |
els = this._elList.childNodes;
|
|
|
3010 |
for(var i=els.length-1; i>=0; i--) {
|
|
|
3011 |
allListItemEls[i] = els[i];
|
|
|
3012 |
}
|
|
|
3013 |
return allListItemEls;
|
|
|
3014 |
};
|
|
|
3015 |
|
|
|
3016 |
/////////////////////////////////////////////////////////////////////////
|
|
|
3017 |
//
|
|
|
3018 |
// Private static methods
|
|
|
3019 |
//
|
|
|
3020 |
/////////////////////////////////////////////////////////////////////////
|
|
|
3021 |
|
|
|
3022 |
/**
|
|
|
3023 |
* Clones object literal or array of object literals.
|
|
|
3024 |
*
|
|
|
3025 |
* @method AutoComplete._cloneObject
|
|
|
3026 |
* @param o {Object} Object.
|
|
|
3027 |
* @private
|
|
|
3028 |
* @static
|
|
|
3029 |
*/
|
|
|
3030 |
YAHOO.widget.AutoComplete._cloneObject = function(o) {
|
|
|
3031 |
if(!YAHOO.lang.isValue(o)) {
|
|
|
3032 |
return o;
|
|
|
3033 |
}
|
|
|
3034 |
|
|
|
3035 |
var copy = {};
|
|
|
3036 |
|
|
|
3037 |
if(YAHOO.lang.isFunction(o)) {
|
|
|
3038 |
copy = o;
|
|
|
3039 |
}
|
|
|
3040 |
else if(YAHOO.lang.isArray(o)) {
|
|
|
3041 |
var array = [];
|
|
|
3042 |
for(var i=0,len=o.length;i<len;i++) {
|
|
|
3043 |
array[i] = YAHOO.widget.AutoComplete._cloneObject(o[i]);
|
|
|
3044 |
}
|
|
|
3045 |
copy = array;
|
|
|
3046 |
}
|
|
|
3047 |
else if(YAHOO.lang.isObject(o)) {
|
|
|
3048 |
for (var x in o){
|
|
|
3049 |
if(YAHOO.lang.hasOwnProperty(o, x)) {
|
|
|
3050 |
if(YAHOO.lang.isValue(o[x]) && YAHOO.lang.isObject(o[x]) || YAHOO.lang.isArray(o[x])) {
|
|
|
3051 |
copy[x] = YAHOO.widget.AutoComplete._cloneObject(o[x]);
|
|
|
3052 |
}
|
|
|
3053 |
else {
|
|
|
3054 |
copy[x] = o[x];
|
|
|
3055 |
}
|
|
|
3056 |
}
|
|
|
3057 |
}
|
|
|
3058 |
}
|
|
|
3059 |
else {
|
|
|
3060 |
copy = o;
|
|
|
3061 |
}
|
|
|
3062 |
|
|
|
3063 |
return copy;
|
|
|
3064 |
};
|
|
|
3065 |
|
|
|
3066 |
|
|
|
3067 |
|
|
|
3068 |
|
|
|
3069 |
YAHOO.register("autocomplete", YAHOO.widget.AutoComplete, {version: "2.9.0", build: "2800"});
|
|
|
3070 |
|
|
|
3071 |
}, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-dom", "yui2-event", "yui2-skin-sam-autocomplete", "yui2-datasource"], "optional": ["yui2-animation", "yui2-connection"]});
|