front_idill/src/mosaic/js/mosaic.js
changeset 35 4267d6d27a7d
parent 33 2d9b15f99b4e
child 44 8393d3473b98
equal deleted inserted replaced
34:909dfe0c1dca 35:4267d6d27a7d
    20 /*
    20 /*
    21  * Classe définissant la mosaïque.
    21  * Classe définissant la mosaïque.
    22  * Elle contient sa longueur, le nombre d'images total, une liste d'urls pour les vidéos, leurs snapshots principaux et leur position.
    22  * Elle contient sa longueur, le nombre d'images total, une liste d'urls pour les vidéos, leurs snapshots principaux et leur position.
    23  * Contient également les dimensions en px de la mosaïque.
    23  * Contient également les dimensions en px de la mosaïque.
    24  */
    24  */
    25 function mosaic(len, imgToShow, imgTotal, zoomPercentage, prezoomPercentage, zoomedMargin)
    25 function mosaic(config, default_conf)
    26 {
    26 {
    27     //S'il s'agit d'un rectangle.
    27 	//Chemin du fichier de configuration.
    28     if(imgToShow % len == 0)
    28 	this.config_path = config;
    29     {
    29 	//Configuration par défaut en cas de valeur erronnée.
    30         //Longueur horizontale.
    30 	this.default_config = default_conf;
    31         this.length = len;
    31 	this.config = new Object();
    32         //Nombre d'images dans la mosaïque.
    32 	//Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
    33         this.imagesToShow = imgToShow;
    33 	this.videos = [];
    34 		this.imagesTotal = imgTotal;
    34 	this.urls = [];
    35         //Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
    35 	this.imgs = [];
    36         this.videos = [];
    36 	this.ids = [];
    37         this.urls = [];
    37 	this.fillingIds = [];
    38         this.imgs = [];
    38 	this.currentRandomVideoIdx = 0;
    39         this.ids = [];
    39 	
    40 		//On remplit le tableau d'ids.
    40 	//Dimensions de la mosaïque en pixels.
    41 		for(var i = 0 ; i < this.imagesTotal ; i++)
    41 	this.width;
    42 			this.ids.push(i);
    42 	this.height;
    43 		//On les mélange.
    43 	//Dimensions d'un snapshot en pixels.
    44 		this.ids.sort(function()
    44 	this.snapshotWidth;
    45 		{
    45 	this.snapshotHeight;
    46 			return 0.5 - Math.random()
    46 	//Espacement entre les snapshots en pixels.
    47 		});
    47 	this.marginWidth;
    48 		
    48 	
    49 		console.log(this.ids);
    49 	//Booléens permettant ou non certaines intéractions selon le contexte.
    50 		
    50 	this.zoomed;
    51         //Dimensions de la mosaïque en pixels.
    51 	this.fullscreen;
    52         this.width;
    52 	this.canMoveToNeighbour;
    53         this.height;
    53 	this.helpDisplayed;
    54         //Dimensions d'un snapshot en pixels.
    54 	
    55         this.snapshotWidth;
    55 	//Type de marqueur recherché dans la mosaïque (en mode filter).
    56         this.snapshotHeight;
    56 	this.filterSearchedType = "";
    57         //Espacement entre les snapshots en pixels.
    57 	
    58         this.marginWidth;
    58 	//Mode actuel.
    59         
    59 	this.currentMode = "MOSAIC";
    60         //Temps d'intéractions/d'animations.
    60 	//Snapshot sur lequel on a zoomé.
    61         this.preZoomTime;
    61 	this.previousZoomedSN;
    62         this.preUnzoomTime;
    62 	//Son ID.
    63         this.zoomTime;
    63 	this.previousId;
    64         this.unzoomTime;
    64 	//Largeur de la marge pour le centrage vertical de la mosaïque.
    65         this.timeNeighbourGlowing;
    65 	this.MPTop_margin;
    66         this.timeNeighbourUnglowing;
    66 	this.top_margin;
    67         this.timeMovingToNeighbour;
    67 
    68 		this.timeSearchFade;
    68 	//Mosaïque locale.
    69 		this.timeNotifyFade;
    69 	this.localMos;
    70         
    70 	//Position des voisins lors d'un zoom.
    71         //Booléens permettant ou non certaines intéractions selon le contexte.
    71 	this.neighboursIds = [];
    72         this.zoomed;
    72 	//ID du snapshot du milieu lors d'un zoom.
    73         this.fullscreen;
    73 	this.centerId;
    74         this.canMoveToNeighbour;
    74 	
    75 		this.helpDisplayed;
    75 	//Snapshots a afficher.
    76         
    76 	this.snapshotsToShow = 1;
    77         //Mode actuel.
    77 	
    78         this.currentMode;
    78 	//Lecteur.
    79         //Snapshot sur lequel on a zoomé.
    79 	this.player;
    80         this.previousZoomedSN;
    80 	//Annotations (pour les marqueurs los d'un filtrage).
    81         //Son ID.
    81 	this.annotations = [];
    82         this.previousId;
    82 	
    83         //Largeur de la marge pour le centrage vertical de la mosaïque.
    83 	//Coordonnées et dimensions d'un snapshot zoomé.
    84         this.MPTop_margin;
    84 	this.snTop = 0;
    85         this.top_margin;
    85 	this.snLeft = 0;
    86         //Pourcentage d'agrandissement lors d'un prézoom et d'un zoom.
    86 	this.snWidth = 0;
    87         this.prezoomPercentage = prezoomPercentage;
    87 	this.snHeight = 0;
    88         this.zoomPercentage = zoomPercentage;
    88 	
    89         //Espacement des snapshots après un zoom.
    89 	this.searchCanvas;
    90         this.zoomedMargin = zoomedMargin;
    90 	//Position actuelle de la vidéo zoomée.
    91         //Mosaïque locale.
    91 	this.notifyTopVideo;
    92         this.localMos;
    92 	this.notifyLeftVideo;
    93         //Position des voisins lors d'un zoom.
    93 	this.loadParameters(this.config_path);
    94         this.neighboursIds = [];
       
    95         //ID du snapshot du milieu lors d'un zoom.
       
    96         this.centerId;
       
    97 		
       
    98 		//Lecteur.
       
    99 		this.player;
       
   100 		
       
   101 		//Coordonnées et dimensions d'un snapshot zoomé.
       
   102 		this.snTop = 0;
       
   103 		this.snLeft = 0;
       
   104 		this.snWidth = 0;
       
   105 		this.snHeight = 0;
       
   106 		
       
   107 		this.searchCanvas;
       
   108 		
       
   109 		this.loadFromJson('./player/json/videos.json');
       
   110     }
       
   111     else
       
   112     {
       
   113         //Affiche un message d'erreur.
       
   114     }
       
   115 }
    94 }
   116 
    95 
   117 /*
    96 /*
   118  * Méthode d'affichage de la mosaïque.
    97  * Méthode d'affichage de la mosaïque.
   119  * Génère une matrice de imgs.
    98  * Génère une matrice de imgs.
   120  */
    99  */
   121 mosaic.prototype.createMosaic = function()
   100 mosaic.prototype.createMosaic = function()
   122 {
   101 {
   123     this.previousZoomedSN = '';
   102 	console.log('CREATE');
   124     this.previousPrezoomDiv = '';
   103 	this.currentMode = "NO-USER";
   125     this.fullscreen = false;
   104 	var initPanel = '<div id="initPanel"></div>';
   126     this.canMoveToNeighbour = false;
   105 	var mp = $('#mainPanel');
   127 	this.helpDisplayed = false;
   106 	mp.append(initPanel);
   128     var str = '';
   107 	$('#initPanel').css(
   129     
   108 	{
   130     if(this.imgs.length >= this.imagesToShow)
   109 		background: 'transparent',
       
   110 		width: mp.width(),
       
   111 		height: mp.height(),
       
   112 		top: mp.position().top,
       
   113 		left: mp.position().left,
       
   114 		'margin-top': this.MPTop_margin
       
   115 	});
       
   116 	
       
   117 	var len = this.config['length'], imgs = this.config['imagesToShow'], imgsTotal = this.config['imagesTotal'];
       
   118 	
       
   119 	//S'il s'agit d'un rectangle.
       
   120     if(imgs % len == 0)
   131     {
   121     {
   132         for(var i = 0 ; i < this.imagesToShow ; i++)
   122 		this.previousZoomedSN = '';
   133         {
   123 		this.previousPrezoomDiv = '';
   134             //On charge les images de petite taille pour ne pas surcharger la mosaïque lors de l'affichage global.
   124 		this.fullscreen = false;
   135             str += '<div id="snapshotDiv-' + i + '" class="snapshotDivs"><img id="snapshot-' + i + '" class="snapshots" src="snapshots-little/' + this.imgs[i] + '" /></div>';
   125 		this.canMoveToNeighbour = false;
   136         }
   126 		this.helpDisplayed = false;
   137     }
   127 		var str = '';
   138     
   128 		
   139 	console.log(this.imagesToShow);
   129 		if(this.imgs.length >= imgs)
   140 	
   130 		{
   141     return str;
   131 			for(var i = 0 ; i < imgs ; i++)
       
   132 			{
       
   133 				//On charge les images de petite taille pour ne pas surcharger la mosaïque lors de l'affichage global.
       
   134 				str += '<div id="snapshotDiv-' + i + '" class="snapshotDivs" style="opacity: 0;"><img id="snapshot-' + i + '" class="snapshots" src="snapshots-little/' + this.imgs[i] + '" /></div>';
       
   135 			}
       
   136 		}
       
   137 		
       
   138 		return str;
       
   139 	}
       
   140 	else
       
   141 	{
       
   142 		alert("Le nombre d'images a afficher doit être divisible par la longueur de la mosaïque !");
       
   143 	}
   142 }
   144 }
   143 
   145 
   144 /*
   146 /*
   145  * Permet de raffraichir la mosaïque.
   147  * Permet de raffraichir la mosaïque.
   146  */
   148  */
   147 mosaic.prototype.loadMosaic = function()
   149 mosaic.prototype.loadMosaic = function()
   148 {
   150 {
       
   151 	console.log('LOAD');
   149 	var createMosaic = this.createMosaic();
   152 	var createMosaic = this.createMosaic();
   150 	
   153 	
   151 	if(createMosaic == '')
   154 	if(createMosaic == '')
   152 	{
   155 	{
   153 		return;
   156 		return;
   160     //this.width = 
   163     //this.width = 
   161     //On met à jour la mosaïque.
   164     //On met à jour la mosaïque.
   162     $('#mainPanel').html(createMosaic);
   165     $('#mainPanel').html(createMosaic);
   163     //On récupère la taille des bordures.
   166     //On récupère la taille des bordures.
   164     this.marginWidth = $('.snapshotDivs').css('margin-bottom');
   167     this.marginWidth = $('.snapshotDivs').css('margin-bottom');
   165     this.marginWidth = parseFloat(mos.marginWidth)*2;
   168     this.marginWidth = parseFloat(this.marginWidth)*2;
   166     //On calcule la taille des divs contenant les snapshots.
   169     //On calcule la taille des divs contenant les snapshots.
   167     this.width = $('#mainPanel').innerWidth();
   170     this.width = $('#mainPanel').innerWidth();
   168     //On ne calculera pas tout de suite la hauteur de la mosaique étant donnée qu'elle est calculée par la suite dynamiquement.
   171     //On ne calculera pas tout de suite la hauteur de la mosaique étant donnée qu'elle est calculée par la suite dynamiquement.
   169     this.snapshotWidth = this.width / this.length - this.marginWidth;
   172     this.snapshotWidth = this.width / this.config['length'] - this.marginWidth;
   170     this.snapshotHeight = this.snapshotWidth*9/16;
   173     this.snapshotHeight = this.snapshotWidth*9/16;
   171     $('.snapshotDivs').css('width', this.snapshotWidth).css('height', this.snapshotHeight).css('margin', this.marginWidth/2);
   174     $('.snapshotDivs').css('width', this.snapshotWidth).css('height', this.snapshotHeight).css('margin', this.marginWidth/2);
   172     
   175     
   173     this.height = $('#mainPanel').innerHeight();
   176     this.height = $('#mainPanel').innerHeight();
   174     //On centre verticalement la mosaïque.
   177     //On centre verticalement la mosaïque.
   181 	$('.snapshotDivs').mouseenter(function ()
   184 	$('.snapshotDivs').mouseenter(function ()
   182 	{
   185 	{
   183 		//On effectue un prézoom dès qu'on va sur une image.
   186 		//On effectue un prézoom dès qu'on va sur une image.
   184 		_this.preZoom($(this));
   187 		_this.preZoom($(this));
   185 	});
   188 	});
   186 	$('body').keypress(function (event)
   189 	
   187 	{
   190 	this.addPointers();
   188 		//Si on a appuié sur la touche 'q' ou 'Q';
   191 	
   189 		if(event.which == 113 || event.which == 81)
   192 	//Si dans le metadata player _ n'est pas déclaré, on le déclare.
   190 		{
   193 	if(typeof _ !== "undefined" && typeof IriSP._ === "undefined")
   191 		   _this.unzoom();
   194 	{
   192 		}
   195 		IriSP._ = _;
   193 	});
   196 	}
       
   197 	
       
   198 	if(typeof $ !== "undefined" && typeof IriSP.jQuery === "undefined")
       
   199 	{
       
   200 		IriSP.jQuery = $;
       
   201 	}
       
   202 	
       
   203 	//On charge les marqueurs.
       
   204 	var sourceManager = new IriSP.Model.Directory(),
       
   205 	globalAnnotations = new IriSP.Model.List(sourceManager),
       
   206 	nbFichiers = _this.urls.length,
       
   207 	fichiersCharges = 0;
       
   208 	
       
   209 	for (var i = 0; i < nbFichiers; i++)
       
   210 	{
       
   211 		console.log('url : ' + _this.urls[i]);
       
   212 		var source = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt});
       
   213 		source.onLoad(function()
       
   214 		{
       
   215 			globalAnnotations.addElements(source.getAnnotations());
       
   216 			fichiersCharges++;
       
   217 			if (fichiersCharges == nbFichiers)
       
   218 			{
       
   219 				// instructions à exécuter quand tout est chargé
       
   220 				_this.annotations = globalAnnotations;
       
   221 				console.log('annotations loaded');
       
   222 				_this.init();
       
   223 			}
       
   224 		});
       
   225 	}
       
   226 }
       
   227 
       
   228 /*
       
   229  * Charge les paramètres du Front. Local (true/false) est le mode de chargement des données.
       
   230 */
       
   231 mosaic.prototype.loadParameters = function(file_path)
       
   232 {
       
   233 	var _this = this;
       
   234 	
       
   235 	var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeFilling', 'zoomedMargin'];
       
   236 	var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage'];
       
   237 	
       
   238 	$.getJSON(file_path, function(data)
       
   239 	{
       
   240 		for(key in data)
       
   241 		{
       
   242 			var val = data[key];
       
   243 			
       
   244 			if(_.include(supposedToBeInt, key))
       
   245 			{
       
   246 				var intVal = parseInt(val);
       
   247 				if(isNaN(intVal))
       
   248 				{
       
   249 					console.log(_this.default_config);
       
   250 					_this.config[key] = _this.default_config[key];
       
   251 					console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Int). Valeur par défaut " + _this.default_config[key] + " chargée à la place.");
       
   252 				}
       
   253 				else
       
   254 				{
       
   255 					_this.config[key] = intVal;
       
   256 				}
       
   257 			}
       
   258 			else if(_.include(supposedToBeFloat, key))
       
   259 			{
       
   260 				var floatVal = parseFloat(val);
       
   261 				if(isNaN(floatVal))
       
   262 				{
       
   263 					_this.config[key] = _this.default_config[key];
       
   264 					console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Float). Valeur par défaut " + _this.default_config[key] + " chargée à la place.");
       
   265 				}
       
   266 				else
       
   267 				{
       
   268 					_this.config[key] = floatVal;
       
   269 				}
       
   270 			}
       
   271 			else
       
   272 			{
       
   273 				_this.config[key] = val;
       
   274 			}
       
   275 		}
       
   276 		
       
   277 		//On remplit le tableau d'ids.
       
   278 		for(var i = 0 ; i < _this.config['totalImages'] ; i++)
       
   279 			_this.ids.push(i);
       
   280 		//On les mélange.
       
   281 		_this.ids.sort(function()
       
   282 		{
       
   283 			return 0.5 - Math.random()
       
   284 		});
       
   285 		
       
   286 		//On remplit le tableau d'ids destiné à afficher les snapshots au fur et à mesure.
       
   287 		for(var i = 0 ; i < _this.config['imagesToShow'] ; i++)
       
   288 			_this.fillingIds.push(i);
       
   289 		//On les mélange.
       
   290 		_this.fillingIds.sort(function()
       
   291 		{
       
   292 			return 0.5 - Math.random()
       
   293 		});
       
   294 		
       
   295 		if(_this.config['local'] == 'true')
       
   296 		{
       
   297 			console.log("Loading local metadata.");
       
   298 			_this.loadFromJson('./player/json/local_videos.json');
       
   299 		}
       
   300 		else
       
   301 		{
       
   302 			console.log("Loading online metadata.");
       
   303 			_this.loadFromJson('./player/json/online_videos.json');
       
   304 		}
       
   305 	});
       
   306 }
       
   307 
       
   308 /*
       
   309  * Phase principale (utilisateur non détecté). Une vidéo se lance aléatoirement.
       
   310  * L'interface est identique à celle du zoom, mais sans interaction possible avec les voisins, ni les controles timeline.
       
   311  * Lors de la fin d'une lecture, on dézoome vers la mosaïque, puis on rezoome vers un autre snapshot (aléatoire).
       
   312 */
       
   313 mosaic.prototype.init = function()
       
   314 {
       
   315 	var _this = this;
       
   316 	
       
   317 	if(this.currentRandomVideoIdx > this.config['imagesToShow'])
       
   318 	{
       
   319 		this.currentRandomVideoIdx = 0;
       
   320 	}
       
   321 	
       
   322 	this.previousZoomedSN = $('#snapshotDiv-' + this.fillingIds[this.currentRandomVideoIdx]);
       
   323 	this.previousId = $('img', this.previousZoomedSN).attr('id');
       
   324 	
       
   325 	console.log('ids', this.fillingIds[this.currentRandomVideoIdx]);
       
   326 	
       
   327 	this.previousZoomedSN.fadeTo(this.config['timePrezoom'], 1, function()
       
   328 	{
       
   329 		_this.zoom();
       
   330 		_this.currentRandomVideoIdx++;
       
   331 	});
       
   332 }
       
   333 
       
   334 /*
       
   335  * Remplissage de la mosaïque en fonction du nombre d'images à afficher.
       
   336 */
       
   337 mosaic.prototype.showNImages = function(n)
       
   338 {
       
   339 	if(n > 1)
       
   340 	{
       
   341 		this.currentMode = "INCOMING-" + n;
       
   342 		this.unzoom();
       
   343 	}
       
   344 	
       
   345 	for(var i = 0 ; i < n ; i++)
       
   346 	{
       
   347 		if($('#snapshotDiv-' + i).css('opacity') < 1)
       
   348 		{
       
   349 			$('#snapshotDiv-' + i).fadeTo(this.config['timeFilling'], 1);
       
   350 		}
       
   351 	}
       
   352 }
       
   353 
       
   354 /*
       
   355  * Affiche les pointeurs.
       
   356 */
       
   357 mosaic.prototype.addPointers = function()
       
   358 {
       
   359 	var _this = this;
       
   360 	
       
   361 	var mainPointer = '<div id="mainPointer" class="pointers"></div>';
       
   362 	$('body').append(mainPointer);
       
   363 	$('body').mousemove(function(evt)
       
   364 	{
       
   365 		$('#mainPointer').css(
       
   366 		{
       
   367 			top: evt.pageY - $('#mainPointer').height()/2,
       
   368 			left: evt.pageX - $('#mainPointer').width()/2
       
   369 		});
       
   370 	});
       
   371 }
       
   372 
       
   373 /*
       
   374  * Gère les événements de contrôle dans la mosaïque.
       
   375 */
       
   376 mosaic.prototype.manageControlEvents = function(event)
       
   377 {
       
   378 	console.log('manage');
       
   379 	//Sinon si on a appuyé sur 'g' ou 'G'.
       
   380 	if(event.which == 103 || event.which == 71)
       
   381 	{
       
   382 		//Si on est déjà en recherche par courbes.
       
   383 		if(this.currentMode == "SEARCH" || this.currentMode == "FILTER")
       
   384 		{
       
   385 			//On quitte cette recherche.
       
   386 			this.leaveSearch();
       
   387 			//Si on était en mode recherche.
       
   388 			if(this.currentMode == "SEARCH")
       
   389 			{
       
   390 				//On revient dans la vidéo.
       
   391 				this.currentMode = "VIDEO";
       
   392 			}
       
   393 			else
       
   394 			{
       
   395 				//Sinon c'est qu'on était dans la mosaïque.
       
   396 				this.currentMode = "MOSAIC";
       
   397 			}
       
   398 		}
       
   399 		else
       
   400 		{
       
   401 			//Si on est en plein écran.
       
   402 			if(this.fullscreen)
       
   403 			{
       
   404 				//On entre en mode recherche.
       
   405 				this.currentMode = "SEARCH";
       
   406 			}
       
   407 			//Sinon.
       
   408 			else
       
   409 			{
       
   410 				//On entre en mode filtrage.
       
   411 				this.currentMode = "FILTER";
       
   412 			}
       
   413 			
       
   414 			this.startSearch();
       
   415 		}
       
   416 	}
       
   417 	//Si c'est a ou A.
       
   418 	else if(event.which == 65 || event.which == 97)
       
   419 	{
       
   420 		if(!this.helpDisplayed)
       
   421 		{
       
   422 			this.notifyHelp();
       
   423 		}
       
   424 		else
       
   425 		{
       
   426 			this.removeHelp();
       
   427 		}
       
   428 	}
       
   429 	//Si c'est v ou V.
       
   430 	else if(event.which == 86 || event.which == 118)
       
   431 	{
       
   432 		this.notifySearchMarkers('run;jump;fall');
       
   433 	}
       
   434 	//Si c'est b ou B.
       
   435 	else if(event.which == 66 || event.which == 98)
       
   436 	{
       
   437 		this.removeSearchMarkers();
       
   438 	}
       
   439 	//Si c'est k ou K.
       
   440 	else if(event.which == 75 || event.which == 107)
       
   441 	{
       
   442 		this.searchFilter('circle');
       
   443 	}
       
   444 	//Si c'est l ou L.
       
   445 	else if(event.which == 76 || event.which == 108)
       
   446 	{
       
   447 		this.removeFilter();
       
   448 	}
       
   449 	//Si on a appuié sur la touche 'q' ou 'Q';
       
   450 	else if(event.which == 113 || event.which == 81)
       
   451 	{
       
   452 		this.unzoom();
       
   453 	}
       
   454 	else if(event.which == 111 || event.which == 79)
       
   455 	{
       
   456 		if(this.snapshotsToShow > this.imagesToShow)
       
   457 		{
       
   458 			this.snapshotsToShow = this.imagesToShow;
       
   459 		}
       
   460 		else
       
   461 		{
       
   462 			this.snapshotsToShow += 5;
       
   463 		}
       
   464 		
       
   465 		this.showNImages(this.snapshotsToShow);
       
   466 	}
   194 }
   467 }
   195 
   468 
   196 /*
   469 /*
   197  * Zoom sur la position d'une image, 1ère partie. Durant le laps de temps de time ms, l'utilisateur a le choix de zoomer sur une autre image.
   470  * Zoom sur la position d'une image, 1ère partie. Durant le laps de temps de time ms, l'utilisateur a le choix de zoomer sur une autre image.
   198  * Après ce laps de temps, l'image zoom complétement et il n'est plus possible de sélectionner une autre image par pointage.
   471  * Après ce laps de temps, l'image zoom complétement et il n'est plus possible de sélectionner une autre image par pointage.
   206 	
   479 	
   207 	//On enlève les notifications initiales si elles existent.
   480 	//On enlève les notifications initiales si elles existent.
   208 	this.removeSelectionSearchMosaicFull();
   481 	this.removeSelectionSearchMosaicFull();
   209 	
   482 	
   210     //Mosaïque.
   483     //Mosaïque.
   211     var mosaic = this;
   484     var _this = this;
   212     //Dimensions de la mosaïque.
   485     //Dimensions de la mosaïque.
   213     var h = this.height, w = this.width;
   486     var h = this.height, w = this.width;
   214     //Longueur en images, nombre d'images et taille de bordure de la mosaïque.
   487     //Longueur en images, nombre d'images et taille de bordure de la mosaïque.
   215     var len = this.length, imgs = this.imagesToShow, margin = this.marginWidth;
   488     var len = this.config['length'], imgs = this.config['imagesToShow'], margin = this.marginWidth;
   216     //Dimensions et position d'un snapshot dans la mosaïque.
   489     //Dimensions et position d'un snapshot dans la mosaïque.
   217     var snHeight = this.snapshotHeight, snWidth = this.snapshotWidth;
   490     var snHeight = this.snapshotHeight, snWidth = this.snapshotWidth;
   218     var sTop = snapshot.position().top, sLeft = snapshot.position().left;
   491     var sTop = snapshot.position().top, sLeft = snapshot.position().left;
   219     var prezoomPercentage = this.prezoomPercentage;
   492     var prezoomPercentage = this.config['prezoomPercentage'];
   220     
   493     
   221     //ID de l'image actuelle.
   494     //ID de l'image actuelle.
   222     var currentId = $('img', snapshot).attr('id');
   495     var currentId = $('img', snapshot).attr('id');
   223     
   496     
   224     //Si un zoom est déjà en cours, on ne zoom sur rien d'autre en attendant que ce snapshot ai dézoomé en cas de mouseleave.
   497     //Si un zoom est déjà en cours, on ne zoom sur rien d'autre en attendant que ce snapshot ai dézoomé en cas de mouseleave.
   295         {
   568         {
   296             width: finalDivWidth + margin,
   569             width: finalDivWidth + margin,
   297             height: finalDivHeight - margin*2,
   570             height: finalDivHeight - margin*2,
   298             top: finalDivTop + margin,
   571             top: finalDivTop + margin,
   299             left: finalDivLeft + margin
   572             left: finalDivLeft + margin
   300         }, this.preZoomTime);
   573         }, _this.config['timePrezoom']);
   301         $('#prezoomContainer-' + currentId).animate(
   574         $('#prezoomContainer-' + currentId).animate(
   302         {
   575         {
   303             width: finalDivWidth + margin*2,
   576             width: finalDivWidth + margin*2,
   304             height: finalDivHeight - margin,
   577             height: finalDivHeight - margin,
   305             top: finalDivTop + margin,
   578             top: finalDivTop + margin,
   306             left: finalDivLeft
   579             left: finalDivLeft
   307         }, this.preZoomTime, function()
   580         }, _this.config['timePrezoom'], function()
   308 		{
   581 		{
   309 			mosaic.notifyPointMosaicPrezoom();
   582 			_this.notifyPointMosaicPrezoom();
   310 		});
   583 		});
   311     });
   584     });
   312     
   585     
   313     //Si on clique sur le snapshot prézoomé, on enclenche un zoom total sur ce snapshot.
   586     //Si on clique sur le snapshot prézoomé, on enclenche un zoom total sur ce snapshot.
   314     $('#prezoomContainer-' + currentId).click(function ()
   587     $('#prezoomContainer-' + currentId).click(function ()
   315     {
   588     {
   316         if(this.previousZoomedSN != '')
   589         if(this.previousZoomedSN != '')
   317 		{
   590 		{
   318             mosaic.zoom();
   591             _this.zoom();
   319 		}
   592 		}
   320     });
   593     });
   321 }
   594 }
   322 
   595 
   323 /*
   596 /*
   344     {
   617     {
   345         width: this.snapshotWidth,
   618         width: this.snapshotWidth,
   346         height: this.snapshotHeight,
   619         height: this.snapshotHeight,
   347         top: this.previousZoomedSN.position().top,
   620         top: this.previousZoomedSN.position().top,
   348         left: this.previousZoomedSN.position().left
   621         left: this.previousZoomedSN.position().left
   349     }, this.preUnzoomTime);
   622     }, this.config['preUnzoomTime']);
   350     $('#prezoomContainer-' + id).animate(
   623     $('#prezoomContainer-' + id).animate(
   351     {
   624     {
   352         width: this.snapshotWidth + margin,
   625         width: this.snapshotWidth + margin,
   353         height: this.snapshotHeight + margin,
   626         height: this.snapshotHeight + margin,
   354         top: this.previousZoomedSN.position().top,
   627         top: this.previousZoomedSN.position().top,
   355         left: this.previousZoomedSN.position().left
   628         left: this.previousZoomedSN.position().left
   356     }, this.preUnzoomTime, function(){ $(this).remove(); this.zoomed = false; });
   629     }, this.config['preUnzoomTime'], function(){ $(this).remove(); this.zoomed = false; });
   357 }
   630 }
   358 
   631 
   359 
   632 
   360 /*
   633 /*
   361  * Zoom d'un snapshot en plein écran.
   634  * Zoom d'un snapshot en plein écran.
   362  */
   635  */
   363 mosaic.prototype.zoom = function()
   636 mosaic.prototype.zoom = function()
   364 {
   637 {
   365     var mos = this;
   638     var _this = this;
   366     
   639     
   367     //Si la mosaïque est en pleine écran, pas la peine de zoomer.
   640     //Si la mosaïque est en pleine écran, pas la peine de zoomer.
   368     if(this.fullscreen)
   641     if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH")
   369 	{
   642 	{
   370         return;
   643         return;
   371 	}
   644 	}
   372 	
   645 	
   373 	this.removePointMosaicPrezoom();
   646 	this.removePointMosaicPrezoom();
   374     
   647     
   375     //On prend les attributs nécessaires au calculs.
   648     //On prend les attributs nécessaires au calculs.
   376     var margin = this.marginWidth, len = this.length, imgs = this.imagesToShow;
   649     var margin = this.marginWidth, len = this.config['length'], imgs = this.config['imagesToShow'], zoomedMargin = this.config['zoomedMargin'];
       
   650 	var zoomPercentage = this.config['zoomPercentage'];
   377     var initMPWidth = this.previousZoomedSN.width() * len + margin*len, initMPHeight = this.previousZoomedSN.height() * (imgs / len) + margin*(imgs / len);
   651     var initMPWidth = this.previousZoomedSN.width() * len + margin*len, initMPHeight = this.previousZoomedSN.height() * (imgs / len) + margin*(imgs / len);
   378     var newMPWidth = initMPWidth * len + this.zoomedMargin * (len), newMPHeight = initMPHeight * (imgs / len) + this.zoomedMargin * ((imgs / len));
   652     var newMPWidth = initMPWidth * len + zoomedMargin * (len), newMPHeight = initMPHeight * (imgs / len) + zoomedMargin * ((imgs / len));
   379     var newPreMPWidth = initMPWidth * len * this.zoomPercentage + this.zoomedMargin * (len), newPreMPHeight = initMPHeight * (imgs / len) * this.zoomPercentage + this.zoomedMargin * ((imgs / len));
   653     var newPreMPWidth = initMPWidth * len * zoomPercentage + zoomedMargin * (len), newPreMPHeight = initMPHeight * (imgs / len) * zoomPercentage + zoomedMargin * ((imgs / len));
   380     
   654     
   381     //Dimensions et coordonnées initiales du div sur lequel on zoom.
   655     //Dimensions et coordonnées initiales du div sur lequel on zoom.
   382     var initialDivWidth = this.previousZoomedSN.width(), initialDivHeight = this.previousZoomedSN.height();
   656     var initialDivWidth = this.previousZoomedSN.width(), initialDivHeight = this.previousZoomedSN.height();
   383     var initialDivTop = this.previousZoomedSN.position().top, initialDivLeft = this.previousZoomedSN.position().left;
   657     var initialDivTop = this.previousZoomedSN.position().top, initialDivLeft = this.previousZoomedSN.position().left;
   384     //Dimensions et coordonnées finales du div.
   658     //Dimensions et coordonnées finales du div.
   385     var finalDivWidth = initialDivWidth * (this.zoomPercentage+1), finalDivHeight = initialDivHeight * (this.zoomPercentage+1);
   659     var finalDivWidth = initialDivWidth * (zoomPercentage+1), finalDivHeight = initialDivHeight * (zoomPercentage+1);
   386     var newZoomTop = -this.previousZoomedSN.position().top*(newPreMPHeight/initMPHeight) - this.zoomedMargin/2 + (initMPHeight - initMPHeight * this.zoomPercentage)/2, newZoomLeft = -this.previousZoomedSN.position().left*(newPreMPWidth/initMPWidth) - this.zoomedMargin/2 + (initMPWidth - initMPWidth * this.zoomPercentage)/2;
   660     var newZoomTop = -this.previousZoomedSN.position().top*(newPreMPHeight/initMPHeight) - zoomedMargin/2 + (initMPHeight - initMPHeight * zoomPercentage)/2, newZoomLeft = -this.previousZoomedSN.position().left*(newPreMPWidth/initMPWidth) - zoomedMargin/2 + (initMPWidth - initMPWidth * zoomPercentage)/2;
   387     var newSnWidth = initMPWidth * this.zoomPercentage, newSnHeight = initMPHeight * this.zoomPercentage;
   661     var newSnWidth = initMPWidth * zoomPercentage, newSnHeight = initMPHeight * zoomPercentage;
   388     
   662     
   389     this.preUnzoom(this);
   663     this.preUnzoom(this);
   390     /*SINGULARITE*/
   664     /*SINGULARITE*/
   391     this.fullscreen = true;
   665     this.fullscreen = true;
   392     
   666     
   395     var src = zoomedImg.attr('src');
   669     var src = zoomedImg.attr('src');
   396     zoomedImg.attr('src', src.replace('-little/', '/'));
   670     zoomedImg.attr('src', src.replace('-little/', '/'));
   397     
   671     
   398     //On récupère son ID.
   672     //On récupère son ID.
   399     var tab, zoomedImgId;
   673     var tab, zoomedImgId;
   400     tab = mos.previousId.split('-');
   674     tab = _this.previousId.split('-');
   401     zoomedImgId = tab[1];
   675     zoomedImgId = tab[1];
   402 
   676 	
   403     //Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
   677 	//On donne les dimensions des snapshots.
   404     $('.snapshotDivs').animate(
   678 	$('.snapshotDivs').animate(
   405     {
   679 	{
   406         width: newSnWidth,
   680 		width: newSnWidth,
   407         height: newSnHeight,
   681 		height: newSnHeight,
   408         margin: this.zoomedMargin/2 + 'px',
   682 		margin: zoomedMargin/2 + 'px',
   409         opacity: '0.4'
   683 	}, this.config['zoomTime']);
   410     }, this.zoomTime);
   684 	
   411     //Le snapshot du milieu revient à une opacité optimale, ce qui attire l'attention de l'utilisateur.
   685 	if(this.currentMode != 'NO-USER')
   412     $(this.previousZoomedSN).animate(
   686 	{
   413     {
   687 		//Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
   414         opacity: '1'
   688 		$('.snapshotDivs').animate(
   415     }, this.zoomTime);
   689 		{
       
   690 			opacity: '0.4'
       
   691 		}, this.config['zoomTime']);
       
   692 		//Le snapshot du milieu revient à une opacité optimale, ce qui attire l'attention de l'utilisateur.
       
   693 		$(this.previousZoomedSN).animate(
       
   694 		{
       
   695 			opacity: '1'
       
   696 		}, this.config['zoomTime']);
       
   697 	}
       
   698 	
   416     //On zoome sur la mosaïque.
   699     //On zoome sur la mosaïque.
   417     $('#mainPanel').animate(
   700     $('#mainPanel').animate(
   418     {
   701     {
   419         width: newPreMPWidth,
   702         width: newPreMPWidth,
   420         height: newPreMPHeight,
   703         height: newPreMPHeight,
   421         top: newZoomTop,
   704         top: newZoomTop,
   422         left: newZoomLeft
   705         left: newZoomLeft
   423     }, this.zoomTime, function()
   706     }, this.config['zoomTime'], function()
   424     {
   707     {
   425         //On charge les interactions avec les voisins.
   708         //On charge les interactions avec les voisins.
   426         mos.centerId = zoomedImgId;
   709         _this.centerId = zoomedImgId;
   427         mos.listenToNeighbours();
   710 		
   428         mos.currentMode = 'VIDEO';
   711 		if(_this.currentMode != "NO-USER")
   429 		
   712 		{
   430 		console.log('h : ' + -newZoomLeft + " " + zoomedImg.position().left);
   713 			_this.currentMode = 'VIDEO';
   431 
   714 			_this.listenToNeighbours();
   432 		mos.snTop = (zoomedImg.position().top + newZoomTop + mos.MPTop_margin), mos.snLeft = (zoomedImg.position().left + newZoomLeft);
   715 		}
   433 		mos.snWidth = newSnWidth + 1, mos.snHeight = newSnHeight + 1;
   716 		
   434 		
   717 		_this.snTop = (zoomedImg.position().top + newZoomTop + _this.MPTop_margin), _this.snLeft = (zoomedImg.position().left + newZoomLeft);
   435 		mos.loadPlayer(mos.snTop, mos.snLeft, mos.snWidth, mos.snHeight, newZoomTop, newZoomLeft);
   718 		_this.snWidth = newSnWidth + 1, _this.snHeight = newSnHeight + 1;
   436 		
   719 		
   437         /*mos.unload();
   720 		_this.notifyTopVideo = newZoomTop;
   438         mos.localMos.loadLocalMosaic(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, mos.imgs, tab[1]);*/
   721 		_this.notifyLeftVideo = newZoomLeft;
       
   722 		
       
   723 		_this.loadPlayer(_this.snTop, _this.snLeft, _this.snWidth, _this.snHeight, newZoomTop, newZoomLeft);
   439     });
   724     });
   440 }
   725 }
   441 
   726 
   442 /*
   727 /*
   443  * Chargement du player basé sur le metadataplayer.
   728  * Chargement du player basé sur le metadataplayer.
   444 */
   729 */
   445 mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft)
   730 mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft)
   446 {
   731 {
       
   732 	var _this = this;
       
   733 	
   447 	//On configure les options de lancement.
   734 	//On configure les options de lancement.
   448 	IriSP.libFiles.defaultDir = "../lib/";
   735 	IriSP.libFiles.defaultDir = "../lib/";
   449 	IriSP.widgetsDir = "./player/metadataplayer/"
   736 	IriSP.widgetsDir = "./player/metadataplayer/"
   450 	
   737 	
   451 	var videoToPlay = this.videos[this.centerId];
   738 	var videoToPlay = this.videos[this.centerId];
   452 	var currentMetadata = this.urls[this.centerId];
   739 	var currentMetadata = this.urls[this.centerId];
   453 	console.log('VIDEO[' + this.centerId + '] : ' + videoToPlay);
       
   454 	console.log('MD[' + this.centerId + '] : ' + currentMetadata);
       
   455 	
   740 	
   456 	var _metadata = {
   741 	var _metadata = {
   457 		url: currentMetadata,
   742 		url: currentMetadata,
   458 		format: 'ldt'
   743 		format: 'ldt'
   459 	};
   744 	};
   460 	console.log(zoomTop + " m" + this.marginWidth);
   745 	
   461 	var _config = {
   746 	var _config = {
   462 		gui: {
   747 		gui: {
   463 			zoomTop: zoomTop - this.marginWidth*2,
   748 			zoomTop: zoomTop - this.marginWidth*2,
   464 			zoomLeft: zoomLeft,
   749 			zoomLeft: zoomLeft,
   465 			width: newSnWidth,
   750 			width: newSnWidth,
   496 	});
   781 	});
   497 	
   782 	
   498 	//On démarre le player.
   783 	//On démarre le player.
   499 	this.player = null;
   784 	this.player = null;
   500 	this.player = new IriSP.Metadataplayer(_config, _metadata);
   785 	this.player = new IriSP.Metadataplayer(_config, _metadata);
       
   786 	
       
   787 	if(this.currentMode == 'NO-USER')
       
   788 	{
       
   789 		this.player.onLoad(function()
       
   790 		{
       
   791 			console.log(_this.player);
       
   792 			console.log(_this.player.popcorn);
       
   793 			//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
       
   794 			if(_this.player.popcorn != undefined)
       
   795 			{
       
   796 				_this.player.popcorn.listen('pause', function()
       
   797 				{
       
   798 					_this.unzoom();
       
   799 				});
       
   800 			}
       
   801 		});
       
   802 	}
   501 }
   803 }
   502 
   804 
   503 /*
   805 /*
   504  * Retour à la taille normale de la mosaïque.
   806  * Retour à la taille normale de la mosaïque.
   505  */
   807  */
   506 mosaic.prototype.unzoom = function()
   808 mosaic.prototype.unzoom = function()
   507 {
   809 {
   508     //Si on n'est pas en plein écran, on quitte.
   810     //Si on n'est pas en plein écran, on quitte.
   509     if(!this.fullscreen)
   811 	console.log("'" + this.currentMode + "'");
       
   812     if(this.currentMode != "SEARCH" && this.currentMode != "VIDEO" && this.currentMode != "NO-USER" && this.currentMode.indexOf("INCOMING") == -1)
   510 	{
   813 	{
   511         return;
   814         return;
   512 	}
   815 	}
   513 	
   816 	
   514 	this.snTop = 0;
   817 	this.snTop = 0;
   517 	this.snHeight = 0;
   820 	this.snHeight = 0;
   518     
   821     
   519     //On charge les attributs nécessaires aux calculs.
   822     //On charge les attributs nécessaires aux calculs.
   520     var sWidth = this.snapshotWidth, sHeight = this.snapshotHeight;
   823     var sWidth = this.snapshotWidth, sHeight = this.snapshotHeight;
   521     var mpWidth = this.width, mpHeight = this.height;
   824     var mpWidth = this.width, mpHeight = this.height;
   522     var mos = this;
   825     var _this = this;
   523     
   826     
   524     //On passe le snapshot sur lequel on a zoomé en SD.
   827     //On passe le snapshot sur lequel on a zoomé en SD.
   525     var zoomedImg = $('img', this.previousZoomedSN);
   828     var zoomedImg = $('img', this.previousZoomedSN);
   526     var src = zoomedImg.attr('src');
   829     var src = zoomedImg.attr('src');
   527     zoomedImg.attr('src', src.replace('snapshots/', 'snapshots-little/'));
   830     zoomedImg.attr('src', src.replace('snapshots/', 'snapshots-little/'));
   528 	
   831 	
   529 	mos.player.widgets[0].freePlayer();
   832 	_this.player.widgets[0].freePlayer();
   530 	$('.LdtPlayer').remove();
   833 	$('.LdtPlayer').remove();
   531 	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
   834 	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
       
   835 	_this.reaffectKeyPress();
   532     
   836     
   533     //On rend leur opacité aux snapshots. Qui ne sont alors plus grisés.
   837     //On rend leur opacité aux snapshots. Qui ne sont alors plus grisés.
   534     $('.snapshotDivs').animate(
   838     $('.snapshotDivs').animate(
   535     {
   839     {
   536         width: sWidth,
   840         width: sWidth,
   537         height: sHeight,
   841         height: sHeight,
   538         margin: this.marginWidth/2 + 'px',
   842         margin: this.marginWidth/2 + 'px'
   539         opacity: '1'
   843     }, this.config['unzoomTime']);
   540     }, this.unzoomTime);
   844 	
       
   845 	if(this.currentMode != 'NO-USER')
       
   846 	{
       
   847 		if(this.currentMode.indexOf("INCOMING") == -1)
       
   848 		{
       
   849 			$('.snapshotDivs').animate(
       
   850 			{
       
   851 				opacity: '1'
       
   852 			}, this.config['unzoomTime']);
       
   853 		}
       
   854 	}
       
   855 	else
       
   856 	{
       
   857 		console.log('init');
       
   858 		this.previousZoomedSN.fadeTo(this.config['unzoomTime'], 0, function()
       
   859 		{
       
   860 			_this.init();
       
   861 		});
       
   862 	}
       
   863 	
   541     //On dézoom sur la mosaïque.
   864     //On dézoom sur la mosaïque.
   542     $('#mainPanel').animate(
   865     $('#mainPanel').animate(
   543     {
   866     {
   544         width: mpWidth,
   867         width: mpWidth,
   545         height: mpHeight,
   868         height: mpHeight,
   546         top: '0px',
   869         top: '0px',
   547         left: '0px'
   870         left: '0px'
   548     }, this.unzoomTime, function()
   871     }, this.config['unzoomTime'], function()
   549     {
   872     {
   550         //On n'est plus en plein écran, et on ne peut plus se déplacer vers le prochain voisin.
   873         //On n'est plus en plein écran, et on ne peut plus se déplacer vers le prochain voisin.
   551         mos.fullscreen = false;
   874         _this.fullscreen = false;
   552         mos.canMoveToNeighbour = false;
   875         _this.canMoveToNeighbour = false;
   553         //On revient en mode MOSAIC.
   876 		
   554         mos.currentMode = 'MOSAIC';
   877 		if(_this.currentMode != 'NO-USER')
   555         //On ne permet plus le déplacement vers les voisins.
   878 		{
   556         $('.snapshotDivs').unbind('mouseenter', mos.selectNeighbour);
   879 			//On revient en mode MOSAIC.
   557 		//On remet les notifications initiales.
   880 			_this.currentMode = 'MOSAIC';
   558 		mos.notifySelectionSearchMosaicFull();
   881 			//On ne permet plus le déplacement vers les voisins.
       
   882 			$('.snapshotDivs').unbind('mouseover', function()
       
   883 			{
       
   884 				_this.selectNeighbour();
       
   885 			});
       
   886 			//On remet les notifications initiales.
       
   887 			_this.notifySelectionSearchMosaicFull();
       
   888 		}
   559     });
   889     });
   560 }
   890 }
   561 
   891 
   562 /*
   892 /*
   563  * Affecte les listeners mouseenter aux voisins lors d'une vue en plein écran.
   893  * Affecte les listeners mouseenter aux voisins lors d'une vue en plein écran.
   564  */
   894  */
   565 mosaic.prototype.listenToNeighbours = function()
   895 mosaic.prototype.listenToNeighbours = function()
   566 {
   896 {
   567     ////TEST
   897     ////TEST
   568     //$('.test').empty();
   898     //$('.test').empty();
   569     this.canMoveToNeighbour = false;
   899     var _this = this;
   570     var currentLine = Math.floor(this.centerId / this.length), currentColumn = this.centerId % this.length;
   900     
       
   901 	this.canMoveToNeighbour = false;
       
   902     var currentLine = Math.floor(this.centerId / this.config['length']), currentColumn = this.centerId % this.config['length'];
   571     var zoomedImg = $('img', this.previousZoomedSN);
   903     var zoomedImg = $('img', this.previousZoomedSN);
   572     var mos = this;
       
   573     
   904     
   574     //On cherche l'ID des voisins.
   905     //On cherche l'ID des voisins.
   575     //Si le voisin de gauche est sur la même ligne, on n'est pas sur la bordure de gauche.
   906     //Si le voisin de gauche est sur la même ligne, on n'est pas sur la bordure de gauche.
   576     this.neighboursIds[0] = (currentColumn > 0) ? (this.centerId - 1) : -1;
   907     this.neighboursIds[0] = (currentColumn > 0) ? (this.centerId - 1) : -1;
   577     //Si le voisin de droite est sur la même ligne, on n'est pas sur la bordure de droite.
   908     //Si le voisin de droite est sur la même ligne, on n'est pas sur la bordure de droite.
   578     this.neighboursIds[1] = (currentColumn < this.length) ? (+this.centerId + 1) : -1;
   909     this.neighboursIds[1] = (currentColumn < this.config['length']) ? (+this.centerId + 1) : -1;
   579     //Si le voisin du haut est sur la même colonne, on n'est pas sur la bordure du haut.
   910     //Si le voisin du haut est sur la même colonne, on n'est pas sur la bordure du haut.
   580     this.neighboursIds[2] = (currentLine > 0) ? (this.centerId - this.length) : -1;
   911     this.neighboursIds[2] = (currentLine > 0) ? (this.centerId - this.config['length']) : -1;
   581     //Si le voisin du bas est sur la même colonne, on n'est pas sur la bordure du bas.
   912     //Si le voisin du bas est sur la même colonne, on n'est pas sur la bordure du bas.
   582     this.neighboursIds[3] = (currentLine < (this.imagesToShow / this.length)) ? (+this.centerId + this.length) : -1;
   913     this.neighboursIds[3] = (currentLine < (this.config['imagesToShow'] / this.config['length'])) ? (+this.centerId + this.config['length']) : -1;
   583     
   914     
   584 	//ID du cadre voisin.
   915 	//ID du cadre voisin.
   585 	var preId;
   916 	var preId;
   586 	
   917 	
   587     for(var i = 0 ; i < this.neighboursIds.length ; i++)
   918     for(var i = 0 ; i < this.neighboursIds.length ; i++)
   589         if(this.neighboursIds[i] != -1)
   920         if(this.neighboursIds[i] != -1)
   590         {
   921         {
   591 			preId = '#neighbourFrameBorder-' + this.neighboursIds[i];
   922 			preId = '#neighbourFrameBorder-' + this.neighboursIds[i];
   592             //On permet le déplacement vers les voisins.
   923             //On permet le déplacement vers les voisins.
   593             // $('#snapshotDiv-' + this.neighboursIds[i] + ', ' + preId + '-left,' + preId + '-right,' + preId + '-up,' + preId + '-down').mouseenter(mos.selectNeighbour);
   924             // $('#snapshotDiv-' + this.neighboursIds[i] + ', ' + preId + '-left,' + preId + '-right,' + preId + '-up,' + preId + '-down').mouseenter(mos.selectNeighbour);
   594             $('#snapshotDiv-' + this.neighboursIds[i]).mouseenter(mos.selectNeighbour);
   925 			
       
   926             $('#snapshotDiv-' + this.neighboursIds[i]).mouseover(function()
       
   927 			{
       
   928 				_this.selectNeighbour($(this));
       
   929 			});
   595         }
   930         }
   596     }
   931     }
   597 }
   932 }
   598 
   933 
   599 /*
   934 /*
   600  * Change la coloration d'une bordure où on se positionne lors d'une vue en plein écran.
   935  * Change la coloration d'une bordure où on se positionne lors d'une vue en plein écran.
   601  */
   936  */
   602 mosaic.prototype.selectNeighbour = function()
   937 mosaic.prototype.selectNeighbour = function(neighbour)
   603 {
   938 {
   604     ////TEST
   939     ////TEST
   605     //$('.test').append(mos.currentMode + " " + $(this).attr('id') + " " + 'snapshotDiv-' + mos.centerId + ',');
   940     //$('.test').append(mos.currentMode + " " + $(this).attr('id') + " " + 'snapshotDiv-' + mos.centerId + ',');
   606     
   941 	var _this = this;
       
   942 	
   607     //Si on est en mode VIDEO (plein écran) ET si le snapshot pointé est un voisin.
   943     //Si on est en mode VIDEO (plein écran) ET si le snapshot pointé est un voisin.
   608     if((mos.currentMode == 'VIDEO') && ($(this).attr('id') != 'snapshotDiv-' + mos.centerId))
   944     
       
   945     if((this.currentMode == 'VIDEO') && (neighbour.attr('id') != 'snapshotDiv-' + this.centerId))
   609     {
   946     {
   610         //On crée le cadre qui va être superposé au voisin.
   947         //On crée le cadre qui va être superposé au voisin.
   611         //On le colle au voisin.
   948         //On le colle au voisin.
   612 		var tab = $(this).attr('id').split('-');
   949 		var tab = neighbour.attr('id').split('-');
   613 		var snapshotId = tab[1];
   950 		var snapshotId = tab[1];
   614         var neighbourFrame = '';
   951         var neighbourFrame = '';
   615 		var marginValue = parseFloat($(this).css('margin'));
   952 		var marginValue = parseFloat(neighbour.css('margin'));
   616 		
   953 		
   617 		neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"><div class="neighbourImgBg" id="neighbourImgBg-' + snapshotId + '"><div class="neighbourImg" id="neighbourImg-' + snapshotId + '"></div></div></div>';
   954 		neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"><div class="neighbourImgBg" id="neighbourImgBg-' + snapshotId + '"><div class="neighbourImg" id="neighbourImg-' + snapshotId + '"></div></div></div>';
   618 		
   955 		
   619         $('#mainPanel').append(neighbourFrame);
   956         $('#mainPanel').append(neighbourFrame);
   620 		
   957 		
   621 		//On positionne le div de background juste au niveau du voisin.
   958 		//On positionne le div de background juste au niveau du voisin.
   622         $('#neighbourFrame-' + snapshotId).css(
   959         $('#neighbourFrame-' + snapshotId).css(
   623 		{
   960 		{
   624 			'top': (+$(this).position().top + marginValue),
   961 			'top': (+neighbour.position().top + marginValue),
   625 			'left': (+$(this).position().left + marginValue),
   962 			'left': (+neighbour.position().left + marginValue),
   626 			'width': $(this).width(),
   963 			'width': neighbour.width(),
   627 			'height': $(this).height()
   964 			'height': neighbour.height()
   628 		});
   965 		});
   629 		//On positionne le div de background noir juste au niveau de l'image du voisin.
   966 		//On positionne le div de background noir juste au niveau de l'image du voisin.
   630         $('#neighbourImgBg-' + snapshotId).css(
   967         $('#neighbourImgBg-' + snapshotId).css(
   631 		{
   968 		{
   632 			'top': marginValue,
   969 			'top': marginValue,
   633 			'left': marginValue,
   970 			'left': marginValue,
   634 			'width': $(this).width() - marginValue*2,
   971 			'width': neighbour.width() - marginValue*2,
   635 			'height': $(this).height() - marginValue*2,
   972 			'height': neighbour.height() - marginValue*2,
   636 		});
   973 		});
   637 		//On met par dessus le div de l'image clonée du voisin.
   974 		//On met par dessus le div de l'image clonée du voisin.
   638 		$('#neighbourImg-' + snapshotId).css(
   975 		$('#neighbourImg-' + snapshotId).css(
   639 		{
   976 		{
   640 			'top': 0,
   977 			'top': 0,
   641 			'left': 0,
   978 			'left': 0,
   642 			'width': $(this).width() - marginValue*2,
   979 			'width': neighbour.width() - marginValue*2,
   643 			'height': $(this).height() - marginValue*2,
   980 			'height': neighbour.height() - marginValue*2,
   644 			'background-image': 'url("' + $('img', $(this)).attr('src') + '")',
   981 			'background-image': 'url("' + $('img', neighbour).attr('src') + '")',
   645 			'background-size': $(this).width() + 'px ' + $(this).height() + 'px',
   982 			'background-size': neighbour.width() + 'px ' + neighbour.height() + 'px',
   646 			'background-position': -marginValue + 'px ' + -marginValue + 'px',
   983 			'background-position': -marginValue + 'px ' + -marginValue + 'px',
   647 			'opacity': '0.4'
   984 			'opacity': '0.4'
   648 		});
   985 		});
   649 		
   986 		
   650 		var fId = '#neighbourFrame-' + snapshotId;
   987 		var fId = '#neighbourFrame-' + snapshotId;
   651 		
   988 		
   652 		$(fId).animate(
   989 		$(fId).animate(
   653         {
   990         {
   654             //On le fait apparaître.
   991             //On le fait apparaître.
   655             opacity: '1'
   992             opacity: '1'
   656         }, timeNeighbourGlowing, function()
   993         }, _this.config['timeNeighbourGlowing'], function()
   657         {
   994         {
   658             //On peut désormais se déplacer vers ce voisin.
   995             //On peut désormais se déplacer vers ce voisin.
   659             mos.canMoveToNeighbour = true;
   996             _this.canMoveToNeighbour = true;
   660         });
   997         });
   661 		//Lorsqu'on quitte un des snapshots (bien entendu le voisin en question), on retire le cadre.
   998 		//Lorsqu'on quitte un des snapshots (bien entendu le voisin en question), on retire le cadre.
   662 		$(fId).mouseleave(mos.deselectNeighbour)
       
   663 		//Si on clique sur le voisin ou son cadre, on passe au voisin suivant.
   999 		//Si on clique sur le voisin ou son cadre, on passe au voisin suivant.
   664 		$(fId).click(mos.moveToNeighbour);
  1000 		$(fId).mouseout(function()
       
  1001 		{
       
  1002 			_this.deselectNeighbour($(this))
       
  1003 		}).click(function()
       
  1004 		{
       
  1005 			_this.moveToNeighbour($(this))
       
  1006 		});
   665     }
  1007     }
   666 }
  1008 }
   667 
  1009 
   668 /*
  1010 /*
   669  * Change la coloration d'une bordure quittée lors d'une vue en plein écran.
  1011  * Change la coloration d'une bordure quittée lors d'une vue en plein écran.
   670  */
  1012  */
   671 mosaic.prototype.deselectNeighbour = function()
  1013 mosaic.prototype.deselectNeighbour = function(neighbour)
   672 {
  1014 {
   673     ////TEST
  1015     ////TEST
   674     //$('.test').append('un,');
  1016     //$('.test').append('un,');
   675 	
  1017 	
   676     //On ne peut plus se déplacer vers les voisins.
  1018     //On ne peut plus se déplacer vers les voisins.
   677     mos.canMoveToNeighbour = false;
  1019     this.canMoveToNeighbour = false;
   678     
  1020     
   679 	//On récupère le voisin.
  1021 	//On récupère le voisin.
   680 	var neighbourFrame = $(this);
  1022 	var neighbourFrame = neighbour;
   681 	
  1023 	
   682     //Si on est en mode VIDEO.
  1024     //Si on est en mode VIDEO.
   683     if(mos.currentMode == 'VIDEO')
  1025     if(this.currentMode == 'VIDEO')
   684     {
  1026     {
   685         //On le fait disparaître progressivement.
  1027         //On le fait disparaître progressivement.
   686         neighbourFrame.animate(
  1028         neighbourFrame.animate(
   687         {
  1029         {
   688             opacity: '0'
  1030             opacity: '0'
   689         }, timeNeighbourUnglowing, function()
  1031         }, this.config['timeNeighbourUnglowing'], function()
   690         {
  1032         {
   691             //Une fois invisible, on le supprime.
  1033             //Une fois invisible, on le supprime.
   692             neighbourFrame.remove();
  1034             neighbourFrame.remove();
   693         });
  1035         });
   694     }
  1036     }
   695 }
  1037 }
   696 
  1038 
   697 /*
  1039 /*
   698  * Lors d'une vue en plein écran, on se déplace vers le voisin dont l'id a été spécifié dans la fonction appelante.
  1040  * Lors d'une vue en plein écran, on se déplace vers le voisin dont l'id a été spécifié dans la fonction appelante.
   699  */
  1041  */
   700 mosaic.prototype.moveToNeighbour = function()
  1042 mosaic.prototype.moveToNeighbour = function(neighbour)
   701 {
  1043 {
       
  1044 	var _this = this;
   702     //Si on ne peut pas se déplacer vers les voisins, on quitte.
  1045     //Si on ne peut pas se déplacer vers les voisins, on quitte.
   703     if(!mos.canMoveToNeighbour)
  1046     if(!_this.canMoveToNeighbour)
   704 	{
  1047 	{
   705         return;
  1048         return;
   706 	}
  1049 	}
   707     
  1050     
   708     //On obtient l'ID de destination.
  1051     //On obtient l'ID de destination.
   709     var tab = $(this).attr('id').split('-');
  1052     var tab = neighbour.attr('id').split('-');
   710     var destinationId = tab[1];
  1053     var destinationId = tab[1];
   711     
  1054     
   712     //On charge les attributs nécessaires aux calculs.
  1055     //On charge les attributs nécessaires aux calculs.
       
  1056 	var length = _this.config['length'];
   713     var MPCurrentTop = $('#mainPanel').position().top, MPCurrentLeft = $('#mainPanel').position().left;
  1057     var MPCurrentTop = $('#mainPanel').position().top, MPCurrentLeft = $('#mainPanel').position().left;
   714     var divideCoeffTop = Math.floor(destinationId / mos.length) == 0 ? 1 : Math.floor(destinationId / mos.length);
  1058     var divideCoeffTop = Math.floor(destinationId / length) == 0 ? 1 : Math.floor(destinationId / length);
   715     var divideCoeffLeft = destinationId % mos.length == 0 ? 1 : destinationId % mos.length;
  1059     var divideCoeffLeft = destinationId % length == 0 ? 1 : destinationId % length;
   716     var neighbourFrameTop = $('#snapshotDiv-' + destinationId).position().top, neighbourFrameLeft = $('#snapshotDiv-' + destinationId).position().left;
  1060     var neighbourFrameTop = $('#snapshotDiv-' + destinationId).position().top, neighbourFrameLeft = $('#snapshotDiv-' + destinationId).position().left;
   717     
  1061     
   718     //On définit pour le déplacement vertical s'il est nécessaire de se déplacer en haut ou en bas.
  1062     //On définit pour le déplacement vertical s'il est nécessaire de se déplacer en haut ou en bas.
   719     if(mos.previousZoomedSN.position().top > neighbourFrameTop)
  1063     if(_this.previousZoomedSN.position().top > neighbourFrameTop)
   720         MPCurrentTop += Math.abs(neighbourFrameTop - mos.previousZoomedSN.position().top);
  1064         MPCurrentTop += Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
   721     else if(mos.previousZoomedSN.position().top < neighbourFrameTop)
  1065     else if(_this.previousZoomedSN.position().top < neighbourFrameTop)
   722         MPCurrentTop -= Math.abs(neighbourFrameTop - mos.previousZoomedSN.position().top);
  1066         MPCurrentTop -= Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
   723     //On définit pour le déplacement horizontal s'il est nécessaire de se déplacer à gauche ou à droite.
  1067     //On définit pour le déplacement horizontal s'il est nécessaire de se déplacer à gauche ou à droite.
   724     if(mos.previousZoomedSN.position().left > neighbourFrameLeft)
  1068     if(_this.previousZoomedSN.position().left > neighbourFrameLeft)
   725         MPCurrentLeft += Math.abs(neighbourFrameLeft - mos.previousZoomedSN.position().left);
  1069         MPCurrentLeft += Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
   726     else if(mos.previousZoomedSN.position().left < neighbourFrameLeft)
  1070     else if(_this.previousZoomedSN.position().left < neighbourFrameLeft)
   727         MPCurrentLeft -= Math.abs(neighbourFrameLeft - mos.previousZoomedSN.position().left);
  1071         MPCurrentLeft -= Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
   728     
  1072     
   729     //On passe le snapshot de destination en HD.
  1073     //On passe le snapshot de destination en HD.
   730     var destinationImg = $('#snapshot-' + destinationId);
  1074     var destinationImg = $('#snapshot-' + destinationId);
   731     var destinationImgSrc = destinationImg.attr('src');
  1075     var destinationImgSrc = destinationImg.attr('src');
   732     destinationImg.attr('src', destinationImgSrc.replace('snapshots-little/', 'snapshots/'));
  1076     destinationImg.attr('src', destinationImgSrc.replace('snapshots-little/', 'snapshots/'));
   733     
  1077     
   734     //On passe l'ancien snapshot en SD.
  1078     //On passe l'ancien snapshot en SD.
   735     var currentImgSrc = $('img', mos.previousZoomedSN).attr('src');
  1079     var currentImgSrc = $('img', _this.previousZoomedSN).attr('src');
   736     $('img', mos.previousZoomedSN).attr('src', currentImgSrc.replace('snapshots/', 'snapshots-little/'));
  1080     $('img', _this.previousZoomedSN).attr('src', currentImgSrc.replace('snapshots/', 'snapshots-little/'));
   737     
  1081     
   738     //On obtient l'ID du div de coloration du snapshot vers lequel on se déplace afin de le supprimer.
  1082     //On obtient l'ID du div de coloration du snapshot vers lequel on se déplace afin de le supprimer.
   739     var neighbourFrame = $(this);
  1083     var neighbourFrame = neighbour;
   740     var tab = neighbourFrame.attr('id').split('-');
  1084     var tab = neighbourFrame.attr('id').split('-');
   741     mos.centerId = tab[1];
  1085     _this.centerId = tab[1];
   742     $(this).css('opacity', '0');
  1086     $(this).css('opacity', '0');
   743     neighbourFrame.remove();
  1087     neighbourFrame.remove();
   744     
  1088     
   745 	mos.player.widgets[0].freePlayer();
  1089 	_this.player.widgets[0].freePlayer();
   746 	$('.LdtPlayer').remove();
  1090 	$('.LdtPlayer').remove();
   747 	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
  1091 	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
       
  1092 	_this.reaffectKeyPress();
   748 	
  1093 	
   749     //On grise le snapshot qu'on vient de quitter.
  1094     //On grise le snapshot qu'on vient de quitter.
   750     mos.previousZoomedSN.animate(
  1095     _this.previousZoomedSN.animate(
   751     {
  1096     {
   752         opacity: '0.4'
  1097         opacity: '0.4'
   753     });
  1098     });
   754     
  1099     
   755     //On se déplace.
  1100     //On se déplace.
   756     $('#mainPanel').animate(
  1101     $('#mainPanel').animate(
   757     {
  1102     {
   758         top: MPCurrentTop,
  1103         top: MPCurrentTop,
   759         left: MPCurrentLeft
  1104         left: MPCurrentLeft
   760     }, timeMovingToNeighbour, function()
  1105     }, _this.config['timeMovingToNeighbour'], function()
   761     {
  1106     {
   762         //On fait apparaître le snapshot vers lequel on s'est déplacé.
  1107         //On fait apparaître le snapshot vers lequel on s'est déplacé.
   763         $('#snapshotDiv-' + destinationId).animate(
  1108         $('#snapshotDiv-' + destinationId).animate(
   764         {
  1109         {
   765             opacity: '1'
  1110             opacity: '1'
   766         }, mos.zoomTime, function()
  1111         }, _this.config['zoomTime'], function()
   767         {
  1112         {
   768             //On recharge les voisins.
  1113             //On recharge les voisins.
   769             $('.snapshotDivs').unbind('mouseenter', mos.selectNeighbour);
  1114             $('.snapshotDivs').unbind('mouseenter', _this.selectNeighbour);
   770             mos.previousZoomedSN = $('#snapshotDiv-' + mos.centerId);
  1115             _this.previousZoomedSN = $('#snapshotDiv-' + _this.centerId);
   771             mos.listenToNeighbours();
  1116             _this.listenToNeighbours();
   772 			
  1117 			
   773 			mos.loadPlayer((destinationImg.position().top + MPCurrentTop + mos.MPTop_margin), (destinationImg.position().left + MPCurrentLeft), destinationImg.width(), destinationImg.height(), MPCurrentTop, MPCurrentLeft);
  1118 			_this.notifyTopVideo = MPCurrentTop;
       
  1119 			_this.notifyLeftVideo = MPCurrentLeft;
       
  1120 			
       
  1121 			_this.loadPlayer((destinationImg.position().top + MPCurrentTop + _this.MPTop_margin), (destinationImg.position().left + MPCurrentLeft), destinationImg.width(), destinationImg.height(), MPCurrentTop, MPCurrentLeft);
   774         });
  1122         });
   775     });
  1123     });
   776 }
  1124 }
   777 
  1125 
   778 /*
  1126 /*
   832 
  1180 
   833 	$.getJSON(path, function(data)
  1181 	$.getJSON(path, function(data)
   834 	{
  1182 	{
   835 		$.each(data, function(key, val)
  1183 		$.each(data, function(key, val)
   836 		{
  1184 		{
   837 			// console.log(val);
       
   838 			$.each(val, function(key_video, val_video)
  1185 			$.each(val, function(key_video, val_video)
   839 			{
  1186 			{
   840 				$.getJSON(val_video.metadata, function(meta)
  1187 				$.getJSON(val_video.metadata, function(meta)
   841 				{
  1188 				{
   842 					_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
  1189 					if(_this.config['local'] == 'true')
   843 					//console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/'));
  1190 					{
       
  1191 						_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://media.iri.centrepompidou.fr/ddc_player/', './player/videos/').replace('mp4:', '').replace('video/', '').replace('ldtplatform/', '').replace('.m4v', '.mp4'));
       
  1192 						console.log(meta.medias[0].url.replace('rtmp://media.iri.centrepompidou.fr/ddc_player/', './player/videos/').replace('mp4:', '').replace('video/', '').replace('ldtplatform/', '').replace('.m4v', '.mp4'));
       
  1193 					}
       
  1194 					else
       
  1195 					{
       
  1196 						_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
       
  1197 						console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
       
  1198 					}
   844 				});
  1199 				});
   845 				
       
   846 				// _this.imgs.push(val_video.snapshot);
       
   847 				// _this.urls.push(val_video.metadata);
       
   848 				_this.imgs[_this.ids[i]] = val_video.snapshot;
  1200 				_this.imgs[_this.ids[i]] = val_video.snapshot;
   849 				_this.urls[_this.ids[i]] = val_video.metadata;
  1201 				_this.urls[_this.ids[i]] = val_video.metadata;
       
  1202 				console.log('ids : ' + _this.ids[i]);
   850 				i++;
  1203 				i++;
   851 			});
  1204 			});
   852 		});
  1205 		});
   853 		console.log('rdy');
  1206 		console.log('rdy');
   854 		_this.loadMosaic();
  1207 		_this.loadMosaic();
   919 /*
  1272 /*
   920  * Affiche la notification de sélection/recherche lorsque la mosaique est complète.
  1273  * Affiche la notification de sélection/recherche lorsque la mosaique est complète.
   921 */
  1274 */
   922 mosaic.prototype.notifySelectionSearchMosaicFull = function()
  1275 mosaic.prototype.notifySelectionSearchMosaicFull = function()
   923 {
  1276 {
       
  1277 	if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") == -1)
       
  1278 	{
       
  1279 		return;
       
  1280 	}
       
  1281 	
   924 	//On spécifie les notifications en div.
  1282 	//On spécifie les notifications en div.
   925 	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
  1283 	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
   926 	var notification_search = "<div id='notify_search' class='notifications'></div>";
  1284 	var notification_search = "<div id='notify_search' class='notifications'></div>";
   927 	
  1285 	
   928 	//On les ajoute à la mosaïque.
  1286 	//On les ajoute à la mosaïque.
   962 /*
  1320 /*
   963  * Affiche la notification de maintient du pointage lors d'une phase de prézoom.
  1321  * Affiche la notification de maintient du pointage lors d'une phase de prézoom.
   964 */
  1322 */
   965 mosaic.prototype.notifyPointMosaicPrezoom = function()
  1323 mosaic.prototype.notifyPointMosaicPrezoom = function()
   966 {
  1324 {
   967 	if($('#notify_point').length > 0)
  1325 	if($('#notify_point').length > 0 || this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") == -1)
   968 	{
  1326 	{
   969 		return;
  1327 		return;
   970 	}
  1328 	}
   971 	
  1329 	
   972 	//On spécifie les notifications en div.
  1330 	//On spécifie les notifications en div.
   973 	var notification_point = "<div id='notify_point' class='notifications'></div>";
  1331 	var notification_point = "<div id='notify_point' class='notifications'></div>";
   974 	
  1332 	
   975 	//On les ajoute à la mosaïque.
  1333 	//On les ajoute à la mosaïque.
   976 	$('#mainPanel').append(notification_point);
  1334 	$('#mainPanel').append(notification_point);
   977 	console.log('Append');
  1335 	
   978 	//On calcule leurs coordonnées et dimensions.
  1336 	//On calcule leurs coordonnées et dimensions.
   979 	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
  1337 	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
   980 	var notify_margin = parseInt($('.notifications').css('margin'));
  1338 	var notify_margin = parseInt($('.notifications').css('margin'));
   981 	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
  1339 	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
   982 	
  1340 	
  1069 	$('#notify_help').css(
  1427 	$('#notify_help').css(
  1070 	{
  1428 	{
  1071 		left: "0px",
  1429 		left: "0px",
  1072 		top: "0px",
  1430 		top: "0px",
  1073 		width: notify_width - notify_margin * 2,
  1431 		width: notify_width - notify_margin * 2,
  1074 		height: notify_height - notify_margin * 2,
  1432 		height: notify_height - notify_margin * 2
  1075 		"margin-top": notify_margin_top
       
  1076 	});
  1433 	});
  1077 	
  1434 	
  1078 	var search_width = $('#help_search').width();
  1435 	var search_width = $('#help_search').width();
  1079 	
  1436 	
  1080 	$('#search_title').html('Recherche');
  1437 	$('#search_title').html('Recherche');
  1130 	{
  1487 	{
  1131 		_this.helpDisplayed = false;
  1488 		_this.helpDisplayed = false;
  1132 		$('#notify_help').remove();
  1489 		$('#notify_help').remove();
  1133 	});
  1490 	});
  1134 }
  1491 }
       
  1492 
       
  1493 /*
       
  1494  * Affiche les types de marqueurs correspondants à ce qu'on a commencé à tracer lors d'une recherche.
       
  1495 */
       
  1496  mosaic.prototype.notifySearchMarkers = function(markersStr)
       
  1497 {
       
  1498 	if($('.notifications_inSearch_container').length > 0)
       
  1499 	{
       
  1500 		return;
       
  1501 	}
       
  1502 	
       
  1503 	console.log(markersStr);
       
  1504 	
       
  1505 	var markersList = markersStr.split(new RegExp(';'));
       
  1506 	
       
  1507 	var notification_search_markers = "<div class='notifications_inSearch_container'>";
       
  1508 	
       
  1509 	//On spécifie les notifications en div.
       
  1510 	for(var i = 0 ; i < markersList.length ; i++)
       
  1511 	{
       
  1512 		notification_search_markers += "<div class='notifications_inSearch' style='background-image: url(./pictos/big/normal/" + markersList[i] + ".png);'></div>";
       
  1513 	}
       
  1514 	
       
  1515 	notification_search_markers += "</div>";
       
  1516 	
       
  1517 	//On les ajoute à la mosaïque.
       
  1518 	$('#mainPanel').append(notification_search_markers);
       
  1519 	
       
  1520 	//On calcule leurs coordonnées et dimensions.
       
  1521 	var notify_width = $('.notifications_inSearch_container').width(), notify_height = $('.notifications_inSearch_container').height();
       
  1522 	var notify_margin = parseInt($('.notifications_inSearch').css('margin'));
       
  1523 	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
       
  1524 	var point_top = 0;
       
  1525 	
       
  1526 	if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH")
       
  1527 	{
       
  1528 		point_top = -this.notifyTopVideo,
       
  1529 		point_left = -this.notifyLeftVideo + ($(window).width() - notify_width) / 2
       
  1530 	}
       
  1531 	
       
  1532 	//On les positionne.
       
  1533 	$('.notifications_inSearch_container').css(
       
  1534 	{
       
  1535 		left: point_left,
       
  1536 		top: point_top
       
  1537 	});
       
  1538 	
       
  1539 	//On les fait apparaître.
       
  1540 	$('.notifications_inSearch').css(
       
  1541 	{
       
  1542 		opacity: "0.9"
       
  1543 	});
       
  1544 }
       
  1545 
       
  1546 /*
       
  1547  * Supprime la notification de maintient du pointage.
       
  1548 */
       
  1549 mosaic.prototype.removeSearchMarkers = function()
       
  1550 {	
       
  1551 	$('.notifications_inSearch_container').remove();
       
  1552 }
       
  1553 
       
  1554 /*
       
  1555  * Effectuer un filtrage de la mosaïque par rapport à un type de marqueurs.
       
  1556 */
       
  1557 mosaic.prototype.searchFilter = function(type)
       
  1558 {
       
  1559 	var _this = this;
       
  1560 	
       
  1561 	if(this.currentMode == "MOSAIC")
       
  1562 	{
       
  1563 		this.currentMode = "FILTER";
       
  1564 		
       
  1565 		if(this.annotations.length > 0)
       
  1566 		{
       
  1567 			var gestureNumberByVideo = new Object();
       
  1568 			var maxAnnotationNumber = 0;
       
  1569 			// for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
       
  1570 			for(var i = 0 ; i < this.annotations.length ; i++)
       
  1571 			{
       
  1572 				var current = this.annotations[i];
       
  1573 				if(current.annotationType.contents.title == type)
       
  1574 				{
       
  1575 					if(gestureNumberByVideo[current.source.url] == undefined || gestureNumberByVideo[current.source.url] == '')
       
  1576 					{
       
  1577 						gestureNumberByVideo[current.source.url] = 0;
       
  1578 					}
       
  1579 					
       
  1580 					gestureNumberByVideo[current.source.url]++;
       
  1581 				}
       
  1582 			}
       
  1583 			
       
  1584 			for(var i = 0 ; i < this.urls.length ; i++)
       
  1585 			{
       
  1586 				if(gestureNumberByVideo[this.urls[i]] == undefined || gestureNumberByVideo[this.urls[i]] == '')
       
  1587 				{
       
  1588 					gestureNumberByVideo[this.urls[i]] = 0;
       
  1589 				}
       
  1590 			}
       
  1591 			
       
  1592 			//On récupère la vidéo qui score le nombre d'occurences de la gesture le plus haut.
       
  1593 			for(i in gestureNumberByVideo)
       
  1594 			{	
       
  1595 				// console.log(i + " " + gestureNumberByVideo[i]);
       
  1596 				if(maxAnnotationNumber < gestureNumberByVideo[i])
       
  1597 				{
       
  1598 					maxAnnotationNumber = gestureNumberByVideo[i];
       
  1599 				}
       
  1600 			}
       
  1601 			
       
  1602 			var snMargin = parseInt($('.snapshotDivs').css('margin'));
       
  1603 			
       
  1604 			//On affiche l'opacité résultante pour chaque vidéo.
       
  1605 			for(i in gestureNumberByVideo)
       
  1606 			{
       
  1607 				//Opacité conventionelle.
       
  1608 				var opacity = gestureNumberByVideo[i] / maxAnnotationNumber;
       
  1609 				// console.log('opacity b : ' + opacity + ' for ' + gestureNumberByVideo[i]);
       
  1610 				//Ce qui est à zéro le restera (par conséquent le snapshot associé sera invisible).
       
  1611 				if(opacity > 0)
       
  1612 				{
       
  1613 					//On réhausse l'opacité de 50%.
       
  1614 					opacity = this.scaleIntervals(0., 1., 0.5, 1., opacity);
       
  1615 				}
       
  1616 				
       
  1617 				var filterIndex = this.getIdxFromMetadata(i);
       
  1618 				
       
  1619 				if(filterIndex >= 0)
       
  1620 				{
       
  1621 					console.log('#snapshotDiv-' + filterIndex + " " + _this.config['timeFilterFade'] + " " + opacity);
       
  1622 					$('#snapshotDiv-' + filterIndex).fadeTo(_this.config['timeFilterFade'], opacity);
       
  1623 					
       
  1624 					if(opacity == 0)
       
  1625 					{
       
  1626 						var filteredSnapshot = $('#snapshotDiv-' + filterIndex);
       
  1627 						
       
  1628 						if(filteredSnapshot.length > 0)
       
  1629 						{
       
  1630 							var hider = '<div id="filterHider-' + filterIndex + '" class="filterHiders"></div>';
       
  1631 							$('#mainPanel').append(hider);
       
  1632 							
       
  1633 							$('#filterHider-' + filterIndex).css(
       
  1634 							{
       
  1635 								width: +filteredSnapshot.width() + 4 * snMargin,
       
  1636 								height: +filteredSnapshot.height() + 4 * snMargin,
       
  1637 								top: filteredSnapshot.position().top - snMargin,
       
  1638 								left: filteredSnapshot.position().left - snMargin
       
  1639 							});
       
  1640 						}
       
  1641 					}
       
  1642 				}
       
  1643 			}
       
  1644 		}
       
  1645 	}
       
  1646 }
       
  1647 
       
  1648 /*
       
  1649  * Passe une valeur de l'intervalle [A, B] à l'intervalle [C, D].
       
  1650 */
       
  1651 mosaic.prototype.scaleIntervals = function(A, B, C, D, val)
       
  1652 {
       
  1653 	return (D - C + A) * val + (C - A);
       
  1654 }
       
  1655 
       
  1656 /*
       
  1657  * Retourne l'index d'un snapshot en fonction de ses metadonnées.
       
  1658 */
       
  1659 mosaic.prototype.getIdxFromMetadata = function(metadata)
       
  1660 {
       
  1661 	var _this = this;
       
  1662 	
       
  1663 	for(idx in this.urls)
       
  1664 	{
       
  1665 		if(this.urls[idx] == metadata)
       
  1666 		{
       
  1667 			for(id in this.ids)
       
  1668 			{
       
  1669 				if(this.ids[id] == idx)
       
  1670 				{
       
  1671 					return id;
       
  1672 				}
       
  1673 			}
       
  1674 		}
       
  1675 	}
       
  1676 	
       
  1677 	return -1;
       
  1678 }
       
  1679 
       
  1680 /*
       
  1681  * Enlève une recherche par filtre.
       
  1682 */
       
  1683 mosaic.prototype.removeFilter = function()
       
  1684 {
       
  1685 	if(this.currentMode == "FILTER")
       
  1686 	{
       
  1687 		this.currentMode = "MOSAIC";
       
  1688 		
       
  1689 		var _this = this;
       
  1690 		
       
  1691 		$('.filterHiders').remove();
       
  1692 		$('.snapshotDivs').fadeTo(_this.config['timeFilterFade'], 1);
       
  1693 	}
       
  1694 }
       
  1695 
       
  1696 /*
       
  1697  * Rebind keypress pour body.
       
  1698 */
       
  1699 mosaic.prototype.reaffectKeyPress = function()
       
  1700 {
       
  1701 	var _this = this;
       
  1702 	
       
  1703 	$('body').keypress(function (event)
       
  1704 	{
       
  1705 		_this.manageControlEvents(event);
       
  1706 	});
       
  1707 }