jQuery.fn.autocomplete = function (u, valueInput, addressInput, s, p) {
    return this.each(function () {
        $('#do').css({ display: 'block' });
        var t = $(this);
        var v = $(this).next();
        v.after('<ul class="ui-ac"></ul>');
        var list = v.next().css({ top: t.offset().top + t.outerHeight(), left: t.offset().left });
        var o = '', to, z = -1, l = -1;
        $('#do').css({ display: 'none' });

        s = jQuery.extend(
		{
		    minChars: 3,
		    timeout: 250,
		    after: null,
		    before: null,
		    vs: true,
		    parameters: {}
		}, s);

        function getData(text) {
            window.clearInterval(to);
            if (text != o && (s.minChars != null && text.length >= s.minChars)) {
                clear();
                if (s.before != null) {
                    s.before(s.parameters);
                }
                t.addClass('ui-acl');
                s.parameters.t = text;
                $.getJSON(u, s.parameters, function (d) {

                    var items = '';
                    if (d) {
                        z = d.length;
                        for (var i = 0; i < d.length; i++) {
                            items += '<li val="' + d[i].i + '" title="' + d[i].a + '"><img src="/images/culture/' + d[i].c + '.gif" /> ' + d[i].l.replace(new RegExp("(" + text + ")", "i"), "<b>$1</b>") + '</li>';
                            list.html(items);
                            list.show().children().
                            	hover(function () { $(this).addClass("s").siblings().removeClass("s"); }, function () { $(this).removeClass("s") }).
                            	click(function () {
                            	    valueInput.val($.trim($(this).attr('val')));
                            	    if (addressInput != null) {
                            	        addressInput.attr('alt', $(this).attr('title'));
                            	        addressInput.attr('title', $(this).attr('title'));
                            	    }
                            	    t.val($(this).text()); clear();
                            	});
                        }
                        if (s.after != null) {
                            s.after(t, text);
                        }
                    }
                    t.removeClass('ui-acl');
                });
                o = text;
            }
        }

        function clear() {
            list.hide();
            z = -1;
            l = -1;
        }

        $(document).click(function () { clear(); });
        t.keydown(function (e) {
            window.clearInterval(to);
            if (e.which == 27) {
                clear();
            } else if (e.which == 46 || e.which == 8) {
                clear();
                if (s.vs) { valueInput.val(''); if (addressInput != null) { addressInput.attr('alt', ''); addressInput.attr('title', ''); } }
            }
            else if (e.which == 13) {
                if (list.css("display") == "none") {
                    getData(t.val());
                } else {
                    clear();
                }
                e.preventDefault();
                return false;
            }
            else if (e.which == 40 || e.which == 9 || e.which == 38) {
                switch (e.which) {
                    case 40:
                    case 9:
                        l = l >= (z - 1) ? 0 : l + 1; break;
                    case 38:
                        l = l <= 0 ? z - 1 : l - 1; break;
                    default: break;
                }
                t.val(list.children().removeClass('s').eq(l).addClass('s').text());
                valueInput.val($.trim(list.children().eq(l).attr('val')));
                if (addressInput != null) {
                    addressInput.attr('alt', list.children().eq(l).attr('title'));
                    addressInput.attr('title', list.children().eq(l).attr('title'));
                }
            } else {
                if (s.vs) {
                    valueInput.val('');
                    if (addressInput != null) { addressInput.attr('alt', ''); addressInput.attr('title', ''); }
                }
                to = window.setTimeout(function () { getData(t.val()) }, s.timeout);
            }
        });
    });
};
