PageSourceSearch

https://www.tattvagyan.com/wp-content/plugins/autocompleter/jquery.autocomplete.js?ver=1.0

js tattvagyan.com collected 2026-10-02 13:49:39 UTC 14,116 bytes, 507 lines download raw bytes

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

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.