views:

38

answers:

2

I have a jquery plugin that i call as such :

$(function() {

   $('.link_class').jquery_plugin()
})

with many anchor tags in the body

<a href="http:...." class="link_class">link 1 </a>
 <a href="http:...." class="link_class">link 2 </a>
 <a href="http:...." class="link_class">link 3 </a>

the jquery plugin is setup this way :

$.fn.jquery_plugin = function(options) {        

    if ($(this).is('a' ) ) {    

        this.each(function() {


            $(this).bind('click', function(){


                    options.content = options.content ||  $(this).attr('href');


                return javascript_plugin (options), false;



            })


        })

    }

};

javascript_plugin  = function (options) { 

        return  alert(options.content);

};

my problem is that when I use IE which ever link I click on first will dictate with content is displayed in the alert. hence if i click on link 2 first the href from link 2 will be displayed no matter which link i click on there after... any ideas as to what I might be doing wrong? thanks

+2  A: 

I'm not 100% sure about the context of each of the 'this' references, and whether they refer to the 'this' that is implicit in the local function invocation or to the 'this' in the enclosing function, but that is probably related to the explanation.

Either way, there is a slight flaw in your code, which would only manifest itself if one of you assigned 'linkClass' to an element that isn't an 'a'. To fix this, do the check for 'a' inside the loop, as the 'is' method will return true if any of the items in the jquery collection matches the criteria and, when this is done outside the loop, will cause all of the elements to have a click handler bound to them, regardless of whether they are an 'a' or not...

$.fn.jquery_plugin = function(options) {         
    this.each(function() { 
        if ($(this).is('a' ) ) {     
            $(this).bind('click', function(){ 
                options.content = options.content ||  $(this).attr('href'); 
                return javascript_plugin (options), false; 
            }) 
        }) 
    } 
    return this;
}; 

javascript_plugin  = function (options) {  
    return  alert(options.content); 
}; 

Alternatively, simply include the 'a' in the selector used in the invocation of your plugin...

$(function() {       
    $('a.link_class').jquery_plugin()       
})       

...and remove the need for the 'a' check in the plugin...

$.fn.jquery_plugin = function(options) {         
    this.each(function() { 
        $(this).bind('click', function(){ 
            options.content = options.content ||  $(this).attr('href'); 
            return javascript_plugin (options), false; 
        }) 
    } 
    return this;
}; 

The big question for me, is whether the last 'this' refers to the DOM element being clicked on, or the element for the current iteration of the 'each' loop. It should be the former.

EDIT:

I now see the problem - the fact that 'options' is only being set to the value of the element's href if it is currently empty. After this, it is left alone, and retains the previously set value. Try creating a local variable instead...

$.fn.jquery_plugin = function(defaultOptions) {         
    this.each(function() { 
        $(this).bind('click', function(){ 
            var options = createAnOptionsInstance(); //do what it says
            options.content = defaultOptions.content ||  $(this).attr('href'); 
            return javascript_plugin (options), false; 
        }) 
    } 
    return this;
}; 

Your original code doesn't show any option being passed in to the plugin, so you probably need some extra checks for this.

belugabob
Hi there,thanks for the solution. that is exactly what i needed . for some reason IE does not understand "each" as i thought.my trouble is that sometimes an option called content is passed. so I want to leave the plugin open so when that option is passed it would be used otherwise the plugin would fetch the content from href.the way i had it before works fine in FF , Safari , Opera but just not in IE. any suggestions?thanks
salmane
I just noticed that your topic post mentioned IE and started to wonder about other browsers, and then I spotted your comment. I'm pretty sure that the 'each' function works the same across browsers, so would suspect that it's down to the way that the options are handled. Can you post some examples of the cases where options are passed to the plugin?
belugabob
just to give u a better idea from what the plugin does : it is an ajax / html dialog box. sometimes the content is an option that is passed for example : content:'<div>Hello world</div>' but when the content option is not passed the plugin defaults to making an ajax call to the link stored in the href. i guess internet explorer is less forgiving.thank again for your help
salmane
I'm glad that I could help, but I'm still not 100% sure I understand your usage scenario - sounds like two completely different pieces of functionality to me, which would suggets that you need two different plugins.
belugabob
+1  A: 

Overall you're looking at changes like this:

$.fn.jquery_plugin = function(options) {        
  options = options || {};
  return this.filter('a').bind('click', function() {
    var content = options.content || $(this).attr('href');
    return javascript_plugin ({ 'content': content });
  }).end();
};

javascript_plugin  = function (options) { 
  return  alert(options.content);
};

You can try it here, there were a few issues, we'll go in code order:

  • options would be undefined like your example call, need to account for this when accessing options.content.
  • The .is('a') check needs to be per element (otherwise it's checking any element of the set, so instead do a .filter('a') before .bind().
  • You need to return the set to keep chaining, this now does that (notice the .end() so we don't return the .filter() version of the set).
  • Last, don't modify the original options object, that's why you were getting the first-link behavior.
Nick Craver
the 'is' method returns true if any of the elements match, not just the first one.
belugabob
Good point about returning 'this' from the plugin, so that chaining can take place - I added the 'return this;' to my examples.
belugabob
@belugabob - I misspoke there, but it's incorrect either way if you only want to attach to `<a>` elements and you have non-`<a>` in the set :)
Nick Craver
Absolutely true.
belugabob