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?
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
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.
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 */ }
};
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With