diff -r 66092f867c03 -r 0c4acfa2aea1 tweetcast/nodejs-bis/client/js/script.js --- a/tweetcast/nodejs-bis/client/js/script.js Tue Nov 15 11:38:14 2011 +0100 +++ b/tweetcast/nodejs-bis/client/js/script.js Tue Nov 15 18:29:44 2011 +0100 @@ -18,12 +18,17 @@ deltaX : 30, tlWidth : 98, tlHeight : 450, - globalWords : {} + globalWords : {}, + refMouse : { x : 0, y : 0}, + refPosTl : { x : 0, y : 0}, + tlMouseMoved : false, + tlMouseClicked : false }, tlBuffer = '', relHover = null, wheelDelta = 0, - rx_word = /[^ \.&;,'"!\?@#\d\(\)\+\[\]\\\…\-«»:\/]{3,}/g; + rx_word = /[^ \.&;,'"!\?@#\d\(\)\+\[\]\\\…\-«»:\/]{3,}/g, + stop_list = [ 'and', 'les', 'the' ]; function arc(source, target) { var x3 = .3 * target.y - .3 * source.y + .8 * source.x + .2 * target.x; @@ -34,13 +39,15 @@ } function countWords(text, wordobj) { - var tab = text.match(rx_word); + var tab = text.replace(/https?:\/\/[0-9a-zA-Z\.%\/-_]+/g,'').match(rx_word); for (var i in tab) { var word = tab[i].toLowerCase(); - if (wordobj[word]) { - wordobj[word]++; - } else { - wordobj[word] = 1; + if (stop_list.indexOf(word) == -1 && tracking_keywords.indexOf(word) == -1) { + if (wordobj[word]) { + wordobj[word]++; + } else { + wordobj[word] = 1; + } } } } @@ -61,12 +68,26 @@ } } - var tab = tweet.text.split(/\&\#|\;/), - txt = ''; - for (i = 0; i < tab.length; i++) { - txt += (i % 2 && parseInt(tab[i]) != NaN) ? String.fromCharCode(tab[i]) : tab[i]; + var ann = []; + for (var j in annotations) { + if (j != "default") { + for (var k in annotations[j].keywords) { + if (tweet.text.search(annotations[j].keywords[k]) != -1) { + ann.push(j); + break; + } + } + } } - tweet.text = txt; + tweet.annotations = ann; + + var tab = tweet.text.match(/\&\#[0-9]+\;/g); + for (var i in tab) { + var n = parseInt(tab[i].substr(2)); + if (n != NaN) { + tweet.text = tweet.text.replace(tab[i], String.fromCharCode(n )); + } + } twCx.tweets.push(tweet); twCx.idIndex.push(tweet.id); @@ -80,7 +101,7 @@ countWords(tweet.text, twCx.globalWords); - var creadate = new Date(tweet.created_at).valueOf(); + var creadate = tweet.date_value; if (!twCx.timeline.length) { twCx.timeline = [ populateDateStruct(0, twCx.date_levels[0] * parseInt(creadate / twCx.date_levels[0])) ] } @@ -155,7 +176,7 @@ } function insertIntoDateStruct(slices, tweet) { - var creadate = new Date(tweet.created_at).valueOf(); + var creadate = tweet.date_value; for (var i in slices) { if (creadate < slices[i].end) { if (slices[i].slices) { @@ -212,7 +233,7 @@ a_user = ''; html += '
' + a_user + ''; if (className == 'full') { - html += '

' + new Date(tweet.created_at).toLocaleTimeString() + '

'; + html += '

' + new Date(tweet.date_value).toLocaleTimeString() + '

'; } html += '
'; if (className != 'icons') { @@ -252,15 +273,16 @@ return html; } -function tlIdFromPos(x, y) { - if (x < twCx.deltaX) { - return null; - } - var ligne = Math.floor(( twCx.tlHeight - y ) / twCx.scaleY), +function tlIdFromPos(x, y, outside) { + var ligne = Math.min( twCx.tlOnDisplay.length - 1, Math.max( 0, Math.floor(( twCx.tlHeight - y ) / twCx.scaleY) ) ), colonne = Math.floor(( x - twCx.deltaX ) / twCx.scaleX ), l = 0; - if (colonne >= twCx.tlOnDisplay[ligne].totalTweets) { - return null; + if (colonne >= twCx.tlOnDisplay[ligne].totalTweets || colonne < 0 ) { + if (outside) { + colonne = Math.min( twCx.tlOnDisplay[ligne].totalTweets - 1, Math.max( 0, colonne )); + } else { + return null; + } } for (var i in twCx.tlOnDisplay[ligne].displayData) { var nl = l + twCx.tlOnDisplay[ligne].displayData[i].length; @@ -277,7 +299,7 @@ function tlPosTweet(tweet, annotation) { var x, y, - dt = new Date(tweet.created_at).valueOf(), + dt = tweet.date_value, ann = ( annotation ? annotation : ( tweet.annotations.length ? tweet.annotations[0] : 'default' ) ); for (var i = 0; i < twCx.tlOnDisplay.length; i++) { if (twCx.tlOnDisplay[i].end > dt) { @@ -318,7 +340,7 @@ function drawTweetPos(pos, color) { var rel = tlPaper.rect(pos.x - .5 * twCx.scaleX, pos.y - .5 * twCx.scaleY, twCx.scaleX, twCx.scaleY); - rel.attr({ "stroke" : color }); + rel.attr({ "stroke" : color, "fill" : color, "fill-opacity" : .1 }); return rel; } @@ -326,6 +348,7 @@ var p = twCx.position, l = twCx.tweets.length, lines = 0, + ppy = 0, html = '', tweetsOnDisplay = [], localWords = {}; @@ -342,18 +365,21 @@ if (l > p + 18) { lines++; + ppy += 20; for (var i = p + 31; i >= p + 18; i--) { pushTweet(i, 'icons'); } } if (l > p + 4) { lines++; + ppy += 20; for (var i = p + 17; i >= p + 4; i--) { pushTweet(i, 'icons'); } } for (var k = 3; k >= 1; k--) { if (l > p + k) { + ppy += 47; lines++; pushTweet(p + k, 'half'); } @@ -387,19 +413,22 @@ for (var j in localWords) { tab.push({ "word": j, - "freq" : localWords[j] / Math.log(twCx.globalWords[j]) + "freq" : localWords[j] / Math.log(1+twCx.globalWords[j]) }); } - tab.sort( function(a,b){ return b.freq - a.freq }).splice(10); - $("#motscles").html(tab.map(function(t) { return t.word }).join(", ")) + tab.sort( function(a,b){ return ( b.freq - a.freq ) }).splice(15); + var minfreq = tab[tab.length - 1].freq, + maxfreq = Math.max(minfreq + .1, tab[0].freq), + echfreq = 8 / Math.sqrt( maxfreq - minfreq ); + $("#motscles").html(tab.map(function(t) { return '' + t.word + '' }).join(" ")) twCx.tlOnDisplay = trimFDS(flattenDateStruct(twCx.timeline, twCx.timeLevel)); twCx.scaleY = twCx.tlHeight / twCx.tlOnDisplay.length; var maxTweets = 0, startTl = 0, endTl = 0, - startTw = new Date(twCx.tweets[tweetsOnDisplay[tweetsOnDisplay.length - 1]].created_at).valueOf(), - endTw = new Date(twCx.tweets[tweetsOnDisplay[0]].created_at).valueOf(); + startTw = twCx.tweets[tweetsOnDisplay[tweetsOnDisplay.length - 1]].date_value, + endTw = twCx.tweets[tweetsOnDisplay[0]].date_value; for (var i = 0; i < twCx.tlOnDisplay.length; i++) { if (startTw >= twCx.tlOnDisplay[i].start && startTw < twCx.tlOnDisplay[i].end) { startTl = i; @@ -436,6 +465,13 @@ tlPaper.clear(); relHover = null; + // Dessin de la correspondance liste-timeline + + var startY = twCx.tlHeight - startTl * twCx.scaleY, + endY = twCx.tlHeight - ( endTl + 1 ) * twCx.scaleY, + path = "M0 " + twCx.tlHeight + "C" + .7*twCx.deltaX + " " + twCx.tlHeight + " " + .3*twCx.deltaX + " " + startY + " " + twCx.deltaX + " " + startY + "L" + twCx.tlWidth + " " + startY + "L" + twCx.tlWidth + " " + endY + "L" + twCx.deltaX + " " + endY + "C" + .3*twCx.deltaX + " " + endY + " " + .7*twCx.deltaX + " 0 0 0"; + tlPaper.path( path ).attr({ "stroke" : "none", "fill" : "#000080", "opacity" : .2 }); + // dessin de la date de début tlPaper.text(2, twCx.tlHeight - 7, new Date(twCx.tlOnDisplay[0].start).toTimeString().substr(0,5)) @@ -466,19 +502,19 @@ } } - // Dessin de la correspondance liste-timeline + // dessin du tweet courant - var startY = twCx.tlHeight - startTl * twCx.scaleY, - endY = twCx.tlHeight - ( endTl + 1 ) * twCx.scaleY; - tlPaper.path("M0 " + twCx.tlHeight + "L" + twCx.deltaX + " " + startY + "L" + twCx.tlWidth + " " + startY + "L" + twCx.tlWidth + " " + endY + "L" + twCx.deltaX + " " + endY + "L0 0" ) - .attr({ "stroke" : "none", "fill" : "#000080", "opacity" : .1 }); - // dessin du tweet courant - var posp = tlPosTweet(twCx.tweets[p]); if (posp) { drawTweetPos(posp, "#ffff00"); + var yy = posp.y - .5 * twCx.scaleY, + path = "M0 " + ppy + "C" + ( .7 * twCx.deltaX ) + " " + ppy + " " + ( .2 * twCx.deltaX ) + " " + yy + " " + ( twCx.deltaX ) + " " + yy + "L" + ( posp.x - .5 * twCx.scaleX ) + " " + yy; + yy = posp.y + .5 * twCx.scaleY; + ppy += 84; + path += "L" + ( posp.x - .5 * twCx.scaleX ) + " " + yy + "L" + twCx.deltaX + " " + yy + "C" + ( .2 * twCx.deltaX ) + " " + yy + " " + ( .7 * twCx.deltaX ) + " " + ppy + " 0 " + ppy; + tlPaper.path( path ).attr({"stroke":"#ffff00", "fill" : "#ffff00", "fill-opacity" : .2}); // dessin des liens entre tweets @@ -517,6 +553,30 @@ } +function clicTl(evt) { + var o = $("#timeline").offset(); + if (twCx.tlMouseClicked && twCx.tlMouseMoved) { + var twid = tlIdFromPos(evt.pageX - o.left + twCx.refPosTl.x - twCx.refMouse.x, evt.pageY - o.top + twCx.refPosTl.y - twCx.refMouse.y, true); + if (twid) { + selectTweet(twid.id); + } + } else { + var twid = tlIdFromPos(evt.pageX - o.left, evt.pageY - o.top, twCx.tlMouseClicked); + if (twCx.tlMouseMoved && !twCx.tlMouseClicked) { + if (twid) { + rolloverTweet(twid.id, twid.annotation); + } else { + $("#hovertweet").hide(); + } + } + if (twCx.tlMouseClicked && !twCx.tlMouseMoved) { + if (twid) { + selectTweet(twid.id); + } + } + } +} + $(document).ready(function() { tlPaper = Raphael("timeline", twCx.tlWidth, twCx.tlHeight); socket = io.connect('http://' + document.location.hostname ); @@ -570,20 +630,24 @@ return false; }); $("#timeline, #tweetlist").mouseout(function() { + twCx.tlMouseClicked = false; + twCx.tlMouseMoved = false; $("#hovertweet").hide(); }); $("#timeline").mousemove(function(evt) { - var twid = tlIdFromPos(evt.offsetX, evt.offsetY); - if (twid) { - rolloverTweet(twid.id, twid.annotation); - } else { - $("#hovertweet").hide(); - } + twCx.tlMouseMoved = true; + clicTl(evt); }); - $("#timeline").click(function(evt) { - var twid = tlIdFromPos(evt.offsetX, evt.offsetY); - if (twid) { - selectTweet(twid.id); - } + $("#timeline").mousedown(function(evt) { + twCx.tlMouseClicked = true; + twCx.tlMouseMoved = false; + var o = $(this).offset(); + twCx.refMouse = { x : evt.pageX - o.left, y : evt.pageY - o.top }; + twCx.refPosTl = tlPosTweet(twCx.tweets[twCx.position]) || twCx.refMouse; + }); + $("#timeline").mouseup(function(evt) { + clicTl(evt); + twCx.tlMouseClicked = false; + twCx.tlMouseMoved = false; }); }); \ No newline at end of file