function Tapestry(donnees, parametres) {
// Initialisation des attributs
var mesDonnees = donnees;
this.zoomlvl = 0;
this.beginIndexs=[0,5,0,0];
this.decalageParent = [0,10,10,1];
this.listePosition=[[],[]];
this.parametres = {
name: null,
hauteur: 330,
largeur: 1100,
selector: "#tapestry",
selectorHaut : null,
selectorBas : null,
relations: null,
contenu: null,
template: null
};
this.etendre(parametres);
/* -- Gestion des valeurs par defaut -- */
if (null==this.parametres.name) {
this.parametres.name = this.parametres.selector;
}
if (null==this.parametres.hauteur) {
this.parametres.hauteur = 400;
}
if (null==this.parametres.largeur) {
this.parametres.largeur = 900;
}
if (null==this.parametres.selectorBas) {
this.parametres.selectorBas = "#timelinebasse";
}
if (null==this.parametres.selectorHaut) {
this.parametres.selectorHaut = "#timelinehaute";
}
if (null==this.parametres.contenu) {
if (null!=this.parametres.template) {
this.template = jQuery(this.parametres.template.selector);
this.template.remove();
this.parametres.contenu = this.renderContent;
}
else {
this.parametres.contenu = this.defaultContent;
}
}
//----------------------------------------------------------------------
// INITIALISATION : on calcule les positions / dimensions des futurs objets
this.listePosition=this.getPosition();
var object = this;
var larg,haut;
larg = String(this.parametres.largeur/5) + "px";
larg2=String(this.parametres.largeur/10) + "px";
larg3= String(9*this.parametres.largeur/100) + "px";
haut = String(this.parametres.hauteur/2 -1) + "px" ;
haut2 = String(this.parametres.hauteur) + "px" ;
this.lastIndexs = [9,18,160,1441];
//----------------------------------------------------------------------
// FENETRE DE FOND
this.globalTapestry = d3.select(object.parametres.selector);
this.globalTapestry.append('div').attr('id','timelinehaute');
this.globalTapestry.append('div').attr('id','timelinebasse');
this.tapestryHtml = d3.select(object.parametres.selectorHaut)
.style('position', 'relative')
.style('left','0px')
.style('width', object.parametres.largeur + 'px')
.style('height', object.parametres.hauteur + 'px')
.style('background-color', 'black');
//.style('overflow','hidden');
//----------------------------------------------------------------------
// BOUTON DEZOOM
var left = this.parametres.largeur/2 +"px";
this.boutonZoom = d3.select(object.parametres.selectorBas).append('button')
.attr('id',"dezoom")
.style('position', 'relative')
.style('top','5px')
.style('left',left)
.style('width', "200px")
.style('height',"20px")
.style('background-color', 'grey')
.style('margin-top', '5px')
.style('stroke-width','2px')
.style('stroke','black')
.style('display','none')
.html("<p class = 'title' style = \" width:200px;\"> Dezoom </p>")
.on('mouseover', function(){d3.select(this).style('opacity', 0.8);})
.on('mouseout', function(){d3.select(this).style('opacity', 1);})
.on('click',function(){object.agencerDezoom(mesDonnees);});
//----------------------------------------------------------------------
// BOUTON SLIDELEFT
var html = "<img class = 'img' src = \"data/boutongauche.png\" style=\" width:"+larg3+"; height:"+haut+"; margin-top: 0px; margin-left: 0px; stroke-width:0px\" />";
this.boutonSlideGauche = d3.select(object.parametres.selectorHaut).append('button')
.attr('id',"sliderLeft")
.style('position', 'absolute')
.style('z-index',1)
.style('width', larg2)
.style('height',haut)
.style('background-color', 'black')
.style('opacity',0.2)
.style('stroke','black')
.html(html)
.on('mouseover', function(){
if (object.beginIndexs[object.zoomlvl]!=0){
d3.select(this).style('opacity', 0.8);}})
.on('mouseout', function(){
var lvl = object.zoomlvl;
if (object.beginIndexs[lvl]!=0){
d3.select(this).style('opacity', 1);}})
.on('click',function(){object.sliderLeft(mesDonnees);});
//----------------------------------------------------------------------
// BOUTON SLIDERIGHT
left = this.parametres.largeur*9/10 + "px";
this.boutonSlideDroite = d3.select(this.parametres.selectorHaut).append('button')
.attr('id',"sliderRight")
.style('position', 'absolute')
.style('z-index',1)
.style('top',-5)
.style('left',left)
.style('width', larg2)
.style('height',haut)
.style('background-color', 'black')
.style('margin-top', '5px')
.style('stroke-width','2px')
.style('stroke','black')
.style('opacity',0.2)
.html("<img class = 'img' src = \"data/boutondroite.png\" style=\" width:"+larg3+"; height:"+haut+"; margin-top: 0px; margin-left: 0px; stroke-width:0px\" />")
.on('mouseover', function(){
var lvl = object.zoomlvl;
if (object.beginIndexs[lvl]!=object.lastIndexs[lvl]-9){
d3.select(this).style('opacity', 0.8);}})
.on('mouseout', function(){
var lvl = object.zoomlvl;
if (object.beginIndexs[lvl]!=object.lastIndexs[lvl]-9){
d3.select(this).style('opacity', 1);}})
.on('click',function(){object.sliderRight(mesDonnees);});
//----------------------------------------------------------------------
// INIT DES PETITES FENETRES
d3.select(this.parametres.selectorHaut).selectAll()
.data(mesDonnees[0].slice(0, 9)).enter().append("div")
.attr('class', 'cell')
.attr('id', "middle")
.attr('indexInTap',function(index){return index;})
.on('mouseover', function(){if (object.zoomlvl!=3){d3.select(this)
.transition()
.duration(120)
.style('opacity', 0.8)
.style('stroke', 'black')
.style('stroke-width', '3px');}})
.on('mouseout', function(){d3.select(this)
.transition()
.duration(120)
.style('opacity', 1)
.style('stroke', 'white')
.style('stroke-width', '0px');})
.on('click',function(datum,index){object.agencerZoom(datum,index,mesDonnees);})
.on('scroll',function(datum,index){object.agencerZoom(datum,index);})
.style('position', 'absolute')
.style('width', larg)
.style('height',haut)
.style('background-color', 'black')
.style('text-align','center')
.html(function(datum,index){return object.parametres.contenu.call(object, this,datum);})
.style('left', function(datum, index) {
return object.listePosition[index][0];
})
.style('top', function(datum, index) {
return object.listePosition[index][1];
});
if (null!=this.parametres.relations) {
this.parametres.relations.add(this.parametres.name, this);
d3.select(this.parametres.selectorHaut).selectAll("div")
.each(function(datum) {
var item = d3.select(this);
datum["relationName"] = object.parametres.name +'.'+ datum.name;
object.parametres.relations.add(datum.relationName, item);
});
}
// d3.select("#timelinehaute").selectAll("#middle")
// .append('button')
// .attr('class', 'dezoom-butoon')
// .attr('id', "dezoom")
// .style('width','180px')
// .style('height','20px')
// .style('position','absolute')
// .style('top','180')
// .style('opacity',' 0,8')
// .style('background','dark-grey')
// .style('z-index',10)
// .attr('onmouseover',"this.style(\"stroke\",\"white\");" );
;
}
Tapestry.prototype = {
sleep: function(ms, args, obj) {
/* Called at the top of a function to invoke a delay in processing that
function
Returns true if the function should be executed, and false if the sleep
timer is activated.
At the end of the sleep tiemout, the calling function is re-called by
calling it with "apply (obj, args || [])".
*/
var caller = sleep.caller;
if (caller.sleepTimer) {
/* if invoked from timeout function, delete timer and return false */
delete caller.sleepTimer;
return true;
}},
etendre: function(parametres) {
if (null==parametres || "object"!=typeof(parametres)) {
return;
}
for (var cle in parametres) {
this.parametres[cle] = parametres[cle];
}
},
getPosition: function(){ // renvoie une liste contenant la position(x,y) absolute des fen�tres de la tapestry
var l,h;
l= this.parametres.largeur;
h= this.parametres.hauteur;
var listposition=[];
for (var i=0;i<9;i++){listposition.push([(i*0.5)*l/5,h/2*((i+1)%2)]);}
//listposition.push([4.5*l/5,0]);
return listposition;
},
updateLayout: function(lvl,sliceIndex, isSlide,mesDonnees){ // met a jour la tapestry avec les donn�es[lvl] � l'indice sliceIndex
var object = this;
var duration = isSlide? 40 : 160;
this.tapestryHtml.selectAll("#middle")
.transition()
.duration(duration)
//.delay(10)
//.delay(function(index){return 10*index;})
.style("opacity", 0);
var timeout = window.setTimeout(function() {
object.tapestryHtml.selectAll("#middle")
.data(mesDonnees[lvl].slice(sliceIndex,sliceIndex+9))
.html(function(datum,index){return object.parametres.contenu.call(object, this,datum);});
object.tapestryHtml.selectAll("#middle")
.transition()
.duration(2*duration)
.delay(10)
//.delay(function(index){return 10*index;})
.style("opacity", 1);
object.tapestryHtml.select("#sliderRight")
.transition()
.duration(duration)
.delay(10)
.style('opacity',function(){
if (object.beginIndexs[lvl]+9==object.lastIndexs[lvl]){
return 0.2;
}
else{return 1;} });
object.tapestryHtml.select("#sliderLeft")
.transition()
.duration(duration)
.delay(10)
.style('opacity',function(){
if (object.beginIndexs[lvl]==0){
return 0.2;
}
else{return 1;} });
object.boutonZoom
.style('display',function(){
if (lvl==0){return 'none';}
else {return 'block';}
// result = (lvl==0) ? 'none' : 'block';
// return result;
});
}, 3*duration);
},
sliderLeft: function(mesDonnees){
if (this.zoomlvl!=0){
var lvl= this.zoomlvl;
var father = this.beginIndexs[lvl];
if (father!=0){
var coef= (father == 1) ? 1 :2;
this.beginIndexs[lvl]-=coef;
this.updateLayout(lvl, father-coef,true,mesDonnees);
// Gestion des decalages des niveau superieurs
//-------------------------------------------------------------------
if (lvl!=0){
this.decalageParent[lvl-1]-=2;
var decal = this.decalageParent[lvl-1];
if (decal<2){
if (decal==0){
this.decalageParent[lvl-1]=9;
if(this.beginIndexs[lvl-1]!=0){
this.beginIndexs[lvl-1]--;
if (lvl==3){
this.decalageParent[1]--;
if (this.decalageParent[1]==1){
this.decalageParent[1]=10;
if(this.beginIndexs[1]!=0){this.beginIndexs[1]--;}
}}}}
else{
this.decalageParent[lvl-1]=10;
if(this.beginIndexs[lvl-1]!=0){
this.beginIndexs[lvl-1]--;
if (lvl==3){
this.decalageParent[1]--;
if (this.decalageParent[1]==1){
this.decalageParent[1]=10;
if(this.beginIndexs[1]!=0){this.beginIndexs[1]--;}
}}}}}}}
}},
sliderRight: function(mesDonnees){
if (this.zoomlvl!=0){
//var last = donnees1[this.zoomlvl].length-9;
var lvl=this.zoomlvl;
var last = this.lastIndexs[lvl]-9;
var father = this.beginIndexs[lvl];
if (father!=last){
var coef= (father == last-1) ? 1 :2;
this.beginIndexs[lvl]+=coef;
this.updateLayout(lvl, father+coef,true,mesDonnees);
// Gestion des decalages des niveau superieurs
//-------------------------------------------------------------------
if (this.zoomlvl!=1){
//var lastFather = donnees1[lvl-1].length-9;
var lastFather = this.lastIndexs[lvl-1]-9;
this.decalageParent[lvl-1]+=2;
decal =this.decalageParent[lvl-1];
if (decal>18){
if (decal==20){
this.decalageParent[lvl-1]=11;
if(this.beginIndexs[lvl-1]!=lastFather){
this.beginIndexs[lvl-1]++;
if (lvl==3){
this.decalageParent[1]++;
if (this.decalageParent[1]==19){
this.decalageParent[1]=10;
if(this.beginIndexs[1]!=this.lastIndexs-9){this.beginIndexs[1]++;}
}}}}
else{
this.decalageParent[this.zoomlvl-1]=10;
if(this.beginIndexs[this.zoomlvl-1]!=lastFather){
this.beginIndexs[this.zoomlvl-1]++;
if (lvl==3){
this.decalageParent[0]++;
if (this.decalageParent[1]==19){
this.decalageParent[1]=10;
if(this.beginIndexs[1]!=mesDonnees[1].length-9){this.beginIndexs[1]++;}
}}}}}}}
}},
agencerZoom: function(element,indexx,mesDonnees){
var lvl=element.zoomlvl;
if (lvl !=3){
this.beginIndexs[lvl+1]=element.child-indexx;
this.updateLayout(lvl+1, element.child-indexx,false,mesDonnees);
this.decalageParent[lvl]+=4-indexx;
this.zoomlvl = lvl +1;
}},
agencerDezoom: function(mesDonnees){
var lvl = this.zoomlvl;
if (lvl!=0) {
this.updateLayout(lvl-1, this.beginIndexs[lvl-1],false,mesDonnees);
this.zoomlvl--;
this.decalageParent[lvl-1]=10;
}},
getDataTapestry: function(json){
},
renderContent: function(cellule, element) {
var html;
var img = new Image();
indexx = element.indexx;
img.src= images[indexx];
var wc, hc;
wc = cellule.offsetWidth ;
hc = cellule.offsetHeight ;
var data = {
'urlImage': img.src,
'widhtImage': wc +"px",
'heightImage': hc +"px",
'margin-top': hc/2+'px',
'cssDimensionImage': "width:"+ wc + "px; ",
'cssDimensionTitre':" width:" + wc + "px; height:" +hc/10 +"px;",
'titreImage': "image " + indexx
};
return this.template
.render(data, this.parametres.template.directives).html();
},
defaultContent: function(cellule, element) { // cellule contient la div et element ses donn�es
var html;
var img = new Image();
indexx = element.indexx;
img.src= images[indexx];
var wc, hc;
wc = cellule.offsetWidth ;
hc = cellule.offsetHeight ;
html = "<img class = 'img' src = \"" + img.src + "\" style=\"width:"+ wc + "px; height:" +hc + "px; margin-top:5px; margin-left: 0px;\" />";
html += "<p class = 'title' style = \" width:" + wc + "px; height:" +hc/10 +"px;\"> Image "+String(indexx)+"</p>";
return html;
}
};