Function.prototype.createDelegate = function (obj, args)
{
    var method = this;
    return function()
    {
        return method.apply(obj || window, args || arguments);
    }
}

Autocomplete = function (cfg)
{
    // id, ajax_url параметры должны быть заданы
    $.extend(this, cfg);

    this.input = $('#' + this.id);
    if (!this.hidden_id) this.hidden_id = this.id + '_hidden'
    this.hiddenInput = $('#' + this.hidden_id);

    this.init();
}

Autocomplete.prototype = {
    init: function()
    {
        old_value = this.input.val();
        this.input.autocomplete(
            this.ajax_url,
            {
                minChars:2,       // TODO; Сделать параметры конфигурируемыми
                //mustMatch:1,
                matchSubset:1,
                matchContains:1,
                cacheLength:10,
                selectFirst:1,
                selectOnly:1,

                onItemSelect: this.select.createDelegate(this)
//               formatItem: function(row){ return row[0] + (row[2]? ' <span>('+row[2]+')</span>' : '' ) }
            }
        );
        if(old_value != "") {
            this.input.val(old_value);
            this.input.get(0).lastSelected = old_value; // чтобы jquery.autocomplete не сбрасывала по блуру
        }
    },

    select: function(li)
    {
        if (!li.extra || !li.extra[0]) return;
        var id = li.extra[0];
        this.hiddenInput.val(id);
    },

    remove: function(id)
    {
        span_id = this.name+"-item-"+id;
        span = $(this.chosenDiv).find('#'+span_id);
        span.hide('fast', function (){ span.remove() }) // Красиво удаляем спан

        for (var i = 0; i < this.values.length; i++)
            if (id == this.values[i]) { this.values.splice(i,1); break }
        this.values_dict[id] = 0
        this.hiddenInput.value = this.values.join(',');
    }
}


AutocompleteMultiple = function (cfg)
{
    // name, ajax_url параметры должны быть заданы
    $.extend(this, cfg);

    this.input_id = "id_" + this.name;
    this.input = $('#' + this.input_id);
    this.hiddenInput = this.input.get(0).form[this.name];
    this.chosenDiv = $('#' + this.name + '-acm-chosen');

    this.init();
}

AutocompleteMultiple.prototype = {
    init: function()
    {
        this_obj = this;

        this.values = this.hiddenInput.value.split(',');
        this.values_dict = {};
        for (var i = 0; i < this.values.length; i++) {
            this.values_dict[this.values[i]] = 1;

            span_id = this.name+"-item-"+this.values[i];
            $('#' + span_id).click( this.remove.createDelegate(this, [this.values[i]]) );
        }

        this.input.autocomplete(
            this.ajax_url,
            {
                minChars:2,
                //mustMatch:1,
                matchSubset:1,
                matchContains:1,
                cacheLength:10,
                selectOnly:1,
                multipleSelect:true,

                onItemSelect: function(li) { if (li.extra && li.extra[0]) this_obj.add(li) }
//               formatItem: function(row){ return row[0] + (row[2]? ' <span>('+row[2]+')</span>' : '' ) }
            });
    },

    add: function(li)
    {
        var id = li.extra[0];
        span_id = this.name+"-item-"+id;
        if (this.values_dict[id]) { // Если уже добавлено, подсвечиваем и выходим
            span = $(this.chosenDiv).find('#'+span_id);
            old_color = span.css('color');
            span.animate({color: 'red'}, 300)
                .animate({color: old_color}, 1000)
            this.input.val('');
            return;
        }
        var title = $(li).text();
        $(this.chosenDiv).append("<span id="+span_id+">"+title+"</span> ");
        span = $(this.chosenDiv).find('#'+span_id);
        span.hide();
        span.show('slow');

        this_obj = this;
        span.click(function (){ this_obj.remove(id) });

        this.values.push(id);
        this.values_dict[id] = 1;
        this.hiddenInput.value = this.values.join(',');
        this.input.val('');
    },

    remove: function(id)
    {
        span_id = this.name+"-item-"+id;
        span = $(this.chosenDiv).find('#'+span_id);
        span.hide('fast', function (){ span.remove() }) // Красиво удаляем спан

        for (var i = 0; i < this.values.length; i++)
            if (id == this.values[i]) { this.values.splice(i,1); break }
        this.values_dict[id] = 0
        this.hiddenInput.value = this.values.join(',');
    }
}
