Syncing treemap & streamgraph
authorveltr
Wed, 23 Jan 2013 18:21:30 +0100
changeset 26 94f586daa623
parent 25 94073a2af6e1
child 27 8ca7f2cea729
Syncing treemap & streamgraph
integration/css/home.css
integration/data/requete.json
integration/js/main.js
integration/js/streamgraph.js
integration/js/treemap.js
--- a/integration/css/home.css	Tue Jan 22 14:43:22 2013 +0100
+++ b/integration/css/home.css	Wed Jan 23 18:21:30 2013 +0100
@@ -38,7 +38,7 @@
 	bottom: 0;
 	right: 0;
 }
-.actu:hover .links, .actu:hover .voile{
+.actu.selected .links, .actu.selected .voile{
 	display: block;
 }
 .actu .links li{
@@ -87,4 +87,23 @@
 	position: absolute;
 	overflow: hidden;
 	float: none;
-}
\ No newline at end of file
+}
+
+/* Treemap 2 */
+
+.cluster-article {
+    position: absolute; overflow: hidden;
+}
+
+.cluster-article p {
+    position: absolute; top: 2px; left: 2px; right: 2px; bottom: 2px; overflow: hidden;
+}
+
+.abstract {
+    position: absolute; bottom: 40px; left: 0; right: 0; padding: 4px; background: rgba(0,0,0,0.7);
+    color: #ffffff; font-size: 12px; text-shadow: 1px 1px 1px #000000; display: none;
+}
+
+.actu.selected .abstract {
+    display: block;
+}
--- a/integration/data/requete.json	Tue Jan 22 14:43:22 2013 +0100
+++ b/integration/data/requete.json	Wed Jan 23 18:21:30 2013 +0100
@@ -47,9 +47,10 @@
             "weight": "1",
             "title": "PS",
             "abstract": "Proche de S\u00e9gol\u00e8ne Royal, Fran\u00e7ois Rebsamen a un temps envisag\u00e9 de faire le trait-d'union avec les amis de Fran\u00e7ois Hollande pour renverser Martine Aubry de la direction du PS. Rentr\u00e9 dans le rang",
-            "id": 0,
+            "annotations": [],
             "documents_number": 19,
-            "annotations": []
+            "url_image": "http://static.mediapart.fr/files/imagecache/300_pixels/St%C3%A9phane%20Alli%C3%A8s/ResizedImage383255-IMG0707.JPG",
+            "id": 0
         }, {
             "documents": [
                 {
@@ -82,16 +83,17 @@
                     "title": "Pourquoi \u00abDroopy\u00bb Karoutchi ne gagnera pas l'Ile-de-France",
                     "url_document": "http://www.mediapart.fr/journal/france/160309/pourquoi-droopy-karoutchi-ne-gagnera-pas-l-ile-de-france",
                     "date": "2009-03-18T09:42:50.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/300_pixels/Marine%20Turchi/3253562677_526473474b_m.jpg",
                     "id": 36313
                 }
             ],
             "weight": "0.970595",
             "title": "\u00e9lections r\u00e9gionales",
             "abstract": "Lot de consolation pour la droite : La Guyane basculerait. Selon des chiffres encore",
-            "id": 1,
+            "annotations": [],
             "documents_number": 9,
-            "annotations": []
+            "url_image": "http://static.mediapart.fr/files/imagecache/300_pixels/La%20r%C3%A9daction%20Mediapart/rejet.png",
+            "id": 1
         }, {
             "documents": [
                 {
@@ -100,7 +102,7 @@
                     "title": "Travail du dimanche : Nicolas Sarkozy est pour, donc vous aussi",
                     "url_document": "http://www.mediapart.fr/journal/france/151008/travail-du-dimanche-nicolas-sarkozy-est-pour-donc-vous-aussi",
                     "date": "2011-11-17T14:07:45.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/475_pixels/Mathieu%20Magnaudeix/Image%208_2.png",
                     "id": 25201
                 }, {
                     "category": "France",
@@ -116,7 +118,7 @@
                     "title": "Constitution: le PS inflexible, malgr\u00e9 l'appel de Sarkozy",
                     "url_document": "http://www.mediapart.fr/journal/france/170708/constitution-le-ps-inflexible-malgre-l-appel-de-sarkozy",
                     "date": "2008-07-17T14:28:17.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/Mathilde Mathieu/Image 2_2.png",
                     "id": 18705
                 }, {
                     "category": "France",
@@ -131,9 +133,10 @@
             "weight": "0.961693",
             "title": "gouvernement UMP",
             "abstract": "Du changement de statut de La Poste, il n'a \u00e9t\u00e9 que peu question durant la campagne des \u00e9lections europ\u00e9ennes, comme si la r\u00e9forme avait pris du retard ou n'\u00e9tait plus d'actualit\u00e9. Et pourtant, il n'en est rien",
-            "id": 2,
+            "annotations": [],
             "documents_number": 25,
-            "annotations": []
+            "url_image": "http://static.mediapart.fr/files/Laurent Mauduit/Image 8_13.png",
+            "id": 2
         }, {
             "documents": [
                 {
@@ -158,7 +161,7 @@
                     "title": "Une bombe au c\u0153ur de la R\u00e9publique",
                     "url_document": "http://www.mediapart.fr/journal/france/130908/une-bombe-au-coeur-de-la-republique",
                     "date": "2012-01-09T14:55:55.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/475_pixels/Fabrice%20Arfi/bpc140dcn.jpg",
                     "id": 22631
                 }, {
                     "category": "France",
@@ -166,16 +169,17 @@
                     "title": "Ventes d'armes: la corruption au c\u0153ur de la R\u00e9publique",
                     "url_document": "http://www.mediapart.fr/journal/france/130908/ventes-d-armes-la-corruption-au-coeur-de-la-republique",
                     "date": "2012-05-01T18:38:15.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/225_pixels/Fabrice%20Arfi/sarko_0.png",
                     "id": 22632
                 }
             ],
             "weight": "0.936393",
             "title": "affaire de Karachi",
             "abstract": "Une bombe dort au p\u00f4le financier du tribunal de grande instance de Paris. Les juges Fran\u00e7oise Desset et",
-            "id": 3,
+            "annotations": [],
             "documents_number": 4,
-            "annotations": []
+            "url_image": "http://static.mediapart.fr/files/imagecache/475_pixels/Fabrice%20Arfi/article_photo_1218010950574-1-0.jpg",
+            "id": 3
         }, {
             "documents": [
                 {
@@ -184,7 +188,7 @@
                     "title": "Le PS met en sc\u00e8ne la r\u00e9conciliation Aubry-Royal",
                     "url_document": "http://www.mediapart.fr/journal/france/260509/le-ps-met-en-scene-la-reconciliation-aubry-royal",
                     "date": "2009-05-27T17:14:34.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/300_pixels/St%C3%A9phane%20Alli%C3%A8s/Image%205_5.png",
                     "id": 41525
                 }, {
                     "category": "France",
@@ -215,9 +219,10 @@
             "weight": "0.928015",
             "title": "campagne des europ\u00e9ennes",
             "abstract": "\"Dans une telle campagne o\u00f9 les petites phrases et les effets m\u00e9diatiques semblent plus compter que le fond, de belles images au 20 heures ne peuvent pas faire de mal.\" Ce commentaire d'un dirigean",
-            "id": 4,
+            "annotations": [],
             "documents_number": 9,
-            "annotations": []
+            "url_image": "http://static.mediapart.fr/files/imagecache/300_pixels/St%C3%A9phane%20Alli%C3%A8s/Image%205_5.png",
+            "id": 4
         }, {
             "documents": [
                 {
@@ -257,9 +262,10 @@
             "weight": "0.914044",
             "title": "UMP",
             "abstract": "L'UMP et le PS sont des jumeaux dizygotes. Ils ne sont pas issus du m\u00eame",
-            "id": 5,
+            "annotations": [],
             "documents_number": 10,
-            "annotations": []
+            "url_image": "http://static.mediapart.fr/files/imagecache/475_pixels/Marine%20Turchi/2083.jpg",
+            "id": 5
         }, {
             "documents": [
                 {
@@ -268,7 +274,7 @@
                     "title": "Jacques Julliard: \u00abOui, la greffe n\u00e9olib\u00e9rale a contamin\u00e9 la social-d\u00e9mocratie\u00bb",
                     "url_document": "http://www.mediapart.fr/journal/france/230310/jacques-julliard-la-greffe-neoliberale-contamine-la-deuxieme-gauche",
                     "date": "2010-08-30T17:03:11.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/250_pixels/St%C3%A9phane%20Alli%C3%A8s/julliard.png",
                     "id": 78268
                 }, {
                     "category": "France",
@@ -276,7 +282,7 @@
                     "title": "Chirac publie ses m\u00e9moires et charge ses trois ennemis",
                     "url_document": "http://www.mediapart.fr/journal/france/021109/chirac-publie-ses-memoires-et-charge-ses-trois-ennemis",
                     "date": "2009-11-05T10:45:06.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/225_pixels/Marine%20Turchi/9782841113934.jpg",
                     "id": 67685
                 }, {
                     "category": "France",
@@ -292,16 +298,17 @@
                     "title": "Sarkozy au Panth\u00e9on via Camus",
                     "url_document": "http://www.mediapart.fr/journal/culture-idees/231109/sarkozy-au-pantheon-camus",
                     "date": "2009-11-24T22:05:41.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/300_pixels/Sophie%20Dufau/pantheon-de-paris.jpg",
                     "id": 69111
                 }
             ],
             "weight": "0.907456",
             "title": "livre",
             "abstract": "Jacques Julliard, 77 ans, entre en dissidence. Figure historique de la \"deux",
-            "id": 6,
+            "annotations": [],
             "documents_number": 6,
-            "annotations": []
+            "url_image": "http://static.mediapart.fr/files/imagecache/250_pixels/St%C3%A9phane%20Alli%C3%A8s/julliard.png",
+            "id": 6
         }, {
             "documents": [
                 {
@@ -310,7 +317,7 @@
                     "title": "Le Nouveau Centre montre ses muscles \u00e0 l'UMP",
                     "url_document": "http://www.mediapart.fr/journal/france/110110/le-nouveau-centre-montre-ses-muscles-lump",
                     "date": "2010-01-20T19:46:43.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/Marine Turchi/udf.png",
                     "id": 72565
                 }, {
                     "category": "France",
@@ -318,7 +325,7 @@
                     "title": "Fran\u00e7ois Bayrou: \u00abIl faut faire Solidarnosc!\u00bb",
                     "url_document": "http://www.mediapart.fr/journal/france/070509/bayrou-je-suis-un-sans-papiers-gauche",
                     "date": "2009-05-11T21:44:50.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/300_pixels/Marine%20Turchi/800px-Francois_bayrou_forum_democrate_seignosse_20070916_f_1.jpg",
                     "id": 40117
                 }, {
                     "category": "France",
@@ -341,9 +348,10 @@
             "weight": "0.865421",
             "title": "Nouveau Centre Modem",
             "abstract": "\"Dans quelques ann\u00e9es nous dirons: il y a l'UMP et il y a le Nouveau Centre\", a assur\u00e9 Herv\u00e9 Morin, lors des voeux aux cadres de son parti, lundi 18 janvier. Chaque ann\u00e9e, le discours est",
-            "id": 7,
+            "annotations": [],
             "documents_number": 4,
-            "annotations": []
+            "url_image": "http://static.mediapart.fr/files/Marine%20Turchi/udf.png",
+            "id": 7
         }, {
             "documents": [
                 {
@@ -360,7 +368,7 @@
                     "title": "Baroin, ministre sans bouclier face \u00e0 l'Elys\u00e9e",
                     "url_document": "http://www.mediapart.fr/journal/france/310310/xxx",
                     "date": "2010-04-01T11:20:08.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/300_pixels/Marine%20Turchi/baroin_sarkozy.jpg",
                     "id": 78812
                 }, {
                     "category": "France",
@@ -383,9 +391,10 @@
             "weight": "0.851838",
             "title": "panique financi\u00e8re",
             "abstract": "En pleine panique financi\u00e8re, les responsables politiques retrouvent la parole. Apr\u00e8s la r\u00e9union de crise ce ",
-            "id": 8,
+            "annotations": [],
             "documents_number": 6,
-            "annotations": []
+            "url_image": "/home/cea/WebLab/dist/run/mss/images/3883",
+            "id": 8
         }, {
             "documents": [
                 {
@@ -410,7 +419,7 @@
                     "title": "Angola: un fragile processus d\u00e9mocratique aliment\u00e9 par le boom p\u00e9trolier",
                     "url_document": "http://www.mediapart.fr/journal/international/120908/angola-un-fragile-processus-democratique-alimente-par-le-boom-petrolier",
                     "date": "2010-10-28T16:14:25.0Z",
-                    "url_image": "",
+                    "url_image": "http://static.mediapart.fr/files/imagecache/475_pixels/Fran%C3%A7ois%20Bonnet/ango.jpg",
                     "id": 22545
                 }, {
                     "category": "France",
@@ -425,9 +434,10 @@
             "weight": "0.95304",
             "title": "etc.",
             "abstract": "No summary available",
-            "id": 9,
+            "annotations": [],
             "documents_number": 8,
-            "annotations": []
+            "url_image": "/home/cea/WebLab/dist/run/mss/images/3883",
+            "id": 9
         }
     ]
 }
\ No newline at end of file
--- a/integration/js/main.js	Tue Jan 22 14:43:22 2013 +0100
+++ b/integration/js/main.js	Wed Jan 23 18:21:30 2013 +0100
@@ -152,9 +152,6 @@
 	);
 //FRISE
 	//valeurs init du slider à définir
-	var valSlider1 = 75;
-	var valSlider2 = 300;
-	var diffSlide = valSlider2-valSlider1;
 	var widthFrise = $('.frise').width();
 
 	$( "#slider-range" ).dragslider({
@@ -162,16 +159,13 @@
 		rangeDrag: true,
 		min: 0,
 		max: widthFrise,
-		values: [ valSlider1, valSlider2 ],
+		values: [ 0, widthFrise ],
 		slide: function( event, ui ) {
             if (window.streamgraph) {
                 streamgraph.slidevalues(ui.values[0], ui.values[1]);
             }
 		},
 		change: function( event, ui ){
-			//ici on récup les valeurs après un slide
-			var value1 = ui.values[ 0 ];
-			var value2 = ui.values[ 1 ];
 		}
 	});
 
--- a/integration/js/streamgraph.js	Tue Jan 22 14:43:22 2013 +0100
+++ b/integration/js/streamgraph.js	Wed Jan 23 18:21:30 2013 +0100
@@ -1,17 +1,19 @@
-function Streamgraph($selector) {
+function Streamgraph($selector, data) {
     
     /* Constants */
    
     var VMARGIN = 3,
         YEARSHEIGHT = 20,
-        STARTTIME = new Date(2007,6,1),
+        STARTTIME = new Date(2007,5,1),
         ENDTIME = new Date(),
+        DATASTART = new Date(data.from_date),
+        DATAEND = new Date(data.to_date),
         CURVE = .25,
         DATEPADDING = 10,
         COLORS = [ "#943a23", "#fbee97", "#cfbb95", "#da9761", "#ba5036" ],
-        SELECTEDCOLOR = "#c51810"; 
+        SELECTEDCOLOR = "#007dad"; 
     
-    /* Generating random data */
+    /* Generating random data
     
     var data = [],
         clustercount = 12,
@@ -33,7 +35,7 @@
     
     var width = $selector.width(),
         height = $selector.height(),
-        transp = _.zip.apply( _, data ),
+        transp = _.zip.apply( _, _(data.clusters).pluck("volumes") ),
         cumulative = _(transp).map(function(column) {
             var total = 0;
             return _(column).map(function(point) {
@@ -45,22 +47,27 @@
         })
         maxcol = _(sums).max(),
         streamheight = height - YEARSHEIGHT,
+        streamwidth = width * (DATAEND - DATASTART) / (ENDTIME - STARTTIME),
         yscale = (streamheight - 2 * VMARGIN) / maxcol,
         centery = streamheight / 2,
-        xscale = width / (transp.length - 1),
+        xscale = streamwidth / (transp.length - 1),
         txscale = width / (ENDTIME - STARTTIME),
-        coords = _(data).map(function(line, lineindex) {
+        startx = txscale * (DATASTART - STARTTIME),
+        endx = txscale * (DATAEND - STARTTIME),
+        coords = _(data.clusters).map(function(line, lineindex) {
             return {
-                points : _(line).map(function(point, colindex) {
+                points : _(line.volumes).map(function(point, colindex) {
                     var lowercumul = lineindex ? cumulative[colindex][lineindex - 1] : 0,
                         uppercumul = cumulative[colindex][lineindex];
                     return {
                         data: point,
-                        x: xscale * colindex,
+                        x: startx + xscale * colindex,
                         lowery: centery + yscale * ( ( sums[colindex] / 2 ) - lowercumul ),
                         uppery: centery + yscale * ( ( sums[colindex] / 2 ) - uppercumul ),
                     }
-                })
+                }),
+                id : line.id,
+                title: line.title
             }
         }),
         _(coords).each(function(line) {
@@ -93,13 +100,24 @@
     
     /* Drawing streamgraph*/
    
+    $selector.empty();
+   
     var paper = new Raphael($selector[0]);
     
+    paper.path("M0 " + centery + "L" + width + " " + centery).attr({
+        stroke: "#000",
+        "stroke-width": .25
+    })
+    
     _(coords).each(function(line, index) {
         line.color = COLORS[index % COLORS.length];
+        //var hue = (parseInt(line.id)%6)/6;
+        //line.color = Raphael.hsl( hue, 1, .8 );
+        //line.highlightColor = Raphael.hsl( hue, 1, .4 );
         line.surface = paper.path(line.path);
         line.surface.attr({
-            stroke: "none",
+            stroke: "#ffffff",
+            "stroke-width": .25,
             fill: line.color
         });
     });
@@ -127,14 +145,14 @@
         attrcarres = {
             fill: "#333333",
             "fill-opacity": .5,
-            stroke: SELECTEDCOLOR
+            stroke: "#c51810"
         };
     carregauche.attr(attrcarres);
     carredroite.attr(attrcarres);
     
     var rangerect = paper.rect(0, (height - YEARSHEIGHT), width, YEARSHEIGHT);
     rangerect.attr({
-        fill: SELECTEDCOLOR,
+        fill: "#c51810",
         stroke: "none"
     });
     
@@ -163,16 +181,34 @@
         line.mousesurface.attr({
             stroke: "none",
             fill: line.color,
-            opacity: .01
+            opacity: .01,
+            title: line.title
         }).mouseover(function() {
-            line.surface.attr({
-                fill: SELECTEDCOLOR
-            })
+            $("body").trigger("select-cluster", line.id);
         }).mouseout(function() {
+            $("body").trigger("unselect-cluster", line.id);
+        });
+    });
+    
+    $("body").on("unselect-cluster", function(e, clusterid) {
+        var line = _(coords).find(function(line) {
+            return line.id == clusterid;
+        });
+        if (line) {
             line.surface.attr({
                 fill: line.color
-            })
+            });
+        }
+    });
+    $("body").on("select-cluster", function(e, clusterid) {
+        var line = _(coords).find(function(line) {
+            return line.id == clusterid;
         });
+        if (line) {
+            line.surface.attr({
+                fill: SELECTEDCOLOR //line.highlightColor
+            });
+        }
     });
     
     /* Returning a handler for slide value change */
@@ -195,10 +231,21 @@
             width: right - left
         });
     }
+    
+    $("#slider-range").dragslider("values", [startx, endx]);
+    this.slidevalues(startx, endx);
 
 }
 
+function loadStreamgraph(url) {
+    $(".streamgraph").empty();
+    delete window.streamgraph;
+    $.getJSON(url, function(data) {
+        window.streamgraph = new Streamgraph($(".streamgraph"), data);
+        streamgraph.slidevalues.apply(streamgraph,$("#slider-range").dragslider("values"));
+    });
+}
+
 $(function() {
-    window.streamgraph = new Streamgraph($(".streamgraph"));
-    streamgraph.slidevalues.apply(streamgraph,$("#slider-range").dragslider("values"));
+    loadStreamgraph("data/json_streamgraph.json");
 })
--- a/integration/js/treemap.js	Tue Jan 22 14:43:22 2013 +0100
+++ b/integration/js/treemap.js	Wed Jan 23 18:21:30 2013 +0100
@@ -1,6 +1,40 @@
+/* SOURCE : http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript */
+
+/**
+ * Converts an HSV color value to RGB. Conversion formula
+ * adapted from http://en.wikipedia.org/wiki/HSV_color_space.
+ * Assumes h, s, and v are contained in the set [0, 1] and
+ * returns r, g, and b in the set [0, 255].
+ *
+ * @param   Number  h       The hue
+ * @param   Number  s       The saturation
+ * @param   Number  v       The value
+ * @return  Array           The RGB representation
+ */
+function hsvToRgb(h, s, v){
+    var r, g, b;
+
+    var i = Math.floor(h * 6);
+    var f = h * 6 - i;
+    var p = v * (1 - s);
+    var q = v * (1 - f * s);
+    var t = v * (1 - (1 - f) * s);
+
+    switch(i % 6){
+        case 0: r = v, g = t, b = p; break;
+        case 1: r = q, g = v, b = p; break;
+        case 2: r = p, g = v, b = t; break;
+        case 3: r = p, g = q, b = v; break;
+        case 4: r = t, g = p, b = v; break;
+        case 5: r = v, g = p, b = q; break;
+    }
+
+    return _([r * 255, g * 255, b * 255]).map(Math.floor);
+}
+
 $(function(){
 
-    var IDEALRATIO = 1.25;
+    var IDEALRATIO = 1.33;
 
     function cuttree(data, x, y, w, h, cut, ratio, callback) {
         
@@ -77,54 +111,19 @@
         cuttree(data, x, y, w, h, cut, bestcumul / total, squarify);
     }
     
-    /* SOURCE : http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript */
-    
-    /**
-     * Converts an HSV color value to RGB. Conversion formula
-     * adapted from http://en.wikipedia.org/wiki/HSV_color_space.
-     * Assumes h, s, and v are contained in the set [0, 1] and
-     * returns r, g, and b in the set [0, 255].
-     *
-     * @param   Number  h       The hue
-     * @param   Number  s       The saturation
-     * @param   Number  v       The value
-     * @return  Array           The RGB representation
-     */
-    function hsvToRgb(h, s, v){
-        var r, g, b;
-    
-        var i = Math.floor(h * 6);
-        var f = h * 6 - i;
-        var p = v * (1 - s);
-        var q = v * (1 - f * s);
-        var t = v * (1 - (1 - f) * s);
-    
-        switch(i % 6){
-            case 0: r = v, g = t, b = p; break;
-            case 1: r = q, g = v, b = p; break;
-            case 2: r = p, g = v, b = t; break;
-            case 3: r = p, g = q, b = v; break;
-            case 4: r = t, g = p, b = v; break;
-            case 5: r = v, g = p, b = q; break;
-        }
-    
-        return _([r * 255, g * 255, b * 255]).map(Math.floor);
-    }
 
     /* Templates des éléments à insérer */
    
     var articleTemplate = _(
-        '<div class="cluster-article" style="position: absolute; left: <%=x%>px; top: <%=y%>px; width: <%=w%>px; height: <%=h%>px; background: <%=color%>">'+
-            '<%=label%>'+
+        '<div class="cluster-article" style="left: <%=x%>px; top: <%=y%>px; width: <%=w%>px; height: <%=h%>px;">'+
+            '<img src="<%=image_url%>" />' +
         '</div>'
     ).template();
     var clusterTemplate = _( 
-    '<div class="actu" style="left: <%=x%>px; top: <%=y%>px; width: <%=w%>px; height: <%=h%>px; background: <%=color%>">'+
-        '<a href="#">'+
-//            '<img src="img/home-visuel-<%-i%>.jpg" alt="" />'+
-        '<%=articles%>'+
+    '<div class="actu" style="left: <%=x%>px; top: <%=y%>px; width: <%=w - 1%>px; height: <%=h - 1%>px; background: #ffffff" data-cluster-id="<%=id%>">'+
+        '<%=articles%>'+ // Pour l'image composite
+        '<img src="<%=image_url%>" />' + // Pour l'image de cluster
         '<div class="voile"></div>'+
-        '</a>'+
         '<div class="inner-actu">'+
             '<h2><a href="#"><%-label%></a></h2>'+
             '<div class="links">'+
@@ -133,6 +132,7 @@
                 '</ul>'+
             '</div>'+
         '</div>'+
+        '<p class="abstract"><%= abstract %></p>'+
     '</div>'
     ).template();
 
@@ -142,17 +142,22 @@
     
     function showResults(results) {
         var data = _(results.clusters).map(function(cluster, i) {
-            var hue = (i%6)/6
+            var hue = (parseInt(cluster.id)%6)/6
             return {
+                id: cluster.id,
                 label: cluster.title,
+                abstract : cluster.abstract,
                 value: parseFloat(cluster.weight),
                 color: "rgb(" + hsvToRgb(hue,.8,.8).join(",") + ")",
                 annotation_count: cluster.annotations.length,
-                articles: _(cluster.documents).map(function(article, j) {
+                image_url: cluster.url_image || false,
+                articles: cluster.documents.filter(function(article) {
+                    return !!article.url_image
+                })
+                .map(function(article, j) {
                     return {
-                        label: article.title,
                         value: parseFloat(article.weight),
-                        color: "rgb(" + hsvToRgb(hue,.8,.9-.1*(j%6)).join(",") + ")"
+                        image_url: article.url_image || false
                     }
                 })
             }
@@ -162,7 +167,7 @@
         });
         squarify(data,0,0,760,hTreemap);
         _(data).each(function(cluster) {
-            squarify(cluster.articles, 0, 0, cluster.w, cluster.h);
+            squarify(cluster.articles, 0, 0, cluster.w - 1, cluster.h - 1);
             _(cluster.articles).sortBy(function(d) {
                 return -d.value;
             });
@@ -174,6 +179,43 @@
             return mem + clusterTemplate(d);
         },"");
         $('#treemap #actus').html(treemapHtml);
+        
+        //redimensionnement d'image
+        
+        $(".actu img").each(function() {
+            var img = $(this),
+                div = $(this).parent();
+            img.load(function() {
+                var iw = img.width(),
+                    ih = img.height(),
+                    dw = div.width(),
+                    dh = div.height(),
+                    scale = Math.max(dw/iw, dh/ih),
+                    niw = iw * scale,
+                    nih = ih * scale;
+                img.css({
+                    width: niw,
+                    height: nih,
+                    "margin-left": (dw - niw) / 2,
+                    "margin-top": (dh - nih) / 3
+                });
+            });
+        });
+        
+        $(".actu").hover(
+            function() {
+                $("body").trigger("select-cluster", $(this).attr("data-cluster-id"));
+            },
+            function() {
+                $("body").trigger("unselect-cluster", $(this).attr("data-cluster-id"));
+            }
+        )
+        $("body").on("select-cluster", function(e, clusterid) {
+            $(".actu[data-cluster-id='" + clusterid + "']").addClass("selected");
+        });
+        $("body").on("unselect-cluster", function(e, clusterid) {
+            $(".actu[data-cluster-id='" + clusterid + "']").removeClass("selected");
+        });
     }
     
     function renderJson(url) {
@@ -194,46 +236,6 @@
         }
         return false;
     });
-    
-    //redimensionnement d'image
-/*
-     $(".actu").each(function(k,v){
-        var wActu = $(this).width();
-        var hActu = $(this).height();
-        var img = $(this).find('img');
-        img.load(function(){
-            var img = $(this);
-
-            var wImg = img.width();
-            var hImg = img.height();
-
-            var ratioImg = wImg/hImg;
-            img.css('height',hActu);
-            img.css('width',hActu*ratioImg);
-            wImg = img.width();
-            hImg = img.height();
-
-            if(wActu>wImg){
-                var ratioImg = hImg/wImg;
-                img.css('width', wActu);
-                img.css('height',wActu*ratioImg);
-                wImg = img.width();
-                hImg = img.height();
-            }
-
-            if (wImg<wActu) {
-                img.css('margin-left',(wActu-wImg)/2);
-            }else{
-                img.css('margin-left',-(wImg-wActu)/2);
-            }
-            if (hImg<hActu) {
-                img.css('margin-top',(hActu-hImg)/2);
-            }else{
-                img.css('margin-top',-(hImg-hActu)/2);
-            }
-        });
-    });
-*/
 
 
     $("#liste").hide();