1

I have been trying to work out why my public methods do not appear to exist for my custom jQuery plugin object.

I have created a simplified version of the jQuery plugin with a private variable and two public methods to access/modify the private variable. I have looked online but the results are not that clear, that or my searching skills are terrible.

It keeps saying 'TypeError: myObject.getMyValue is not a function', anyone got a clue as to what I am doing wrong, or suggestions for a better approach to this?

The basic object class is below, but a proper code example can be found on the jsFiddle link.

(function ($) {

    var MyClass = function (element) {

        var myValue = 'Hello World';

        this.getMyValue = function() {
            return myValue;
        };

        this.setMyValue = function(value) {
            myValue = value;
        };

        return this;
    };

    $.fn.myPlugin = function() {
        return this.each(function(key, value){
            if ($(this).data('myclass')) {
                return $(this).data('myclass');
            }

            var instance = new MyClass(this);
            $(this).data('myclass', instance);
            return instance;
        });
    };

})(jQuery);

var myObject = $('#test').myPlugin();

alert(myObject.getMyValue());
myObject.setMyValue('Goodbye World');
alert(myObject.getMyValue());

http://jsfiddle.net/hZExb/4/

Shane Yu
  • 252
  • 3
  • 9
  • because you do `return this.each` so your `myPlugin()` call returns the jQuery object for chainability. The `return instance` call you are doing is just returning it to the iterator function of `this.each` which discards the value. – Chad Mar 31 '13 at 16:03
  • Classic blunder of using multiple returns within a function - bad practice - used a lot... – iGanja Mar 31 '13 at 16:07
  • @iGanja - using multiple returns within a function is [perfectly acceptable when used properly](http://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement). – cmallard Mar 31 '13 at 16:14
  • except when it isn't "used properly", like in this instance... a single return has no such caveat. – iGanja Mar 31 '13 at 17:17

1 Answers1

1

Because you're returning the result of this.each() which would be this. Create a variable outside of this.each() and return that after your this.each has completed.

jsFiddle

$.fn.myPlugin = function() {
    var instance;
    this.each(function(key, value){
        if ($(this).data('myclass')) {
            return $(this).data('myclass');
        }

        instance = new MyClass(this);
        $(this).data('myclass', instance);
    });
    return instance;
};

If you wanted to return an array of MyClass's if your jQuery object was a collection you could do it like this:

jsFiddle

$.fn.myPlugin = function() {
    var instances = [];
    this.each(function(key, value){
        if ($(this).data('myclass')) {
            return $(this).data('myclass');
        }

        var instance = new MyClass(this);
        $(this).data('myclass', instance);
        instances.push(instance);
    });
    if (instances.length == 1)
        return instances[0];
    return instances;
};
Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
  • Thank you so much for this answer, this is something I should have realized to be perfectly honest. – Shane Yu Mar 31 '13 at 16:19
  • Would you say that it is best to return the instance like this, or do you think it would be better to return the jQuery stuff, and provide a new method of some sort to return the instance of the object? Also, in this instance, if we were applying the plugin to multiple selectors, then it would still only return the last created instance? If this makes sense? – Shane Yu Mar 31 '13 at 16:20
  • 1
    Updated adding another version to return an array if called on a colletion. – Daniel Imms Mar 31 '13 at 16:28
  • Hmm, yes! This is great, thank you. Still cannot believe I didn't realize I wasn't actually returning the object instance in my first example code. Many thanks Daniel. – Shane Yu Mar 31 '13 at 21:32