开发者

jQuery plugin 'this.each is not a function'

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') then this will already be a jQuery object and calling $(this) is redundant.
  • If you call the function from the each loop in init, then this will refer to one DOM element. So calling $(this) is necessary, but using each 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 the init and destroy 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜