0

I am working with the AddThis JavaScript API. The method I am struggling with is documented here:

http://support.addthis.com/customer/portal/articles/1137944-getting-counter-values-dynamically

I can obtain the data I require from the "obj" object - but only within that method. I can't seem to return the data to a global variable that I can use in my jQuery loop. The problem is I have a limited understanding of Javascript objects. Here is my code:

    addthis.addEventListener('addthis.ready', addthisReady);
function addthisReady() {

    var myobj = {};
    addthis.sharecounters.getShareCounts({service: ['facebook', 'twitter', 'pinterest'], countUrl: 'http://www.addthis.com/'}, function(obj) {
        console.log(obj); // OK
        myobj = obj;

    });
    console.log(myobj); // Not OK
}

My ultimate goal is to have multiple article links on a page and then use jQuery and this API method to append the total share counts to their linked titles. EG;

  • Article Link X (22 Shares)
  • Article Link Y (13 Shares)
  • Article Link Z (13 Shares)

Any help would be grand.

CJ

PROGRESS UPDATE - Almost there...

The code below factors in your advice and an example provide by the API vendors. It is almost there, but the callback randomly updates only one of the elements in the Each loop.

The example code - commented out - indicated that multiple calls to the method should be possible.

Here is the code:

$(document).ready(function(){


addthis.addEventListener('addthis.ready', addthisReady);
function addthisReady() {
    /*
    addthis.sharecounters.getShareCounts('facebook', function(obj) {
        document.getElementById('basic-example').innerHTML = '<code>'+JSON.stringify(obj, undefined, 4)+'</code>';
    });

    addthis.sharecounters.getShareCounts(['facebook', 'twitter', 'pinterest'], function(obj) {
        document.getElementById('multiple-services').innerHTML = '<code>'+JSON.stringify(obj, undefined, 4)+'</code>';
    });

    addthis.sharecounters.getShareCounts({service: 'facebook', countUrl: 'http://www.addthis.com/'}, function(obj) {
        document.getElementById('specific-url').innerHTML = '<code>'+JSON.stringify(obj, undefined, 4)+'</code>';
    });

    addthis.sharecounters.getShareCounts({service: ['facebook','twitter'], countUrl: 'http://www.addthis.com/'}, function(obj) {
        document.getElementById('specific-url-multiple-services').innerHTML = '<code>'+JSON.stringify(obj, undefined, 4)+'</code>';
    });
    */

    $('.ico-shares').each(function(index) {

        var elem = this;
        var share_url  =  $(elem).attr('href').split('#')[0];
        var shareLabel = $(elem).text();
        var total_count = 0;

        //Request Counts
        addthis.sharecounters.getShareCounts({service: ['facebook', 'twitter'], countUrl: share_url}, function(obj) {

            for (var key in obj)
            {
                total_count  += obj[key].count;
            }
            if (total_count > 0)
            {
                shareLabel = total_count + ' Share';
            }
            if (total_count > 1)
            {
                shareLabel = total_count + ' Shares';
            }
            alert(shareLabel);
            $(elem).text(shareLabel);

        });
    });
}

});

My URL is here: http://banarra.cjweb.com.au/html/news_article.php

Note there are 3 x "More News" articles at the bottom, but only one has it's Share link updated.

Thanks very much for your time.

CJ

CJWEB
  • 581
  • 6
  • 13

2 Answers2

3

The code you've posted isn't going to be the problem.

If you sent your request, and then waited a few seconds, and then checked the value of the variable using the console, you should see it set to the value you were expecting.

The problem is asynchronicity.

See, when you send a request off to the server (ie: when that function actually fires), it doesn't sit there and wait for it to come back, before moving to your next line of code.

So if you have code that looks like:

var myObj = {};
getAsyncData(function myCallback (o) { myObj = o; });
console.log(myObj);

What's actually going to happen is that function is going to fire, and your code is going to keep on running.

The server hasn't returned your data, so myObj === {}.
Some time later, the server will return your data, and run that function that you gave it.

So if you come back in some time:

setTimeout(function () { console.log(myObj); }, 10000); // 10 sec

Then you should see it's being set.

The trick here is that you actually need to trigger stuff in your async code.
The rest of your program doesn't know anything is changed or anything is new, and it certainly hasn't sat and waited for it.

var myObj = {};
getAsyncData(function (o) { myObj = o; doStuff(myObj); });
var doStuff = function (obj) { console.log("Back from the server"); console.log(obj); };

To that end, I'd suggest looking at the link in the comments.

EDIT

To better grasp the problem (not the many solutions), imagine your async calls used a setTimeout to fire your function and pass in the data.
You wouldn't expect your whole JS app to sit and wait for one change in a setTimeout.

var data_is_set = false,
    get_data = function (callback) {
        var data = true,
            time_to_wait = 3000; // 3sec
        setTimeout(function () { callback(data); }, time_to_wait);
    };

get_data(function (val) { data_is_set = val; });

console.log(data_is_set); // false

The rest of the program is going to run, until that time goes by, and then your function gets called.
Nobody else knows what happened, so you need to make functions which now trigger updates, that you can call inside of your callback.

Norguard
  • 26,167
  • 5
  • 41
  • 49
  • Thanks Norguard, your explanation is helpful. I had a hunch it was related to asynchronicity because the console logs were coming back out of the expected order. I will check that link and try to finally wrap my head around this. – CJWEB Jan 28 '14 at 03:43
  • @CJWEB hopefully, if you have some experience with timers in JS, the edit will give you some perspective on the problem (and not the solutions). There are lots and lots of fantastic solutions out there (personally, I love `Promises` which are usable today, and the `Generators` that will be in the next major version of JS), but good ol' calling `.update()` methods works, too. – Norguard Jan 28 '14 at 04:06
1

Can you just return obj?

var myobj = addthis.sharecounters.getShareCounts({service: ['facebook', 'twitter', 'pinterest'], countUrl: 'http://www.addthis.com/'}, function(obj) {
    console.log(obj); // OK
    return obj;
});
Bic
  • 3,141
  • 18
  • 29