0

I have a script that I didn't write already running on a page. I'd like to, in a script I did write, be able to execute a function from the original script. Here's a simplified example of what I'm trying to do:

(function ($) {
$.fn.myExistingFunction = function (options) {
    function doMyThing(text) {
        alert(text);
    }
}
}(jQuery));

jQuery(document).ready(function($) {
    $.fn.myExistingFunction.doMyThing("alert text");
});

However, when I run this, I get the console output:

Uncaught TypeError: Object function (options) {

    function doMyThing(text) {
       alert(text);
    }

} has no method 'doMyThing'

But it clearly has the method! I can see it right there. What am I getting wrong here?

bcorkins
  • 129
  • 6
  • You need to use `var methods = some object`, and pass to the plugin, it's explained in the [plugin authoring](http://docs.jquery.com/Plugins/Authoring#Plugin_Methods) docs! – adeneo Sep 03 '12 at 18:40

2 Answers2

1

You can only access that method from the scope of the plugin function. It is not defined in the global scope.

So you can't call that function. All you can do in your code is call functions that are available through what's called the scope chain where the function is called. In your case that is everything that is either defined in your function($){} or in global scope. But the function in the plugin is neither.

When you call $.fn.myExistingFunction.doMyThing you are treating doMyThing like an field in the myExistingFunction object. But actually it is defined inside the function. Maybe this code makes it clearer:

$.fn.myExistingFunction = function (options) {
    var doMyThing = function(text) {
        alert(text);
    }
    var hi = "hello";
}

In hi and doMyThing are local variables in the scope of myExistingFunction. If the plugin wasn't designed to expose the functionality to external code you can't access the variables.

An example of a plugin that was designed to expose some of its internal functions would be the jQuery UI datepicker (documentation). It needs functions like parseDate and formatDate interally, but these utility functions are likely to be useful for general development as well, which is why they have been added to the datepicker object explicitly.

Community
  • 1
  • 1
Matt Zeunert
  • 16,075
  • 6
  • 52
  • 78
  • Ok, thank you. So supposing I were to change doMyThing in order to make it work, I'd have to set it up like you did in the example above? With "var doMyThing = function() {}"? I could do it that way.. I was just trying to avoid modifying the original file since it's huge and will probably take me a while to get everything working again. – bcorkins Sep 03 '12 at 20:58
  • @BCDesign No, if you set it as a local variable it won't work. You need to add the function to the $.fn.myExistingFunction object, which you can then access from outside the plugin. Just make sure that the doMyThing function doesn't rely on variables that are in the myExistingFunction scope. If there aren't any issues with that you can move the function to the $.fn.myExistingFunction object. To keep the changes to the plugin minimal I'd keep the function declaration for doMyThing in the myExistingFunction code and then just do function doMyThing(arg){$.fn.myExistingFunction.doMyThing(arg)}; – Matt Zeunert Sep 03 '12 at 22:22
0

I think your code needs a major rewriting, 'cause as it is it will never work, in fact your function doMyThing is not a property of $.fn.myExistingFunction, it is simply declared inside of it, and due to how the scope works in javascript, you'll never be able to call it.

Matteo Tassinari
  • 18,121
  • 8
  • 60
  • 81