integ/js/vs/tweets/tweetsource.js
changeset 28 84719280c84d
equal deleted inserted replaced
27:c21cffd36f98 28:84719280c84d
       
     1 /* Author: Raphaƫl Velt, IRI
       
     2  * 
       
     3  * Licence: CeCILL-B - http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
       
     4  * 
       
     5  * */
       
     6 
       
     7 function regexpFromText(_text) {
       
     8     return new RegExp('(' + _text.replace(/(\W)/gim,'\\$1') + ')','gim');
       
     9 }
       
    10 
       
    11 Btv_TweetArray = function() {
       
    12     this.tweets = [];
       
    13     this.idIndex = [];
       
    14 }
       
    15 
       
    16 Btv_TweetArray.prototype.push = function(_tweet) {
       
    17     this.tweets.push(_tweet);
       
    18     this.idIndex.push(_tweet.id_str);
       
    19 }
       
    20 
       
    21 Btv_TweetArray.prototype.setOnAdd = function(_callback) {
       
    22     this.onAdd = _callback;
       
    23 }
       
    24 
       
    25 Btv_TweetArray.prototype.addTweet = function(_tweet) {
       
    26     if (this.idIndex.indexOf(_tweet.id_str) != -1) {
       
    27         return;
       
    28     }
       
    29     if (!_tweet.date_value) {
       
    30         _tweet.date_value = Date.parse(_tweet.created_at.replace(/(\+|-)/,'UTC$1'));
       
    31     }
       
    32     var _pos = this.tweets.length;
       
    33     while (_pos && this.idIndex[_pos - 1] > _tweet.id_str) {
       
    34         _pos--;
       
    35     }
       
    36     this.tweets.splice(_pos,0,_tweet);
       
    37     this.idIndex.splice(_pos,0,_tweet.id_str);
       
    38     if (typeof this.onAdd == "function") {
       
    39         this.onAdd(_tweet);
       
    40     }
       
    41 }
       
    42 
       
    43 Btv_TweetArray.prototype.addMultipleTweets = function(_multiTweets) {
       
    44     var _l = _multiTweets.length;
       
    45     for (var _i = 0; _i < _l; _i++) {
       
    46         this.addTweet(_multiTweets[_i], true);
       
    47     }
       
    48 }
       
    49 
       
    50 Btv_TweetArray.prototype.count = function() {
       
    51     return this.tweets.length;
       
    52 }
       
    53 
       
    54 Btv_TweetArray.prototype.tweetAtPos = function(_i) {
       
    55     return this.tweets[_i];
       
    56 }
       
    57 
       
    58 Btv_TweetArray.prototype.slice = function(_start, _end) {
       
    59     var _slice = this.tweets.slice(_start, _end),
       
    60         _result = new Btv_TweetArray(),
       
    61         _l = _slice.length;
       
    62     for (var _i = 0; _i < _l; _i++) {
       
    63         _result.push(_slice[_i]);
       
    64     }
       
    65     return _result;
       
    66 }
       
    67 
       
    68 Btv_TweetArray.prototype.reverse = function() {
       
    69     var _result = new Btv_TweetArray(),
       
    70         _l = this.tweets.length;
       
    71     for (var _i = _l-1; _i >= 0; _i--) {
       
    72         _result.push(this.tweets[_i]);
       
    73     }
       
    74     return _result;
       
    75 }
       
    76 
       
    77 Btv_TweetArray.prototype.each = function(_callback) {
       
    78     var _l = this.count();
       
    79     for (var _i = 0; _i < _l; _i++) {
       
    80         _callback(this.tweets[_i]);
       
    81     }
       
    82 }
       
    83 
       
    84 Btv_TweetArray.prototype.map = function(_callback) {
       
    85     var _result = [];
       
    86     this.each(function(_tweet) {
       
    87         _result.push(_callback(_tweet))
       
    88     });
       
    89     return _result;
       
    90 }
       
    91 
       
    92 Btv_TweetArray.prototype.search = function(_filter) {
       
    93     var _filtered = new Btv_TweetArray(),
       
    94         _reFilter = regexpFromText(_filter);
       
    95     this.each(function(_tweet) {
       
    96         var _mention = '@' + _tweet.from_user;
       
    97         if (( _tweet.text.search(_reFilter) != -1 ) || ( _mention.search(_reFilter) != -1 )) {
       
    98             _filtered.push(_tweet);
       
    99         }
       
   100     });
       
   101     return _filtered;
       
   102 }
       
   103 
       
   104 Btv_TweetArray.prototype.beforeDate = function(_date) {
       
   105     var _filtered = new Btv_TweetArray();
       
   106     this.each(function(_tweet) {
       
   107         if (_tweet.date_value <= _date) {
       
   108             _filtered.push(_tweet);
       
   109         }
       
   110     });
       
   111     return _filtered;
       
   112 }
       
   113 
       
   114 Btv_TweetArray.prototype.afterDate = function(_date) {
       
   115     var _filtered = new Btv_TweetArray();
       
   116     this.each(function(_tweet) {
       
   117         if (_tweet.date_value > _date) {
       
   118             _filtered.push(_tweet);
       
   119         }
       
   120     });
       
   121     return _filtered;
       
   122 }
       
   123 
       
   124 Btv_TweetArray.prototype.tweetById = function(_tweetId) {
       
   125     var _index = this.idIndex.indexOf(_tweetId);
       
   126     return (_index ? this.tweets[_index] : null);
       
   127 }
       
   128 
       
   129 Btv_TweetArray.prototype.lastTweet = function() {
       
   130     return this.tweets[this.tweets.length - 1];
       
   131 }
       
   132 
       
   133 /*
       
   134  * 
       
   135  */
       
   136 
       
   137 Btv_TweetSource = function(_opts) {
       
   138     Btv_TweetArray.call(this);
       
   139     this.loading = false;
       
   140     if (!_opts || !_opts.keywords || !_opts.keywords.length) {
       
   141         return;
       
   142     }
       
   143     this.options = _opts;
       
   144     var _this = this;
       
   145     this.retrieveInitialTweets();
       
   146     setInterval(function() {
       
   147         _this.retrieveNewTweets();
       
   148     }, 5000);
       
   149 }
       
   150 
       
   151 Btv_TweetSource.prototype = new Btv_TweetArray();
       
   152 
       
   153 Btv_TweetSource.prototype.retrieveTweets = function(_opts) {
       
   154     
       
   155     function getTwitterUrl(url) {
       
   156         $.getJSON(url, function(data) {
       
   157             _currentPage++;
       
   158             var _isLast = true;
       
   159             if (data.results && data.results.length) {
       
   160                 _this.addMultipleTweets(data.results);
       
   161                 var _oldestTweetId = data.results[data.results.length - 1].id_str,
       
   162                     _maxId = _oldestTweetId;
       
   163                 if (_currentPage < _opts.pages) {
       
   164                     _isLast = false;
       
   165                     getTwitterUrl(_baseurl + _firstparams + '&max_id=' + _maxId + _lastparams);
       
   166                 }
       
   167             }
       
   168             
       
   169             if (_isLast) {
       
   170                 _this.loading = false;
       
   171                 if (typeof _this.onNewTweets == "function") {
       
   172                     _this.onNewTweets();
       
   173                 }
       
   174             }
       
   175         });
       
   176     }
       
   177     
       
   178     
       
   179     if (this.loading) {
       
   180         return;
       
   181     }
       
   182     this.loading = true;
       
   183     var _baseurl = "http://search.twitter.com/search.json",
       
   184         _currentPage = 0,
       
   185         _firstparams = "?q="
       
   186             + encodeURIComponent(this.options.keywords.join(' OR '))
       
   187             + "&rpp=100"
       
   188             + (this.options.lang ? "&lang=" + this.options.lang : '' ),
       
   189         _lastparams = ( _opts.since_id ? "&since_id=" + _opts.since_id : '' )
       
   190             + "&callback=?",
       
   191         _jsonurl = _baseurl + _firstparams + _lastparams,
       
   192         _this = this;
       
   193     getTwitterUrl(_jsonurl);
       
   194     
       
   195 }
       
   196 
       
   197 Btv_TweetSource.prototype.retrieveInitialTweets = function() {
       
   198     this.retrieveTweets({
       
   199         "pages": 1
       
   200     });
       
   201 }
       
   202 
       
   203 Btv_TweetSource.prototype.retrieveNewTweets = function() {
       
   204     var _last = this.lastTweet();
       
   205     this.retrieveTweets({
       
   206         "pages": 1,
       
   207         "since_id": _last ? _last.id_str : 0
       
   208     });
       
   209 }
       
   210 
       
   211 Btv_TweetSource.prototype.setOnNewTweets = function(_callback) {
       
   212     this.onNewTweets = _callback;
       
   213 }
       
   214 
       
   215 Btv_TweetQueueManager = function(_tweetArray, _callback) {
       
   216     this.tweetArray = _tweetArray;
       
   217     this.majorInterval = 10000; // Time slices for calculating the minor Interval setting
       
   218     this.minimumInterval = 1000; // Safe limit to avoid tweets going to the wrong column
       
   219     this.initialBuffer = 300000; // don't start with empty columns, but show the tweets of the last five minutes - 5 * 60 * 1000 = 300000
       
   220     this.waitIfNoTweets = 2000;
       
   221     this.callback = _callback;
       
   222     this.lastEndTime = new Date().valueOf() - this.initialBuffer;
       
   223     this.isPaused = false;
       
   224     this.onMajorInterval();
       
   225 }
       
   226 
       
   227 Btv_TweetQueueManager.prototype.onMinorInterval = function() {
       
   228     if (this.isPaused) {
       
   229         this.waitMinorInterval();
       
   230     } else {
       
   231         var _l = this.currentSlice.count();
       
   232         if (this.position < _l) {
       
   233             this.callback(this.currentSlice.tweetAtPos(this.position));
       
   234             this.position++;
       
   235             this.waitMinorInterval();
       
   236         } else {
       
   237             this.onMajorInterval();
       
   238         }
       
   239     }
       
   240 }
       
   241 
       
   242 Btv_TweetQueueManager.prototype.waitMinorInterval = function() {
       
   243     var _this = this;
       
   244     window.setTimeout(function() {
       
   245         _this.onMinorInterval();
       
   246     }, this.minorInterval);
       
   247 }
       
   248 
       
   249 Btv_TweetQueueManager.prototype.onMajorInterval = function() {
       
   250     this.position = 0;
       
   251     this.currentSlice = this.tweetArray.afterDate(this.lastEndTime);
       
   252     var _l = this.currentSlice.count();
       
   253     if (_l) {
       
   254         this.lastEndTime = this.currentSlice.tweetAtPos(_l - 1).date_value;
       
   255         this.minorInterval = Math.floor(Math.max(this.minimumInterval, this.majorInterval / _l));
       
   256         this.onMinorInterval();
       
   257     } else {
       
   258         var _this = this;
       
   259         window.setTimeout(function() {
       
   260             _this.onMajorInterval();
       
   261         }, this.waitIfNoTweets);
       
   262     }
       
   263 }
       
   264 
       
   265 Btv_TweetQueueManager.prototype.playPause = function() {
       
   266     this.isPaused = !this.isPaused;
       
   267     return this.isPaused;
       
   268 }