уничтожение экземпляров плагина jquery ui - PullRequest
1 голос
/ 07 февраля 2011

У меня есть плагин для тегов.

Плагин используется для элемента формы, сгенерированного с помощью ajax.

что-то вроде

...
success : function(data) {
   $.lightbox(data);
   $('#groups').tagit();
}
...

Теперь, когда форма отправлена ​​(с помощью ajax), лайтбокс удаляется, поэтому форма тоже.

Но

Если я нажму кнопку, чтобы создать новую форму, плагин будет в своем прежнем состоянии, хотя #groups теперь является совершенно новым элементом dom.

почему это так и как я могу это исправить?

(в том же состоянии я имею в виду)

У меня есть переменная плагина

_vars : {tags: []}

заполняется при добавлении тегов. когда плагин вызывается снова в новой #groups, переменная tags содержит все теги из предыдущего экземпляра.

как я могу это исправить?

<ч /> код

$.widget("ui.tagit", {

    // default options
    options: {
        tagSource:   [],
        allowSpace:  true,
        initialTags: [],
        minLength:   1
    },

    //private variables
    _vars: {
        lastKey: null,
        element: null,
        input:   null,
        tags:    []
    },

    _keys: {
        backspace: 8,
        enter:     13,
        space:     32,
        comma:     44
    },

    //initialization function
    _create: function() {

        var instance = this;

        //store reference to the ul
        this._vars.element = this.element;

        //add class "tagit" for theming
        this._vars.element.addClass("tagit");

        //add any initial tags added through html to the array
        this._vars.element.children('li').each(function() {
            instance.options.initialTags.push($(this).text());
        });

        //add the html input
        this._vars.element.html('<li class="tagit-new"><input class="tagit-input" type="text" /></li>');

        this._vars.input = this._vars.element.find(".tagit-input");

        //setup click handler
        $(this._vars.element).click(function(e) {
            if (e.target.tagName == 'A') {
                // Removes a tag when the little 'x' is clicked.
                $(e.target).parent().remove();
                instance._popTag();
            }
            else {
                instance._vars.input.focus();
            }
        });

        //setup autcomplete handler

        this.options.appendTo = this._vars.element;
        this.options.source = this.options.tagSource;
        this.options.select = function(event, ui) {
            instance._addTag(ui.item.value, ui.item.id);
            return false;
        }
        this._vars.input.autocomplete(this.options);

        //setup keydown handler
        this._vars.input.keydown(function(event) {
            var lastLi = instance._vars.element.children(".tagit-choice:last");
            if (event.which == instance._keys.backspace)
                return instance._backspace(lastLi);

            if (lastLi.hasClass('selected'))
                lastLi.removeClass('selected');

            // Comma/Space/Enter are all valid delimiters for new tags.
            else if (event.which == instance._keys.comma || (event.which == instance._keys.space && !instance.options.allowSpace) || event.which == instance._keys.enter) {
                event.preventDefault();
                instance._addTag(this.value, 0);
            }
            instance._vars.lastKey = event.which;
        })

        //define missing trim function for strings
        String.prototype.trim = function() {
            return this.replace(/^\s+|\s+$/g, "");
        };

        this._initialTags();

    },
    _popTag: function() {
        return this._vars.tags.pop();
    },

    _addTag: function(value, id) {
        id = (id == null ? 0 : id);
        this._vars.input.val("");
        value = value.replace(/,+$/, "");
        value = value.trim();
        if (value == "" || this._exists(value))
            return false;

        var tag = "";
        tag = '<li class="tagit-choice">' + value + '<a class="tagit-close">x</a></li>';
        $(tag).insertBefore(this._vars.input.parent());
        this._vars.input.val("");
        this._vars.tags.push({id: id, value: value});
    },

    _exists: function(value) {
        if (this._vars.tags.length == 0)
            return false;
        for (var i = 0; i <= this._vars.tags.length-1; i++)
            if (this._vars.tags[i].value == value)
                return true;
        return false;
    }
    ,

    _oc: function(array) {
        var object = {};
        for (var i = 0; i < array.length; i++) {
            object[array[i]] = '';
        }
        return object;
    }
    ,

    _backspace: function(li) {
        if (this._vars.input.val() == "") {
            // When backspace is pressed, the last tag is deleted.
            if (this._vars.lastKey == this._keys.backspace) {
                $(this)._tagger('remove');
                li.remove();
                this._vars.lastKey = null;
            } else {
                li.addClass('selected');
                this._vars.lastKey = this._keys.backspace;
            }
        }
        return true;
    }
    ,

    _initialTags: function() {
        if (this.options.initialTags.length != 0) {
            for (var i in this.options.initialTags)
                if (!this._exists(this.options.initialTags[i]))
                    this._addTag(this.options.initialTags[i]);
        }
    }
    ,

    tags: function() {
        return this._vars.tags;
    }
})
        ;

1 Ответ

3 голосов
/ 07 февраля 2011

вы можете сделать следующее

success : function(data) {
   $.lightbox(data);
   $('#groups').tagit("destroy").tagit();
}

не забудьте переопределить метод уничтожения в вашем классе

destroy: function() {
       $.Widget.prototype.destroy.apply(this, arguments); // default destroy
        // now do other stuff particular to this widget
   }

для ваших нужд, я думаю, вы должны уничтожить свои переменные, очистить их, освободить связи и удалить события. метод destroy должен восстановить элемент, к которому был применен виджет, в исходное состояние.

Это, например, метод базового уничтожения, просто чтобы знать, для чего вы можете его использовать.

destroy: function() {
        this.element
            .unbind( "." + this.widgetName )
            .removeData( this.widgetName );
        this.widget()
            .unbind( "." + this.widgetName )
            .removeAttr( "aria-disabled" )
            .removeClass(
                this.widgetBaseClass + "-disabled " +
                "ui-state-disabled" );
    }
...