Home » Demos » Live tweets

Live tweets



About this demo


Tweets from Twitter trends using their FireHose API. Enjoy the reactivity of real time :)

Which features this demo is using?

  • Http.js
  • ServerSide JavaScript



A simple chat demo, multi-user and private messages.

APE real time chat

A simple chat demo, multi-user and private messages.

Demo of multi-user moving and chating in real time.

Move demo

Demo of multi-user moving and chating in real time.

Live tweets from Twitter trends, in real time!

Live tweets

Live tweets from Twitter trends, in real time!


Gateway to IRC using the TCPSocket feature. Come chat with us ;)

TCPSocket Demo (IRC)

Gateway to IRC using the TCPSocket feature. Come chat with us ;)

A demo of a small massive multiplayer role playing game!

MMORPG

A demo of a small massive multiplayer role playing game!

Draw with everyone in real time!

Pixelbox

Draw with everyone in real time!


Homepage demo

Homepage demo

This is the demo from the home page of APE, but you've probably already seen it ;-)


Study the source code


Check out the Client JavaScript, HTML and ServerSide JavaScript source code of this demo by reading the following :


  1. <script type="text/javascript" src="http://static.weelya.com/weelya_ape/demos/twitter/twitter.js"></script>
  2. <link type="text/css" rel="stylesheet"  href="/demos/twitter/twitter.css" title="APE Stylesheet" />
  3. <script type="text/javascript">
  4.         window.addEvent('domready', function() {
  5.                 APE.Config.channel = '*twitterfall';
  6.                 APE.Config.identifier = 'twitrends';                                           
  7.  
  8.                 var client = new APE.Twitter({'container':'ape_master_container'});
  9.                 client.load({
  10.                                 'identifier':'twittertrenddemo'
  11.                 });
  12.         });
  13. </script>
  14.  
  1. function rand_chars(){
  2.         var keylist="abcdefghijklmnopqrstuvwxyz"
  3.                 var temp=''
  4.                 var plength=5;
  5.         for (var i=0;i<plength;i++){
  6.                 temp+=keylist.charAt(Math.floor(Math.random()*keylist.length))
  7.         }
  8.         return temp;
  9. }
  10.  
  11. APE.Twitter = new Class({
  12.  
  13.         Extends: APE.Client,
  14.  
  15.         Implements: Options,
  16.  
  17.         options: {
  18.                 container: document.body
  19.         },
  20.  
  21.         initialize: function(options){
  22.                 this.setOptions(options);
  23.                 this.els = {};
  24.                 this.trends = new $H;
  25.                 this.twittAnimSpeed = 500;
  26.                 this.twittHeight = 10;
  27.                 this.twitt_text = [];
  28.                 this.trendResize = false;
  29.                 this.trendFx = new $H;
  30.                 this.tQueue = [];
  31.  
  32.                 this.addEvent('load', this.initPlayground);
  33. //              this.addEvent('multiPipeCreate', this.pipeCreate);
  34.                
  35.                 this.onRaw('trends', this.rawTrends);
  36.                 this.onRaw('twitter', this.twitter);
  37.                 this.onRaw('trendupdate', this.updateTrend);
  38.  
  39.  
  40.                 for (var i = 0; i < 10; i++) {
  41.                         this.tQueue[i] = [];
  42.                 }
  43.  
  44.                 this.colors = ['bc5353', 'dec46a', '8bde6a', '6aded7', '1c3fb0', '9d1cb0', 'f5fbb6', '085822', '70bdff', '5f5f5f'];
  45.         },
  46.  
  47.         initPlayground: function(){
  48.                 this.core.start({"name":rand_chars()});
  49.                 this.els.container = new Element('div', {'id': 'twitter_container'}).inject(this.options.container);   
  50.                 this.els.twitter_container = new Element('div',{'id': 'twitter_containers_twitts'}).inject(this.els.container);
  51.                 this.els.name_container = new Element('div', {'id': 'trend_name_container'}).inject(this.els.container);
  52.                 this.twittPoll.delay(this.getRandom(400, 700), this);
  53.         },
  54.  
  55.         rawTrends: function(raw) {
  56.                                 for(var i = 0; i < 10; i++) {
  57.                                         this.newTrend(raw.data[i], i);
  58.                                 }
  59. /*                              var trendHistory = JSON.decode(decodeURIComponent(pipe.pipe.properties.trend_history));
  60.                                 for (var k in trendHistory) {
  61.                                         var trend = this.trends.get(k.toLowerCase());
  62.                                         if (trend) {
  63.                                                 for (var i = 0; i < trendHistory[k].length; i++) {
  64.                                                         this.tQueue[trend.index].push([trend, trendHistory[k][i]]);
  65.                                                 }
  66.                                          }
  67.                                 }*/
  68.         },
  69.  
  70.         twittPoll: function() {
  71.                 var idx = [];
  72.                 var i = 0;
  73.                 var args;
  74.                 var stop = false;
  75.                 for (var i = 0; i < 10; i++) {
  76.                         args = this.tQueue[i].shift();
  77.                         if (args) {
  78.                                 this.addTwitt.delay(this.getRandom(0, 350), this, args );
  79.                         }
  80.                 }
  81.  
  82.                 this.twittPoll.delay(this.getRandom(500, 900), this);
  83.         },
  84.  
  85.         updateTrend: function(data) {
  86.                 var trendDiff = data.data;
  87.                
  88.                 var oldIndex = new Array();
  89.  
  90.                 for (var i = 0; i < trendDiff.toDel.length; i++) {
  91.                         if (this.trends.get(trendDiff.toDel[i].toLowerCase())) {
  92.                                 oldIndex.push(this.delTrend(trendDiff.toDel[i]));
  93.                         }
  94.                 }
  95.                 var l = oldIndex.length;
  96.                 for (var i = 0; i < l; i++) {
  97.                         this.newTrend(trendDiff.toAdd[i], oldIndex.shift());
  98.                 }
  99.  
  100.         },
  101.  
  102.         delTrend: function(trend) {
  103.                 var tmp = this.trends.get(trend.toLowerCase());
  104.                 var index = tmp.index;
  105.                 tmp.els.t_container.destroy();
  106.                 tmp.els.name.destroy();
  107.                
  108.                 this.trends.erase(trend);
  109.  
  110.                 return index;
  111.         },
  112.  
  113.         newTrend: function(trend, index){
  114.                         var t_container = new Element('div',{'class':'trend trend_'+index}).inject(this.els.twitter_container);
  115.                         var t = new Element('div').inject(t_container, 'top');
  116.                         var top = new Element('div', {
  117.                                         'class': 'trend_top',
  118.                                         'styles': {
  119.                                                 'margin-top':'363px',
  120.                                                 'background-color':'#' + this.colors[index]
  121.                                         }
  122.                                 }).inject(t_container);
  123.  
  124.                         var top_over = new Element('div', {
  125.                                         'class': 'trend_top_over',
  126.                                         'styles':{
  127.                                                 'opacity': 0
  128.                                         }
  129.                         }).inject(top,'after');
  130.  
  131.                         var container = new Element('div', {
  132.                                         'class': 'trend_container',
  133.                                         'styles': {
  134.                                                 'background-color':'#' + this.colors[index]
  135.                                         }
  136.                                 }).inject(t_container);
  137.  
  138.                         var container_over = new Element('div', {
  139.                                                 'class': 'trend_container_over',
  140.                                                 'styles':{
  141.                                                         'opacity': 0
  142.                                                 }
  143.                                         }).inject(container,'after');
  144.                         var trendName = trend;
  145.                         if (trend.length>10) trendName = trendName.substring(0,10)+'...';
  146.                         var name =  new Element('div', {
  147.                                                 'class': 'trend_name',
  148.                                                 'text': unescape(trendName).replace(/\+/g,' ')
  149.                                         }).inject(this.els.name_container);
  150.                         this.trends.set(trend.toLowerCase(),{
  151.                                         'els': {
  152.                                                 't_container': t_container,
  153.                                                 'container': container,
  154.                                                 'top': top,
  155.                                                 'container_over': container_over,
  156.                                                 'top_over': top_over,
  157.                                                 't':t,
  158.                                                 'name': name
  159.                                         },
  160.                                         'index': index,
  161.                                         'topPos': 363
  162.                                 });
  163.         },
  164.  
  165.         resetTrendSize: function() {
  166.                 this.trendResize = true;
  167.                 this.trends.each(function(trend) {
  168.                         if (trend.fx) {
  169.                                 trend.fx.cancel();
  170.                         }
  171.                         $$('.twitter_container').destroy();
  172.                         var fx = new Fx.Morph(trend.els.top, {duration:200});
  173.                         trend.topPos = 363;
  174.                         fx.start({
  175.                                 'margin-top': 363
  176.                         });
  177.                 }.bind(this));
  178.                 (function(){ this.trendResize = false}).delay(220,this);
  179.         },
  180.  
  181.         addTwitt: function(trend, twitt){
  182.                 if (trend.topPos <= 25) {
  183.                         this.resetTrendSize();
  184.                         return null;
  185.                 }
  186.  
  187.                 if (!this.trendResize) {
  188.                         var tmp = new Element('div', {'class': 'twitter_container'}).inject(trend.els.t,'top');
  189.                         new Element('div', {'styles':{'background-color':'#' + this.colors[trend.index]}, 'class': 'twitt'}).inject(tmp);
  190.                         var twitt_el = new Element('div', {'class': 'twitt_over', 'styles':{'opacity':0}} ).inject(tmp);
  191.                         var first_fx = new Fx.Morph(tmp, {'duration': this.twittAnimSpeed});
  192.  
  193.                         (function(el) { //flash the falling element
  194.                                 var fx = new Fx.Morph(el, {'duration':100});
  195.                                 fx.start({'opacity':1});
  196.                         }).delay(this.twittAnimSpeed-340, this, twitt_el);
  197.                        
  198.                         //Make the falling element fall
  199.                         first_fx.start({
  200.                                         'margin-top': [0, trend.topPos-15]
  201.                                 });
  202.  
  203.                         //destroy the falling element
  204.                         //make the trend grow
  205.                         //Flash  the trend
  206.                         first_fx.addEvent('complete', function(trend, twitt, el){
  207.                                         el.destroy();
  208.                                         if (!this.trendResize) {
  209.                                                 var fx = new Fx.Morph(trend.els.top,{'duration':550, transition: Fx.Transitions.Elastic.easeOut});
  210.                                                 var old_top = trend.els.top.getStyle('margin-top').toInt();
  211.  
  212.                                                 trend.fx = fx;
  213.  
  214.                                                 fx.start({
  215.                                                         'margin-top': old_top-this.twittHeight
  216.                                                 });
  217.  
  218.  
  219.                                                 var fxc1 = new Fx.Morph(trend.els.container_over, {'duration':'50'});
  220.                                                 var fxc2 = new Fx.Morph(trend.els.container_over, {'duration':'250'});
  221.  
  222.                                                 var fxt1 = new Fx.Morph(trend.els.top_over, {'duration':'50'});
  223.                                                 var fxt2 = new Fx.Morph(trend.els.top_over, {'duration':'250'});
  224.  
  225.                                                 fxc1.start({'opacity':1});
  226.  
  227.                                                 fxc1.addEvent('complete', function(fx2) {
  228.                                                         fx2.start({'opacity':0})
  229.                                                 }.bind(this, fxc2));
  230.  
  231.                                                 fxt1.start({'opacity':1});
  232.  
  233.                                                 fxt1.addEvent('complete', function(fx2) {
  234.                                                         fx2.start({'opacity':0})
  235.                                                 }.bind(this, fxt2));
  236.                                         }
  237.                                 }.bind(this, [trend, twitt, tmp]));
  238.  
  239.                         //Add the twitt text
  240.                         first_fx.addEvent('complete', function(trend, twitt, el){
  241.                                         if (this.twitt_text.length >= 9) {
  242.                                                 var el = this.twitt_text.shift();
  243.                                                 el.destroy();
  244.                                         }
  245.                                         twitt=  unescape(twitt).replace(/\+/g,' ');
  246.                                         if (twitt> 70) twitt= twitt.substring(0, 70)+ '...';
  247.                                         var tmp = new Element('div', {
  248.                                                 'html': twitt,
  249.                                                 'class': 'twitt_txt twitt_' + trend.index,
  250.                                                 'styles': {
  251.                                                         'color': '#'+this.colors[trend.index]
  252.                                                 }
  253.                                         }).inject(this.els.name_container, 'after');
  254.  
  255.                                         this.twitt_text.push(tmp);
  256.  
  257.  
  258.                         }.bind(this, [trend, twitt, tmp]));
  259.  
  260.                         trend.topPos -= this.twittHeight;
  261.                 }
  262.         },
  263.  
  264.         twitter: function(data){
  265.                 var twitts = data.data;
  266.                 var trend = this.trends.get(twitts.trend.toLowerCase());
  267.                 if (!trend && this.trends.getLength() < 10 ) {
  268.                         this.newTrend(twitts.trend.toLowerCase(), this.trends.getLength());
  269.                         trend = this.trends.get(twitts.trend.toLowerCase());
  270.                 }
  271.                 if (trend) {
  272.                         this.tQueue[trend.index].push([trend, twitts.text]);
  273.                 }
  274.         },
  275.  
  276.         getRandom: function(min, max) {
  277.                 return Math.floor(Math.random() * (max - min + 1)) + min;
  278.         }
  279.  
  280. });
  281.  
  1. //
  2. // demoTwitter.ape.js
  3. //
  4.  
  5. include('Social/Social.js');
  6.  
  7. var keys   = 'ape,ajax,comet,javascript,mootools,push,ape,ape-project';
  8.  
  9. var trends = new Class({
  10.         trendsList:     [],
  11.         oldTrendsList:  [],
  12.         stream:                 {},
  13.         user:                   '',
  14.         count:                  0,
  15.        
  16.         initialize: function (user, callback) {
  17.                 this.user = user;
  18.                 this.updateTrends(callback);
  19.         },
  20.        
  21.         updateTrends: function (callback) {
  22.                 new Http('http://search.twitter.com/trends.json').getContent(function (result) {
  23.                         try {
  24.                                 trends = eval('(' +  result + ')');
  25.                                 for (var i = 0; i < 10; i++) {
  26.                                         this.trendsList.push(trends.trends[i].name);
  27.                                 }
  28.                                
  29.                                 if (this.oldTrendsList.length != 0) {
  30.                                         var toAdd = [];
  31.                                         var toDel  = [];
  32.                                         for (var i = 0; i < 10; i++) {
  33.                                                 if (!this.oldTrendsList.contains(this.trendsList[i])) {
  34.                                                         toAdd.push(this.trendsList[i]);
  35.                                                 }
  36.                                                 if (!this.trendsList.contains(this.oldTrendsList[i])) {
  37.                                                         toDel.push(this.trendsList[i]);
  38.                                                 }
  39.                                         }
  40.                                        
  41.                                         if (toAdd.length != 0 && toDel.length != 0) {
  42.                                                 Ape.getChannelByName('*twitterfall').pipe.sendRaw('trendupdate', {'toAdd': toAdd, 'toDel': toDel});
  43.                                         }
  44.                                 }
  45.                         } catch(err) {
  46.                                 this.trendsList = this.oldTrendsList;
  47.                         }
  48.                
  49.                         callback.run([this.trendsList]);
  50.                 }.bind(this)); 
  51.         },
  52.        
  53.         startStream: function (callback) {
  54.                 var list = '';
  55.                
  56.                 for (var i = 0; i < 10; i++) {
  57.                         if (this.trendsList[i] != null) {
  58.                                 if (i != 0) list += ',';
  59.                                 var tmpTrend            = this.trendsList[i].toLowerCase();
  60.                                 var trendSplited        = tmpTrend.split(' ');
  61.                                 list += trendSplited[0];
  62.                         }
  63.                 }
  64.                
  65.                 var tmp = this.user.split(':');
  66.                 Ape.log(tmp);
  67.                 var tweetStream = new TwitterStream(tmp[0], tmp[1], 'track='+list);
  68.                 tweetStream.set('logs', true);
  69.                 tweetStream.connect(function (tweet) {
  70.                         this.count++;
  71.                        
  72.                         var channel = Ape.getChannelByName('*twitterfall');
  73.  
  74.                         if (channel) {
  75.                                 if (this.count >= 2500 ) {
  76.                                         tweetStream.close();
  77.                                         this.count                      = 0;
  78.                                         this.oldTrendsList      = this.trendsList;
  79.                                         this.trendsList         = [];
  80.                                
  81.                                         this.updateTrends( function () {       
  82.                                                 this.startStream(callback);
  83.                                         }.bind(this));
  84.                                 } else {
  85.                                         var tmpTrend;
  86.                                         var tmpTweet = unescape(tweet.content.toLowerCase());
  87.                                        
  88.                                         for (var i = 0; i < 10; i++) {
  89.                                                 if ($defined(this.trendsList[i])) {
  90.                                                         if (tmpTweet.contains(this.trendsList[i].toLowerCase()) || tmpTweet.contains('#' + this.trendsList[i].toLowerCase())) {
  91.                                                                 tmpTrend = this.trendsList[i];
  92.                                                                 i = 10;
  93.                                                         }
  94.                                                 }
  95.                                         }
  96.  
  97.                                         if (tmpTrend != null) {
  98.                                                 channel.pipe.sendRaw('twitter', {'text':tweet.content, 'user':tweet.user.nickname, 'trend': tmpTrend});
  99.                                         }
  100.                                        
  101.                                         if (callback != null) {
  102.                                                 callback.run(tweet);
  103.                                         }
  104.                                 }
  105.                         }
  106.                 }.bind(this));
  107.         }
  108. });
  109.  
  110. var butterfly = new TwitterStream('login','pass', 'track=%23ape,%23ape-project');
  111. butterfly.connect(function (tweet) {
  112.         var channel = Ape.getChannelByName('*twitter');
  113.         if (channel) channel.pipe.sendRaw('butterfly', {'text':tweet.content, 'user':tweet.user.nickname});
  114. });
  115.  
  116. var tS = new TwitterStream('login','pass', 'track='+encodeURIComponent(keys));
  117. tS.connect(function (tweet) {
  118.         var channel = Ape.getChannelByName('*twitter');
  119.         if (channel) channel.pipe.sendRaw('twitter', {'text':tweet.content, 'user':tweet.user.nickname});
  120. });
  121.  
  122. var trendsUser = 'login:pass';
  123.  
  124. var t = new trends(trendsUser, function () {
  125.         Ape.addEvent("join", function(user, channel) {
  126.                 if (channel.getProperty('name') == '*twitterfall') {
  127.                         user.pipe.sendRaw('trends', t.trendsList);
  128.                 }
  129.         });
  130.         t.startStream();
  131. });