RSAdmin
RSAdmin

Reputation: 589

JS Module pattern and invoking another function

So I have repeatedly run into this situation: I write a module patterned object, but am unable to invoke one function from within another (prototyped) function.

;(function($,window,documnet,undefined) {
    var id,
        _defaults = { };

    var MyObject = function(element,options) {
        this.el = element;
        this.opt = $.extend({},_defaults,options);
        this.init();   //  works fine
    };

    MyObject.prototype.init = function() {
        var self = this;
        self.id = localStorage.getItem('myobject_id');
        if( self.id !== null ) {
             $('#myobject_id').val(self.id);
        }
    };


    MyObject.prototype.fetch = function() {
        var self = this;
        var data = { 
                    action: 'program_fetch',
                    program_idx: $('#program_idx').val()
                   };

        // assume session is valid and has a uri in opt.callback
        $.post( session.opt.callback, data ).complete(function(r){
            var prog = JSON.parse(r.responseText).program;
            self.id = prog.id;

            $('#myobject_id').val( self.id );  // this works

            self.display();                    // this does not work
        });

    }; /* fetch */


    MyObject.prototype.display = function() {
        var self = this;

        $('#myobject_id').val( self.id );

    };  /* display */


    $.fn.MyObject = function(options) {
        return this.each(function(){
            if(!$.data(this,'plugin_MyObject')) {
                $.data(this,'plugin_MyObject', new MyObject(options));
            }
        });
    };

    window.myobject = new MyObject();

})(jQuery,window,document);

From what I understand, the fetch function ought to be setting the value of the window-attached instance of MyObject, so that when the display() function is called, it has a value to place into the HTML input field, identified by #myobject_id.

What actually seems to happen is there is a race condition during which the value assigned to self.id is viable, but leaving the scope of the .complete(..) callback the value of MyObject.id is no longer valid.

How ought I be invoking these things to achieve persistence in the instance data within my object ?

Upvotes: 2

Views: 120

Answers (2)

RSAdmin
RSAdmin

Reputation: 589

The simple truth is I didn't know how to structure a class object in JS. Here's a simple model:

;(function($,window) {

    var self;
    var MyClass = function(opt) {
        self = this;
        return self.init(opt);
    }

    MyClass.prototype = {

        init: function(opt) {
            self.opt = $.extend({},opt);
            // other set up stuff
            return self;
        },

        display: function() {

        },

        show: function() {
            self.display();
        }
    }; /* end of prototype */

    $.fn.myclass = function(opt) {
        return new MyClass(opt);
    }

}(jQuery,window));  /* end of clas object */

jQuery().ready(function($) {
    window.myInstance = $().myclass({ /* options here */ });
    $('#some_button').click( window.myInstance.show );
}

On activation of the button #some_button the show method is invoked. It in turn will invoke the display() method. Easy peasy.

Upvotes: 0

RSAdmin
RSAdmin

Reputation: 589

;(function($,window,documnet,undefined) {
var id, 
    _defaults = { };

var MyObject = function(element,options) {
    this.el = element;
    this.opt = $.extend({},_defaults,options);
    this.init();   //  works fine
};

MyObject.prototype.init = function() {

    id = localStorage.getItem('myobject_id');
    if( id !== null ) {
         $('#myobject_id').val(id);
    }
};

    MyObject.prototype.fetch = function() {
    var data = { 
                action: 'program_fetch',
                program_idx: $('#program_idx').val()
               };

    // assume session is valid and has a uri in opt.callback
    $.post( session.opt.callback, data ).complete(function(r){
        var prog = JSON.parse(r.responseText).program;
        id = prog.id;

        $('#myobject_id').val( id );  // this works
        self.display();               // this does not work
    });

}; /* fetch */


MyObject.prototype.display = function() {
    $('#myobject_id').val( id );
};  /* display */


$.fn.MyObject = function(options) {
    return this.each(function(){
        if(!$.data(this,'plugin_MyObject')) {
            $.data(this,'plugin_MyObject', new MyObject(options));
        }
    });
};

})(jQuery,window,document);

In this version I have removed the pattern of using var self = this; within each function scope, as it was masking the object level variables of the same names. (Can't set object properties through this.var?)

There is still the outstanding issue of self.display() not working at all.

Upvotes: 1

Related Questions