0

I posted a similar issue earlier, but it was flagged as a duplicate. However, this referenced article did not answer my question, so I'll try this again, this time using the solution of said article in my example.

The solution provided in this article creates the same issue I had before: when there is more than one element, I cannot call any of the public methods of the plugin.

Since no working example was provided, let's start with the code the article gave:

(function($){

     $.fn.myPlugin = function(options) {
          // support multiple elements
          if (this.length > 1){
              this.each(function() { $(this).myPlugin(options) });
              return this;
          }

          // private variables
          var pOne = '';
          var pTwo = '';
          // ...

          // private methods
          var foo = function() {
              // do something ...
          }
          // ...

          // public methods        
          this.initialize = function() {
              // do something ...
              return this;
          };

          this.bar = function() {
              // do something ...
          };
          return this.initialize();
      }
 })(jQuery);

I LOVE the internal loop so that it's applied to each instance of the element, but I feel the repeated "return this" is redundant. I think if we removed every single one of them, this plugin would work exactly the same. But, for the sake of argument, I'm going to leave them in my working example.

As you can see in this jsfiddle example, it works fine when there is only one element. The public method runs fine.

However, if I were to comment the other 4 elements back in like here, it throws an error in the console: "undefined is not a function". This, of course, makes sense since I'm attempting to run the public method on a reference to all elements on not an individual element.

Well, then I use .eq(0) to run the method only on the first instance of the element here, but I get the exact same error in the console.

So, why isn't calling the public method on the individual element working? Is this a scoping issue?

Please advise. Thanks!

Community
  • 1
  • 1
linnium
  • 368
  • 1
  • 4
  • 15

1 Answers1

0

Ok, so I think I've answered my own question. The issue is that I'm not applying a jQuery plugin to a DOM element. I'm applying it to a jQuery element. So, if I were to apply the jQuery plugin to a jQuery element, referenced like $element or $('.element'), I can then run any public methods because the scope is the same. But, if I were to reference it in a different way, like say $parentelement.eq(0), I'm using a difference reference, one that did not get the plugin applied to it, so naturally, it would not have the defined method. I think I'm getting the concept right. Still a little shaky on this. Maybe someone else can explain it better.

Nevertheless, while the above code does technically work, public methods are not practical on a jQuery plugin. I suggest instead using a Custom Event to make the jQuery plugin do something. Like this:

 (function($) {
     $.fn.extend({
         myTestPlugin: function() {

             if (this.length > 1) {
                 this.each(function() { $(this).myTestPlugin(); });
             }

             this.done = function() {
                 $(this).html('Done!');
             };

             var alsoDone = function() {
                 $(this).html('Also done!');
             };

             this.html('Replace me!');
             this.on('alsoDone', alsoDone);
         }
     });
 })(jQuery);

Here is an example where I am using trigger to make the plugin do something on an individual element, which works, but the method still fails as expected.

I hope this helps other people with similar issues.

linnium
  • 368
  • 1
  • 4
  • 15