Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
    <div id="tweets">
        <div>
        </div>
    </div>
    <nav>
        <ul>
            <li><a href="#" data-link="http://search.twitter.com/search.json?rpp=4&q=%23rails"><span>Rails</span></a></li>
            <li><a href="#" data-link="http://search.twitter.com/search.json?rpp=4&q=%23grails"><span>Grails</span></a></li>
            <li><a href="#" data-link="http://search.twitter.com/search.json?rpp=4&q=%23django"><span>Django</span></a></li>
            <li><a href="#" data-link="http://search.twitter.com/search.json?rpp=4&q=%23coldfusion"><span>ColdFusion</span></a></li>
            <li><a href="#" data-link="http://search.twitter.com/search.json?rpp=4&q"><span>Error</span></a></li>
        </ul>
    </nav>
</body>
</html>
 
#tweets{
    -webkit-box-shadow: inset 1px 1px 1px 1px rgba(44, 44, 44, 75);
    box-shadow: inset 1px 1px 1px 1px rgba(44, 44, 44, 75);
    -webkit-border-radius: 4px;
    border-radius: 4px;
    width: 500px;
    height: 350px;
    overflow: scroll;
    padding: 5px 0px 0px 5px;
}
nav{
    text-align: center; 
}
#tweets div div{
    padding-bottom: 5px;
    padding-top: 5px;
    border-bottom: 1px solid black;
}
nav ul
{
    padding: 0;
    margin: 0;
    list-style: none;   
}
nav li
{
    float: left;
}
.username{
    font-weight: bold;
}
nav a
{
    float: left;
    color: #eee;
    margin: 0 5px;
    padding: 3px;
    text-decoration: none;
    border: 1px solid #831608;
    font: bold 14px Arial, Helvetica;   
    background-color: #831608;
    background-image: -moz-linear-gradient(#bb413b, #831608);
    background-image: -webkit-gradient(linear, left top, left bottom, from(#bb413b), to(#831608));    
    background-image: -webkit-linear-gradient(#bb413b, #831608);
    background-image: -o-linear-gradient(#bb413b, #831608);
    background-image: -ms-linear-gradient(#bb413b, #831608);
    background-image: linear-gradient(#bb413b, #831608);
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    text-shadow: 0 -1px 0 rgba(0,0,0,.8);    
    -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.3), 0 3px 0 rgba(0, 0, 0, 0.7), 0 2px 2px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.5) inset;
    -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.3), 0 3px 0 rgba(0, 0, 0, 0.7), 0 2px 2px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.5) inset;
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.3), 0 3px 0 rgba(0, 0, 0, 0.7), 0 2px 2px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.5) inset; 
}
nav a:hover
{
    background-color: #bb413b;
    background-image: -moz-linear-gradient(#831608, #bb413b);
    background-image: -webkit-gradient(linear, left top, left bottom, from(#831608), to(#bb413b));      
    background-image: -webkit-linear-gradient(#831608, #bb413b);
    background-image: -o-linear-gradient(#831608, #bb413b);
    background-image: -ms-linear-gradient(#831608, #bb413b);
    background-image: linear-gradient(#831608, #bb413b);
}
nav a:active
{
    background: #bb413b;
    position: relative;
    top: 2px;    
    -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.7) inset;
    -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.7) inset;
    box-shadow: 0 0 3px rgba(0, 0, 0, 0.7) inset; 
}
nav span
{
    border: 1px dashed #eba1a3;
    display: inline-block;
    padding: 4px 15px;
    cursor: pointer;    
    background-color: #bb413b;
    background-image: -moz-linear-gradient(#d4463c, #aa2618);
    background-image: -webkit-gradient(linear, left top, left bottom, from(#d4463c), to(#aa2618));      
    background-image: -webkit-linear-gradient(#d4463c, #aa2618);
    background-image: -o-linear-gradient(#d4463c, #aa2618);
    background-image: -ms-linear-gradient(#d4463c, #aa2618);
    background-image: linear-gradient(#d4463c, #aa2618);
}
nav a:hover span
{   
    background-color: #bb413b;
    background-image: -moz-linear-gradient(#aa2618, #d4463c);
    background-image: -webkit-gradient(linear, left top, left bottom, from(#aa2618), to(#d4463c));      
    background-image: -webkit-linear-gradient(#aa2618, #d4463c);
    background-image: -o-linear-gradient(#aa2618, #d4463c);
    background-image: -ms-linear-gradient(#aa2618, #d4463c);
    background-image: linear-gradient(#aa2618, #d4463c);
}
 
$(function(){
    var $tweetDiv = $("#tweets>div");
    var tweetClickHandler = function(e){
        var $that = $(this);            
        //while we are cleaning up the div go ahead and get
        //the tweets
        $.when(
            getTweets($that.find('a').data('link'))
        //since we care weather the dfd was resolved or rejected we use the .done method
        //this only fires when the dfd is resolved
        ).done(
            //each function we call in the when will pass its response
            //to the then callback, in order
            function(tweets){
                //now lets fade the div out and remove everything that was in it
                //we could add add tweets in the clean div's fade out callback 
                //but this is more expressive in my opinion
                $.when(
                    cleanDiv()
                )
                //then is called weather the dfd is resolved or rejected
                .then(
                    function(){
                        //again we want to only show the div after the tweets
                        //have been added
                        $.when(
                            addTweets(tweets)
                        )
                        .then(
                            function(){
                                $tweetDiv.fadeIn('slow');
                            }
                        )
                        
                    }
                )
            }
        )
        //this is called when the deferred is rejected, in this
        //case when there is an issue getting tweets
        .fail(
            function(text){
                alert("Error getting tweets: " + text || '');   
            }
        );
    };
    var cleanDiv = function(){
        return $.Deferred(function(dfd){
            //otherwise fade the dive out before removing the children
            $tweetDiv.fadeOut('slow',function(){
                $tweetDiv.children().remove();
                dfd.resolve();
            });
        }).promise();
    };
    var addTweets = function(tweets){
        return $.Deferred(function(dfd){
            var stop = tweets.length - 1;
            $.each(tweets,function(i,tweet){
                var $newElem = $('<div><span class="username"></span><span class="tweettext"></span></div>');
                $newElem.find("span.username")
                    .html('<img src="' + tweet.profile_image_url_https + '">')
                    .end()
                    .find("span.tweettext")
                    .html(tweet.text)
                    .end()
                    .appendTo($tweetDiv);
                if(i === stop){
                    return dfd.resolve();
                }
            });
        }).promise();
    };
    var getTweets = function(searchURL){
        //since the deferred response relies on the data coming back from
        //the server we wrap the ajax call in a deferred. If we only wanted
        //to rely on the status of the ajax call we could have returned the
        //ajax call itself since it also returns a promise
        return $.Deferred(function(dfd){
            $.ajax({
                url : searchURL,
                
                dataType : 'jsonp',
                success : function(data){
                    //make sure what we got back valid data from twitter
                    if(typeof data === 'object' && ! ('error' in data)){
                        dfd.resolve(data.results);
                    }
                    else{
                        //we can pass variables to our callbacks
                        dfd.reject('bad response from server');
                    }
                },
                error : function(){
                    dfd.reject('ajax error');
                }
            });
        }).promise();
    };
    $('li').on('click', $.proxy(tweetClickHandler,this));
});
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x