PageSourceSearch

https://sanwa-intec.com/template/default60/statics/js/set/autocomplete.js

js sanwa-intec.com collected 2026-10-05 18:57:22 UTC 25,768 bytes, 660 lines download raw bytes

1/*
2 * jQuery Autocomplete plugin 1.1
3 *
4 * Copyright (c) 2009 Jörn Zaefferer
5 *
6 * Dual licensed under the MIT and GPL licenses:
7 *   http://www.opensource.org/licenses/mit-license.php
8 *   http://www.gnu.org/licenses/gpl.html
9 *
10 * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
11 */;
12$.browser = navigator.userAgent;
13(function($) {
14    $.fn.extend({
15        autocomplete: function(urlOrData, options) {
16            var isUrl = typeof urlOrData == "string";
17            options = $.extend({}, $.Autocompleter.defaults, {
18                url: isUrl ? urlOrData : null,
19                data: isUrl ? null : urlOrData,
20                delay: isUrl ? $.Autocompleter.defaults.delay : 10,
21                max: options && !options.scroll ? 10 : 150
22            }, options);
23            options.highlight = options.highlight ||
24                function(value) {
25                    return value;
26                };
27            options.formatMatch = options.formatMatch || options.formatItem;
28            return this.each(function() {
29                new $.Autocompleter(this, options);
30            });
31        },
32        result: function(handler) {
33            return this.bind("result", handler);
34        },
35        search: function(handler) {
36            return this.trigger("search", [handler]);
37        },
38        flushCache: function() {
39            return this.trigger("flushCache");
40        },
41        setOptions: function(options) {
42            return this.trigger("setOptions", [options]);
43        },
44        unautocomplete: function() {
45            return this.trigger("unautocomplete");
46        }
47    });
48    $.Autocompleter = function(input, options) {
49        var KEY = {
50            UP: 38,
51            DOWN: 40,
52            DEL: 46,
53            TAB: 9,
54            RETURN: 13,
55            ESC: 27,
56            COMMA: 188,
57            PAGEUP: 33,
58            PAGEDOWN: 34,
59            BACKSPACE: 8
60        };
61        var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
62        var timeout;
63        var previousValue = "";
64        var cache = $.Autocompleter.Cache(options);
65        var hasFocus = 0;
66        var lastKeyPressCode;
67        var config = {
68            mouseDownOnSelect: false
69        };
70        var select = $.Autocompleter.Select(options, input, selectCurrent, config);
71        var blockSubmit;
72        $.browser.opera && $(input.form).bind("submit.autocomplete", function() {
73            if (blockSubmit) {
74                blockSubmit = false;
75                return false;
76            }
77        });
78        $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
79            hasFocus = 1;
80            lastKeyPressCode = event.keyCode;
81            switch (event.keyCode) {
82                case KEY.UP:
83                    event.preventDefault();
84                    if (select.visible()) {
85                        select.prev();
86                    } else {
87                        onChange(0, true);
88                    }
89                    break;
90                case KEY.DOWN:
91                    event.preventDefault();
92                    if (select.visible()) {
93                        select.next();
94                    } else {
95                        onChange(0, true);
96                    }
97                    break;
98                case KEY.PAGEUP:
99                    event.preventDefault();
100                    if (select.visible()) {
101                        select.pageUp();
102                    } else {
103                        onChange(0, true);
104                    }
105                    break;
106                case KEY.PAGEDOWN:
107                    event.preventDefault();
108                    if (select.visible()) {
109                        select.pageDown();
110                    } else {
111                        onChange(0, true);
112                    }
113                    break;
114                case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
115                case KEY.TAB:
116                case KEY.RETURN:
117                    if (selectCurrent()) {
118                        event.preventDefault();
119                        blockSubmit = true;
120                        return false;
121                    }
122                    break;
123                case KEY.ESC:
124                    select.hide();
125                    break;
126                default:
127                    clearTimeout(timeout);
128                    timeout = setTimeout(onChange, options.delay);
129                    break;
130            }
131        }).focus(function() {
132            hasFocus++;
133        }).blur(function() {
134            hasFocus = 0;
135            if (!config.mouseDownOnSelect) {
136                hideResults();
137            }
138        }).click(function() {
139            if (hasFocus++ > 1 && !select.visible()) {
140                onChange(0, true);
141            }
142        }).bind("search", function() {
143            var fn = (arguments.length > 1) ? arguments[1] : null;
144
145            function findValueCallback(q, data) {
146                var result;
147                if (data && data.length) {
148                    for (var i = 0; i < data.length; i++) {
149                        if (data[i].result.toLowerCase() == q.toLowerCase()) {
150                            result = data[i];
151                            break;
152                        }
153                    }
154                }
155                if (typeof fn == "function") fn(result);
156                else $input.trigger("result", result && [result.data, result.value]);
157            }
158            $.each(trimWords($input.val()), function(i, value) {
159                request(value, findValueCallback, findValueCallback);
160            });
161        }).bind("flushCache", function() {
162            cache.flush();
163        }).bind("setOptions", function() {
164            $.extend(options, arguments[1]);
165            if ("data" in arguments[1]) cache.populate();
166        }).bind("unautocomplete", function() {
167            select.unbind();
168            $input.unbind();
169            $(input.form).unbind(".autocomplete");
170        });
171
172        function selectCurrent() {
173            var selected = select.selected();
174            if (!selected) return false;
175            var v = selected.result;
176            previousValue = v;
177            if (options.multiple) {
178                var words = trimWords($input.val());
179                if (words.length > 1) {
180                    var seperator = options.multipleSeparator.length;
181                    var cursorAt = $(input).selection().start;
182                    var wordAt, progress = 0;
183                    $.each(words, function(i, word) {
184                        progress += word.length;
185                        if (cursorAt <= progress) {
186                            wordAt = i;
187                            return false;
188                        }
189                        progress += seperator;
190                    });
191                    words[wordAt] = v;
192                    v = words.join(options.multipleSeparator);
193                }
194                v += options.multipleSeparator;
195            }
196            $input.val(v);
197            hideResultsNow();
198            $input.trigger("result", [selected.data, selected.value]);
199            return true;
200        }
201        function onChange(crap, skipPrevCheck) {
202            if (lastKeyPressCode == KEY.DEL) {
203                select.hide();
204                return;
205            }
206            var currentValue = $input.val();
207            if (!skipPrevCheck && currentValue == previousValue) return;
208            previousValue = currentValue;
209            currentValue = lastWord(currentValue);
210            if (currentValue.length >= options.minChars) {
211                $input.addClass(options.loadingClass);
212                if (!options.matchCase) currentValue = currentValue.toLowerCase();
213                request(currentValue, receiveData, hideResultsNow);
214            } else {
215                stopLoading();
216                select.hide();
217            }
218        };
219
220        function trimWords(value) {
221            if (!value) return [""];
222            if (!options.multiple) return [$.trim(value)];
223            return $.map(value.split(options.multipleSeparator), function(word) {
224                return $.trim(value).length ? $.trim(word) : null;
225            });
226        }
227        function lastWord(value) {
228            if (!options.multiple) return value;
229            var words = trimWords(value);
230            if (words.length == 1) return words[0];
231            var cursorAt = $(input).selection().start;
232            if (cursorAt == value.length) {
233                words = trimWords(value)
234            } else {
235                words = trimWords(value.replace(value.substring(cursorAt), ""));
236            }
237            return words[words.length - 1];
238        }
239        function autoFill(q, sValue) {
240            if (options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE) {
241                $input.val($input.val() + sValue.substring(lastWord(previousValue).length));
242                $(input).selection(previousValue.length, previousValue.length + sValue.length);
243            }
244        };
245
246        function hideResults() {
247            clearTimeout(timeout);
248            timeout = setTimeout(hideResultsNow, 200);
249        };
250
251        function hideResultsNow() {
252            var wasVisible = select.visible();
253            select.hide();
254            clearTimeout(timeout);
255            stopLoading();
256            if (options.mustMatch) {
257                $input.search(function(result) {
258                    if (!result) {
259                        if (options.multiple) {
260                            var words = trimWords($input.val()).slice(0, -1);
261                            $input.val(words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : ""));
262                        } else {
263                            $input.val("");
264                            $input.trigger("result", null);
265                        }
266                    }
267                });
268            }
269        };
270
271        function receiveData(q, data) {
272            if (data && data.length && hasFocus) {
273                stopLoading();
274                select.display(data, q);
275                autoFill(q, data[0].value);
276                select.show();
277            } else {
278                hideResultsNow();
279            }
280        };
281
282        function request(term, success, failure) {
283            if (!options.matchCase) term = term.toLowerCase();
284            var data = cache.load(term);
285            if (data && data.length) {
286                success(term, data);
287            } else if ((typeof options.url == "string") && (options.url.length > 0)) {
288                var extraParams = {
289                    timestamp: +new Date()
290                };
291                $.each(options.extraParams, function(key, param) {
292                    extraParams[key] = typeof param == "function" ? param() : param;
293                });
294                $.ajax({
295                    mode: "abort",
296                    port: "autocomplete" + input.name,
297                    dataType: options.dataType,
298                    url: options.url,
299                    data: $.extend({
300                        wd: lastWord(term),
301                        limit: options.max
302                    }, extraParams),
303                    success: function(data) {
304                        var parsed = options.parse && options.parse(data) || parse(data);
305                        cache.add(term, parsed);
306                        success(term, parsed);
307                    }
308                });
309            } else {
310                select.emptyList();
311                failure(term);
312            }
313        };
314
315        function parse(data) {
316            var parsed = [];
317            var rows = data.split("\n");
318            for (var i = 0; i < rows.length; i++) {
319                var row = $.trim(rows[i]);
320                if (row) {
321                    row = row.split("|");
322                    parsed[parsed.length] = {
323                        data: row,
324                        value: row[0],
325                        result: options.formatResult && options.formatResult(row, row[0]) || row[0]
326                    };
327                }
328            }
329            return parsed;
330        };
331
332        function stopLoading() {
333            $input.removeClass(options.loadingClass);
334        };
335    };
336    $.Autocompleter.defaults = {
337        inputClass: "ac_input",
338        resultsClass: "ac_results",
339        loadingClass: "ac_loading",
340        minChars: 1,
341        delay: 400,
342        matchCase: false,
343        matchSubset: false,
344        matchContains: false,
345        cacheLength: 10,
346        max: 100,
347        mustMatch: false,
348        extraParams: {},
349        selectFirst: true,
350        formatItem: function(row) {
351            return row[0];
352        },
353        formatMatch: null,
354        autoFill: false,
355        width: 0,
356        multiple: false,
357        multipleSeparator: ", ",
358        highlight: function(value, term) {
359            return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
360        },
361        scroll: true,
362        scrollHeight: 180
363    };
364    $.Autocompleter.Cache = function(options) {
365        var data = {};
366        var length = 0;
367
368        function matchSubset(s, sub) {
369            if (!options.matchCase) s = s.toLowerCase();
370            var i = s.indexOf(sub);
371            if (options.matchContains == "word") {
372                i = s.toLowerCase().search("\\b" + sub.toLowerCase());
373            }
374            if (i == -1) return false;
375            return i == 0 || options.matchContains;
376        };
377
378        function add(q, value) {
379            if (length > options.cacheLength) {
380                flush();
381            }
382            if (!data[q]) {
383                length++;
384            }
385            data[q] = value;
386        }
387        function populate() {
388            if (!options.data) return false;
389            var stMatchSets = {},
390                nullData = 0;
391            if (!options.url) options.cacheLength = 1;
392            stMatchSets[""] = [];
393            for (var i = 0, ol = options.data.length; i < ol; i++) {
394                var rawValue = options.data[i];
395                rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
396                var value = options.formatMatch(rawValue, i + 1, options.data.length);
397                if (value === false) continue;
398                var firstChar = value.charAt(0).toLowerCase();
399                if (!stMatchSets[firstChar]) stMatchSets[firstChar] = [];
400                var row = {
401                    value: value,
402                    data: rawValue,
403                    result: options.formatResult && options.formatResult(rawValue) || value
404                };
405                stMatchSets[firstChar].push(row);
406                if (nullData++ < options.max) {
407                    stMatchSets[""].push(row);
408                }
409            };
410            $.each(stMatchSets, function(i, value) {
411                options.cacheLength++;
412                add(i, value);
413            });
414        }
415        setTimeout(populate, 25);
416
417        function flush() {
418            data = {};
419            length = 0;
420        }
421        return {
422            flush: flush,
423            add: add,
424            populate: populate,
425            load: function(q) {
426                if (!options.cacheLength || !length) return null;
427                if (!options.url && options.matchContains) {
428                    var csub = [];
429                    for (var k in data) {
430                        if (k.length > 0) {
431                            var c = data[k];
432                            $.each(c, function(i, x) {
433                                if (matchSubset(x.value, q)) {
434                                    csub.push(x);
435                                }
436                            });
437                        }
438                    }
439                    return csub;
440                } else if (data[q]) {
441                    return data[q];
442                } else if (options.matchSubset) {
443                    for (var i = q.length - 1; i >= options.minChars; i--) {
444                        var c = data[q.substr(0, i)];
445                        if (c) {
446                            var csub = [];
447                            $.each(c, function(i, x) {
448                                if (matchSubset(x.value, q)) {
449                                    csub[csub.length] = x;
450                                }
451                            });
452                            return csub;
453                        }
454                    }
455                }
456                return null;
457            }
458        };
459    };
460    $.Autocompleter.Select = function(options, input, select, config) {
461        var CLASSES = {
462            ACTIVE: "ac_over"
463        };
464        var listItems, active = -1,
465            data, term = "",
466            needsInit = true,
467            element, list;
468
469        function init() {
470            if (!needsInit) return;
471            element = $("<div/>").hide().addClass(options.resultsClass).css("position", "absolute").appendTo(document.body);
472            list = $("<ul/>").appendTo(element).mouseover(function(event) {
473                if (target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
474                    active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
475                    $(target(event)).addClass(CLASSES.ACTIVE);
476                }
477            }).click(function(event) {
478                $(target(event)).addClass(CLASSES.ACTIVE);
479                select();
480                input.focus();
481                return false;
482            }).mousedown(function() {
483                config.mouseDownOnSelect = true;
484            }).mouseup(function() {
485                config.mouseDownOnSelect = false;
486            });
487            if (options.width > 0) element.css("width", options.width);
488            needsInit = false;
489        }
490        function target(event) {
491            var element = event.target;
492            while (element && element.tagName != "LI") element = element.parentNode;
493            if (!element) return [];
494            return element;
495        }
496        function moveSelect(step) {
497            listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
498            movePosition(step);
499            var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
500            if (options.scroll) {
501                var offset = 0;
502                listItems.slice(0, active).each(function() {
503                    offset += this.offsetHeight;
504                });
505                if ((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
506                    list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
507                } else if (offset < list.scrollTop()) {
508                    list.scrollTop(offset);
509                }
510            }
511        };
512
513        function movePosition(step) {
514            active += step;
515            if (active < 0) {
516                active = listItems.size() - 1;
517            } else if (active >= listItems.size()) {
518                active = 0;
519            }
520        }
521        function limitNumberOfItems(available) {
522            return options.max && options.max < available ? options.max : available;
523        }
524        function fillList() {
525            list.empty();
526            var max = limitNumberOfItems(data.length);
527            for (var i = 0; i < max; i++) {
528                if (!data[i]) continue;
529                var formatted = options.formatItem(data[i].data, i + 1, max, data[i].value, term);
530                if (formatted === false) continue;
531                var li = $("<li/>").html(options.highlight(formatted, term)).addClass(i % 2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
532                $.data(li, "ac_data", data[i]);
533            }
534            listItems = list.find("li");
535            if (options.selectFirst) {
536                listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
537                active = 0;
538            }
539            if ($.fn.bgiframe) list.bgiframe();
540        }
541        return {
542            display: function(d, q) {
543                init();
544                data = d;
545                term = q;
546                fillList();
547            },
548            next: function() {
549                moveSelect(1);
550            },
551            prev: function() {
552                moveSelect(-1);
553            },
554            pageUp: function() {
555                if (active != 0 && active - 8 < 0) {
556                    moveSelect(-active);
557                } else {
558                    moveSelect(-8);
559                }
560            },
561            pageDown: function() {
562                if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
563                    moveSelect(listItems.size() - 1 - active);
564                } else {
565                    moveSelect(8);
566                }
567            },
568            hide: function() {
569                element && element.hide();
570                listItems && listItems.removeClass(CLASSES.ACTIVE);
571                active = -1;
572            },
573            visible: function() {
574                return element && element.is(":visible");
575            },
576            current: function() {
577                return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
578            },
579            show: function() {
580                var offset = $(input).offset();
581                element.css({
582                    width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
583                    top: offset.top + input.offsetHeight,
584                    left: offset.left
585                }).show();
586                if (options.scroll) {
587                    list.scrollTop(0);
588                    list.css({
589                        maxHeight: options.scrollHeight,
590                        overflow: 'auto'
591                    });
592                    if ($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
593                        var listHeight = 0;
594                        listItems.each(function() {
595                            listHeight += this.offsetHeight;
596                        });
597                        var scrollbarsVisible = listHeight > options.scrollHeight;
598                        list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight);
599                        if (!scrollbarsVisible) {
600                            listItems.width(list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")));
601                        }
602                    }
603                }
604            },
605            selected: function() {
606                var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
607                return selected && selected.length && $.data(selected[0], "ac_data");
608            },
609            emptyList: function() {
610                list && list.empty();
611            },
612            unbind: function() {
613                element && element.remove();
614            }
615        };
616    };
617    $.fn.selection = function(start, end) {
618        if (start !== undefined) {
619            return this.each(function() {
620                if (this.createTextRange) {
621                    var selRange = this.createTextRange();
622                    if (end === undefined || start == end) {
623                        selRange.move("character", start);
624                        selRange.select();
625                    } else {
626                        selRange.collapse(true);
627                        selRange.moveStart("character", start);
628                        selRange.moveEnd("character", end);
629                        selRange.select();
630                    }
631                } else if (this.setSelectionRange) {
632                    this.setSelectionRange(start, end);
633                } else if (this.selectionStart) {
634                    this.selectionStart = start;
635                    this.selectionEnd = end;
636                }
637            });
638        }
639        var field = this[0];
640        if (field.createTextRange) {
641            var range = document.selection.createRange(),
642                orig = field.value,
643                teststring = "<->",
644                textLength = range.text.length;
645            range.text = teststring;
646            var caretAt = field.value.indexOf(teststring);
647            field.value = orig;
648            this.selection(caretAt, caretAt + textLength);
649            return {
650                start: caretAt,
651                end: caretAt + textLength
652            }
653        } else if (field.selectionStart !== undefined) {
654            return {
655                start: field.selectionStart,
656                end: field.selectionEnd
657            }
658        }
659    };
660})(jQuery);

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.