destroying jquery ui plugin instances
I have a tagging plugin.
The plugin is getting used on an element of a form that is generated via ajax.
something like
...
success : function(data) {
$.lightbox(data);
$('#groups').tagit();
}
...
Now when the form is submitted (by ajax) the lightbox is removed, hence so is the form.
But,
If I click the button to create a new form the plugin is in its previous state, even though #groups is now a completely new dom element.
why is this and how can I fix it?
(by in the same state I mean)
I have a variable is the plugin
_vars : {tags: []}
this gets populated as tags are added. when the plugin is called again on the new #groups the tags variable contains all tags from the previous instance.
how can I fix this?
Code
$.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.op开发者_运维知识库tions.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;
}
})
;
you could do following
success : function(data) {
$.lightbox(data);
$('#groups').tagit("destroy").tagit();
}
dont forget to override the destroy method in your class
destroy: function() {
$.Widget.prototype.destroy.apply(this, arguments); // default destroy
// now do other stuff particular to this widget
}
for your need, i think you should destroy your vars, clear them, free connections and unbind events. the destroy method should restore the element on which the widget was applied to the original state.
This for example is doing the base destroy method, just to know, what for you can use it.
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" );
}
精彩评论