animated twitterfeed js class

2011
Atmosphere BBDO
conference ipad app/site

Javascript class that pulls tweets from the twitter api based on a search term, populates a carousel with results. jQuery used for animation. Unfortunately, it’s about as reliable as Twitter, which, as I’m writing this, isn’t that reliable, so there are times the api just wont’ return any results. CD requested that I hide the first tweet and then reveal upon page load with a delay so it has an ‘active’ feel to it.

DOWNLOAD SRC


This can be implemented using a script node where you want the carousel to appear in your html page:
 <script type="text/javascript">
                               
                                var twitter_test = new TwitterFeed();
                                twitter_test.search("anything", 4,"orange");
                        
                        </script>


Here’s the class:
function TwitterFeed(){
    
    this.searchPrefix = "http://search.twitter.com/search.json?q=";
    this.searchTerm = "";
    this.maxTweetRetrieve = 5;
    this.tweetData = null;
    this.itemHeight = 0;
    this.linkClass = "#000000";
    this.maxTweets = 10;
    this.displayTweets = [];
    
    // how often do you want to get the tweets? (seconds)
    this.updateInterval = 5;
    
    // the latest tweet is hidden initially. How many seconds after loading do you
    // want it to appear?
    this.initialAnimDelay = 1;
    this.firstrun = true;
    this.getTweetsInt = null;
    this.animInterval = .1;
    this.checkInterval;
    this.intervalSet = false;
    this.maxAttempts = 5;
    this.attemptDelay = 1.5;
    this.attempts = 0;

    this.setupComplete = false;

    this.failCopy = "Sorry, Twitter appears to be down:-(";
    this.progressCopy = "Retrieving Twitter Feed...";
    
    this.carouselHolderIdPrefix = "carouselholder_";
    this.carouselIdPrefix = "carousel_";
    
    this.query = "";

}

TwitterFeed.prototype.search = function(_term, _maxDisplay, _linkClass){
    // alert("search");
    if (!this.setupComplete) {
        this.searchTerm = _term;
        this.displayTweets = _maxDisplay;
        this.linkClass = _linkClass;              
        this.maxTweets = _maxDisplay + 1;
        this.linkColor = _linkClass;
         
        var _html = "<div id='"+this.carouselHolderIdPrefix + _term + "' class='tcarousel-holder'><div id='"+this.carouselIdPrefix + _term + "' class='tcarousel'></div></div>";
        document.write(_html);
        
        this.setupComplete = true;
    }

    var _query = this.searchPrefix + _term + "&callback=?&rpp=" + this.maxTweets;
    var self = this;
    $(document).ready(function() {
        jQuery.getJSON(_query, function(data) {
            self.callback(data);
        });
    });
}

TwitterFeed.prototype.callback = function(_tweets){
    
    if (_tweets.results.length > 0) {
                
        var _totalTweets = _tweets.results.length;
        var _results = _tweets.results;
        this.tweetData = [];
       
        for (i = 0; i < _totalTweets; i++) {
            var _data = this.parseResult(_results[i]);
            this.tweetData.push(_data);
            this.addResult(_data.string);
        }
        
        this.itemHeight = Math.ceil(document.getElementById(this.carouselIdPrefix + this.searchTerm).offsetHeight / _results.length);
        document.getElementById(this.carouselHolderIdPrefix+ this.searchTerm).style.height = this.itemHeight * this.displayTweets + "px";
        this.drawList(this.tweetData, 1);

    } else {
        if (!this.intervalSet) {
            this.intervalSet = true;
            // alert("intervalSet: " + intervalSet);
            this.checkInterval = setInterval("reattempt()", this.attemptDelay * 1000);
            this.emptyDisplay(this.progressCopy);
        }
    } 
}

TwitterFeed.prototype.reattempt = function() {

    this.attempts++;
    if (this.attempts < this.maxAttempts) {
        this.search(this.searchTerm, null, null);
    } else {
        window.clearInterval(this.checkInterval);
        this.emptyDisplay(this.failCopy);
    }
}


TwitterFeed.prototype.emptyDisplay = function(_copy) {
        
    var _holder = document.getElementById(this.carouselHolderIdPrefix+ this.searchTerm);
    var _footer = document.getElementById("thefooter");

    _holder.innerHTML = "<div class='tcarousel-item invisible'>" + _copy + "</div>";
    _holder.style.marginTop = "0px";
    _holder.style.height = "auto";

    var _windowHeight = (typeof window.innerHeight != 'undefined' ? window.innerHeight : document.body.offsetHeight);

    _holder.style.height = (_windowHeight - findPosY(_holder) - 112) + "px";

}


TwitterFeed.prototype.parseResult = function(_obj) {

    var _message = this.parseLink(_obj.text);
    _message = this.parseHash(_message);

    var _user = _obj.from_user;
    var _created = _obj.created_at.replace(/(\+\d*\s)/g, "");

    var _date = new Date(_created);
    var _newDateString = this.relativeTime(_date);

    var _id = _obj.id;
    var _string = "<div class='tcarousel-item class='invisible''>" + _message + "<div class='tweet-extras'>" + _user + " <span class='time'>(" + _newDateString + ")</span></div></div>";


    // now put it all into a model
    var _dataObject = new Object();
    _dataObject.originalObject = _obj;
    _dataObject.message = _message;
    _dataObject.user = _user;
    _dataObject.id = _id;
    _dataObject.dateOriginal = _obj._date;
    _dataObject.dateString = _newDateString;
    _dataObject.string = _string;

        
    return _dataObject;
}

TwitterFeed.prototype.drawList = function(_data, _numAdded) {
    
    var _feed = document.getElementById(this.carouselIdPrefix + this.searchTerm);
       
    _feed.innerHTML = "loading...";
   
    var _margin = -this.itemHeight * _numAdded;
    _feed.style.marginTop = _margin + "px";
    
    for (i = 0; i < _data.length; i++) {
        this.addResult(_data[i].string);
    }
   
    if (this.firstrun == false) {
        this.bringToTop();
        for (i = 0; i < _numAdded; i++) {
            this.tweetData.pop();
        }
    } else { 
        
        this.firstrun = false;
        this.initTimers();
        var _self = this;
        setTimeout(function(){
            _self.bringToTop();
        }, this.initialAnimDelay * 1000);
    }
}

TwitterFeed.prototype.initialReveal = function() {
    bringToTop();
}

TwitterFeed.prototype.bringToTop = function() {
    $('#'+this.carouselIdPrefix + this.searchTerm).animate( {
        marginTop : '0px'
    });
    
}

TwitterFeed.prototype.addResult = function(_string) {
    var _feed = document.getElementById(this.carouselIdPrefix + this.searchTerm);
       
    if ( _feed.innerHTML == "loading..."){
        _feed.innerHTML = "";
    };
    
    _feed.innerHTML += _string;

}

TwitterFeed.prototype.parseLink = function(_s) {
    return _s.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!])/g, function(url) {
        return "<a href='" + url + "' >" + url + "</a>";
    });
}

TwitterFeed.prototype.parseHash = function(_s) {
     
    var _new = _s.replace("#" + this.searchTerm, "<a href='http://twitter.com/search?q=%23" + this.searchTerm + "' class='" + this.linkClass + "' target='_blank'>#" + this.searchTerm + "</a>");
    return _new;
}

TwitterFeed.prototype.K = function() {
    var a = navigator.userAgent;
    return {
        ie : a.match(/MSIE\s([^;]*)/)
    };
}

TwitterFeed.prototype.relativeTime = function(a) {
    var b = new Date();
    var c = new Date(a);
    /*
         * if (navigator.userAgent.match(/MSIE\s([^;]*)/)) { c =
         * Date.parse(a.replace(/( \+)/, ' UTC$1')) }
         */
         
    if (this.K.ie) {
        c = Date.parse(a.replace(/( \+)/, ' UTC$1'));
    }
       
    var d = b - c;
    var e = 1000;
    var minute = e * 60;
    var hour = minute * 60;
    var day = hour * 24;
    var week = day * 7;
        
        
    if (isNaN(d) || d < 0) {
        return "";
    }
       
    if (d < e * 7) {
        return "right now";
    }
    if (d < minute) {
        return Math.floor(d / e) + " seconds ago";
    }
    if (d < minute * 2) {
        return "about 1 minute ago";
    }
    if (d < hour) {
        return Math.floor(d / minute) + " minutes ago";
    }
    if (d < hour * 2) {
        return "about 1 hour ago";
    }
    if (d < day) {
        return Math.floor(d / hour) + " hours ago";
    }
    if (d > day && d < day * 2) {
        return "yesterday";
    }
    if (d < day * 365) {
        return Math.floor(d / day) + " days ago";
    } else {
        return "over a year ago";
    }
      
};

TwitterFeed.prototype.initTimers = function() {
    if (!this.getTweetsInt) {
        var _self = this;
        this.getTweetsInt = setInterval(function(){
            _self.getTweets();
        }, this.updateInterval * 1000);
    }
   
}

TwitterFeed.prototype.getTweets = function() {
    // alert("getTweets " + this)
    
    var _query = this.searchPrefix + this.searchTerm + "&callback=?&rpp=" + this.maxTweetRetrieve;
   
    // alert("_query: " + _query) 
    var _self = this;
    $(document).ready(function() {
        jQuery.getJSON(_query, function(data) {
            _self.callback2(data);
        });
    });
}

TwitterFeed.prototype.callback2 = function(_twitter) {
    //alert("callback2 " + this)
    var _totalNew = 0;

    for (i = _twitter.results.length - 1; i >= 0; i--) {
        var _data = this.parseResult(_twitter.results[i]);
        var _exists = false;

        for (j = 0; j < this.tweetData.length; j++) {
            if (this.tweetData[j].id == _data.id) {
                _exists = true;
            }

            // need to update the relative time for all tweets
            var _updatedData = this.parseResult(this.tweetData[j].originalObject);
            this.tweetData[j] = _updatedData;
        }
                
        if (!_exists) {
            this.tweetData.unshift(_data);
            _totalNew++;
        }

    }
    this.drawList(this.tweetData, _totalNew);
}

TwitterFeed.prototype.bind = function(scope) {
    var _function = this;
  
    return function() {
        return _function.apply(scope, arguments);
    }
}

TwitterFeed.prototype.findPosX = function(obj) {
    var curleft = 0;
    if (obj.offsetParent)
        while (1) {
            curleft += obj.offsetLeft;
            if (!obj.offsetParent)
                break;
            obj = obj.offsetParent;
        }
    else if (obj.x)
        curleft += obj.x;
    return curleft;
}

TwitterFeed.prototype.findPosY = function(obj) {
    var curtop = 0;
    if (obj.offsetParent)
        while (1) {
            curtop += obj.offsetTop;
            if (!obj.offsetParent)
                break;
            obj = obj.offsetParent;
        }
    else if (obj.y)
        curtop += obj.y;
    return curtop;
}

Posted 27. March 2013 by admin
Tags: , , , , , |

Leave a Reply

Required fields are marked *