1

I'm working on a jQuery plugin. It's my first, so I apologize if this is a dumb question.

I have several public methods within the plugin.

I'm trying to call these methods from within the plugin definition AND outside the plugin in a similar way to how the public keyword works in Java for methods, but I keep getting undefined is not a function errors.

I've tried calling it several ways, but still can't get it to work.

Any ideas on how to do this?

Here's an example of my codebase:

$(document).ready(function() {    

    (function($) {

        // Plugin Definition
        $.fn.popup = function(options){
            // code here...

            // SUBMIT FORM
            $(settings.popupSubmitSelector).on("click", function(e) {
                submitForm();             // call to my method
                this.submitForm();
                $.fn.popup.submitForm();   
            });

            // more code here...

            // my public method
            this.submitForm = function(){
                // method code here
            }

            // more code...
        }
    }(jQuery));
});
dartanian300
  • 247
  • 2
  • 16
  • Can we see the skeleton of your plugin definition? – PeterKA Jul 10 '14 at 18:41
  • Did you follow a tutorial how to develop a jQuery Plugin? – wiesion Jul 10 '14 at 18:47
  • @wiesion yes, I viewed the examples on [jquery.com](http://learn.jquery.com/plugins/basic-plugin-creation/), http://scriptble.com/2011/02/14/expanding-the-jquery-plugin-development-pattern/, and http://www.learningjquery.com/2007/10/a-plugin-development-pattern/ – dartanian300 Jul 10 '14 at 18:51
  • @dartanian300 The latter is from 2007, the former seems to be a broken link. Please go to http://learn.jquery.com/plugins/ – wiesion Jul 10 '14 at 18:57
  • @wiesion I'm not sure why that second link is broken. Try putting http:// before it. Also, that page you posted is one of the pages on the jQuery page I posted. – dartanian300 Jul 10 '14 at 19:01
  • See: http://stackoverflow.com/questions/1117086/ – PeterKA Jul 10 '14 at 19:18

3 Answers3

5

I think i understand your problem now. If you want to execute a public method WITHIN an instance of the same object, you have to refer properly to the current instance. In JS you can achieve that this way:

var MyObj = function() {
  var instance = this;

  this.publicMethod = function() {
    alert('test');
  }

  var privateMethod = function() {
    instance.publicMethod();
  }

  return this;

}

Update Here's the basic skeleton for a plugin using a proxy function to expose functionality

(function($) {
    var settings = { ... };

    var methods = {
        init: function(options) { ... submitForm() ... },
        submitForm: function() { /* code here */ }
    };

    $.fn.popup = 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.popup');
        }
    };

})(jQuery);

You can then access from outside by

$('selector').popup('submitForm');
wiesion
  • 2,349
  • 12
  • 21
  • But still, this isn't best practice for jQuery Plugins. You should collect all methods as private and expose them through a proxy function. – wiesion Jul 10 '14 at 19:09
  • That seems to be working! Could you also provide an example of the proxy function method you mentioned? – dartanian300 Jul 10 '14 at 19:14
  • Updated my answer and added a basic plugin skeleton using a proxy method – wiesion Jul 10 '14 at 19:25
  • Thanks for all your help! Could you perhaps explain why your first answer is bad practice? – dartanian300 Jul 10 '14 at 19:43
  • It's absolutely not bad practice in terms of JS; it's just not best practice for jQuery plugins. By using a proxy method you don't have to explicitly reference the instance of the plugin when using its methods internally, and to call them publicly from the outside you just pass the name of the method as an argument to your plugin. – wiesion Jul 10 '14 at 20:05
  • If I utilize the proxy method, can I overwrite methods for specific instances of the plugin? – dartanian300 Jul 11 '14 at 20:15
0

Try something like:

$(document).ready(function () {

$(selector).click(function() {
    nameFunc();
});

});

var nameFunc = function () {

//Code

};

OR:

$(document).ready(function () {

$(selector).click(function() {
    OtherFunc();
});

function OtherFunc() {
 //Code
};

});
Glegan
  • 110
  • 1
  • 8
  • I've wrapped the entire plugin in `$(document).ready(function() {});` already, but it doesn't seem to solve this problem. The event listener is being called from within the plugin definition. – dartanian300 Jul 10 '14 at 18:41
  • I think you have to remove the "this" prefix because you're calling it outside the function... – Glegan Jul 10 '14 at 19:00
  • I think @user3558931 has the right answer in the post that he share to you. – Glegan Jul 10 '14 at 19:11
0

From Provide Public Access to Secondary Functions as Applicable one way you can achieve your goal is to define you method as follows:

$.fn.popup.submitForm = function() {
    //method body
};

And you can call it the same way, outside or inside the plugin:

$.fn.popup.submitForm();
PeterKA
  • 24,158
  • 5
  • 26
  • 48
  • I think you misunderstand. I need to call that function from the plugin itself. I also posted more information, does that help? – dartanian300 Jul 10 '14 at 18:53
  • Exactly the point of sharing enough information at the start. Unless you really want to call that method outside the plugin, you should not prefix it with `this` .... just declare it as any other function and it will be accessible in side the plugin only. – PeterKA Jul 10 '14 at 18:56
  • I need access from within the plugin AND outside the plugin. – dartanian300 Jul 10 '14 at 18:59
  • 1
    Very well then. I think we are getting somewhere now. You may want then to define your methods as in the answer to this post: http://stackoverflow.com/questions/1117086/ with a slight modification as I will show above. – PeterKA Jul 10 '14 at 19:04