Вопрос по Jquery autocomplete

Dark Wizard

Гуру форума
Регистрация
23 Сен 2007
Сообщения
194
Реакции
80
Доброго дня,

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

Есть форма:

Код:
<form action="#">
<p><label>Логин:</label> <input id="login" type="text" autocomplete="off"></p>
</form>

есть php файл, который выдаёт данные из базы в нужном формате (например:(

Код:
test1||муж||17
test2||жен||22
test2||жен||45
test2||муж||11

и есть сам плагин отсюда Для просмотра ссылки Войди или Зарегистрируйся , с преобразованной разметкой:

Код:
/*
* 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. Знаю, что это сделать можно - вот тут по-другому реализованно Для просмотра ссылки Войди или Зарегистрируйся , но напечатанные буквы не становятся жирными.
 
Смотри, в официальной документации Для просмотра ссылки Войди или Зарегистрируйсяесть пример:
Код:
<!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-строку, можно воспользоваться функцией Для просмотра ссылки Войди или Зарегистрируйся.

Далее, например, чтобы буковки, введенные пользователем, в результатах выделялись жирненьким, тебе нужно выполнить следующее:
Код:
<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 любые сколько угодно много данных размечая их хоть таблицами.

Как-то так. коды я не проверял, могут быть написаны с ляпами. Но разжевал все по-максимуму )
 
Спасибо большое за объяснения, я сделал немного по-другому - доработал код с Для просмотра ссылки Войди или Зарегистрируйся - оказалось проще всего под мои нужды.
 
Назад
Сверху