var socket,
paper,
tweetData = {
"tweetcount" : 0,
"position" : -1,
"zoomLevel" : 3,
"timeLevel" : 2
},
zoomLevels = [
{
"description" : "160 tweets per page",
"className" : "icons",
"displayCount" : 160
},
{
"description" : "24 tweets per page",
"className" : "quarter",
"displayCount" : 24
},
{
"description" : "12 tweets per page",
"className" : "half",
"displayCount" : 12
},
{
"description" : "6 tweets per page",
"className" : "full",
"displayCount" : 6
}
],
colors = {
'positive' : "#1D973D",
'reference' : "#C5A62D",
'negative' : "#CE0A15",
'question' : "#036AAE"
},
timeWindow;
function tweetToHtml(tweet) {
html = '<li class="tweet ' + zoomLevels[tweetData.zoomLevel].className;
for (var i in tweet.annotations) {
html += ' a_' + tweet.annotations[i]
}
html += '" id="tweet_' + tweet.id + '">';
a_user = '<a href="http://twitter.com/' + tweet.user.screen_name + '" target="_blank" title="' + tweet.user.name + '">';
if (tweet.user.profile_image_url) {
html += a_user + '<img class="tweet_profile_image" src="' + tweet.user.profile_image_url + '" /></a>';
}
html += '<h4>' + a_user + '@' + tweet.user.screen_name + '</a></h4><p class="tweet_created_at">' + new Date(tweet.created_at).toLocaleTimeString() + '</p><p>';
lastend = 0;
txt = '';
entities = [];
for (var i in tweet.entities.hashtag) {
entities.push({
"start" : tweet.entities.hashtag[i].indices[0],
"end" : tweet.entities.hashtag[i].indices[1],
"html" : '<a href="http://twitter.com/search?q=%23' + tweet.entities.hashtag[i].text + '" target="_blank">#' + tweet.entities.hashtag[i].text + '</a>'
});
}
for (var i in tweet.entities.urls) {
entities.push({
"start" : tweet.entities.urls[i].indices[0],
"end" : tweet.entities.urls[i].indices[1],
"html" : '<a href="' + tweet.entities.urls[i].expanded_url + '" target="_blank">' + tweet.entities.urls[i].display_url + '</a>'
});
}
for (var i in tweet.entities.user_mentions) {
entities.push({
"start" : tweet.entities.user_mentions[i].indices[0],
"end" : tweet.entities.user_mentions[i].indices[1],
"html" : '<a href="http://twitter.com/' + tweet.entities.user_mentions[i].screen_name + '" target="_blank" title="' + tweet.entities.user_mentions[i].name + '">@' + tweet.entities.user_mentions[i].screen_name + '</a>'
});
}
entities.sort(function(a, b) { return a.start - b.start });
for (var i in entities) {
txt += tweet.text.substring(lastend, entities[i].start) + entities[i].html;
lastend = entities[i].end;
}
txt += tweet.text.substring(lastend);
html += txt + '</p></li>';
return html;
}
function displayTweets() {
var to = tweetData.position + 1,
from = Math.max(0, to - zoomLevels[tweetData.zoomLevel].displayCount);
socket.emit('getTweets',{ "from": from, "to": to, "callback" : "display" });
}
function setZoom(level) {
tweetData.zoomLevel = Math.max(0, Math.min( zoomLevels.length - 1 , level ) );
displayTweets();
}
function setTimeZoom(level) {
tweetData.timeLevel = Math.max(0, Math.min( 3, level ));
getTimeline();
}
function getTimeline() {
socket.emit('getTimeline',{"level":tweetData.timeLevel});
}
function showTimeWindow() {
if (timeWindow) {
timeWindow.remove();
timeWindow = null;
}
if (tweetData.tweetsOnDisplay && tweetData.timelineOnDisplay) {
var dtfintl = new Date ( tweetData.timelineOnDisplay[ tweetData.timelineOnDisplay.length - 1 ].end ),
dtdebtl = new Date ( tweetData.timelineOnDisplay[0].start ),
dtfintw = new Date( tweetData.tweetsOnDisplay[0].created_at ),
dtdebtw = new Date( tweetData.tweetsOnDisplay[ tweetData.tweetsOnDisplay.length - 1 ].created_at ),
scaleY = 600 / ( dtfintl - dtdebtl );
timeWindow = paper.rect( 0, scaleY * ( dtfintl - dtfintw ), 600, scaleY * ( dtfintw - dtdebtw )).attr({"stroke":"#000080","fill":"#8080ff","fill-opacity":.2});
}
}
$(document).ready(function() {
paper = Raphael("timeline", 160, 600);
socket = io.connect('http://' + S_IO_HOST + ':' + S_IO_PORT );
socket.on('tweetSummary', function (data) {
if (tweetData.position == tweetData.tweetcount - 1) {
tweetData.position = data.tweetcount - 1;
displayTweets();
getTimeline();
}
tweetData.tweetcount = data.tweetcount;
});
socket.on('tweets', function (data) {
switch (data.callback) {
case "display":
tweetData.tweetsOnDisplay = data.tweets;
tweetData.tweetsOnDisplay.reverse();
html = '';
for (var i in tweetData.tweetsOnDisplay) {
html += tweetToHtml(tweetData.tweetsOnDisplay[i]);
}
$("#tweetlist").html(html);
showTimeWindow();
break;
}
});
socket.on('timeline', function (data) {
tweetData.timelineOnDisplay = data.timeline;
paper.clear();
timeWindow = null;
var max = 0;
for (var i in data.timeline) {
max = Math.max(max, data.timeline[i].tweets.length);
}
var scaleX = 160 / max,
scaleY = 600 / data.timeline.length,
tmptw = [];
for (var i = 0; i < tweetData.tweetcount; i++) {
tmptw.push({});
}
for (var i = 0; i < data.timeline.length; i++) {
for (var j = 0; j < data.timeline[i].tweets.length; j++) {
var coul = "#585858";
for (var k in data.timeline[i].annotations) {
if (data.timeline[i].annotations[k].indexOf(data.timeline[i].tweets[j]) != -1) {
coul = colors[k];
}
}
tmptw[data.timeline[i].tweets[j]].y = i;
tmptw[data.timeline[i].tweets[j]].x = j;
paper.rect(scaleX * j + (scaleX > 3 ? .5 : 0), 600 - ((i+1) * scaleY) + (scaleY > 3 ? .5 : 0), scaleX - (scaleX > 3 ? 1 : 0), scaleY - (scaleY > 3 ? 1 : 0)).attr({"stroke":"none","fill":coul});
}
}
for (var i = 0; i < data.arcs.length; i++) {
var x1 = scaleX * (tmptw[data.arcs[i].from].x + .5),
x2 = scaleX * (tmptw[data.arcs[i].to].x + .5),
y1 = 600 - scaleY * (tmptw[data.arcs[i].from].y + .5),
y2 = 600 - scaleY * (tmptw[data.arcs[i].to].y + .5),
d = "M"+x1+" "+y1+"C";
if (y1 == y2) {
d += x1+" "+(y1 - 60)+" "+x2+" "+(y2 - 60);
} else {
d += (x1 + 60)+" "+y1+" "+(x2 + 60)+" "+y2;
}
paper.path(d+" "+x2+" "+y2);
}
showTimeWindow();
});
});