PageSourceSearch

https://3drugs.com/vendor/jquery/autocomplete.js?v=1782458293

js 3drugs.com collected 2026-10-04 19:55:22 UTC 20,182 bytes, 727 lines download raw bytes

1jQuery.autocomplete = function(input, options) {
2	// Create a link to self
3	var me = this;
4
5	// Create jQuery object for input element
6	var $input = $(input).attr("autocomplete", "off");
7
8	// Apply inputClass if necessary
9	if (options.inputClass) $input.addClass(options.inputClass);
10
11	// Create results
12	var results = document.createElement("div");
13	// Create jQuery object for results
14	var $results = $(results);
15	$results.hide().addClass(options.resultsClass).css("position", "absolute");
16	if( options.width > 0 ) $results.css("width", options.width);
17
18	// Add to body element
19	// $(".search-bar").append(results);
20    if (design == 17) {
21        $("body").append(results);
22    } else {
23        $(".search-bar").append(results);
24    }
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 scrollResultToActive(li) {
134        var container = $results.get(0);
135
136        if (!li || !container) {
137            return;
138        }
139
140        var liTop = li.offsetTop;
141        var liBottom = liTop + li.offsetHeight;
142
143        var visibleTop = container.scrollTop;
144        var visibleBottom = visibleTop + container.clientHeight;
145
146        if (liTop < visibleTop) {
147            container.scrollTop = liTop;
148        } else if (liBottom > visibleBottom) {
149            container.scrollTop = liBottom - container.clientHeight;
150        }
151    }
152
153 	// function moveSelect(step) {
154
155	// 	var lis = $("li", results);
156	// 	if (!lis) return;
157
158	// 	active += step;
159
160	// 	if (active < 0) {
161	// 		active = 0;
162	// 	} else if (active >= lis.length) {
163	// 		active = lis.length- 1;
164	// 	}
165
166	// 	lis.removeClass("ac_over");
167
168	// 	$(lis[active]).addClass("ac_over");
169
170	// 	// Weird behaviour in IE
171	// 	// if (lis[active] && lis[active].scrollIntoView) {
172	// 	// 	lis[active].scrollIntoView(false);
173	// 	// }
174
175	// };
176
177    function moveSelect(step) {
178        var lis = $("li", results);
179
180        if (!lis.length) {
181            return;
182        }
183
184        active += step;
185
186        if (active < 0) {
187            active = 0;
188        } else if (active >= lis.length) {
189            active = lis.length - 1;
190        }
191
192        lis.removeClass("ac_over");
193
194        var activeLi = lis[active];
195
196        $(activeLi).addClass("ac_over");
197
198        scrollResultToActive(activeLi);
199    }
200
201	function selectCurrent() {
202		var li = $("li.ac_over", results)[0];
203		if (!li) {
204			var $li = $("li", results);
205			if (options.selectOnly) {
206				if ($li.length == 1) li = $li[0];
207			} else if (options.selectFirst) {
208				li = $li[0];
209			}
210		}
211		if (li) {
212			selectItem(li);
213			return true;
214		} else {
215			return false;
216		}
217	};
218
219	function selectItem(li) {
220		if (!li) {
221			li = document.createElement("li");
222			li.extra = [];
223			li.selectValue = "";
224		}
225		var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);
226		input.lastSelected = v;
227		prev = v;
228		$results.html("");
229		$input.val(v);
230		hideResultsNow();
231		if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1);
232	};
233
234	// selects a portion of the input string
235	function createSelection(start, end){
236		// get a reference to the input element
237		var field = $input.get(0);
238		if( field.createTextRange ){
239			var selRange = field.createTextRange();
240			selRange.collapse(true);
241			selRange.moveStart("character", start);
242			selRange.moveEnd("character", end);
243			selRange.select();
244		} else if( field.setSelectionRange ){
245			field.setSelectionRange(start, end);
246		} else {
247			if( field.selectionStart ){
248				field.selectionStart = start;
249				field.selectionEnd = end;
250			}
251		}
252		field.focus();
253	};
254
255	// fills in the input box w/the first match (assumed to be the best match)
256	function autoFill(sValue){
257		// if the last user key pressed was backspace, don't autofill
258		if( lastKeyPressCode != 8 ){
259			// fill in the value (keep the case the user has typed)
260			$input.val($input.val() + sValue.substring(prev.length));
261			// select the portion of the value not typed by the user (so the next character will erase)
262			createSelection(prev.length, sValue.length);
263		}
264	};
265
266	function showResults() {
267		// get the position of the input field right now (in case the DOM is shifted)
268		var pos = findPos(input);
269		// either use the specified width, or autocalculate based on form element
270		var iWidth = (options.width > 0) ? options.width : $input.width();
271
272		// reposition
273		if (design == 3) {
274			if (window.innerWidth >= 946 && window.innerWidth <= 1025) {
275					$results.css({
276							width: parseInt(iWidth) + "px",
277							// top: "-"+(input.offsetHeight) + "px",
278							top:  "-" + (pos.y + pos.x) + "px",
279							height: "min-content",
280							// left: pos.x + "px"
281					}).show();
282			} else {
283				if (window.innerWidth >= 790 && window.innerWidth <= 945) {
284					$results.css({
285							width: parseInt(iWidth) + "px",
286							top: "-" + (pos.y - input.offsetHeight + pos.x) + "px",
287							// top: "-"+(pos.y - pos.x/3) + "px",
288							// top: "-"+(input.offsetHeight) + "px",
289							// top:  "-" + (pos.y + pos.x - pos.x/3) + "px",
290							height: "min-content",
291							// left: pos.x + "px"
292					}).show();
293				} else {
294					if (window.innerWidth >= 755 && window.innerWidth <= 789) {
295						$results.css({
296								width: parseInt(iWidth) + "px",
297								// top: "-" + (pos.y - input.offsetHeight + pos.x) + "px",
298								top: "-"+(pos.y - pos.x) + "px",
299								// top: "-"+(input.offsetHeight) + "px",
300								// top:  "-" + (pos.y + pos.x - pos.x/3) + "px",
301								height: "min-content",
302								// left: pos.x + "px"
303						}).show();
304					} else {
305						if (window.innerWidth >= 630 && window.innerWidth <= 754) {
306							$results.css({
307									width: parseInt(iWidth) + "px",
308									// top: "-" + (pos.y - input.offsetHeight + pos.x) + "px",
309									// top: "-"+(pos.y - pos.x) + "px",
310									top: "-"+(pos.y - input.offsetHeight) + "px",
311									// top:  "-" + (pos.y + pos.x - pos.x/3) + "px",
312									height: "min-content",
313									// left: pos.x + "px"
314							}).show();
315						} else {
316							if (window.innerWidth >= 530 && window.innerWidth <= 629) {
317								$results.css({
318										width: parseInt(iWidth) + "px",
319										// top: "-" + (pos.y - input.offsetHeight + pos.x) + "px",
320										// top: "-"+(pos.y - pos.x) + "px",
321										top: "-" + (input.offsetHeight + pos.x) + "px",
322										// top:  "-" + (pos.y + pos.x - pos.x/3) + "px",
323										height: "min-content",
324										// left: pos.x + "px"
325								}).show();
326							} else {
327								$results.css({
328										width: parseInt(iWidth) + "px",
329										top: "-" + (input.offsetHeight) + "px",
330										// top: (pos.y + input.offsetHeight) + "px",
331										height: "min-content",
332										// left: pos.x + "px"
333								}).show();
334							}
335						}
336					}
337				}
338			}
339		} else if (design == 6) {
340			$results.css({
341				width: parseInt(iWidth + 60) + "px",
342				height: "min-content",
343			}).show();
344		} else {
345			if (window.innerWidth >= 600 && window.innerWidth <= 1025 && design == 2) {
346				$results.css({
347					width: parseInt(iWidth) + "px",
348					// top: (input.offsetHeight) + "px",
349					top:  "-2%",
350					height: "min-content",
351					left: "-2%",
352				}).show();
353			} else {
354				$results.css({
355					width: parseInt(iWidth) + "px",
356					top: (input.offsetHeight) + "px",
357					// top: (pos.y + input.offsetHeight) + "px",
358					height: "min-content",
359					// left: pos.x + "px"
360				}).show();
361			}
362		}
363    };
364
365    function showResultsNew() {
366        var inputEl = $input.get(0);
367
368        if (!inputEl) {
369            return;
370        }
371
372        var rect = inputEl.getBoundingClientRect();
373        var searchBarRect = $(".search-bar").get(0).getBoundingClientRect();
374        var gap = 8;
375
376        // var iWidth = (options.width > 0) ? options.width : $input.outerWidth();
377        var iWidth = searchBarRect.width;
378
379        if (design == 6) {
380            iWidth += 60;
381        }
382
383        $results.css({
384            position: "fixed",
385            width: parseInt(iWidth) + "px",
386            left: searchBarRect.left + "px",
387            boxSizing: "border-box",
388            top: "auto",
389            bottom: "auto",
390            // height: "auto",
391            // maxHeight: "none",
392            overflowY: "visible",
393            visibility: "hidden",
394            display: "block"
395        });
396
397        var resultsHeight = $results.outerHeight();
398
399        var spaceBelow = window.innerHeight - rect.bottom - gap;
400        var spaceAbove = rect.top - gap;
401
402        var showAbove = resultsHeight > spaceBelow && spaceAbove > spaceBelow;
403
404        var availableHeight = showAbove ? spaceAbove : spaceBelow;
405        var finalHeight = Math.min(resultsHeight, availableHeight);
406
407        if (showAbove) {
408            $results.css({
409                top: Math.max(gap, rect.top - finalHeight - gap) - 5 + "px",
410                bottom: "auto",
411                // maxHeight: Math.max(80, availableHeight) + "px",
412                overflowY: "scroll",
413                visibility: "visible",
414                display: "block"
415            });
416        } else {
417            $results.css({
418                top: rect.bottom + gap + 5 + "px",
419                bottom: "auto",
420                // maxHeight: Math.max(80, availableHeight) + "px",
421                overflowY: "scroll",
422                visibility: "visible",
423                display: "block"
424            });
425        }
426    };
427
428    function repositionResults() {
429        if (design == 17 && $results.is(":visible") && hasFocus) {
430            showResultsNew();
431        }
432    }
433
434    $(window).on("scroll resize", repositionResults);
435
436    // Для вложенных scroll-контейнеров нужен native addEventListener
437    document.addEventListener("scroll", repositionResults, true);
438
439	function hideResults() {
440		if (timeout) clearTimeout(timeout);
441		timeout = setTimeout(hideResultsNow, 200);
442	};
443
444	function hideResultsNow() {
445		if (timeout) clearTimeout(timeout);
446		$input.removeClass(options.loadingClass);
447		if ($results.is(":visible")) {
448			$results.hide();
449		}
450		if (options.mustMatch) {
451			var v = $input.val();
452			if (v != input.lastSelected) {
453				selectItem(null);
454			}
455		}
456	};
457
458	function receiveData(q, data) {
459		if (data) {
460			$input.removeClass(options.loadingClass);
461			results.innerHTML = "";
462
463			// if the field no longer has focus or if there are no matches, do not display the drop down
464			if( !hasFocus || data.length == 0 ) return hideResultsNow();
465
466			if ($.browser.msie) {
467				// we put a styled iframe behind the calendar so HTML SELECT elements don't show through
468				$results.append(document.createElement('iframe'));
469			}
470			results.appendChild(dataToDom(data));
471			// autofill in the complete box w/the first match as long as the user hasn't entered in more data
472			if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]);
473
474            if (design == 17) {
475                showResultsNew();
476
477                // function repositionResults() {
478                //     if ($results.is(":visible") && hasFocus) {
479                //         showResultsNew();
480                //     }
481                // }
482
483                // $(window).on("scroll resize", repositionResults);
484
485                // $(document).on("scroll", repositionResults, true);
486            } else {
487                showResults();
488            }
489
490		} else {
491			hideResultsNow();
492		}
493	};
494
495	function parseData(data) {
496		if (!data) return null;
497		var parsed = [];
498		var rows = data.split(options.lineSeparator);
499		for (var i=0; i < rows.length; i++) {
500			var row = $.trim(rows[i]);
501			if (row) {
502				parsed[parsed.length] = row.split(options.cellSeparator);
503			}
504		}
505		return parsed;
506	};
507
508	function dataToDom(data) {
509		var ul = document.createElement("ul");
510		var num = data.length;
511
512		// limited results to a max number
513		if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow;
514
515		for (var i=0; i < num; i++) {
516			var row = data[i];
517			if (!row) continue;
518			var li = document.createElement("li");
519			if (options.formatItem) {
520				li.innerHTML = options.formatItem(row, i, num);
521				li.selectValue = row[0];
522			} else {
523				li.innerHTML = row[0];
524				li.selectValue = row[0];
525			}
526			var extra = null;
527			if (row.length > 1) {
528				extra = [];
529				for (var j=1; j < row.length; j++) {
530					extra[extra.length] = row[j];
531				}
532			}
533			li.extra = extra;
534			ul.appendChild(li);
535			$(li).hover(
536				function() { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); },
537				function() { $(this).removeClass("ac_over"); }
538			).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) });
539		}
540		return ul;
541	};
542
543	function requestData(q) {
544		if (!options.matchCase) q = q.toLowerCase();
545		var data = options.cacheLength ? loadFromCache(q) : null;
546		// recieve the cached data
547		if (data) {
548			receiveData(q, data);
549		// if an AJAX url has been supplied, try loading the data now
550		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
551			$.get(makeUrl(q), function(data) {
552				data = parseData(data);
553				addToCache(q, data);
554				receiveData(q, data);
555			});
556		// if there's been no data found, remove the loading class
557		} else {
558			$input.removeClass(options.loadingClass);
559		}
560	};
561
562	function makeUrl(q) {
563		var url = options.url + "?q=" + encodeURI(q);
564		for (var i in options.extraParams) {
565			url += "&" + i + "=" + encodeURI(options.extraParams[i]);
566		}
567		return url;
568	};
569
570	function loadFromCache(q) {
571		if (!q) return null;
572		if (cache.data[q]) return cache.data[q];
573		if (options.matchSubset) {
574			for (var i = q.length - 1; i >= options.minChars; i--) {
575				var qs = q.substr(0, i);
576				var c = cache.data[qs];
577				if (c) {
578					var csub = [];
579					for (var j = 0; j < c.length; j++) {
580						var x = c[j];
581						var x0 = x[0];
582						if (matchSubset(x0, q)) {
583							csub[csub.length] = x;
584						}
585					}
586					return csub;
587				}
588			}
589		}
590		return null;
591	};
592
593	function matchSubset(s, sub) {
594		if (!options.matchCase) s = s.toLowerCase();
595		var i = s.indexOf(sub);
596		if (i == -1) return false;
597		return i == 0 || options.matchContains;
598	};
599
600	this.flushCache = function() {
601		flushCache();
602	};
603
604	this.setExtraParams = function(p) {
605		options.extraParams = p;
606	};
607
608	this.findValue = function(){
609		var q = $input.val();
610
611		if (!options.matchCase) q = q.toLowerCase();
612		var data = options.cacheLength ? loadFromCache(q) : null;
613		if (data) {
614			findValueCallback(q, data);
615		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
616			$.get(makeUrl(q), function(data) {
617				data = parseData(data)
618				addToCache(q, data);
619				findValueCallback(q, data);
620			});
621		} else {
622			// no matches
623			findValueCallback(q, null);
624		}
625	}
626
627	function findValueCallback(q, data){
628		if (data) $input.removeClass(options.loadingClass);
629
630		var num = (data) ? data.length : 0;
631		var li = null;
632
633		for (var i=0; i < num; i++) {
634			var row = data[i];
635
636			if( row[0].toLowerCase() == q.toLowerCase() ){
637				li = document.createElement("li");
638				if (options.formatItem) {
639					li.innerHTML = options.formatItem(row, i, num);
640					li.selectValue = row[0];
641				} else {
642					li.innerHTML = row[0];
643					li.selectValue = row[0];
644				}
645				var extra = null;
646				if( row.length > 1 ){
647					extra = [];
648					for (var j=1; j < row.length; j++) {
649						extra[extra.length] = row[j];
650					}
651				}
652				li.extra = extra;
653			}
654		}
655
656		if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1);
657	}
658
659	function addToCache(q, data) {
660		if (!data || !q || !options.cacheLength) return;
661		if (!cache.length || cache.length > options.cacheLength) {
662			flushCache();
663			cache.length++;
664		} else if (!cache[q]) {
665			cache.length++;
666		}
667		cache.data[q] = data;
668	};
669
670	function findPos(obj) {
671		var curleft = obj.offsetLeft || 0;
672		var curtop = obj.offsetTop || 0;
673		while (obj = obj.offsetParent) {
674			curleft += obj.offsetLeft
675			curtop += obj.offsetTop
676		}
677		return {x:curleft,y:curtop};
678	}
679}
680
681jQuery.fn.autocomplete = function(url, options, data) {
682	// Make sure options exists
683	options = options || {};
684	// Set url as option
685	options.url = url;
686	// set some bulk local data
687	options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;
688
689	// Set default values for required options
690	options.inputClass = options.inputClass || "ac_input";
691	options.resultsClass = options.resultsClass || "ac_results";
692	options.lineSeparator = options.lineSeparator || "\n";
693	options.cellSeparator = options.cellSeparator || "|";
694	options.minChars = options.minChars || 1;
695	options.delay = options.delay || 400;
696	options.matchCase = options.matchCase || 0;
697	options.matchSubset = options.matchSubset || 1;
698	options.matchContains = options.matchContains || 0;
699	options.cacheLength = options.cacheLength || 1;
700	options.mustMatch = options.mustMatch || 0;
701	options.extraParams = options.extraParams || {};
702	options.loadingClass = options.loadingClass || "ac_loading";
703	options.selectFirst = options.selectFirst || false;
704	options.selectOnly = options.selectOnly || false;
705	options.maxItemsToShow = options.maxItemsToShow || -1;
706	options.autoFill = options.autoFill || false;
707	options.width = parseInt(options.width, 10) || 0;
708
709	this.each(function() {
710		var input = this;
711		new jQuery.autocomplete(input, options);
712	});
713
714	// Don't break the chain
715	return this;
716}
717
718jQuery.fn.autocompleteArray = function(data, options) {
719	return this.autocomplete(null, options, data);
720}
721
722jQuery.fn.indexOf = function(e){
723	for( var i=0; i<this.length; i++ ){
724		if( this[i] == e ) return i;
725	}
726	return -1;
727};

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.