PageSourceSearch

https://testauto.eu/sitejs/jquery.autocomplete.js

js testauto.eu collected 2026-10-08 18:06:26 UTC 14,811 bytes, 557 lines download raw bytes

1jQuery.autocomplete = function(input, options) {
2	// Create a link to self
3	var me = this;
4	var isScroll = false;
5
6	// Create jQuery object for input element
7	var $input = $d(input).attr("autocomplete", "off");
8	var idd = input;
9	// Apply inputClass if necessary
10	if (options.inputClass) $input.addClass(options.inputClass);
11
12	// Create results
13	var results = document.createElement("div");
14	// Create jQuery object for results
15	var $results = $d(results);
16	$results.hide().addClass(options.resultsClass).css("position", "absolute");
17	if( options.width > 0 ) $results.css("width", options.width);
18	
19	// Add to body element
20	$d("body").append(results);
21
22	input.autocompleter = me;
23
24	var timeout = null;
25	var prev = "";
26	var active = -1;
27	var cache = {};
28	var keyb = false;
29	var hasFocus = false;
30	var lastKeyPressCode = null;
31
32	// flush cache
33	function flushCache(){
34		cache = {};
35		cache.data = {};
36		cache.length = 0;
37	};
38
39	// flush cache
40	flushCache();
41
42	// if there is a data array supplied
43	if( options.data != null ){
44		var sFirstChar = "", stMatchSets = {}, row = [];
45
46		// no url was specified, we need to adjust the cache length to make sure it fits the local data store
47		if( typeof options.url != "string" ) options.cacheLength = 1;
48
49		// loop through the array and create a lookup structure
50		for( var i=0; i < options.data.length; i++ ){
51			// if row is a string, make an array otherwise just reference the array
52			row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]);
53
54			// if the length is zero, don't add to list
55			if( row[0].length > 0 ){
56				// get the first character
57				sFirstChar = row[0].substring(0, 1).toLowerCase();
58				// if no lookup array for this character exists, look it up now
59				if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = [];
60				// if the match is a string
61				stMatchSets[sFirstChar].push(row);
62			}
63		}
64
65		// add the data items to the cache
66		for( var k in stMatchSets ){
67			// increase the cache size
68			options.cacheLength++;
69			// add to the cache
70			addToCache(k, stMatchSets[k]);
71		}
72	}
73
74	$input
75	.keydown(function(e) {
76		// track last key pressed
77		lastKeyPressCode = e.keyCode;
78		switch(e.keyCode) {
79			case 38: // up
80				e.preventDefault();
81				moveSelect(-1);
82				break;
83			case 40: // down
84				e.preventDefault();
85				moveSelect(1);
86				break;
87			case 9:  // tab
88			case 13: // return
89				if( selectCurrent() ){
90					// make sure to blur off the current field
91					$input.get(0).blur();
92					e.preventDefault();
93				}
94				break;
95			default:
96				active = -1;
97				if (timeout) clearTimeout(timeout);
98				timeout = setTimeout(function(){onChange();}, options.delay);
99				break;
100		}
101	})
102	.focus(function(){
103		// track whether the field has focus, we shouldn't process any results if the field no longer has focus
104		hasFocus = true;
105	})
106	.blur(function() {
107		// track whether the field has focus
108		hasFocus = false;
109		//var ua = navigator.userAgent.toLowerCase();
110		//if (ua.indexOf("chrome") == -1) 
111		//if (isScroll == false) 
112		hideResults();  // !!! Oleg!
113	});
114
115	hideResultsNow();
116
117	//remove starting whitespaces
118	function LTrim( value ) {
119		
120		var re = /\s*((\S+\s*)*)/;
121		return value.replace(re, "$1");
122		
123	}
124	
125	// Removes ending whitespaces
126	function RTrim( value ) {
127		
128		var re = /((\s*\S+)*)\s*/;
129		return value.replace(re, "$1");
130		
131	}
132	
133	// Removes leading and ending whitespaces
134	function trim( value ) {
135		
136		return LTrim(RTrim(value));
137		
138	}
139
140	function onChange() {
141		// ignore if the following keys are pressed: [del] [shift] [capslock]
142		if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide();
143		var v = trim($input.val());
144		if(options.inputSeperator.length != 0){
145			var broken = v.split(options.inputSeperator);
146			v = trim(broken[broken.length-1]);
147		}
148		if (v == prev) return;
149		prev = v;
150		if (v.length >= options.minChars) {
151			$input.addClass(options.loadingClass);
152			requestData(v);
153		} else {
154			$input.removeClass(options.loadingClass);
155			$results.hide();
156		}
157	};
158
159 	function moveSelect(step) {
160
161		var lis = $d("li", results);
162		if (!lis) return;
163
164		active += step;
165
166		if (active < 0) {
167			active = 0;
168		} else if (active >= lis.size()) {
169			active = lis.size() - 1;
170		}
171
172		lis.removeClass("ac_over");
173
174		$d(lis[active]).addClass("ac_over");
175
176		// Weird behaviour in IE
177		// if (lis[active] && lis[active].scrollIntoView) {
178		// 	lis[active].scrollIntoView(false);
179		// }
180
181	};
182
183	function selectCurrent() {
184		var li = $d("li.ac_over", results)[0];
185		if (!li) {
186			var $li = $d("li", results);
187			if (options.selectOnly) {
188				if ($li.length == 1) li = $li[0];
189			} else if (options.selectFirst) {
190				li = $li[0];
191			}
192		}
193		if (li) {
194			selectItem(li);
195			return true;
196		} else {
197			return false;
198		}
199	};
200
201	function selectItem(li) {
202		if (!li) {
203			li = document.createElement("li");
204			li.extra = [];
205			li.selectValue = "";
206		}
207		var v = $d.trim(li.selectValue ? li.selectValue : li.innerHTML);
208		input.lastSelected = v;
209		prev = v;
210		$results.html("");
211		if(options.inputSeperator.length != 0){
212			var broken = $input.val().split(options.inputSeperator);
213			broken.splice(broken.length-1, 1, v);
214			$input.val(broken.join(options.inputSeperator + " "));
215		}else{
216			$input.val(v);
217			try {						//Silvester: autocomplete hiddenelement
218				$d("#"+idd.name + "Code").val(li.hiddenValue);	//<input type="hidden" id="DestinationCode" name="DestinationCode">
219			} catch(e) {}
220			
221			try {						//Silvester: autocomplete othes ways
222				cell_change(input.id);	//
223			} catch(e) {}				//
224		}
225		hideResultsNow();
226		if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1);
227	};
228
229	// selects a portion of the input string
230	function createSelection(start, end){
231		// get a reference to the input element
232		var field = $input.get(0);
233		if( field.createTextRange ){
234			var selRange = field.createTextRange();
235			selRange.collapse(true);
236			selRange.moveStart("character", start);
237			selRange.moveEnd("character", end);
238			selRange.select();
239		} else if( field.setSelectionRange ){
240			field.setSelectionRange(start, end);
241		} else {
242			if( field.selectionStart ){
243				field.selectionStart = start;
244				field.selectionEnd = end;
245			}
246		}
247		field.focus();
248	};
249
250	// fills in the input box w/the first match (assumed to be the best match)
251	function autoFill(sValue){
252		// if the last user key pressed was backspace, don't autofill
253		if( lastKeyPressCode != 8 ){
254			// fill in the value (keep the case the user has typed)
255			$input.val($input.val() + sValue.substring(prev.length));
256			// select the portion of the value not typed by the user (so the next character will erase)
257			createSelection(prev.length, sValue.length);
258		}
259	};
260
261	function showResults() {
262		// get the position of the input field right now (in case the DOM is shifted)
263		var pos = findPos(input);
264		// either use the specified width, or autocalculate based on form element
265		var iWidth = (options.width > 0) ? options.width : $input.width();
266		// reposition
267		$results.css({
268			width: parseInt(iWidth+150) + "px",
269			top: (pos.y + input.offsetHeight) + "px",
270			left: pos.x + "px"
271		}).show();
272	};
273
274	function hideResults() {
275		if (isScroll == false) {
276			if (timeout) clearTimeout(timeout);
277			timeout = setTimeout(hideResultsNow, 600);
278		}
279	};
280
281	function hideResultsNow() {
282		if (isScroll == true) return;
283
284		if (timeout) clearTimeout(timeout);
285		
286		$input.removeClass(options.loadingClass);
287		if ($results.is(":visible")) {
288			$results.hide();
289		}
290		if (options.mustMatch) {
291			var v = $input.val();
292			if (v != input.lastSelected) {
293				selectItem(null);
294			}
295		}
296	};
297
298	function receiveData(q, data) {
299		if (data) {
300			$input.removeClass(options.loadingClass);
301			results.innerHTML = "";
302
303			// if the field no longer has focus or if there are no matches, do not display the drop down
304			if( !hasFocus || data.length == 0 ) return hideResultsNow();
305
306			if ($d.browser.msie) {
307				// we put a styled iframe behind the calendar so HTML SELECT elements don't show through
308				$results.append(document.createElement('iframe'));
309			}
310			results.appendChild(dataToDom(data));
311			// autofill in the complete box w/the first match as long as the user hasn't entered in more data
312			if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]);
313			showResults();
314		} else {
315			hideResultsNow();
316		}
317	};
318
319	function parseData(data) {
320		if (!data) return null;
321		var parsed = [];
322		var rows = data.split(options.lineSeperator);
323		for (var i=0; i < rows.length; i++) {
324			var row = $d.trim(rows[i]);
325			if (row) {
326				parsed[parsed.length] = row.split(options.cellSeperator);
327			}
328		}
329		return parsed;
330	};
331
332	function dataToDom(data) {
333		var ul = document.createElement("ul");
334		var num = data.length;
335
336		// limited results to a max number
337		if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow;
338
339		for (var i=0; i < num; i++) {
340			var row = data[i];
341			if (!row) continue;
342			var li = document.createElement("li");
343			if (options.formatItem) {
344				li.innerHTML = options.formatItem(row, i, num);
345				li.selectValue = row[0];
346				li.hiddenValue = row[1];
347			} else {
348				li.innerHTML = row[0];
349				li.selectValue = row[0];
350				li.hiddenValue = row[1];
351			}
352			var extra = null;
353			if (row.length > 1) {
354				extra = [];
355				for (var j=1; j < row.length; j++) {
356					extra[extra.length] = row[j];
357				}
358			}
359			li.extra = extra;
360			ul.appendChild(li);
361			$d(li).hover(
362				function() { $d("li", ul).removeClass("ac_over"); $d(this).addClass("ac_over"); active = $d("li", ul).indexOf($d(this).get(0)); },
363				function() { $d(this).removeClass("ac_over"); }
364			).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this); isScroll = false; });
365		}
366
367		$d(ul).scroll(function() { isScroll = true; } );
368		
369		return ul;
370	};
371
372	function requestData(q) {
373		if (!options.matchCase) q = q.toLowerCase();
374		var data = options.cacheLength ? loadFromCache(q) : null;
375		// recieve the cached data
376		if (data) {
377			receiveData(q, data);
378		// if an AJAX url has been supplied, try loading the data now
379		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
380			$d.get(makeUrl(q), function(data) {
381				data = parseData(data);
382				addToCache(q, data);
383				receiveData(q, data);
384			});
385		// if there's been no data found, remove the loading class
386		} else {
387			$input.removeClass(options.loadingClass);
388		}
389	};
390
391	function makeUrl(q) {
392		var url = options.url + "?q=" + encodeURI(q);
393		for (var i in options.extraParams) {
394			url += "&" + i + "=" + encodeURI(options.extraParams[i]);
395		}
396		return url;
397	};
398
399	function loadFromCache(q) {
400		if (!q) return null;
401		if (cache.data[q]) return cache.data[q];
402		if (options.matchSubset) {
403			for (var i = q.length - 1; i >= options.minChars; i--) {
404				var qs = q.substr(0, i);
405				var c = cache.data[qs];
406				if (c) {
407					var csub = [];
408					for (var j = 0; j < c.length; j++) {
409						var x = c[j];
410						var x0 = x[0];
411						if (matchSubset(x0, q)) {
412							csub[csub.length] = x;
413						}
414					}
415					return csub;
416				}
417			}
418		}
419		return null;
420	};
421
422	function matchSubset(s, sub) {
423		if (!options.matchCase) s = s.toLowerCase();
424		var i = s.indexOf(sub);
425		if (i == -1) return false;
426		return i == 0 || options.matchContains;
427	};
428
429	this.flushCache = function() {
430		flushCache();
431	};
432
433	this.setExtraParams = function(p) {
434		options.extraParams = p;
435	};
436
437	this.findValue = function(){
438		var q = $input.val();
439
440		if (!options.matchCase) q = q.toLowerCase();
441		var data = options.cacheLength ? loadFromCache(q) : null;
442		if (data) {
443			findValueCallback(q, data);
444		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
445			$d.get(makeUrl(q), function(data) {
446				data = parseData(data)
447				addToCache(q, data);
448				findValueCallback(q, data);
449			});
450		} else {
451			// no matches
452			findValueCallback(q, null);
453		}
454	}
455
456	function findValueCallback(q, data){
457		if (data) $input.removeClass(options.loadingClass);
458
459		var num = (data) ? data.length : 0;
460		var li = null;
461
462		for (var i=0; i < num; i++) {
463			var row = data[i];
464
465			if( row[0].toLowerCase() == q.toLowerCase() ){
466				li = document.createElement("li");
467				if (options.formatItem) {
468					li.innerHTML = options.formatItem(row, i, num);
469					li.selectValue = row[0];
470				} else {
471					li.innerHTML = row[0];
472					li.selectValue = row[0];
473				}
474				var extra = null;
475				if( row.length > 1 ){
476					extra = [];
477					for (var j=1; j < row.length; j++) {
478						extra[extra.length] = row[j];
479					}
480				}
481				li.extra = extra;
482			}
483		}
484
485		if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1);
486	}
487
488	function addToCache(q, data) {
489		if (!data || !q || !options.cacheLength) return;
490		if (!cache.length || cache.length > options.cacheLength) {
491			flushCache();
492			cache.length++;
493		} else if (!cache[q]) {
494			cache.length++;
495		}
496		cache.data[q] = data;
497	};
498
499	function findPos(obj) {
500		var curleft = obj.offsetLeft || 0;
501		var curtop = obj.offsetTop || 0;
502		while (obj = obj.offsetParent) {
503			curleft += obj.offsetLeft
504			curtop += obj.offsetTop
505		}
506		return {x:curleft,y:curtop};
507	}
508}
509
510jQuery.fn.autocomplete = function(url, options, data) {
511	// Make sure options exists
512	options = options || {};
513	// Set url as option
514	options.url = url;
515	// set some bulk local data
516	options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;
517
518	// Set default values for required options
519	options.inputClass = options.inputClass || "ac_input";
520	options.resultsClass = options.resultsClass || "ac_results";
521	options.lineSeperator = options.lineSeperator || "\n";
522	options.cellSeperator = options.cellSeperator || "|";
523	options.minChars = options.minChars || 1;
524	options.delay = options.delay || 400;
525	options.matchCase = options.matchCase || 0;
526	options.matchSubset = options.matchSubset || 1;
527	options.matchContains = options.matchContains || 0;
528	options.cacheLength = options.cacheLength || 1;
529	options.mustMatch = options.mustMatch || 0;
530	options.extraParams = options.extraParams || {};
531	options.loadingClass = options.loadingClass || "ac_loading";
532	options.selectFirst = options.selectFirst || false;
533	options.selectOnly = options.selectOnly || false;
534	options.inputSeperator = options.inputSeperator || '';
535	options.maxItemsToShow = options.maxItemsToShow || -1;
536	options.autoFill = options.autoFill || false;
537	options.width = parseInt(options.width, 10) || 0;
538
539	this.each(function() {
540		var input = this;
541		new jQuery.autocomplete(input, options);
542	});
543
544	// Don't break the chain
545	return this;
546}
547
548jQuery.fn.autocompleteArray = function(data, options) {
549	return this.autocomplete(null, options, data);
550}
551
552jQuery.fn.indexOf = function(e){
553	for( var i=0; i<this.length; i++ ){
554		if( this[i] == e ) return i;
555	}
556	return -1;
557}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.