Gijs
Gijs

Reputation: 2082

Parent variable in plugin gets overwritten

I'm very new to making jQuery plugins and there is one problem i stumble upon every time. The plugin below is a simple plugin to embed a facebook likebox for a page or link to a user profile based on a username or facebook url. It works like a charm when it's executed once.

When executed multiple times only the last one gets filled with the $.ajax part. If i console.log($this) there al the last one.

It looks like the $this in the ajax call is overwritten... it also happens in other plugins when i use another each() in the plugin.

I hope i'm clear, i tried to put it in a jsFiddle but i get the error "Input plain JavaScript code, no HTML."

jQuery.fn.facebookEmbed = function( options ) {

var defaults = {
    likebox: "Loading facebook...",
    faces: false,
    stream: true,
    header: false,
    width: 252,
    customClass: 'facebookembed',
    account: "skrillex"
};  

var settings = $.extend( {}, defaults, options );

if(!$('#fb-root').length) { $('body').prepend('<div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script>'); }

return this.each(function() {

    $this = $(this);
    $this.addClass(settings.customClass);

    if(settings.loading) { $(this).html('<span class="facebook-loading">'+settings.loading+'</span>'); }

    var url = ($this.attr('data-account')) ? $this.attr('data-account') : settings.account;

    if(!/facebook.com/.test(url)) {
        url = "http://www.facebook.com/"+url;
    }
    var user = (/pages/.test(url)) ? url.split("/").pop() : url.match(/https?:\/\/(www\.)?facebook\.com\/(#!\/)?@?([^\/]*)/)[3];

    // here begins the trouble, i think
    $.ajax( {
        url: 'http://graph.facebook.com/'+user
        , dataType: 'json'
        , success: function( data ) { 
            if(data.category) {
                // I guess $this is overwritten somehow?
                $this.html('<div class="facebookembed"><fb:like-box href="'+url+'"  width="'+settings.width+'" show_faces="'+settings.faces+'" stream="'+settings.stream+'" header="'+settings.header+'"></fb:like-box></div>');
            } else {
                $this.html('<div class="facebookuser"><a href="'+url+'" target="_blank"><img src="http://graph.facebook.com/'+user+'/picture" /> Wordt vrienden met <strong>'+data.name+'</strong> op Facebook</a>');
            }
        }
        , error: function( data ) { $this.text('Deze gebruiker bestaat niet of niet meer...'); }
    } );

});
};

Html:

<div class="facebook-feed" data-account="skrillex"></div>
<div class="facebook-feed" data-account="noisia"></div>
etc..
<script type="text/javascript">$('.facebook-feed').facebookEmbed();</script>

Upvotes: 2

Views: 175

Answers (2)

Mika Tuupola
Mika Tuupola

Reputation: 20377

Without testing it looks like you are using $this in global scope. To keep it in local scope add var into declaration:

var $this = $(this);

Upvotes: 4

Raidri
Raidri

Reputation: 17550

Have you tried the context option?

$.ajax( {
    url: 'http://graph.facebook.com/'+user
    , context: $this
    , ...

From the documentation:
This object will be made the context of all Ajax-related callbacks. By default, the context is an object that represents the ajax settings used in the call ($.ajaxSettings merged with the settings passed to $.ajax).

In your code you set the $this variable to a new object before the ajax call returns. Presumely all ajax calls return after you have set $this in the last each method.

Upvotes: 0

Related Questions