Reputation: 43
I have a collection of checkboxs and I want to create a custom method for them depending on which class they have.
var checkboxs = $("input[type=checkbox]");
checkboxs.each(function(){
if($(this).hasClass("class1")){
$(this).method1 = function(){
$(this).removeAttr("checked");
return $(this);
}
}
if($(this).hasClass("class2")){
$(this).method1 = function(){
$(this).parents("tr").next().hide();
$(this).removeAttr("checked");
return $(this);
}
}
});
Then if, I want to do this:
checkboxs.each(function(){
$(this).method1();
});
It tells me that there's no method1 method. Why doesn't that work?
Upvotes: 2
Views: 87
Reputation: 123739
Or you could write an common function extending jquery prototype.
$.fn.method1 = function(){
if(!this.is(':checkbox')) return this; //If it is called on a non check box just do nothing
if(!this.is('.class1, .class2')) return this; //if this is not of targetted classes return
if(this.is('.class2')){ //if class2 hide the next of its closest tr which comes up in its parent hierarchy.
this.closest('tr').next().hide(); //using closest assuming you want to check only its immediate tr in its parent hierarchy
}
this.prop("checked", false); //uncheck it if it is class 1 or 2
return this;
}
With the below you can avoid iteration at source:
Method:
$.fn.method1 = function () {
this.each(function(){
var $this = $(this);
if (!$this.is(':checkbox')) return true;
if (!$this.is('.class1, .class2')) return true;
if ($this.is('.class2')) {
$this.next().css('color', 'red');
}
$this.prop("checked", false);
});
return this;
}
Usage:
$("input[type=checkbox]").method1();
Upvotes: 1
Reputation: 3097
You can't just assign properties like that to a jQuery object, as it's just a wrapper around the element and will be re-created each time.
If you want to attach attributes to an element, use the data()
method. I'm not sure if this works for functions, but it's worth a shot.
In your case though, I suspect we have a bit of an XY problem. I would simply check the class of the object in the callback.
An example of what this might look like:
method1 = function() {
if($(this).hasClass("class2")) {
$(this).parents("tr").next().hide();
}
$(this).removeAttr("checked");
return $(this);
}
checkboxs.each(function(){
method1();
});
Depending on your use case, it may also work to just call each() on selections, which might look something like just running this instead of the last bit of code:
$('input[type=checkbox].class1').each(function(){
$(this).method1 = function(){
$(this).removeAttr("checked");
return $(this);
}
});
$('input[type=checkbox].class2').each(function(){
$(this).method1 = function(){
$(this).parents("tr").next().hide();
$(this).removeAttr("checked");
return $(this);
}
});
Without some actual code and context, we can't really tell you how best to do what you want.
Upvotes: 1
Reputation: 2879
The problem is that $(this)
creates a new jQuery object with the this
variable. This is done each time you call $(this)
therefor adding a method to $(this)
in one place will not make the method last in subsequent calls to $(this)
.
This jsFiddle shows the problem http://jsfiddle.net/92cub/1/
EDIT: I that the function could differ for each element, I've changed the given code to use the data
function in jQuery instead. Also you were doing $(this)
repeatedly so I removed that. The call $(this)
is quite heavy to do over and over again.
Instead you could do something likes this:
var checkboxs = $("input[type=checkbox]");
checkboxs.each(function(){
var $this = $(this);
if($this.hasClass("class1")){
$this.data("func", function (){
$this.removeAttr("checked");
return $this;
});
}
if($this.hasClass("class2")){
$this.data("func", function(){
$this.parents("tr").next().hide();
$this.removeAttr("checked");
return $this;
});
}
});
To call the function use:
checkboxs.each(function(){
$(this).data("func").apply();
});
Upvotes: 2