|
1 function Tapestry(donnees, parametres) { |
|
2 |
|
3 // Initialisation des attributs |
|
4 var mesDonnees = donnees; |
|
5 this.zoomlvl = 0; |
|
6 this.beginIndexs=[0,5,0,0]; |
|
7 this.decalageParent = [0,10,10,1]; |
|
8 this.listePosition=[[],[]]; |
|
9 |
|
10 |
|
11 this.parametres = { |
|
12 name: null, |
|
13 hauteur: 330, |
|
14 largeur: 1100, |
|
15 selector: "#tapestry", |
|
16 selectorHaut : null, |
|
17 selectorBas : null, |
|
18 relations: null, |
|
19 contenu: null, |
|
20 template: null |
|
21 }; |
|
22 |
|
23 this.etendre(parametres); |
|
24 |
|
25 |
|
26 /* -- Gestion des valeurs par defaut -- */ |
|
27 |
|
28 if (null==this.parametres.name) { |
|
29 this.parametres.name = this.parametres.selector; |
|
30 } |
|
31 if (null==this.parametres.hauteur) { |
|
32 this.parametres.hauteur = 400; |
|
33 } |
|
34 if (null==this.parametres.largeur) { |
|
35 this.parametres.largeur = 900; |
|
36 } |
|
37 if (null==this.parametres.selectorBas) { |
|
38 this.parametres.selectorBas = "#timelinebasse"; |
|
39 } |
|
40 if (null==this.parametres.selectorHaut) { |
|
41 this.parametres.selectorHaut = "#timelinehaute"; |
|
42 } |
|
43 if (null==this.parametres.contenu) { |
|
44 if (null!=this.parametres.template) { |
|
45 this.template = jQuery(this.parametres.template.selector); |
|
46 this.template.remove(); |
|
47 this.parametres.contenu = this.renderContent; |
|
48 } |
|
49 else { |
|
50 this.parametres.contenu = this.defaultContent; |
|
51 } |
|
52 } |
|
53 |
|
54 |
|
55 |
|
56 //---------------------------------------------------------------------- |
|
57 // INITIALISATION : on calcule les positions / dimensions des futurs objets |
|
58 this.listePosition=this.getPosition(); |
|
59 var object = this; |
|
60 var larg,haut; |
|
61 larg = String(this.parametres.largeur/5) + "px"; |
|
62 larg2=String(this.parametres.largeur/10) + "px"; |
|
63 larg3= String(9*this.parametres.largeur/100) + "px"; |
|
64 haut = String(this.parametres.hauteur/2 -1) + "px" ; |
|
65 haut2 = String(this.parametres.hauteur) + "px" ; |
|
66 this.lastIndexs = [9,18,160,1441]; |
|
67 |
|
68 |
|
69 //---------------------------------------------------------------------- |
|
70 // FENETRE DE FOND |
|
71 this.globalTapestry = d3.select(object.parametres.selector); |
|
72 this.globalTapestry.append('div').attr('id','timelinehaute'); |
|
73 this.globalTapestry.append('div').attr('id','timelinebasse'); |
|
74 |
|
75 this.tapestryHtml = d3.select(object.parametres.selectorHaut) |
|
76 .style('position', 'relative') |
|
77 .style('left','200px') |
|
78 .style('width', object.parametres.largeur + 'px') |
|
79 .style('height', object.parametres.hauteur + 'px') |
|
80 .style('background-color', 'black'); |
|
81 //.style('overflow','hidden'); |
|
82 |
|
83 //---------------------------------------------------------------------- |
|
84 // BOUTON DEZOOM |
|
85 var left = this.parametres.largeur/2 +100+"px"; |
|
86 this.boutonZoom = d3.select(object.parametres.selectorBas).append('button') |
|
87 .attr('id',"dezoom") |
|
88 .style('position', 'relative') |
|
89 .style('top','5px') |
|
90 .style('left',left) |
|
91 .style('width', "200px") |
|
92 .style('height',"20px") |
|
93 .style('background-color', 'grey') |
|
94 .style('margin-top', '5px') |
|
95 .style('stroke-width','2px') |
|
96 .style('stroke','black') |
|
97 .style('display','none') |
|
98 .html("<p class = 'title' style = \" width:200px;\"> Dezoom </p>") |
|
99 .on('mouseover', function(){d3.select(this).style('opacity', 0.8);}) |
|
100 .on('mouseout', function(){d3.select(this).style('opacity', 1);}) |
|
101 .on('click',function(){object.agencerDezoom(mesDonnees);}); |
|
102 |
|
103 //---------------------------------------------------------------------- |
|
104 // BOUTON SLIDELEFT |
|
105 var html = "<img class = 'img' src = \"data/boutongauche.png\" style=\" width:"+larg3+"; height:"+haut+"; margin-top: 0px; margin-left: 0px; stroke-width:0px\" />"; |
|
106 this.boutonSlideGauche = d3.select(object.parametres.selectorHaut).append('button') |
|
107 .attr('id',"sliderLeft") |
|
108 .style('position', 'absolute') |
|
109 .style('z-index',1) |
|
110 .style('width', larg2) |
|
111 .style('height',haut) |
|
112 .style('background-color', 'black') |
|
113 .style('opacity',0.2) |
|
114 .style('stroke','black') |
|
115 .html(html) |
|
116 .on('mouseover', function(){ |
|
117 if (object.beginIndexs[object.zoomlvl]!=0){ |
|
118 d3.select(this).style('opacity', 0.8);}}) |
|
119 .on('mouseout', function(){ |
|
120 var lvl = object.zoomlvl; |
|
121 if (object.beginIndexs[lvl]!=0){ |
|
122 d3.select(this).style('opacity', 1);}}) |
|
123 .on('click',function(){object.sliderLeft(mesDonnees);}); |
|
124 |
|
125 //---------------------------------------------------------------------- |
|
126 // BOUTON SLIDERIGHT |
|
127 left = this.parametres.largeur*9/10 + "px"; |
|
128 this.boutonSlideDroite = d3.select(this.parametres.selectorHaut).append('button') |
|
129 .attr('id',"sliderRight") |
|
130 .style('position', 'absolute') |
|
131 .style('z-index',1) |
|
132 .style('top',-5) |
|
133 .style('left',left) |
|
134 .style('width', larg2) |
|
135 .style('height',haut) |
|
136 .style('background-color', 'black') |
|
137 .style('margin-top', '5px') |
|
138 .style('stroke-width','2px') |
|
139 .style('stroke','black') |
|
140 .style('opacity',0.2) |
|
141 .html("<img class = 'img' src = \"data/boutondroite.png\" style=\" width:"+larg3+"; height:"+haut+"; margin-top: 0px; margin-left: 0px; stroke-width:0px\" />") |
|
142 .on('mouseover', function(){ |
|
143 var lvl = object.zoomlvl; |
|
144 if (object.beginIndexs[lvl]!=object.lastIndexs[lvl]-9){ |
|
145 d3.select(this).style('opacity', 0.8);}}) |
|
146 .on('mouseout', function(){ |
|
147 var lvl = object.zoomlvl; |
|
148 if (object.beginIndexs[lvl]!=object.lastIndexs[lvl]-9){ |
|
149 d3.select(this).style('opacity', 1);}}) |
|
150 .on('click',function(){object.sliderRight(mesDonnees);}); |
|
151 |
|
152 |
|
153 //---------------------------------------------------------------------- |
|
154 // INIT DES PETITES FENETRES |
|
155 |
|
156 d3.select(this.parametres.selectorHaut).selectAll() |
|
157 .data(mesDonnees[0].slice(0, 9)).enter().append("div") |
|
158 .attr('class', 'cell') |
|
159 .attr('id', "middle") |
|
160 .attr('indexInTap',function(index){return index;}) |
|
161 .on('mouseover', function(){if (object.zoomlvl!=3){d3.select(this) |
|
162 .transition() |
|
163 .duration(120) |
|
164 .style('opacity', 0.8) |
|
165 .style('stroke', 'black') |
|
166 .style('stroke-width', '3px');}}) |
|
167 .on('mouseout', function(){d3.select(this) |
|
168 .transition() |
|
169 .duration(120) |
|
170 .style('opacity', 1) |
|
171 .style('stroke', 'white') |
|
172 .style('stroke-width', '0px');}) |
|
173 .on('click',function(datum,index){object.agencerZoom(datum,index,mesDonnees);}) |
|
174 .on('scroll',function(datum,index){object.agencerZoom(datum,index);}) |
|
175 .style('position', 'absolute') |
|
176 .style('width', larg) |
|
177 .style('height',haut) |
|
178 .style('background-color', 'black') |
|
179 .style('text-align','center') |
|
180 .html(function(datum,index){return object.parametres.contenu.call(object, this,datum);}) |
|
181 .style('left', function(datum, index) { |
|
182 return object.listePosition[index][0]; |
|
183 }) |
|
184 .style('top', function(datum, index) { |
|
185 return object.listePosition[index][1]; |
|
186 }); |
|
187 if (null!=this.parametres.relations) { |
|
188 this.parametres.relations.add(this.parametres.name, this); |
|
189 |
|
190 d3.select(this.parametres.selectorHaut).selectAll("div") |
|
191 .each(function(datum) { |
|
192 var item = d3.select(this); |
|
193 datum["relationName"] = object.parametres.name +'.'+ datum.name; |
|
194 object.parametres.relations.add(datum.relationName, item); |
|
195 }); |
|
196 } |
|
197 // d3.select("#timelinehaute").selectAll("#middle") |
|
198 // .append('button') |
|
199 // .attr('class', 'dezoom-butoon') |
|
200 // .attr('id', "dezoom") |
|
201 // .style('width','180px') |
|
202 // .style('height','20px') |
|
203 // .style('position','absolute') |
|
204 // .style('top','180') |
|
205 // .style('opacity',' 0,8') |
|
206 // .style('background','dark-grey') |
|
207 // .style('z-index',10) |
|
208 // .attr('onmouseover',"this.style(\"stroke\",\"white\");" ); |
|
209 ; |
|
210 } |
|
211 |
|
212 Tapestry.prototype = { |
|
213 sleep: function(ms, args, obj) { |
|
214 /* Called at the top of a function to invoke a delay in processing that |
|
215 function |
|
216 |
|
217 Returns true if the function should be executed, and false if the sleep |
|
218 timer is activated. |
|
219 |
|
220 At the end of the sleep tiemout, the calling function is re-called by |
|
221 calling it with "apply (obj, args || [])". |
|
222 */ |
|
223 |
|
224 var caller = sleep.caller; |
|
225 if (caller.sleepTimer) { |
|
226 /* if invoked from timeout function, delete timer and return false */ |
|
227 delete caller.sleepTimer; |
|
228 return true; |
|
229 }}, |
|
230 |
|
231 etendre: function(parametres) { |
|
232 if (null==parametres || "object"!=typeof(parametres)) { |
|
233 return; |
|
234 } |
|
235 |
|
236 for (var cle in parametres) { |
|
237 this.parametres[cle] = parametres[cle]; |
|
238 } |
|
239 }, |
|
240 |
|
241 getPosition: function(){ // renvoie une liste contenant la position(x,y) absolute des fenêtres de la tapestry |
|
242 var l,h; |
|
243 l= this.parametres.largeur; |
|
244 h= this.parametres.hauteur; |
|
245 var listposition=[]; |
|
246 for (var i=0;i<9;i++){listposition.push([(i*0.5)*l/5,h/2*((i+1)%2)]);} |
|
247 //listposition.push([4.5*l/5,0]); |
|
248 return listposition; |
|
249 }, |
|
250 |
|
251 |
|
252 |
|
253 updateLayout: function(lvl,sliceIndex, isSlide,mesDonnees){ // met a jour la tapestry avec les données[lvl] à l'indice sliceIndex |
|
254 var object = this; |
|
255 var duration = isSlide? 40 : 160; |
|
256 this.tapestryHtml.selectAll("#middle") |
|
257 |
|
258 .transition() |
|
259 .duration(duration) |
|
260 //.delay(10) |
|
261 //.delay(function(index){return 10*index;}) |
|
262 .style("opacity", 0); |
|
263 |
|
264 var timeout = window.setTimeout(function() { |
|
265 |
|
266 |
|
267 |
|
268 object.tapestryHtml.selectAll("#middle") |
|
269 .data(mesDonnees[lvl].slice(sliceIndex,sliceIndex+9)) |
|
270 .html(function(datum,index){return object.parametres.contenu.call(object, this,datum);}); |
|
271 |
|
272 object.tapestryHtml.selectAll("#middle") |
|
273 .transition() |
|
274 .duration(2*duration) |
|
275 .delay(10) |
|
276 //.delay(function(index){return 10*index;}) |
|
277 .style("opacity", 1); |
|
278 |
|
279 object.tapestryHtml.select("#sliderRight") |
|
280 .transition() |
|
281 .duration(duration) |
|
282 .delay(10) |
|
283 .style('opacity',function(){ |
|
284 if (object.beginIndexs[lvl]+9==object.lastIndexs[lvl]){ |
|
285 return 0.2; |
|
286 } |
|
287 else{return 1;} }); |
|
288 |
|
289 object.tapestryHtml.select("#sliderLeft") |
|
290 .transition() |
|
291 .duration(duration) |
|
292 .delay(10) |
|
293 .style('opacity',function(){ |
|
294 if (object.beginIndexs[lvl]==0){ |
|
295 return 0.2; |
|
296 } |
|
297 else{return 1;} }); |
|
298 |
|
299 object.boutonZoom |
|
300 .style('display',function(){ |
|
301 if (lvl==0){return 'none';} |
|
302 else {return 'block';} |
|
303 // result = (lvl==0) ? 'none' : 'block'; |
|
304 // return result; |
|
305 }); |
|
306 }, 3*duration); |
|
307 }, |
|
308 |
|
309 |
|
310 |
|
311 sliderLeft: function(mesDonnees){ |
|
312 if (this.zoomlvl!=0){ |
|
313 var lvl= this.zoomlvl; |
|
314 var father = this.beginIndexs[lvl]; |
|
315 if (father!=0){ |
|
316 var coef= (father == 1) ? 1 :2; |
|
317 this.beginIndexs[lvl]-=coef; |
|
318 this.updateLayout(lvl, father-coef,true,mesDonnees); |
|
319 |
|
320 |
|
321 // Gestion des decalages des niveau superieurs |
|
322 //------------------------------------------------------------------- |
|
323 if (lvl!=0){ |
|
324 this.decalageParent[lvl-1]-=2; |
|
325 var decal = this.decalageParent[lvl-1]; |
|
326 if (decal<2){ |
|
327 if (decal==0){ |
|
328 this.decalageParent[lvl-1]=9; |
|
329 if(this.beginIndexs[lvl-1]!=0){ |
|
330 this.beginIndexs[lvl-1]--; |
|
331 if (lvl==3){ |
|
332 this.decalageParent[1]--; |
|
333 if (this.decalageParent[1]==1){ |
|
334 this.decalageParent[1]=10; |
|
335 if(this.beginIndexs[1]!=0){this.beginIndexs[1]--;} |
|
336 }}}} |
|
337 else{ |
|
338 this.decalageParent[lvl-1]=10; |
|
339 if(this.beginIndexs[lvl-1]!=0){ |
|
340 this.beginIndexs[lvl-1]--; |
|
341 if (lvl==3){ |
|
342 this.decalageParent[1]--; |
|
343 if (this.decalageParent[1]==1){ |
|
344 this.decalageParent[1]=10; |
|
345 if(this.beginIndexs[1]!=0){this.beginIndexs[1]--;} |
|
346 }}}}}}} |
|
347 |
|
348 }}, |
|
349 sliderRight: function(mesDonnees){ |
|
350 if (this.zoomlvl!=0){ |
|
351 //var last = donnees1[this.zoomlvl].length-9; |
|
352 var lvl=this.zoomlvl; |
|
353 var last = this.lastIndexs[lvl]-9; |
|
354 var father = this.beginIndexs[lvl]; |
|
355 if (father!=last){ |
|
356 var coef= (father == last-1) ? 1 :2; |
|
357 this.beginIndexs[lvl]+=coef; |
|
358 this.updateLayout(lvl, father+coef,true,mesDonnees); |
|
359 |
|
360 // Gestion des decalages des niveau superieurs |
|
361 //------------------------------------------------------------------- |
|
362 if (this.zoomlvl!=1){ |
|
363 //var lastFather = donnees1[lvl-1].length-9; |
|
364 var lastFather = this.lastIndexs[lvl-1]-9; |
|
365 this.decalageParent[lvl-1]+=2; |
|
366 decal =this.decalageParent[lvl-1]; |
|
367 if (decal>18){ |
|
368 if (decal==20){ |
|
369 this.decalageParent[lvl-1]=11; |
|
370 if(this.beginIndexs[lvl-1]!=lastFather){ |
|
371 this.beginIndexs[lvl-1]++; |
|
372 if (lvl==3){ |
|
373 this.decalageParent[1]++; |
|
374 if (this.decalageParent[1]==19){ |
|
375 this.decalageParent[1]=10; |
|
376 if(this.beginIndexs[1]!=this.lastIndexs-9){this.beginIndexs[1]++;} |
|
377 }}}} |
|
378 else{ |
|
379 this.decalageParent[this.zoomlvl-1]=10; |
|
380 if(this.beginIndexs[this.zoomlvl-1]!=lastFather){ |
|
381 this.beginIndexs[this.zoomlvl-1]++; |
|
382 if (lvl==3){ |
|
383 this.decalageParent[0]++; |
|
384 if (this.decalageParent[1]==19){ |
|
385 this.decalageParent[1]=10; |
|
386 if(this.beginIndexs[1]!=mesDonnees[1].length-9){this.beginIndexs[1]++;} |
|
387 }}}}}}} |
|
388 }}, |
|
389 |
|
390 agencerZoom: function(element,indexx,mesDonnees){ |
|
391 var lvl=element.zoomlvl; |
|
392 if (lvl !=3){ |
|
393 this.beginIndexs[lvl+1]=element.child-indexx; |
|
394 this.updateLayout(lvl+1, element.child-indexx,false,mesDonnees); |
|
395 this.decalageParent[lvl]+=4-indexx; |
|
396 this.zoomlvl = lvl +1; |
|
397 }}, |
|
398 |
|
399 agencerDezoom: function(mesDonnees){ |
|
400 var lvl = this.zoomlvl; |
|
401 if (lvl!=0) { |
|
402 this.updateLayout(lvl-1, this.beginIndexs[lvl-1],false,mesDonnees); |
|
403 this.zoomlvl--; |
|
404 this.decalageParent[lvl-1]=10; |
|
405 }}, |
|
406 |
|
407 getDataTapestry: function(json){ |
|
408 |
|
409 }, |
|
410 renderContent: function(cellule, element) { |
|
411 |
|
412 var html; |
|
413 var img = new Image(); |
|
414 indexx = element.indexx; |
|
415 img.src= images[indexx]; |
|
416 var wc, hc; |
|
417 wc = cellule.offsetWidth ; |
|
418 hc = cellule.offsetHeight ; |
|
419 |
|
420 var data = { |
|
421 'urlImage': img.src, |
|
422 'widhtImage': wc +"px", |
|
423 'heightImage': hc +"px", |
|
424 'margin-top': hc/2+'px', |
|
425 'cssDimensionImage': "width:"+ wc + "px; ", |
|
426 'cssDimensionTitre':" width:" + wc + "px; height:" +hc/10 +"px;", |
|
427 'titreImage': "image " + indexx |
|
428 }; |
|
429 |
|
430 return this.template |
|
431 .render(data, this.parametres.template.directives).html(); |
|
432 }, |
|
433 |
|
434 defaultContent: function(cellule, element) { // cellule contient la div et element ses données |
|
435 |
|
436 var html; |
|
437 var img = new Image(); |
|
438 |
|
439 indexx = element.indexx; |
|
440 img.src= images[indexx]; |
|
441 var wc, hc; |
|
442 wc = cellule.offsetWidth ; |
|
443 hc = cellule.offsetHeight ; |
|
444 html = "<img class = 'img' src = \"" + img.src + "\" style=\"width:"+ wc + "px; height:" +hc + "px; margin-top:5px; margin-left: 0px;\" />"; |
|
445 html += "<p class = 'title' style = \" width:" + wc + "px; height:" +hc/10 +"px;\"> Image "+String(indexx)+"</p>"; |
|
446 return html; |
|
447 |
|
448 } |
|
449 |
|
450 |
|
451 }; |
|
452 |
|
453 |