views:

40

answers:

3

Hi,

I'm creating a plugin for jQuery. I wont attempt to explain the plugin here, so lets say for simplicity that my plugin opens an alert when you click on the targeted element. Here is a simple version of my plugin.

(function($) {  

    // Options
    var defaults = {
        message:    'Default message'
    };

    var options = $.extend(defaults, options);

    $.fn.jAlert = function(options) {
        return this.each(function(){

            var $this = $(this);

            $this.click(function(){
                alert(options.message);
            });

        });
    };
})(jQuery);

I can get that far. It works great. However, if I call my plugin like this:

$('h1.simon').plugin({ message: 'Hello ' + $(this).attr('class') });

The message returns as 'Hello undefined', I'd prefer it to be 'Hello simon' (the class of the H1 tag).

I'm sure this is the simplest thing to do, but I'm not even sure what I should be Googling to find the solution.

Any help would be greatly appreciated!

Cheers,
Will

Update:

After playing about a bit, this seems to work... And I have no idea why! I don't think I really understand scope yet. I think I'll go do some reading.

$('h1.simon').click(function(){
    $(this).jAlert({
        icon:   'Hello ' + $(this).attr('class')
    });
});
+2  A: 

Save a reference to the element:

var $el = $('h1.simon');
$el.plugin({ message: 'Hello ' + $el.attr('class') }); 

Otherwise this refers to window which doesn't have a class.

meder
You don't need the `$(el)` do you? it should just be `el` (saves processing).
Brock Adams
This solves the issue, thanks, but is there a way of building this into the plugin javascript so that calling the plugin is as easy as possible? Ideally, allowing me to use $(this). Thanks again!
will
A: 

at the time you are calling the plugin and passing the options .. this refers to window and NOT the element as you seem to expect

Scott Evernden
Not necessarily. It depends on what scope they're calling the plugin from. If they did something like `$('a').click(function() { $('h1.simon').... })` then it wouldn't refer to window. But in any case, it doesn't refer to what OP wants.
Jamie Wong
Yes, this is the issue, but how can I change that?
will
+1  A: 

If you want to be able to use this for convenience, you could allow message to accept a function that returns the value you want to display.

Try it out: http://jsfiddle.net/9hyJc/

(function($) {  

    $.fn.jAlert = function(options) {

    // Options
    var defaults = {
        message:    'Default message'
    };

    var options = $.extend(defaults, options);

        return this.each(function(){

            var $this = $(this);

            $this.click(function(){
                if($.isFunction(options.message)) {
                       // If it is a function, call it, 
                       //    setting "this" to the current element
                    alert(options.message.call(this));
                } else {
                       // Otherwise, assume it is a string
                    alert(options.message);
                }
            });

        });
    };
})(jQuery);

$('h1.simon').jAlert({ message: function() { return 'Hello ' + $(this).attr('class'); } });
patrick dw