I am trying to create my first jQuery plugin and I am geting the error this.each is not a function
, which is referencing this line return this.each(function() {
in the bindUi
method. I thought that this
referred to the "jQuery object the plugin was invoked on", which in my case would be the #location
node I used 开发者_StackOverflow社区when creating my plugin with $('#location').locationSearch()
, right? I get this error on page load.
Here is my plugin code:
(function($) {
var methods = {
init : function( options ) {
return this.each(function() {
var settings = {
//none yet
};
if ( options ) {
$.extend( settings, options );
}
methods.log('init');
//attach events
methods.bindUi();
});
},
destroy : function( ) {
return this.each(function(){ });
},
bindUi : function() {
return this.each(function() {
methods.log('bindUi');
this.click(function() {
methods.log('clicked');
});
});
},
log : function(text) {
if (window.console && window.console.log) {
window.console.log(text);
};
}
} // end methods
jQuery.fn.locationSearch = function(method) {
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
};
})( jQuery );
I am also a little confused if every one of my methods needs to use return this.each(function() { ..
or if only the init and destroy methods use it?
You have to call
methods.bundUi.apply(this);
in your init
method.
If you only do methods.bindUi()
, then this
inside bindUi
will refer to the methods
object.
Update:
Oh I just saw it. You are calling methods.bindUi()
inside the each
loop. Then this
will refer to the current DOM element. So the question is now, what do you want to refer to inside bindUi
? All the selected elements, or only the current one from the loop?
Here are the two possibilites:
A: All elements
init : function( options ) {
this.each(function() {
var settings = {
//none yet
};
if ( options ) {
$.extend( settings, options );
}
methods.log('init'); // <- this might be also better outside the loop
});
//attach events
methods.bindUi.apply(this); // <- called outside the each loop
return this;
}
(no need to change bindUi
)
B: One element. this
inside the each
loop in init
will refer to the current DOM element. We deal with only one element at the time, so we don't need to use each
in the bindUi
method. (still use methods.bindUi.apply(this)
in init
(but inside the loop, just like you already have it)). But you can't call bindUi
from the outside anymore (i.e. you can't call .locationSearch('bindUi')
).
bindUi : function() {
// don't need `each`, as `this` will refer to only one element.
methods.log('bindUi');
$(this).click(function() {
methods.log('clicked');
});
},
A third solution would indeed be to just change this
to $(this)
inside the bindUi
function. This will definitely work, but has two "misconceptions":
- If the function is called via
.locationSearch('bindUi')
thenthis
will already be a jQuery object and calling$(this)
is redundant. - If you call the function from the
each
loop ininit
, thenthis
will refer to one DOM element. So calling$(this)
is necessary, but usingeach
to loop over one element is pointless.
I am also a little confused if every one of my methods needs to use return
this.each(function() { ..
or if only theinit
anddestroy
methods use it?
Every method that should be callable via .locationSearch(method)
should return this
.
Try $(this).each(
.
jQuery usually lets you use this
to refer to the pure HTML element (not the jQuery wrapped one). You have to wrap it again to gain jQuery functionality.
精彩评论