Writing a web widget  4


Web widgets are widely used across the Internet but still lacks good documentation. From online advertisement to videos to blogs, widgets are highly used. Some of the popular widgets being Google Adsense, Youtube, MyBlogLog widgets and Twitter badges.

Note: This page will be slow to load because of many widget examples.

Table of Contents

  1. Before you start
  2. Flash widget
  3. HTML widget
  4. JavaScript widget
    1. Passive widgets
    2. Active widgets
  5. Examples
  6. Key issues

To formally define : The web widget is a portable chunk of code that can be installed and executed within any separate HTML-based web page by an end user without requiring additional compilation. A widget adds some content to that page that is (mostly) not static. Generally widgets are third party originated, though they can be home made. Widgets are also known as modules, snippets, and plug-ins.

This article is my journey of understanding and making a widget myself. I have tried to make things look simple and insightful by taking a lot of examples.

Before you start

Clearly identify the information which will be distributed by your widget or the information you would like your client to embed in their webpage. Then find the most suitable mechanism to send this information. Mechanism can be one of the following :

  • Flash (need not be static i.e. it can take parameters) as a widget.
  • Simple HTML page
  • JavaScript
  • JSON API

Flash widget

This is a highly used method for making widgets. Most of the flashy irritating advertisements seen on many websites are flash widgets. A good usage being youtube videos and twitter badge type-1. Flash widget code includes an "embed" or "object" HTML tag with the source to flash file. Extra parameters may be passed to flash file to customize flash content. And remember, ActionScript is always there for more magic :-)

HTML widget

Instead of flash embed an HTML page or HTML code at client's webpage using iframe.
This can be as simple as:

<iframe src="http://www.google.com"  height="100px" width="90%" frameborder="0"></iframe>
Mostly used when content is static for all users (like brand advertisements). Flash and HTML widgets are the most simplest to develop but can be of limited use in many cases.

JavaScript widget

JavaScript is the most powerful tool to make widgets. Top examples being, Google Adsense and MyBlogLog recent visitors widget. There are two ways to develop widgets via scripting:
  1. Passive widget : The widget code is a script tag which links to external JavaScript file and this file has the code to directly print the HTML markup on client's webpage. AideRSS provides a passive widget.
    For example::
    1
    2
    
    // widget code
    <script src="http://www.quarkruby.com/assets/script-raw-dump.js"></script>
    1
    2
    3
    4
    5
    6
    
    // script-raw-dump.js contains the following code
    document.write("<ul>");
    document.write("<li>Hello world</li>");
    document.write("<li>Hello world2</li>");
    document.write("</ul>");
    document.write("Powered by <img src='quarkruby' alt='quarkruby'/>");
    Output seen on webpage will be:

  2. Active widget : As the name says, they do work/processing/calculations before just printing HTML code. The widget code contains a script tag to download one or more external JavaScript files, which does work (getting client information, passing information around, etc.) and then HTML is dumped at client side. Google adsense, Mybloglog's widget all fall in this category.

    Active widgets can be very powerful if, each client is given a unique identifier by the widget source for user identification. This allows widget providing site to send/collect user-related data. Active widget's can be made in two ways :

    1. Using simple JavaScript
      Sample widget code:
      1
      2
      3
      4
      5
      
      <script type="text/javascript">
      unique_key_each_host = "quarkruby_123";
      // some other variables ..
      </script>
      <script src="http://www.quarkruby.com/assets/static-javascript-variable.js"></script>
      What the code does:
      - Get the JavaScript as mentioned in last line above
      - This JavaScript file when executed, will read the values of above defined variables + possibly collect other information
      A sample of static-javascript-variable.js:
      1
      2
      3
      4
      5
      6
      7
      8
      
      // static-javascript-variable.js contains the following code
      (function(){
        var url = "http://www.quarkruby.com/show_data";
        var current_location = window.location.hostname;
        url += "?" + "host=" + current_location + "&width="+200 + "&key="+unique_key_each_host;
        // sample url generated : http://www.quarkruby.com/show_data?host=quarkruby.com&width=200&key=quarkruby_123
        document.write("<iframe src='" + url + "'></iframe>");
      })()
      This creates an iframe element at client's webpage and set the source to an external url (defined in static-javascript-variable.js file) passing above calculated parameters. The output fetched is an HTML page which is inserted iframe created in last line of code

    2. JSON widget
      For using JSON API's or JSON data. Twitter badge type 2 is a good example of widget using JSON calls.
      Sample Widget code:
      1
      2
      3
      
      <div id="quarkruby_widget"></div>
      <script type="text/javascript" src="http://www.quarkruby.com/js/static-javascript-dom.js"></script>
      <script text="text/javascript" src="http://www.quarkruby.com/js/json-data-callback.js"></script>
      Explanation :
      - Download the script files mentioned in last 2 lines. The latter one fetches the JSON data and calls the callback function.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
       // sample static-javascript-dom.js file 
        function printHelloWorld(args) {
          var outputhtml = "<h3>List of Visitors: </h3><ul>";
          for(var x=0;x<args.length;x++) {outputhtml += "<li>" + args[i]+"</li>");}
          outputhtml += "</ul>";
          document.getElementById('quarkruby_widget').innerHTML = outputhtml;
        }
      
        //sample json-data-callback.js
        printHelloWorld(["Nakul", "Ritesh"]);
      - The first JavaScript contains the callback function definition (possibly other functions also). These will process the JSON data, generate HTML code and insert into DOM at "#quarkruby_widget" element using innerHTML method or DOM manipulation by creating/adding/appending elements.

Examples

  1. Youtube
    Widget code :
    1
    2
    3
    4
    5
    
    <object width="425" height="355">
      <param name="movie" value="http://www.youtube.com/v/dMH0bHeiRNg&rel=1"></param>
      <param name="wmode" value="transparent"></param>
      <embed src="http://www.youtube.com/v/dMH0bHeiRNg&rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed>
    </object>
    - Here, a static youtube video is loaded in flash player.

    Output :
  2. Twitter Flash widget
    Widget code :
    1
    2
    3
    4
    5
    6
    
    <div style="width:176px;text-align:center">
      <embed src="http://twitter.com/flash/twitter_badge.swf"  flashvars="color1=16594585&type=user&id=8484232"  quality="high" width="176" height="176" name="twitter_badge" align="middle" allowScriptAccess="always" wmode="transparent" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
      <br>
      <a style="font-size: 10px; color: #FD3699; text-decoration: none" href="http://twitter.com/nakula">follow nakula at http://twitter.com</a>
    </div>
    <br/>
    - This embeds a flash file passing it color of widget, user_id as variables. So, after flash file is loaded, it makes request for user specific data (mentioned in user_id variable) and loads it later.

    Output :

  3. AideRSS
    Widget code :
    
    
    <script src="http://www.aiderss.com/widget/top_content/year/100" type="text/javascript"></script>
    Here the widget codes gets the JavaScript, which directly does a document.write at client's webpage.

    Output :
  4. Google Adsense

    This is one of those widget which gathers a lot of information before it generates output. Widget code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    <script type="text/javascript"><!--
    google_ad_client = "pub-xyzvalue";
    google_alternate_color = "FFFFFF";
    google_ad_width = 468;
    google_ad_height = 60;
    google_ad_format = "468x60_as";
    google_ad_type = "text";
    google_ad_channel = "";
    google_color_border = "FFFFFF";
    google_color_bg = "FFFFFF";
    google_color_link = "000000";
    google_color_text = "333333";
    google_color_url = "666666";
    //--></script>
    <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
    It works as follows:
    1. Fetches the JavaScript file mentioned in last line.
    2. This file then uses the defined parameters and gathers value for hidden parameters (so that resulting ads are more local and content specific).
    3. Finally creates an iframe element at client's webpage and set the source to the external url passing above calculated parameters. The output is an HTML page which is inserted into this iframe.
  5. Twitter badge type2
    Widget code :
    1
    2
    3
    4
    5
    
    <div id="twitter_div">
    <h2 class="twitter-title">Twitter Updates</h2>
    <ul id="twitter_update_list"></ul></div>
    <script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"></script>
    <script text="text/javascript" src="http://twitter.com/statuses/user_timeline/username.json?callback=twitterCallback2&count=5"></script>
    The second JavaScript link is the JSON call to their API, which fetches the JSON data and calls back "twitterCallback2" function which is defined in blogger.js file. Then blogger.js downloads the JavaScript code which processes the JSON data and inserts the final output into "twitter_div" element.

    Output :
    • Amazon
      Widget code :
      
      
      <SCRIPT charset="utf-8" type="text/javascript" src="http://ws.amazon.com/widgets/q?ServiceVersion=20070822&MarketPlace=US&ID=V20070822/US/xyz/8001/f5c7593b-5be8-4c15-345d-e8f70675f476"> </SCRIPT> <NOSCRIPT><A HREF="http://ws.amazon.com/widgets/q?ServiceVersion=20070822&MarketPlace=US&ID=V20070822%2FUS%2Fxyz-20%2F8001%2Ff5c75233b-5be8-4c15-916d-e8f70675f476&Operation=NoScript">Amazon.com Widgets</A></NOSCRIPT>
      The JavaScript file mentioned in script tag is fetched which contains the JSON data + link to more JavaScript files. These additional JavaScript files are fetched and then JSON data is processed and using DOM manipulation output is inserted into webpage.

      Output :

    • MyBloglog recent visitors widget
      Widget code :
      
      
      <script type="text/javascript" src="http://pub.mybloglog.com/comm2.php?mblID=2007123816343566&c_width=180&c_sn_opt=y&c_rows=5&c_img_size=f&c_heading_text=Recent+Readers&c_color_heading_bg=005A94&c_color_heading=ffffff&c_color_link_bg=E3E3E3&c_color_link=005A94&c_color_bottom_bg=005A94"></script>
      - Fetch this file, which generates HTML code + CSS data for the final output
      - Fetch one more JavaScript file linked in the above mentioned file which is used for tracking the users.

      Output :

    Key issues

    • Slowing down loading of client's site.:
      What are you talking? Yes, widgets can bring down client's site who is embedding widget code in their page because:
      1. script tag stops page rendering until code inside it is executed and rendered.
      2. Script tag blocks parallel downloads :(
      If the widget source goes down or is slow, the client's webpage won't load unless the widget code is executed and rendered. To avoid this problem consider following workarounds :
      1. Use "defer" attribute with script (firefox doesn't support this though :-( ). This tells the browser to continue rendering and do not block the other downloads. Moreover, this can only be used if there is no "document.write" statement in your script. See more details here
      2. Put timeout on script attachment (source: WEDJE)
        Here, external scripts in widget code are not downloaded during page load, but attached after sometime. So, this does not affects loading/rendering of site. Hence, after sometime, the external scripts are downloaded, attached/executed thereafter. In example mentioned below, Twitter type-2 badge is modified to download the external scripts after 1 sec. So, if you embed this code in some html page, you will see the output after delay of 1sec
        Example: modifying the twitter widget code :
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        
        <div id="twitter_div">
        <h2 class="twitter-title">Twitter Updates</h2>
        <ul id="twitter_update_list"></ul></div>
        <div id="twitter_script"></div>
        <script type="text/javascript">
        var script1 = document.createElement("script");
        script1.src="http://twitter.com/javascripts/blogger.js";
        setTimeout("document.getElementById('twitter_script').appendChild(script1)",1000);
        var script2 = document.createElement("script");
        script2.src="http://twitter.com/statuses/user_timeline/username.json?callback=twitterCallback2&count=5";
        setTimeout("document.getElementById('twitter_script').appendChild(script2)",1000);
        </script>
    • Avoid conflict's with client's JavaScript:
      Widget code and external loaded Javascript files should contain minimum global variables, so as to prevent any chances of conflict with client's JavaScript which is embedding the widget. If your widget does not take any parameters from client, one should try to use anonymous JavaScript classes.
    • Let client apply its own CSS to widget:
      This helps in customizing the style of widget as per the design/looks of client's webpage. Google allows this even via iframes by using global variables, Amazon allows this while making widget, Mybloglog and twitter doesn't use iframes so your CSS directly applies to the widget's HTML.
    • Minimize number of request:
      This is to load your widget faster which applies to any HTML page
    • Do you want to prevent content editing?:
      If you do not want to allow content editing of the widget, then use iframes since they cannot be manipulated by JavaScript outside the iframe element.
    • Using API
      If you are using an API, then callback method must be provided by that API. This is just to keep in mind if you want to use some external API and display the content dynamically.
    Filed in tutorials
    Tagged as javascript widget 
    Posted on 07 January
    4 comment Bookmark   AddThis Social Bookmark Button
    Comments

    Leave a response

    1. SudhanshuJanuary 08, 2008 @ 12:01 AM

      Pretty Cool. looking forward to more…

    2. Forex Strategy BuilderJanuary 10, 2008 @ 04:13 PM

      Nice advice. did you already created some widgets yourself? would be nice to show them.

      best regards

    3. QuarkJanuary 11, 2008 @ 06:45 AM

      @forex

      yes we did, you can find our widget at http://www.quarkrank.com/widget.

      We will try to get with explanation on how we developed it.

    4. carlosMarch 19, 2008 @ 12:28 AM

      Thanks for the information, I found it really useful!!. However, I don’t know anything about JSON, and I got lost in that part…

    Comment