Improving the JSON/P Twitter Widget

For quite some time now I've had a sidebar widget that displays an excerpt of my Twitter feed on my blog.  It uses the standard Twitter JSON/P interface for loading the tweets and then a Twitter-provided script (http://twitter.com/javascripts/blogger.js) for rendering them on the page.  Unfortunately the default installation instructions would have you set up something like this:

<ul id="twitter_update_list"></ul>
<script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"></script>
<script type="text/javascript" src="http://twitter.com/statuses/user_timeline/barneyb.json?callback=twitterCallback2&count=5"></script>

That works, but it puts the JSON/P call (the second SCRIPT tag) into the main page flow, so anything after the call won't render until the script load is complete.  When Twitter is slow/down it can cause problems, but even when it's fast you still get a brief hang with a partial page before the rest snaps into view.  Fortunately, the solution is simple: do the call on DOMLoaded instead of inline.  I'm using jQuery, but the principle is the same regardless of what framework you use (or none at all):

<ul id="twitter_update_list"><li class="load-ind"><img src="http://www.barneyb.com/s/loading_indicator.gif" /></li></ul>
<script type="text/javascript">
jQuery(function() {
  jQuery("body").append(
    '<sc'+'ript type="text/javascript" src="http://twitter.com/javascripts/blogger.js"></sc'+'ript>' +
    '<sc'+'ript type="text/javascript" src="http://twitter.com/statuses/user_timeline/barneyb.json?callback=twitterCallback2&amp;count=5"></sc'+'ript>'
  );
});
</script>

Now the SCRIPT tags will be written on DOMReady, allowing the full page to render before the calls to Twitter are dispatched.  This gives a faster user experience, though you do get a reflow of the sidebar when the statuses load.  This has become so prevalent on modern websites, however, that I don't think it's worth caring about, but if you're concerned, you could specify a height to the loading indicator LI that is approximately what the rendered tweet list will be to mitigate the effect.  It won't avoid the reflow, but it'll make things move less because the space will be reserved up front.

I've also added a simple "loading" image to the UL that the JS will place the tweets in.  The way blogger.js is written, any content within the UL will be removed (i.e. the tweets overwrite the content; they're not appended to the content), so no need to explicitly remove the image or it's container LI.

40 responses to “Improving the JSON/P Twitter Widget”

  1. Kristina (Pretty Shiny Sparkly)

    Wonderful! I am going to try this out. That lag has been bugging me.

  2. grace

    Was there a reason to split up script into sc + ript? just curious

  3. Estella

    Hi Barney,

    Thanks for posting this! Very useful to know. :)

    I have a question–not sure if you'd be able to answer. With Twitter's new ReTweet feature via its web interface, it seems like RTing will display nothing when using the original json code. Might you have a solution for this? Even to skip these new RTs would work for me too. Would you have any suggestions or ideas?

    Thank you so much, and thanks again for sharing your code! :)

    -Estella

  4. Estella

    Ahh! That's true. (I know, imma js n00b~)

    Thanks for the friendly suggestion and advice! I'll definitely look into that. :)

  5. Sam Brasseale

    I'm no javascript whiz by any means and though I understand how this works, I can't really recreate it for the twitter widget they provide.

    Is there a simple way of using this technique with that? The particular widget is: http://twitter.com/goodies/widget_list

    Thanks!

    -Sam

  6. Sam

    Yeah, but the json is still the second piece of javascript to load, and the method above doesn't seem to work for it. That was my point I suppose.

  7. Norcross

    I've been pulling my hair out trying to exclude @replies from this. I've got the standard JSON script hosted locally on a site. I've seen a few examples, but they either haven't worked or involved setting a high number of returns (in the case of someone who replies often). Any ideas? I'm a HTML / CSS / PHP guy by trade, knowing just enough javascript to be dangerous.

  8. Pete Ippel

    Thank you for posting this, Barney. I have been creating my art portfolio and the JSON tutorial greatly helped because the call to Twitter was making the thumbnails un-viewable till it loaded. With your method, and a different, smaller loading .gif file I was able to get the exact functionality that I wanted. I really appreciate your effort.

    Take a look at http://peteippel.com.

    All my best,
    Pete

  9. Sandro

    Thanks fot the info on this page. Why, is the max of the number tweets without @reply 5?
    How can I increase that number?

  10. Sandro

    Ok, I found it ;-) Thanks!

  11. chaz

    cheers for the script will improve using the .json loads

    Am using it with the following – http://www.mclelun.com/lab/jqtwitter/ as the .json seriously hangs the site i am developing, however using the script you provided it conflicts with the auto refreshing of the tweets… any help!?

  12. David

    I have just implemented the twitter widget into a website and the lag was obvious. Great and simple little snippet that works perfectly. Thanks for sharing.

  13. Michael

    Thanks for sharing! Even though I always have the original twitter snippet in the footer, I was still seeing some lag with other jquery effects. Your clever solution solved the delay. Much appreciated!

  14. Wayne austin

    Barney

    Been looking for this solution for a while our twitter widget in word press hangs whilst blogger.js is loaded sometimes up to 5 seconds so will implement this shortly

    Cheers for posting

    Wayne Austin

  15. How to add Tweets to your blog and debugging basic JavaScript: Why did Twitter.com/JavaScript/Blogger JSONP Widget stop working? - Scott Hanselman

    [...] found some code on BarneyB's blog that is a modification of Twitter's original code. He mentions in the comments that he's removing replies in his code. I just took his code and stop [...]

  16. Mark Hesketh

    Hi Barney,

    Been tearing my hair out trying to get @replies removed from a client's twitter feed upon their request. I've implemented your custom 'blogger.js' and its working great!

    I've credited you in the script of course!

    Thanks
    Mark

  17. Harm

    Hey Barney,

    Is it possible to show newschool Retweets as well? Because in my implementation those don't show up.

  18. Steve

    This is fantastic, thanks! I could see in firebug WHY my page was lagging, but I didn't know I could dynamically write script tags in to solve that!

  19. Steve

    Thank you thank you thank you! Always bugged me that the old .json stuff didn't work, to the point that the only way to include the Twitter part of our site was right at the bottom of the .css stack to avoid it hitching up. This has helped immensely for the site re-design I'm currently working on.

    I owe you a pint!

    As a tip to others, you can take out the as long as you have a to replace it – I already had a and the was messing up the formating of the page.

  20. HvToor

    Dear all,

    since this weekend our tweets won't load anymore with Internet Explorer 9.
    The other browsers are working perfect.

    Does anyone have the same problem or knows what to to do to fix this problem?

  21. Matt

    Yes i have the same issue. The script works perfectly in all browseres exept IE9.
    This must be a microsoft bug in a recent IE9 update.
    I havent had chance to try and fix this yet but hopefully I should get some time to look at it over the weekend.
    Does anyone else have a solution to this problem yet?

  22. Murk

    Hi Barney, Thank you for sharing your knowledge!
    There is an issue when I use your modified blogger.js – the links to the tweets on twitter.com do not function (I get a "Sorry, that page doesn’t exist!" message on twitter.com).
    Do you have a solution for that?

  23. Murk

    Hello Barney,
    Thanks for finding a solution for this issue and again thanks a lot for this very usefull script!
    I will use your scripts and offcourse I will put your credits in the script.

    Could it be made possible to get feeds with particular hashtag by this script?

  24. Tom Owen

    Thank you so much for this…. was really bugging me because I have a JS image loader and it was hanging badly displaying all the images in a big row until the twitter loaded….

    Now it works great…

    YOURE THE MAN

    thank you

  25. Tom Hodgson

    I have the following code as the twitter feed is a widget within my footer on wordpress, how should I adapt the following code to conform with this method:

    function tz_twitter_js($tz_twitter_username, $tz_twitter_postcount) {
            return '
    		';
    }

    Thanks very much
    Tom

  26. Tom Hodgson

    @barneyb

    I'm really sorry but I'm not suite sure what I need to do, I have the following code which calls the feed from my tweet widget which is:

    function tz_twitter_js($tz_twitter_username, $tz_twitter_postcount) {
    return '[script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"][/script]
    [script type="text/javascript" src="http://twitter.com/statuses/user_timeline/'.$tz_twitter_username.'.json?callback=twitterCallback2&count='.$tz_twitter_postcount.'"][/script]';
    }

    ————————–

    and then I have the following in my php to call the widget:

    [!-- BEGIN .widget-section --]
    [div class="widget-section"]

    [?php /* Widgetised Area */ if ( !function_exists( 'dynamic_sidebar' ) || !dynamic_sidebar( 'Footer Two' ) ) ?]

    [!-- END .widget-section --]
    [/div]

    ——————————–

    Obviously i have replaced the arrowed parenthesis with square [] so it shows in the comments here.

    Thanks for any help in advance.

  27. Matt

    Hey, just used your page to exclude @replies from my tweets. MAJORLY helpful man, thanks!

    One more thing I wanted to add though – in my case I just wanted to pull the one latest tweet. In the case where the latest tweet was a reply, this would mean nothing was returned. So what I did was make a slight modification – I added an else case and a break at the end of the loop. This means that it will search for the latest non-reply tweet and then break out of the loop like so:

    for (var i=0; i<twitters.length; i++){
      	if (twitters[i].in_reply_to_screen_name != null) {
      	  continue;
      	} else {
        var username = twitters[i].user.screen_name;
        var status = twitters[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\]*[^.,;'">\:\s\\)\]\!])/g, function(url) {
          return ''+url+'';
        }).replace(/\B@([_a-z0-9]+)/ig, function(reply) {
          return  reply.charAt(0)+''+reply.substring(1)+'';
        });
        statusHTML.push(''+status+' '+relative_time(twitters[i].created_at)+'');
        break;
        }
      }
    
  28. site

    Is it alright to place part of this on my web site if I submit a reference point to this website?

  29. Taylor

    Is there any way that I can edit what you have posted?

    I would like to see the 3 not-mentions tweets at all time. Not just the not-mention tweets of my last three (which is how this works now?)

    Thank you