diff -r d92c38c912ec -r 239f91ac1f31 tweetcast/nodejs-bis/client/js/script.js --- a/tweetcast/nodejs-bis/client/js/script.js Tue Nov 22 18:22:37 2011 +0100 +++ b/tweetcast/nodejs-bis/client/js/script.js Tue Nov 22 18:33:51 2011 +0100 @@ -7,7 +7,7 @@ twCx = { zoomLevel : 1, followLast : true, - position : 0, + position : "0", date_levels : [ 15 * 60 * 1000, 5 * 60 * 1000, @@ -22,7 +22,8 @@ refMouse : { x : 0, y : 0}, refPosTl : { x : 0, y : 0}, tlMouseMoved : false, - tlMouseClicked : false + tlMouseClicked : false, + filtre : null }, tlBuffer = '', relHover = [], @@ -169,9 +170,10 @@ } function trimFDS() { - var slices = flattenDateStruct(twCx.timeline, twCx.timeLevel), + var centralTweet = ( twCx.centralTweet ? twCx.centralTweet : twCx.tweets[twCx.tweets.length - 1] ) + slices = flattenDateStruct(twCx.timeline, twCx.timeLevel), delta = 30 * twCx.date_levels[twCx.timeLevel], - centre = Math.min(slices[slices.length - 1].end - delta , Math.max(slices[0].start + delta, twCx.tweets[twCx.position].date_value)), + centre = Math.min(slices[slices.length - 1].end - delta , Math.max(slices[0].start + delta, centralTweet.date_value)), min = centre - delta, max = centre + delta; while (slices[0].start < min) { @@ -227,22 +229,19 @@ } function selectTweet(tweetid) { - var pos = twCx.idIndex.indexOf(tweetid); - if (pos != -1) { - twCx.position = pos; - twCx.followLast = (twCx.position == twCx.tweets.length - 1); - updateDisplay() - } + twCx.position = tweetid; + twCx.followLast = (twCx.position == twCx.idIndex[twCx.tweets.length - 1]); + updateDisplay(); } function goToPos(nPos) { - twCx.position = Math.min( twCx.tweets.length - 1, Math.max(0, nPos ) ); - twCx.followLast = (twCx.position == twCx.tweets.length - 1); + twCx.position = twCx.idIndex[Math.min( twCx.tweets.length - 1, Math.max(0, nPos ) )]; + twCx.followLast = (nPos == twCx.tweets.length - 1); updateDisplay(); } function movePos(delta) { - goToPos( delta + twCx.position ); + goToPos( delta + twCx.idIndex.indexOf(twCx.position) ); } function tweetToHtml(tweet, className, elName) { @@ -438,24 +437,44 @@ } function updateDisplay() { + + if (twCx.filtre) { + var tweets = twCx.tweets.filter(function(tweet) { + return ( tweet.text.search(twCx.filtre) != -1 ) || ( tweet.user.screen_name.search(twCx.filtre) != -1 ) + }); + if (tweets.length) { + var idIndex = tweets.map(function(tweet) { + return tweet.id; + }); + var p = idIndex.indexOf(twCx.position); + if (p == -1) { + for (p = idIndex.length - 1; p > 0 && idIndex[p] > twCx.position; p--) { + } + } + console.log(p); + } + + } else { + var tweets = twCx.tweets; + var p = twCx.idIndex.indexOf(twCx.position); + if (p == -1) { + p = (twCx.followLast ? twCx.idIndex.length - 1 : 0); + } + } - var p = twCx.position, - l = twCx.tweets.length, + var l = tweets.length, lines = 0, ppy = 0, html = '', tweetsOnDisplay = [], localWords = {}; - lastScrollPos = Math.floor( scrollExtent * ( 1 - ( p / twCx.tweets.length ) ) ); - $("#scrollcont").scrollTop(lastScrollPos); - function pushTweet(tp, className) { if (tp < l && tp >= 0) { - html += tweetToHtml(twCx.tweets[tp], className) + html += tweetToHtml(tweets[tp], className) tweetsOnDisplay.push(tp); - for (var i in twCx.tweets[tp].words) { - var w = twCx.tweets[tp].words[i]; + for (var i in tweets[tp].words) { + var w = tweets[tp].words[i]; if (localWords[w]) { localWords[w].freq++ } else { @@ -469,8 +488,8 @@ } } } - for (var j in twCx.tweets[tp].annotations) { - localWords[w].annotations[twCx.tweets[tp].annotations[j]]++; + for (var j in tweets[tp].annotations) { + localWords[w].annotations[tweets[tp].annotations[j]]++; } } } else { @@ -478,102 +497,119 @@ } } - 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; + if (l) { + + lastScrollPos = Math.floor( scrollExtent * ( 1 - ( p / l ) ) ); + $("#scrollcont").scrollTop(lastScrollPos); + + if (l > p + 18) { lines++; - pushTweet(p + k, 'half'); - } - } - pushTweet(p, 'full'); - var n = p - 1; - for (var i = 0; i < Math.min(6, Math.max(3, 6 - lines)); i++) { - if (n < 0) { - break; - } - pushTweet(n, 'half'); - n--; - } - for (var i = 0; i < 14 * Math.min(4, Math.max(2, 7 - lines)); i++) { - if (n < 0) { - break; + ppy += 20; + for (var i = p + 31; i >= p + 18; i--) { + pushTweet(i, 'icons'); + } } - pushTweet(n, 'icons'); - n--; - } - if (html != tlBuffer) { - $("#tweetlist").html(html); - $(".tweet.full").fadeIn(); - tlBuffer = html; - } - - for (var j in localWords) { - if (localWords[j].freq < 2) delete localWords[j]; - } - var tab = []; - for (var j in localWords) { - tab.push({ - "word": j, - "freq" : localWords[j].freq, - "annotations" : localWords[j].annotations, - "score" : localWords[j].freq / Math.log(1+twCx.globalWords[j]) - }); - } - tab.sort( function(a,b){ return ( b.score - a.score ) }).splice(20); - var minfreq = tab[tab.length - 1].score, - maxfreq = Math.max(minfreq + .1, tab[0].score), - echfreq = 8 / Math.sqrt( maxfreq - minfreq ), - html = ''; - for (var j in tab) { - var maxann = 0, - ann = "default"; - for (var k in tab[j].annotations) { - if (tab[j].annotations[k] == maxann) { - ann = "default"; + if (l > p + 4) { + lines++; + ppy += 20; + for (var i = p + 17; i >= p + 4; i--) { + pushTweet(i, 'icons'); } - if (tab[j].annotations[k] > maxann) { - ann = k; - maxann = tab[j].annotations[k]; + } + for (var k = 3; k >= 1; k--) { + if (l > p + k) { + ppy += 47; + lines++; + pushTweet(p + k, 'half'); } } - if (ann == "default") { - var coul = ''; - } else { - var c = getColor(ann, .4), - coul = "background: rgba(" + [ Math.floor(c.r), Math.floor(c.g), Math.floor(c.b), ( tab[j].annotations[ann] / tab[j].freq )].join(',') + ")"; + pushTweet(p, 'full'); + var n = p - 1; + for (var i = 0; i < Math.min(6, Math.max(3, 6 - lines)); i++) { + if (n < 0) { + break; + } + pushTweet(n, 'half'); + n--; + } + for (var i = 0; i < 14 * Math.min(4, Math.max(2, 7 - lines)); i++) { + if (n < 0) { + break; + } + pushTweet(n, 'icons'); + n--; + } + if (html != tlBuffer) { + $("#tweetlist").html(html); + $(".tweet.full").fadeIn(); + tlBuffer = html; + } + + /* Recherche des mots pertinents correspondant à la sélection */ + + for (var j in localWords) { + if (localWords[j].freq < 2) delete localWords[j]; } - var fontsize = Math.floor( ( 12 + Math.sqrt( tab[j].score - minfreq ) * echfreq ) ); - html += '' + tab[j].word + ' '; + var tab = []; + for (var j in localWords) { + tab.push({ + "word": j, + "freq" : localWords[j].freq, + "annotations" : localWords[j].annotations, + "score" : localWords[j].freq / Math.log(1+twCx.globalWords[j]) + }); + } + tab.sort( function(a,b){ return ( b.score - a.score ) }).splice(20); + var minfreq = tab[tab.length - 1].score, + maxfreq = Math.max(minfreq + .1, tab[0].score), + echfreq = 8 / Math.sqrt( maxfreq - minfreq ), + html = ''; + for (var j in tab) { + var maxann = 0, + ann = "default"; + for (var k in tab[j].annotations) { + if (tab[j].annotations[k] == maxann) { + ann = "default"; + } + if (tab[j].annotations[k] > maxann) { + ann = k; + maxann = tab[j].annotations[k]; + } + } + if (ann == "default") { + var coul = ''; + } else { + var c = getColor(ann, .6), + coul = "background: rgba(" + [ Math.floor(c.r), Math.floor(c.g), Math.floor(c.b), ( tab[j].annotations[ann] / tab[j].freq )].join(',') + ")"; + } + var fontsize = Math.floor( ( 12 + Math.sqrt( tab[j].score - minfreq ) * echfreq ) ); + html += '' + tab[j].word + ' '; + } + $("#motscles").html(html); + twCx.centralTweet = tweets[p]; + } else { + $("#tweetlist").html(''); + tlBuffer = ''; + $("#motscles").html(''); } - $("#motscles").html(html); twCx.tlOnDisplay = trimFDS(); twCx.scaleY = twCx.tlHeight / twCx.tlOnDisplay.length; var maxTweets = 0, startTl = 0, - endTl = twCx.tlOnDisplay.length - 1, - startTw = twCx.tweets[tweetsOnDisplay[tweetsOnDisplay.length - 1]].date_value, - endTw = twCx.tweets[tweetsOnDisplay[0]].date_value; + endTl = twCx.tlOnDisplay.length - 1; + if (l) { + var startTw = tweets[tweetsOnDisplay[tweetsOnDisplay.length - 1]].date_value, + endTw = 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; - } - if (endTw >= twCx.tlOnDisplay[i].start && endTw < twCx.tlOnDisplay[i].end) { - endTl = i; + if (l) { + if (startTw >= twCx.tlOnDisplay[i].start && startTw < twCx.tlOnDisplay[i].end) { + startTl = i; + } + if (endTw >= twCx.tlOnDisplay[i].start && endTw < twCx.tlOnDisplay[i].end) { + endTl = i; + } } var displayData = {}; for (var j in annotations) { @@ -605,31 +641,31 @@ 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 }); - + if (l) { + 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)) - .attr({ "text-anchor" : "start", "font-size": "9px" }); + tlPaper.text(twCx.deltaX / 2, twCx.tlHeight - 7, new Date(twCx.tlOnDisplay[0].start).toTimeString().substr(0,5)) + .attr({ "text-anchor" : "middle", "font-size": "9px" }); // dessin de la date de fin - tlPaper.text(2, 7, new Date(twCx.tlOnDisplay[twCx.tlOnDisplay.length - 1].end).toTimeString().substr(0,5)) - .attr({ "text-anchor" : "start", "font-size": "9px" }); + tlPaper.text(twCx.deltaX / 2, 7, new Date(twCx.tlOnDisplay[twCx.tlOnDisplay.length - 1].end).toTimeString().substr(0,5)) + .attr({ "text-anchor" : "middle", "font-size": "9px" }); for (var i = 0; i < twCx.tlOnDisplay.length; i++) { var n = 0, posY = twCx.tlHeight - ( i + 1 ) * twCx.scaleY; for (var j in twCx.tlOnDisplay[i].displayData) { - var l = twCx.tlOnDisplay[i].displayData[j].length; - if (l > 0) { - tlPaper.rect( twCx.deltaX + n * twCx.scaleX, posY, l * twCx.scaleX, twCx.scaleY ) + var ll = twCx.tlOnDisplay[i].displayData[j].length; + if (ll > 0) { + tlPaper.rect( twCx.deltaX + n * twCx.scaleX, posY, ll * twCx.scaleX, twCx.scaleY ) .attr({"stroke" : "none", "fill" : getColor(j, .4).hex }); - n += l; + n += ll; } } @@ -637,27 +673,48 @@ if (i < twCx.tlOnDisplay.length - 1 && !(twCx.tlOnDisplay[i].end % 1800000)) { tlPaper.path("M0 "+posY+"L" + twCx.tlWidth +" "+posY).attr({"stroke":"#ccc"}); - tlPaper.text(2, posY, new Date(twCx.tlOnDisplay[i].end).toTimeString().substr(0,5)).attr({ "text-anchor" : "start", "font-size": "9px" }); + tlPaper.text(twCx.deltaX / 2, posY, new Date(twCx.tlOnDisplay[i].end).toTimeString().substr(0,5)).attr({ "text-anchor" : "middle", "font-size": "9px" }); } } // dessin du tweet courant - - var posp = tlPosTweet(twCx.tweets[p]); - if (posp) { + if (l) { + + if (twCx.filtre) { + for (var i = 0; i < tweets.length; i++) { + if (i != p) { + var pos = tlPosTweet(tweets[i]); + if (pos) { + drawTweetPos(pos, "#ffccff"); + } + } + } + + } - 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" : .15}); - - drawTweetArcs(twCx.tweets[p], posp, '#800080'); + var posp = tlPosTweet(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" : .15}); + + drawTweetArcs(tweets[p], posp, '#800080'); + } } - +} + +function filtrer(valeur) { + twCx.filtreTexte = valeur; + $("#inp_q").val(valeur).attr("class","rechercheCourante"); + twCx.filtre = ( valeur ? new RegExp(valeur.replace(/(\W)/g, '\\$1'),'ig') : null ); + twCx.followLast = !valeur && (twCx.position == twCx.idIndex[twCx.tweets.length - 1]); + updateDisplay(); } function clicTl(evt) { @@ -692,11 +749,23 @@ addTweet(tweets[i]); } if (twCx.followLast) { - twCx.position = twCx.tweets.length - 1; + twCx.position = twCx.idIndex[twCx.tweets.length - 1]; } updateDisplay(); } +function focusOutRecherche() { + var inpq = $("#inp_q"), + val = inpq.val(); + if (val == '' || val == twCx.filtreTexte) { + if (twCx.filtre) { + inpq.attr("class", "rechercheCourante").val(twCx.filtreTexte); + } else { + inpq.attr("class", "greyed").val("Rechercher dans les tweets"); + } + } +} + $(document).ready(function() { tlPaper = Raphael("timeline", twCx.tlWidth, twCx.tlHeight); @@ -714,7 +783,7 @@ addTweet(data.new_tweets[i]); } if (twCx.followLast) { - twCx.position = twCx.tweets.length - 1; + twCx.position = twCx.idIndex[twCx.tweets.length - 1]; } updateDisplay(); }); @@ -761,13 +830,38 @@ 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; + twCx.refPosTl = tlPosTweet(tweetById(twCx.position)) || twCx.refMouse; }); $("#timeline").mouseup(function(evt) { clicTl(evt); twCx.tlMouseClicked = false; twCx.tlMouseMoved = false; }); + $("#inp_q").focus(function() { + if ($(this).hasClass("greyed")) { + $(this).val(""); + } + $(this).attr("class",""); + }); + $("#inp_q").focusout(function() { + focusOutRecherche(); + }); + $("#inp_reset").click(function() { + if (twCx.filtre) { + twCx.filtre = null; + updateDisplay(); + } + focusOutRecherche(); + return false; + }) + $("#recherche").submit(function() { + if (!$("#inp_q").hasClass("greyed")) { + var valeur = $("#inp_q").val(); + filtrer(valeur); + } + return false; + }); + setInterval(function() { var sc = $("#scrollcont"); if (sc.scrollTop() != lastScrollPos) {