Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery: Is it possible to attach fields/methods to a jQuery wrapper object?

I'm trying to write a plugin that will add a few methods to a jQuery wrapper object. Basically, I want to initialize it like this:

var smart = $('img:first').smartImage();

The 'smartImage' plugin would attach 2 methods to the object referenced by 'smart', so I'll be able to do something like:

smart.saveState();
// do work
smart.loadState();

Unfortunately, I can't figure out how to attach these 2 methods to the wrapper object. The code I have follows the typical jQuery plugin pattern:

(function($)
{
    $.fn.smartImage = function()
    {
        return this.each(function()
        {
            $(this).saveState = function() { /* save */ }
            $(this).loadState = function() { /* load */ }
        }
    }
 }

After I call smartImage(), neither 'saveState' nor 'loadState' is defined. What am I doing wrong?

like image 909
Outlaw Programmer Avatar asked Feb 25 '09 22:02

Outlaw Programmer


3 Answers

You cannot attach methods/properties in they way you have demonstrated, because as you said, the jQuery object is just a wrapper around whatever DOM elements it contains. You can certainly attach methods/properties to it, but they will no persist when they are selected by jQuery again.

var a = $('.my-object');
a.do_something = function(){ alert('hiya'); }
a.do_something(); // This alerts.

var b = $('.my-object');
b.do_something(); // Freak-out.

If you want a method to exist on the jQuery object when recovering it a second time, it needs to be assigned to jQuery.fn. So you could define your secondary method, assign it to the jQuery.fn, and use the jQuery data setup to maintain state for you...

$.fn.setup_something = function()
{
    this.data('my-plugin-setup-check', true);
    return this;
}

$.fn.do_something = function()
{
    if (this.data('my-plugin-setup-check'))
    {
        alert('Tada!');
    }
    return this;
}

var a = $('.my-object').setup_something();
a.do_something(); // Alerts.
$('.my-object').do_something(); // Also alerts.

I suggest you look at http://docs.jquery.com/Internals/jQuery.data and http://docs.jquery.com/Core/data#name

like image 71
Mike Boers Avatar answered Nov 20 '22 01:11

Mike Boers


You are actually returning a jQuery object in the smartImage() function. That is the correct way to write a jQuery plugin, so that you can chain that with other jQuery functions.

I'm not sure if there is a way to do what you want. I would recommend the following:

(function($) {
     var smartImageSave = function() { return this.each(function() { } ); };
     var smartImageLoad = function() { return this.each(function() { } ); };

     $.fn.extend( { "smartImageSave":smartImageSave, 
                     "smartImageLoad":smartImageLoad });
 });

 var $smart = $("img:first");
 $smart.smartImageSave();
 $smart.smartImageLoad();

That's one technique that I am familiar with and have used successfully.

like image 44
jonstjohn Avatar answered Nov 20 '22 01:11

jonstjohn


I'm not entirely sure why you are designing your plugin this way - you might want to consider something along the lines of jonstjohn's suggestion - but the following should be similar to what you're asking for:

jQuery.fn.extend({
    smartImage: function() {
        return {
            saveState: function() { /* save */ },
            loadState: function() { /* load */ }
        };
    }
});
like image 2
Alex Barrett Avatar answered Nov 20 '22 01:11

Alex Barrett