Sunday, March 27, 2011

Posted by SAMAJ SHEKHAR

0

How to: Create a Twitter widget in your blog


So this my next attempt, after Google Code Prettify which i explained in previous post, to add custom features to my blog. In this post I'll explain how I made that Twitter Feed box you see in widgets column.

It uses little bit of HTML, CSS3 Styling and and jQuery to do the magic. I 'll give you a walk-through of how "I made it". I actually started this small app when someone at StackOverflow asked how to embed Tweet' text's special words like @usernames, #Hashtags and Url's in an anchor (<a>) tag, i wrote some small JS code to take raw tweet string Linkify it and return HTML. Later i moved on create a tweet box for my own Blog. in this walk-through to create a Tweet Feed Box for @samajshekhar (which is me of-course), so code and HTML are hard-coded with values related to my account but you can change it very well.
(The HTML and jQuery script is downloadable from my repository at Bitbucket, you can check it out and fork it to add custom features and styling).

Before starting i assume you have a little bit of knowledge of basic HTML, CSS (actually CSS3 for curves and gradients), jQuery library and some understanding of Twitter's API (its easy to understand and simple), I am using Public timeline API to get tweet in JSON format without authentication so we have a Rate-Limit of 150 requests per hour. So keeping these things in mind lets start!

The HTML

The HTML for the Tweeter Feed Box is simple collection of div(<div>) tags which make up skeleton to contain tweets. It contain hard coded username @samajshekhar (which is my username at Twitter).

<div>
    <div id="SPTFB">
        <div id="SPTFBHeader">  
         <a href="http://www.twitter.com/samajshekhar" target="_blank" style="text-decoration:none;color:#333;">
             <img alt="@samajshekhar" src="http://a2.twimg.com/a/1299109335/phoenix/img/twitter_logo_right.png" style="border:none;"/>
             <span>@samajshekhar</span>
         </a>
        </div>
        <div id="SPTFBBody">
             <span id="SPTFBLoading" style="display:block;font-size:10px;" class="SPTFBLoading">loading tweets...</span>
        </div>
        <div id="SPTFBFooter">   
            <table cellspacing="0px" cellpadding="0px">
                <tr>
                    <td>Developed By <a style="color:Black;" rel="author" href="http://shekhar-pro.blogspot.com">Samaj Shekhar</a><br/>License: Creative Commons</td>
                    <td><a style="color:White;" id="ShekharProCCLicenseLogo" rel="license" href="http://creativecommons.org/license/by/2.5/">cc</a></td>
                </tr>
            </table>      
        </div>
    </div>
</div>

Where:
SPTFB: is the main <div> which contains all the elements of this Twitter Feed Box (actually SPTFB is the acronym for Shekhar Pro Twitter Feed Box).
SPTFBHeader: is the <div> which act as title bar and contains the Twitter @username with a twitter image.
SPTFBBody: is the <div> in which all tweets are shown.
SPTFBLoading: is a <span> element which just shows a loading... text while we dynamically insert Tweets.
SPTFBFooter: is the Footer <div> contains my attribution and a link to Creative Commons page.

The Tweet text's <div> which will be added later will have a CSS class of ".SPTFBFeed"

The CSS

The CSS is what makes this app look like it should. Match the styling with the element id and class in the above shown HTML.

<style type="text/css">
    #SPTFB /*Acronym for ShekharProTwitterFeedBox*/
    {
        width:230px;
        height:450px;            
        padding:0px;            
    }
    #SPTFBHeader
    {
        height:40px; 
        padding:3px 0px 0px 10px;
        margin:0px;
    }
    #SPTFBBody
    {
        height:360px;
        margin:2px;
    }
    #SPTFBFooter
    {
        height:30px;
    }
    #SPTFB
    { 
        -moz-border-radius:20px 1px 1px 1px;
        -webkit-border-radius:20px 1px 1px 1px;
        border-radius:20px 1px 1px 1px;
        border:2px solid #9C9C9C; 
        background-color:#9C9C9C; 
    }
    #SPTFB a
    {
        text-decoration:underline;
        color:#666;            
    }
    #SPTFBHeader
    {            
        -moz-border-radius:18px 0px 0px 0px;
        -webkit-border-radius:18x 0px 0px 0px;
        border-radius:18px 0px 0px 0px; 
        border:1px hidden azure;
        font-family:Verdana;
        font-size:16px;
        overflow:hidden;
    }
    #SPTFBHeader , #ShekharProCCLicenseLogo
    {    
        background-color:#9C9C9C;
        background-image: -webkit-gradient(
            linear,
            left bottom,
            left top,
            color-stop(0.3, rgb(156,156,156)),
            color-stop(0.88, rgb(219,219,219))
        );
        background-image: -moz-linear-gradient(
            center bottom,
            rgb(156,156,156) 30%,
            rgb(219,219,219) 88%
        );
        overflow:hidden;
    }
    #SPTFBBody
    {
        -moz-border-radius:4px 4px 4px 4px;
        -webkit-border-radius:4px 4px 4px 4px;
        border-radius:4px 4px 4px 4px; 
        border:1px solid #888888;
        background-color:#efefef;
        overflow-y:auto;
        overflow-x:hidden;            
    }
    #SPTFBFooter
    {
        font-family:arial;
        font-size:11px;
        color:White;
        text-decoration:none;
        padding:5px 0px 0px 20px;
    }
    #ShekharProCCLicenseLogo
    {
        -moz-border-radius:50%;
        -webkit-border-radius:50%;
        border-radius:50%; 
        border:1px solid #666666;
        height:26px;width:26px;
        font-family:Verdana;
        font-size:18px;
        font-weight:bold;
        text-align:center;
        color:White;
        text-decoration:none !important;
        display:block;
        margin:0px 0px 0px 20px;padding:0px;
    }
    .SPTFBFeed , .SPTFBLoading
    {
        background-color:#d0d0d0;
        background-image: -webkit-gradient(
            linear,
            left bottom,
            left top,
            color-stop(0.25, rgb(179,179,179)),
            color-stop(0.75, rgb(224,224,224))
        );
        background-image: -moz-linear-gradient(
            center bottom,
            rgb(179,179,179) 25%,
            rgb(224,224,224) 75%
        );
        border:1px solid #888888;
        -moz-border-radius:3px;
        -webkit-border-radius:3px;
        border-radius:3px; 
        margin:3px;
        padding:3px;
        font-family:arial;
        font-size:13px;
        font-weight:normal;
        color:black;            
    }
</style>

There's nothing complicated about above CSS its simply contains styles related to margins, size, etc just go through and you will know what it does. It also has default colors with gradients so that it appears with matching color where gradients are where its not supported like in IE. If you don't know how to make gradients then there is a nice CSS3 Gradient Generator which you can use.

The Code !

The last and most important one is the code which does the actual work of filling the box with tweets. Now i know some JavaScript ninjas may frown at my code but this is what "I made" and you are free to improve it, however if you see anything obvious then add a comment and I will correct it. It small JavaScript that uses jQuery, so remember to include the jQuery in your document before using following code.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>

The code can be divided in two parts, one is simple one which linkifies the tweet text, i.e surrounds the url's, #hashtags and @usernames in an anchor (<a>) tag and other is the code which actually brings in the tweets from Twitter

Code for Linkifier
var userNameRegEx = /@(\w*)\b/;
var hashTagRegEx = /#(\w*)\b/;
var urlLinkRegEx = /(^|[(\s]|&lt;)((?:(?:https?|ftp):\/\/|mailto:).+?)((?:[:?]|\.+)?(?:\s|$)|&gt;|[)])/;
function myTwitterLinkify(rawText) {
    var stringArray = rawText.split(' ');
    var stringStack = [];
    $.each(stringArray, function () {
        if (userNameRegEx.test(this)) {
            var userlink = '<a href="http://twitter.com/' + userNameRegEx.exec(this)[0].toString().replace('@', '') + '">' + this.toString() + '</a>';
            stringStack.push(userlink);
        }
        if (hashTagRegEx.test(this)) {
            var userlink = '<a href="http://twitter.com/search?q=' + escape(hashTagRegEx.exec(this)[0].toString()) + '">' + this.toString() + '</a>';
            stringStack.push(userlink);
        }
        if (urlLinkRegEx.test(this)) {
            var userlink = '<a href="' + urlLinkRegEx.exec(this)[0].toString() + '">' + this.toString() + '</a>';
            stringStack.push(userlink);
        }
        if (!userNameRegEx.test(this) && !hashTagRegEx.test(this) && !urlLinkRegEx.test(this)) {
            stringStack.push(this);
        }
    });
    return stringStack.join(' ');
}

Working of above code can be explained in following simple steps:

  1. Define Regular expression strings for each of @usernames, #hashtags and url.
  2. Take the string and split it for ' ' (space)into an array of words
  3. Take each word at a time and match it with all regular expression strings
  4. If a match is found then surround the word with anchor (<a>) tag and set its href="" attribute with respective url's and push the resultent string the stack, if not then simply insert that word in the stack.
    (usually its http://twitter.com/username for @username, http://twitter.com/search?q=hashtag for #hashtag and for urls just use the url itself.)
  5. Finally join the stack values with a ' ' (space) and return the complete string.
Code to fill tweets
var username = 'samajshekhar';  /* @username of the user at twitter*/
var format = 'json';            /* format in which to recive response, can be on of json, xml, rss, atom*/
var count = '6';                /* number of tweets to load*/
var include_retweets = 't';  /* wheather to include retweeets by user in timeline, can be true, t or 1*/
    /*the API uri at which we will make the call to get tweets*/
var theapiurl = 'http://api.twitter.com/1/statuses/user_timeline.' + format + '?callback=?';
var fillReqSucceded = false; /**/
var sptfbFillTimer = 'undefined'; /**/

/*
Function to fill tweets in the tweet box
*/
function fillTweets() {
    /*show loading... span*/
    $('#SPTFBLoading').fadeIn('slow');
    $.getJSON(theapiurl,
        {
            /*query string parameters to be passed to the api url*/
            screen_name: username,          /* @username of the user at twitter*/
            count: count,                   /* number of tweets to load*/
            trim_user: 't',                 /* whether to include extra information related to user profile,can be true, t or 1*/
            include_rts: include_retweets   /* whether to include retweets by user in timeline, can be true, t or 1*/

        },
        function (data) {
            /*remove all previous tweets already in the box*/
         $('.SPTFBFeed').remove();
         /*read each tweet linkify  its text and append it to #SPTFBBody <div> */
         $.each(data, function () {
                 var elem = $('<div/>');
                 elem.addClass('SPTFBFeed').html(myTwitterLinkify(this.text));                                                        
                 $('#SPTFBBody').append(elem);
         });
         /**
          *if we reached this far then we surely succeed in getting
          * tweets and filling it in the box, so just remove the loading... span
          */
         fillReqSucceded = true;
         $('#SPTFBLoading').fadeOut('slow');
        });
    /**
     *if this is NOT the first time we are flling tweets and we didn't succeed then 
     *show error in span schedule next fill after 20 seconds and exit this function
     */    
    if (sptfbFillTimer != 'undefined' && fillReqSucceded === false) {
        $('#SPTFBLoading').html('Problem in loading Tweets :(<br/><br/>Please wait while we try again...').css({ 'color': 'red' }); 
        sptfbFillTimer = setTimeout('fillTweets()', 20000); 
        return; 
    }
    /*if we reached this far then all is well and lets schedule the next fill to occur after 30 seconds*/    
    sptfbFillTimer = setTimeout('fillTweets()', 30000);
    /*just reset the style of loading... span as previous failure may have changed it*/
    $($('#SPTFBLoading').html('loading tweets...')).css({ 'color': 'black' });
}

This 'fillTweets()' method is the one which you are going to call when you are ready to load Tweets like at '$(document).ready();'. Now the for the working of above code comments are well enough , also as you can see we have defined some variables to store configuration related to the API uri on which we will make GET request to receive the JSON for tweet (we can also request XML for tweets, but we will need to change the code for that). Also note that we have included a 'callback=?' parameter to make the JSON response a JSONP.

And that's all you need to do. Below is the snapshots f how it looked in Firefox3,4 and IE9


READ MORE - How to: Create a Twitter widget in your blog

Saturday, March 5, 2011

Posted by SAMAJ SHEKHAR

2

Google Code Prettify


For a long while code snippets on my blog were inconsistently formatted as i always kept experimenting with CSS for code and every post came out with its own formatting, sometimes i used tools on web to format my code and give me the HTML, so it looked very awful. Recently i found out "Google Code Prettify", its a java-script code which contains those lexers to recognize the code and format it appropriately accompanied by a CSS which you can of-course customize it to suit your needs. Its easy to use and supports almost all languages, from java to Haskel and all C family languages. Though there is a readme at Google code website here are the steps to add it to your blog or website.

Setup

  • Download a distribution
  • Include the script and style-sheets in your document (you will need to make sure the css and js file are on your server, and adjust the paths in the script and link tag)
  • <link href="prettify.css" type="text/css" rel="stylesheet" />
    <script type="text/javascript" src="prettify.js"></script>
  • Add onload="prettyPrint()" to your document's body tag.
  • Modify the stylesheet to get the coloring you prefer
  • Usage

    Put code snippets in <pre class="prettyprint">...</pre> or <code class="prettyprint">...</code> and it will automatically be pretty printed. The original
    class Voila {
    public:
      // Voila
      static const string VOILA = "Voila";
    
      // will not interfere with embedded tags.
    }
    Prettier (I have applied custom CSS on my blog so it will be different then what you'll get)
    class Voila {
    public:
      // Voila
      static const string VOILA = "Voila";
    
      // will not interfere with embedded tags.
    }
    So as it says you will need to download it on your own server and then link it in your script tag, but for your (and my own) convenience i have hosted it at Bitbucket DVCS Source Code hosting site. On the download page you will find the minified versions of the prettify.js(19kb) and prettify.css(1kb)

    So your tags become:

    <link href="http://cdn.bitbucket.org/shekharpro/google_code_prettify/downloads/prettify.css" type="text/css" rel="stylesheet" />
    <script type="text/javascript" src="http://cdn.bitbucket.org/shekharpro/google_code_prettify/downloads/prettify.js"></script>
    READ MORE - Google Code Prettify