Вопрос по Jquery autocomplete

Тема в разделе "JavaScript", создана пользователем Dark Wizard, 18 ноя 2012.

Модераторы: ZiX
  1. Dark Wizard

    Dark Wizard

    Регистр.:
    23 сен 2007
    Сообщения:
    153
    Симпатии:
    76
    Доброго дня,

    никак не получается найти в этом плагине место, где выводится результат.

    Есть форма:

    Код:
    <form action="#">
    <p><label>Логин:</label> <input id="login" type="text" autocomplete="off"></p>
    </form>
    есть php файл, который выдаёт данные из базы в нужном формате (например:(

    Код:
    test1||муж||17
    test2||жен||22
    test2||жен||45
    test2||муж||11  
    и есть сам плагин отсюда http://ruseller.com/lessons.php?rub=37&id=1336 , с преобразованной разметкой:

    Код:
    /*
    * jQuery Autocomplete plugin 1.1
    *
    * Copyright (c) 2009 Jörn Zaefferer
    *
    * Dual licensed under the MIT and GPL licenses:
    *  http://www.opensource.org/licenses/mit-license.php
    *  http://www.gnu.org/licenses/gpl.html
    *
    * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
    */;
    (function ($) {
        $.fn.extend({
            autocomplete: function (b, d) {
                var c = typeof b == "string";
                d = $.extend({}, $.Autocompleter.defaults, {
                    url: c ? b : null,
                    data: c ? null : b,
                    delay: c ? $.Autocompleter.defaults.delay : 10,
                    autoFill: false,
                    minChars: 2,
                    max: d && !d.scroll ? 10 : 150
                }, d);
                d.highlight = d.highlight || function (a) {
                    return a
                };
                d.formatMatch = d.formatMatch || d.formatItem;
                return this.each(function () {
                    new $.Autocompleter(this, d)
                })
            },
            result: function (a) {
                return this.bind("result", a)
            },
            search: function (a) {
                return this.trigger("search", [a])
            },
            flushCache: function () {
                return this.trigger("flushCache")
            },
            setOptions: function (a) {
                return this.trigger("setOptions", [a])
            },
            unautocomplete: function () {
                return this.trigger("unautocomplete")
            }
        });
        $.Autocompleter = function (o, r) {
            var t = {
                UP: 38,
                DOWN: 40,
                DEL: 46,
                TAB: 9,
                RETURN: 13,
                ESC: 27,
                COMMA: 188,
                PAGEUP: 33,
                PAGEDOWN: 34,
                BACKSPACE: 8
            };
            var u = $(o).attr("autocomplete", "off").addClass(r.inputClass);
            var p;
            var m = "";
            var n = $.Autocompleter.Cache(r);
            var s = 0;
            var k;
            var h = {
                mouseDownOnSelect: false
            };
            var l = $.Autocompleter.Select(r, o, selectCurrent, h);
            var j;
            $.browser.opera && $(o.form).bind("submit.autocomplete", function () {
                if (j) {
                    j = false;
                    return false
                }
            });
            u.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function (a) {
                s = 1;
                k = a.keyCode;
                switch (a.keyCode) {
                    case t.UP:
                        a.preventDefault();
                        if (l.visible()) {
                            l.prev()
                        } else {
                            onChange(0, true)
                        }
                        break;
                    case t.DOWN:
                        a.preventDefault();
                        if (l.visible()) {
                            l.next()
                        } else {
                            onChange(0, true)
                        }
                        break;
                    case t.PAGEUP:
                        a.preventDefault();
                        if (l.visible()) {
                            l.pageUp()
                        } else {
                            onChange(0, true)
                        }
                        break;
                    case t.PAGEDOWN:
                        a.preventDefault();
                        if (l.visible()) {
                            l.pageDown()
                        } else {
                            onChange(0, true)
                        }
                        break;
                    case r.multiple && $.trim(r.multipleSeparator) == "," && t.COMMA:
                    case t.TAB:
                    case t.RETURN:
                        if (selectCurrent()) {
                            a.preventDefault();
                            j = true;
                            return false
                        }
                        break;
                    case t.ESC:
                        l.hide();
                        break;
                    default:
                        clearTimeout(p);
                        p = setTimeout(onChange, r.delay);
                        break
                }
            }).focus(function () {
                s++
            }).blur(function () {
                s = 0;
                if (!h.mouseDownOnSelect) {
                    hideResults()
                }
            }).click(function () {
                if (s++ > 1 && !l.visible()) {
                    onChange(0, true)
                }
            }).bind("search", function () {
                var c = (arguments.length > 1) ? arguments[1] : null;
     
                function findValueCallback(q, a) {
                    var b;
                    if (a && a.length) {
                        for (var i = 0; i < a.length; i++) {
                            if (a[i].result.toLowerCase() == q.toLowerCase()) {
                                b = a[i];
                                break
                            }
                        }
                    }
                    if (typeof c == "function") c(b);
                    else u.trigger("result", b && [b.data, b.value])
                }
                $.each(trimWords(u.val()), function (i, a) {
                    request(a, findValueCallback, findValueCallback)
                })
            }).bind("flushCache", function () {
                n.flush()
            }).bind("setOptions", function () {
                $.extend(r, arguments[1]);
                if ("data" in arguments[1]) n.populate()
            }).bind("unautocomplete", function () {
                l.unbind();
                u.unbind();
                $(o.form).unbind(".autocomplete")
            });
     
            function selectCurrent() {
                var e = l.selected();
                if (!e) return false;
                var v = e.result;
                m = v;
                if (r.multiple) {
                    var b = trimWords(u.val());
                    if (b.length > 1) {
                        var f = r.multipleSeparator.length;
                        var c = $(o).selection().start;
                        var d, progress = 0;
                        $.each(b, function (i, a) {
                            progress += a.length;
                            if (c <= progress) {
                                d = i;
                                return false
                            }
                            progress += f
                        });
                        b[d] = v;
                        v = b.join(r.multipleSeparator)
                    }
                    v += r.multipleSeparator
                }
                u.val(v);
                hideResultsNow();
                u.trigger("result", [e.data, e.value]);
                return true
            }
     
            function onChange(b, c) {
                if (k == t.DEL) {
                    l.hide();
                    return
                }
                var a = u.val();
                if (!c && a == m) return;
                m = a;
                a = lastWord(a);
                if (a.length >= r.minChars) {
                    u.addClass(r.loadingClass);
                    if (!r.matchCase) a = a.toLowerCase();
                    request(a, receiveData, hideResultsNow)
                } else {
                    stopLoading();
                    l.hide()
                }
            };
     
            function trimWords(b) {
                if (!b) return [""];
                if (!r.multiple) return [$.trim(b)];
                return $.map(b.split(r.multipleSeparator), function (a) {
                    return $.trim(b).length ? $.trim(a) : null
                })
            }
     
            function lastWord(a) {
                if (!r.multiple) return a;
                var c = trimWords(a);
                if (c.length == 1) return c[0];
                var b = $(o).selection().start;
                if (b == a.length) {
                    c = trimWords(a)
                } else {
                    c = trimWords(a.replace(a.substring(b), ""))
                }
                return c[c.length - 1]
            }
     
            function autoFill(q, a) {
                if (r.autoFill && (lastWord(u.val()).toLowerCase() == q.toLowerCase()) && k != t.BACKSPACE) {
                    u.val(u.val() + a.substring(lastWord(m).length));
                    $(o).selection(m.length, m.length + a.length)
                }
            };
     
            function hideResults() {
                clearTimeout(p);
                p = setTimeout(hideResultsNow, 200)
            };
     
            function hideResultsNow() {
                var c = l.visible();
                l.hide();
                clearTimeout(p);
                stopLoading();
                if (r.mustMatch) {
                    u.search(function (a) {
                        if (!a) {
                            if (r.multiple) {
                                var b = trimWords(u.val()).slice(0, -1);
                                u.val(b.join(r.multipleSeparator) + (b.length ? r.multipleSeparator : ""))
                            } else {
                                u.val("");
                                u.trigger("result", null)
                            }
                        }
                    })
                }
            };
     
            function receiveData(q, a) {
                if (a && a.length && s) {
                    stopLoading();
                    l.display(a, q);
                    autoFill(q, a[0].value);
                    l.show()
                } else {
                    hideResultsNow()
                }
            };
     
            function request(f, d, g) {
                if (!r.matchCase) f = f.toLowerCase();
                var e = n.load(f);
                if (e && e.length) {
                    d(f, e)
                } else if ((typeof r.url == "string") && (r.url.length > 0)) {
                    var c = {
                        timestamp: +new Date()
                    };
                    $.each(r.extraParams, function (a, b) {
                        c[a] = typeof b == "function" ? b() : b
                    });
                    $.ajax({
                        mode: "abort",
                        port: "autocomplete" + o.name,
                        dataType: r.dataType,
                        url: r.url,
                        data: $.extend({
                            q: lastWord(f),
                            limit: r.max
                        }, c),
                        success: function (a) {
                            var b = r.parse && r.parse(a) || parse(a);
                            n.add(f, b);
                            d(f, b)
                        }
                    })
                } else {
                    l.emptyList();
                    g(f)
                }
            };
     
            function parse(c) {
                var d = [];
                var b = c.split("\n");
                for (var i = 0; i < b.length; i++) {
                    var a = $.trim(b[i]);
                    if (a) {
                        a = a.split("||");
                        d[d.length] = {
                            data: a,
                            value: a[0],
                            result: r.formatResult && r.formatResult(a, a[0]) || a[0]
                        }
                    }
                }
                return d
            };
     
            function stopLoading() {
                u.removeClass(r.loadingClass)
            }
        };
        $.Autocompleter.defaults = {
            inputClass: "ac_input",
            resultsClass: "ac_results",
            loadingClass: "ac_loading",
            minChars: 1,
            delay: 400,
            matchCase: false,
            matchSubset: true,
            matchContains: false,
            cacheLength: 10,
            max: 100,
            mustMatch: false,
            extraParams: {},
            selectFirst: true,
            formatItem: function (a) {
                return a[0]
            },
            formatMatch: null,
            autoFill: false,
            width: 0,
            multiple: false,
            multipleSeparator: ", ",
            highlight: function (b, a) {
                return b.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + a.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>")
            },
            scroll: true,
            scrollHeight: 180
        };
        $.Autocompleter.Cache = function (g) {
            var h = {};
            var j = 0;
     
            function matchSubset(s, a) {
                if (!g.matchCase) s = s.toLowerCase();
                var i = s.indexOf(a);
                if (g.matchContains == "word") {
                    i = s.toLowerCase().search("\\b" + a.toLowerCase())
                }
                if (i == -1) return false;
                return i == 0 || g.matchContains
            };
     
            function add(q, a) {
                if (j > g.cacheLength) {
                    flush()
                }
                if (!h[q]) {
                    j++
                }
                h[q] = a
            }
     
            function populate() {
                if (!g.data) return false;
                var f = {}, nullData = 0;
                if (!g.url) g.cacheLength = 1;
                f[""] = [];
                for (var i = 0, ol = g.data.length; i < ol; i++) {
                    var c = g.data[i];
                    c = (typeof c == "string") ? [c] : c;
                    var d = g.formatMatch(c, i + 1, g.data.length);
                    if (d === false) continue;
                    var e = d.charAt(0).toLowerCase();
                    if (!f[e]) f[e] = [];
                    var b = {
                        value: d,
                        data: c,
                        result: g.formatResult && g.formatResult(c) || d
                    };
                    f[e].push(b);
                    if (nullData++ < g.max) {
                        f[""].push(b)
                    }
                };
                $.each(f, function (i, a) {
                    g.cacheLength++;
                    add(i, a)
                })
            }
            setTimeout(populate, 25);
     
            function flush() {
                h = {};
                j = 0
            }
            return {
                flush: flush,
                add: add,
                populate: populate,
                load: function (q) {
                    if (!g.cacheLength || !j) return null;
                    if (!g.url && g.matchContains) {
                        var a = [];
                        for (var k in h) {
                            if (k.length > 0) {
                                var c = h[k];
                                $.each(c, function (i, x) {
                                    if (matchSubset(x.value, q)) {
                                        a.push(x)
                                    }
                                })
                            }
                        }
                        return a
                    } else if (h[q]) {
                        return h[q]
                    } else if (g.matchSubset) {
                        for (var i = q.length - 1; i >= g.minChars; i--) {
                            var c = h[q.substr(0, i)];
                            if (c) {
                                var a = [];
                                $.each(c, function (i, x) {
                                    if (matchSubset(x.value, q)) {
                                        a[a.length] = x
                                    }
                                });
                                return a
                            }
                        }
                    }
                    return null
                }
            }
        };
        $.Autocompleter.Select = function (e, g, f, k) {
            var h = {
                ACTIVE: "ac_over"
            };
            var j, active = -1,
                data, term = "",
                needsInit = true,
                element, list;
     
            function init() {
                if (!needsInit) return;
                element = $("<div/>").hide().addClass(e.resultsClass).css("position", "absolute").appendTo(document.body);
                list = $("<ul/>").appendTo(element).mouseover(function (a) {
                    if (target(a).nodeName && target(a).nodeName.toUpperCase() == 'LI') {
                        active = $("li", list).removeClass(h.ACTIVE).index(target(a));
                        $(target(a)).addClass(h.ACTIVE)
                    }
                }).click(function (a) {
                    $(target(a)).addClass(h.ACTIVE);
                    f();
                    g.focus();
                    return false
                }).mousedown(function () {
                    k.mouseDownOnSelect = true
                }).mouseup(function () {
                    k.mouseDownOnSelect = false
                });
                if (e.width > 0) element.css("width", e.width);
                needsInit = false
            }
     
            function target(a) {
                var b = a.target;
                while (b && b.tagName != "LI") b = b.parentNode;
                if (!b) return [];
                return b
            }
     
            function moveSelect(b) {
                j.slice(active, active + 1).removeClass(h.ACTIVE);
                movePosition(b);
                var a = j.slice(active, active + 1).addClass(h.ACTIVE);
                if (e.scroll) {
                    var c = 0;
                    j.slice(0, active).each(function () {
                        c += this.offsetHeight
                    });
                    if ((c + a[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
                        list.scrollTop(c + a[0].offsetHeight - list.innerHeight())
                    } else if (c < list.scrollTop()) {
                        list.scrollTop(c)
                    }
                }
            };
     
            function movePosition(a) {
                active += a;
                if (active < 0) {
                    active = j.size() - 1
                } else if (active >= j.size()) {
                    active = 0
                }
            }
     
            function limitNumberOfItems(a) {
                return e.max && e.max < a ? e.max : a
            }
     
            function fillList() {
                list.empty();
                var b = limitNumberOfItems(data.length);
                for (var i = 0; i < b; i++) {
                    if (!data[i]) continue;
                    var a = e.formatItem(data[i].data, i + 1, b, data[i].value, term);
                    if (a === false) continue;
                    var c = $("<li/>").html(e.highlight(a, term)).addClass(i % 2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
                    $.data(c, "ac_data", data[i])
                }
                j = list.find("li");
                if (e.selectFirst) {
                    j.slice(0, 1).addClass(h.ACTIVE);
                    active = 0
                }
                if ($.fn.bgiframe) list.bgiframe()
            }
            return {
                display: function (d, q) {
                    init();
                    data = d;
                    term = q;
                    fillList()
                },
                next: function () {
                    moveSelect(1)
                },
                prev: function () {
                    moveSelect(-1)
                },
                pageUp: function () {
                    if (active != 0 && active - 8 < 0) {
                        moveSelect(-active)
                    } else {
                        moveSelect(-8)
                    }
                },
                pageDown: function () {
                    if (active != j.size() - 1 && active + 8 > j.size()) {
                        moveSelect(j.size() - 1 - active)
                    } else {
                        moveSelect(8)
                    }
                },
                hide: function () {
                    element && element.hide();
                    j && j.removeClass(h.ACTIVE);
                    active = -1
                },
                visible: function () {
                    return element && element.is(":visible")
                },
                current: function () {
                    return this.visible() && (j.filter("." + h.ACTIVE)[0] || e.selectFirst && j[0])
                },
                show: function () {
                    var a = $(g).offset();
                    element.css({
                        width: typeof e.width == "string" || e.width > 0 ? e.width : $(g).width(),
                        top: a.top + g.offsetHeight,
                        left: a.left
                    }).show();
                    if (e.scroll) {
                        list.scrollTop(0);
                        list.css({
                            maxHeight: e.scrollHeight,
                            overflow: 'auto'
                        });
                        if ($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
                            var c = 0;
                            j.each(function () {
                                c += this.offsetHeight
                            });
                            var b = c > e.scrollHeight;
                            list.css('height', b ? e.scrollHeight : c);
                            if (!b) {
                                j.width(list.width() - parseInt(j.css("padding-left")) - parseInt(j.css("padding-right")))
                            }
                        }
                    }
                },
                selected: function () {
                    var a = j && j.filter("." + h.ACTIVE).removeClass(h.ACTIVE);
                    return a && a.length && $.data(a[0], "ac_data")
                },
                emptyList: function () {
                    list && list.empty()
                },
                unbind: function () {
                    element && element.remove()
                }
            }
        };
        $.fn.selection = function (b, f) {
            if (b !== undefined) {
                return this.each(function () {
                    if (this.createTextRange) {
                        var a = this.createTextRange();
                        if (f === undefined || b == f) {
                            a.move("character", b);
                            a.select()
                        } else {
                            a.collapse(true);
                            a.moveStart("character", b);
                            a.moveEnd("character", f);
                            a.select()
                        }
                    } else if (this.setSelectionRange) {
                        this.setSelectionRange(b, f)
                    } else if (this.selectionStart) {
                        this.selectionStart = b;
                        this.selectionEnd = f
                    }
                })
            }
            var c = this[0];
            if (c.createTextRange) {
                var e = document.selection.createRange(),
                    orig = c.value,
                    teststring = "<->",
                    textLength = e.text.length;
                e.text = teststring;
                var d = c.value.indexOf(teststring);
                c.value = orig;
                this.selection(d, d + textLength);
                return {
                    start: d,
                    end: d + textLength
                }
            } else if (c.selectionStart !== undefined) {
                return {
                    start: c.selectionStart,
                    end: c.selectionEnd
                }
            }
        }
    })(jQuery);
    

    Вот никак не могу найти, как вывести во всплывающий список вторую-третью колонку (например, чтобы иконку пола вывести перед именем). Даже достаточно просто мне строку указать, где можно отредактировать формат списка-подсказки (например, чтобы выводилось для test1 "123test1", а при клике в input вставлялся test1.

    Надеюсь, понятно объяснил, большое спасибо тем, кого не затруднит отписать комментарий.

    P.S. Знаю, что это сделать можно - вот тут по-другому реализованно http://www.linkexchanger.su/2008/39.html , но напечатанные буквы не становятся жирными.
     
  2. recasher2k12

    recasher2k12

    Регистр.:
    19 фев 2012
    Сообщения:
    156
    Симпатии:
    78
    Смотри, в официальной документации api jQuery есть пример:
    Код:
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>autocomplete demo</title>
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css">
        <script src="http://code.jquery.com/jquery-1.8.2.js"></script>
        <script src="http://code.jquery.com/ui/1.9.1/jquery-ui.js"></script>
    </head>
    <body>
     
    <label for="autocomplete">Select a programming language: </label>
    <input id="autocomplete">
     
    <script>
    var tags = [ "c++", "java", "php", "coldfusion", "javascript", "asp", "ruby" ];
    $( "#autocomplete" ).autocomplete({
        source: function( request, response ) {
                var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( request.term ), "i" );
                response( $.grep( tags, function( item ){
                    return matcher.test( item );
                }) );
            }
    });
    </script>
     
    </body>
    </html>
    Тут тебя интересует опция source. Для твоей задачи необходимо использовать функцию как значение этой опции.
    В примере, приведенном выше, используется статичный справочник. Изменим пример на использование ajax:
    Код:
    <script>
    $( "#autocomplete" ).autocomplete({
        source: function( request, response ) {
                $.ajax({
                    type: 'POST',
                    url: '/ajax/autocomplete.php',
                    data: { term: request.term },
                    dataType: 'json',
                    success: function(data, status, xhr) {
                        response( data );
                    }
                });
            }
    });
    </script>
    Тогда запросы будут приходить на скрипт по адресу /ajax/autocomplete.php
    ту часть слова, которую ввели в input можно получить из переменной $_REQUEST['term']
    Скрипт на php должен отдавать результат в формате json, например:
    Код:
    [ "c++", "java", "php", "coldfusion", "javascript", "asp", "ruby" ]
    Чтобы в php преобразовать обычный массив в json-строку, можно воспользоваться функцией json_encode().

    Далее, например, чтобы буковки, введенные пользователем, в результатах выделялись жирненьким, тебе нужно выполнить следующее:
    Код:
    <script>
    $( "#autocomplete" ).autocomplete({
        source: function( request, response ) {
                $.ajax({
                    type: 'POST',
                    url: '/ajax/autocomplete.php',
                    data: { term: request.term },
                    dataType: 'json',
                    success: function(data, status, xhr) {
                        // новый массив данных
                        var newData = [];
                        // регулярочка
                        var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( request.term ), "i" );
                        for(var i=0; i<data.length; i++) {
                            // добавляем в новый массив данных строку data[i] с выделенным ожирением
                            // введенной пользователем части слова
                            newData.push( data[i].replace(matcher, '<b>$&</b>') );
                        }
                        response( newData );
                    }
                });
            }
    });
    </script>
    В принципе, на основе последнего примера, ты можешь выводить в массив newData любые сколько угодно много данных размечая их хоть таблицами.

    Как-то так. коды я не проверял, могут быть написаны с ляпами. Но разжевал все по-максимуму )
     
    Dark Wizard нравится это.
  3. Dark Wizard

    Dark Wizard

    Регистр.:
    23 сен 2007
    Сообщения:
    153
    Симпатии:
    76
    Спасибо большое за объяснения, я сделал немного по-другому - доработал код с http://www.linkexchanger.su/2008/39.html - оказалось проще всего под мои нужды.