front_idill/src/mosaic/js/mosaic.js
changeset 44 8393d3473b98
parent 35 4267d6d27a7d
child 45 0e29ae4568a0
--- a/front_idill/src/mosaic/js/mosaic.js	Fri Jun 29 15:46:34 2012 +0200
+++ b/front_idill/src/mosaic/js/mosaic.js	Fri Jun 29 16:16:24 2012 +0200
@@ -24,62 +24,183 @@
  */
 function mosaic(config, default_conf)
 {
+	//Interactions souris/kinect.
+	this.mouseInteractions = false;
+	//Interactions avec/sans préphase.
+	this.prephaseEnabled = true;
+	
+	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run"];
+
 	//Chemin du fichier de configuration.
 	this.config_path = config;
 	//Configuration par défaut en cas de valeur erronnée.
 	this.default_config = default_conf;
-	this.config = new Object();
+	this.config = new Object();
 	//Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
 	this.videos = [];
 	this.urls = [];
+	this.sources = [];
 	this.imgs = [];
+	this.opacities = [];
+	this.timeToGoAt = [];
 	this.ids = [];
 	this.fillingIds = [];
 	this.currentRandomVideoIdx = 0;
-	
+	
+	//Dernières positions des pointeurs.
+	this.mainPointerLastX;
+	this.mainPointerLastY;
+	this.secondPointerLastX;
+	this.secondPointerLastY;
+	//Dernières positions avant le lancement de la fonction d'idle.
+	this.mainPointerIdleStartX;
+	this.mainPointerIdleStartY;
+	this.secondPointerIdleStartX;
+	this.secondPointerIdleStartY;
+	
 	//Dimensions de la mosaïque en pixels.
 	this.width;
-	this.height;
+	this.height;
 	//Dimensions d'un snapshot en pixels.
 	this.snapshotWidth;
-	this.snapshotHeight;
+	this.snapshotHeight;
 	//Espacement entre les snapshots en pixels.
 	this.marginWidth;
-	
+	
 	//Booléens permettant ou non certaines intéractions selon le contexte.
 	this.zoomed;
 	this.fullscreen;
 	this.canMoveToNeighbour;
+	this.mainPointerExitBorder;
+	this.secondPointerExitBorder;
+	this.isMainPointerDisplayed;
+	this.isSecondPointerDisplayed;
 	this.helpDisplayed;
+	//Indique si l'utilisateur a manuellement pausé la vidéo.
+	this.userPaused;
+	//Indique si on est en train de se déplacer vers un voisin.
+	this.currentlyMoving;
+	//Indique si on est en train de dézoomer vers la mosaïque.
+	this.currentlyUnzooming;
+	//Indique si on peut s'approcher de kinect.
+	this.canStart;
+	//Indique si on est actuellement sur un snapshot.
+	this.isOnASnapshot;
+	//Indique si l'idle des pointeurs est disponible (deux mains détectées).
+	this.pointersIdleAvailable;
+	//Indique si le timeout pour l'idle des pointeurs à besoin d'être lancé.
+	this.pointersIdleNeedLaunch;
+	//Indique si les deux mains sont là.
+	this.areBothPointersHere;
+	//Indique si le timeout pour la détection de deux pointeurs a été lancé.
+	this.areBothPointersTimeoutLaunched;
+	//Indique si la mosaïque a été filtrée.
+	this.isMosaicFiltered;
+	//Indique si on est actuellement dans une recherche par gesture.
+	this.isCurrentlyInASearchByGesture;
+	//Indique si un pointeur est déjà sur une notification de recherche par gesture.
+	this.alreadyOnNotification;
+	//Si on a fait un swipe.
+	this.isSwipe;
+	//On peut swiper.
+	this.canSwipe;
+	//On passe vers une autre video automatiquement à la fin d'une lecture.
+	this.autoMove;
+	//Si l'utilisateur a demandé à sélectionner la TL.
+	this.isTLRequested;
+	//Le pointeur gauche a sélectionné la TL.
+	this.isTLSelectedBySecondPointer;
+	//Le pointeur droit a sélectionné la TL.
+	this.isTLSelectedByMainPointer;
+	//On peut afficher l'aide.
+	this.canNotifyHelp;
+	//Indique si la mosaique est en train d'être filtrée.
+	this.isMosaicFiltering;
+	this.arrowLeftLoading = false;
+	this.arrowRightLoading = false;
+	this.arrowUpLoading = false;
+	this.arrowDownLoading = false;
+	//On est dans une recherche par courbes.
+	this.isSearchByCurvesOn;
+	this.canDrawNextCurve = false;
+	
+	//Timeout (attente) pour le zoom après un préZoom.
+	this.zoomTimeout;
+	//Timeout (attente) pour le passage vers un voisin.
+	this.moveToNeighbourTimeout;
+	this.mainPointerExitBorderTimeout;
+	this.secondPointerExitBorderTimeout;
+	//Idle time pour les pointeurs afin d'informer le front qu'on souhaite faire une recherche.
+	this.pointersSearchIdleTimeout;
+	//Vérifie toutes les N ms que les deux pointeurs sont détectés.
+	this.areBothPointersHereTimeout;
+	//Délai de suppression d'une notification de recherche par gesture.
+	this.removeNotificationByGestureTimeout;
+	//Délai de suppression d'une notification de recherche par gesture infructueuse.
+	this.removeFailedNotificationByGestureTimeout;
+	//Délai avant la suppression de notification swipe.
+	this.notifySwipeTimeout;
+	//Délai pour la sélection de la TL.
+	this.selectTLTimeout;
+	//Délai pour slider sur la TL.
+	this.canSlideInTLTimeout;
+	//Délai pour afficher l'aide.
+	this.canNotifyHelpTimeout;
+	this.arrowLeftTimeout;
+	this.arrowRightTimeout;
+	this.arrowUpTimeout;
+	this.arrowDownTimeout;
+	
+	this.arrowSpinnerTimeout;
+	this.nouserTimeout;
+	this.nextDrawCurveTimeout;
+	
+	//Dernier message INCOMING (pour éviter d'effectuer n fois la même action.
+	this.lastIncomingMessage;
 	
 	//Type de marqueur recherché dans la mosaïque (en mode filter).
 	this.filterSearchedType = "";
-	
+	
 	//Mode actuel.
-	this.currentMode = "MOSAIC";
+	this.currentMode = "NO-USER";
 	//Snapshot sur lequel on a zoomé.
-	this.previousZoomedSN;
+	this.previousZoomedSN = null;
 	//Son ID.
-	this.previousId;
+	this.previousId;
+	//Dernier snapshot prézoomé non null.
+	this.lastNonNullSN = null;
 	//Largeur de la marge pour le centrage vertical de la mosaïque.
 	this.MPTop_margin;
-	this.top_margin;
-
+	this.top_margin;
+	
+	//Gesture actuellement cherchée.
+	this.currentSearchGesture;
+
 	//Mosaïque locale.
-	this.localMos;
+	this.localMos;
 	//Position des voisins lors d'un zoom.
-	this.neighboursIds = [];
+	this.neighboursIds = [];
 	//ID du snapshot du milieu lors d'un zoom.
 	this.centerId;
 	
+	//Voisins sélectionnés par les pointeurs.
+	this.mainPointerNeighbourSelectedId = null;
+	this.secondPointerNeighbourSelectedId = null;
+	
 	//Snapshots a afficher.
 	this.snapshotsToShow = 1;
 	
 	//Lecteur.
 	this.player;
+	//Si le lecteur est prêt.
+	this.playerIsReady;
+	
 	//Annotations (pour les marqueurs los d'un filtrage).
 	this.annotations = [];
 	
+	//Client websocket pour recevoir les notifications du Middleware.
+	this.client;
+	
 	//Coordonnées et dimensions d'un snapshot zoomé.
 	this.snTop = 0;
 	this.snLeft = 0;
@@ -99,8 +220,8 @@
  */
 mosaic.prototype.createMosaic = function()
 {
-	console.log('CREATE');
-	this.currentMode = "NO-USER";
+	// console.log('CREATE');
+	// this.currentMode = "NO-USER";
 	var initPanel = '<div id="initPanel"></div>';
 	var mp = $('#mainPanel');
 	mp.append(initPanel);
@@ -119,11 +240,36 @@
 	//S'il s'agit d'un rectangle.
     if(imgs % len == 0)
     {
-		this.previousZoomedSN = '';
-		this.previousPrezoomDiv = '';
+		this.previousZoomedSN = null;
+		this.previousPrezoomDiv = null;
 		this.fullscreen = false;
 		this.canMoveToNeighbour = false;
+		this.currentlyZooming = false;
+		this.currentlyUnzooming = false;
 		this.helpDisplayed = false;
+		this.canStart = false;
+		this.isOnASnapshot = false;
+		this.isMosaicFiltered = false;
+		this.areBothPointersHere = false;
+		this.areBothPointersTimeoutLaunched = false;
+		this.isCurrentlyInASearchByGesture = false;
+		this.alreadyOnNotification = false;
+		this.playerIsReady = false;
+		this.currentSearchGesture = '';
+		this.isMainPointerDisplayed = false;
+		this.isSecondPointerDisplayed = false;
+		this.isSwipe = false;
+		this.canSwipe = false;
+		this.autoMove = false;
+		this.isTLRequested = false;
+		this.isTLSelectedByMainPointer = false;
+		this.isTLSelectedBySecondPointer = false;
+		this.canNotifyHelp = false;
+		this.isMosaicFiltering = false;
+		this.isSearchByCurvesOn = false;
+		
+		this.lastIncomingMessage = 'INCOMING-0';
+		
 		var str = '';
 		
 		if(this.imgs.length >= imgs)
@@ -148,7 +294,7 @@
  */
 mosaic.prototype.loadMosaic = function()
 {
-	console.log('LOAD');
+	// console.log('LOAD');
 	var createMosaic = this.createMosaic();
 	
 	if(createMosaic == '')
@@ -178,14 +324,15 @@
     this.MPTop_margin = ($(document).height() - $('#mainPanel').height())/2;
     $('#mainPanel').css('margin-top', this.MPTop_margin).css('margin-bottom', this.MPTop_margin);
 	
-	//On affiche les notifications.
-	this.notifySelectionSearchMosaicFull();
+	//On fait coincider le background du body avec celui de la mosaïque.
+	$('body').css('background-position', '0px ' + this.MPTop_margin + 'px');
+	console.log(this.MPTop_margin);
 	
-	$('.snapshotDivs').mouseenter(function ()
+	/*$('.snapshotDivs').mouseover(function ()
 	{
 		//On effectue un prézoom dès qu'on va sur une image.
 		_this.preZoom($(this));
-	});
+	});*/
 	
 	this.addPointers();
 	
@@ -208,18 +355,56 @@
 	
 	for (var i = 0; i < nbFichiers; i++)
 	{
-		console.log('url : ' + _this.urls[i]);
-		var source = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt});
-		source.onLoad(function()
+		// console.log('url : ' + _this.urls[i]);
+		_this.sources[i] = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt});
+		_this.sources[i].onLoad(function()
 		{
+			var source = this;
+			// console.log(source);
 			globalAnnotations.addElements(source.getAnnotations());
+			// console.log(source.url + ' ' + source.getAnnotations().length);
 			fichiersCharges++;
 			if (fichiersCharges == nbFichiers)
 			{
 				// instructions à exécuter quand tout est chargé
 				_this.annotations = globalAnnotations;
-				console.log('annotations loaded');
-				_this.init();
+				// console.log(_this.annotations.length + ' ' + nbFichiers);
+				console.log(_this.annotations.length + ' annotations loaded from ' + nbFichiers + ' files.');
+				
+				//Si on gère les interactions à la souris.
+				if(_this.mouseInteractions)
+				{
+					$('body').mousemove(function(e){_this.refreshMainPointer(e.pageX, e.pageY, _this)});
+				}
+				
+				// if(false)
+				// {
+				if(_this.prephaseEnabled)
+				{
+					_this.init();
+					_this.showNImages(0);
+					_this.currentMode = "NO-USER";
+				}
+				else
+				{
+					_this.showNImages(20);
+					_this.currentMode = "MOSAIC";
+				}
+				// }
+				
+				// /!\ //
+				// _this.currentMode = "FILTER";
+				// _this.showNImages(20);
+				//_this.isSearchByCurvesOn = true;
+				// _this.startSearch();
+				// console.log('CANVAS READY');
+				// /!\ //
+				
+				/*_this.currentSearchGesture = 'bend';
+				_this.currentMode = 'FILTER';
+				_this.searchFilter('bend');*/
+				
+				_this.previousZoomedSN = $('#snapshotDiv-' + _this.fillingIds[0]);
 			}
 		});
 	}
@@ -232,7 +417,7 @@
 {
 	var _this = this;
 	
-	var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeFilling', 'zoomedMargin'];
+	var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'zoomTime', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeANFade', 'timeFilling', 'zoomedMargin', 'timeoutZoom', 'timeoutUnzoom', 'timeoutMoveToNeighbour', 'timeoutPointersIdle', 'timeoutAreBothPointersHere', 'timeoutRemoveNotificationByGesture', 'timeoutRemoveFailedNotificationByGesture', 'timeoutNotifySwipe', 'timeoutSelectTL', 'timeoutSlideTL', 'timeoutCanNotifyHelp', 'timeoutRemoveSpinner', 'timeoutNouser', 'timeoutNextDrawCurve'];
 	var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage'];
 	
 	$.getJSON(file_path, function(data)
@@ -246,7 +431,7 @@
 				var intVal = parseInt(val);
 				if(isNaN(intVal))
 				{
-					console.log(_this.default_config);
+					// console.log(_this.default_config);
 					_this.config[key] = _this.default_config[key];
 					console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Int). Valeur par défaut " + _this.default_config[key] + " chargée à la place.");
 				}
@@ -294,14 +479,17 @@
 		
 		if(_this.config['local'] == 'true')
 		{
-			console.log("Loading local metadata.");
+			// console.log("Loading local metadata.");
 			_this.loadFromJson('./player/json/local_videos.json');
 		}
 		else
 		{
-			console.log("Loading online metadata.");
+			// console.log("Loading online metadata.");
 			_this.loadFromJson('./player/json/online_videos.json');
 		}
+		
+		//On initialise le client.
+		_this.client = new client(_this.config['host'], _this.config['port'], _this);
 	});
 }
 
@@ -313,19 +501,22 @@
 mosaic.prototype.init = function()
 {
 	var _this = this;
-	
+
 	if(this.currentRandomVideoIdx > this.config['imagesToShow'])
 	{
 		this.currentRandomVideoIdx = 0;
 	}
 	
+	
 	this.previousZoomedSN = $('#snapshotDiv-' + this.fillingIds[this.currentRandomVideoIdx]);
 	this.previousId = $('img', this.previousZoomedSN).attr('id');
 	
-	console.log('ids', this.fillingIds[this.currentRandomVideoIdx]);
+	// console.log('CURRENT MODE : ' + _this.currentMode);
+	// console.log('ids', this.fillingIds[this.currentRandomVideoIdx]);
 	
 	this.previousZoomedSN.fadeTo(this.config['timePrezoom'], 1, function()
 	{
+		// console.log('CURRENT MODE : ' + _this.currentMode);
 		_this.zoom();
 		_this.currentRandomVideoIdx++;
 	});
@@ -336,38 +527,68 @@
 */
 mosaic.prototype.showNImages = function(n)
 {
-	if(n > 1)
+	if(this.currentlyMoving)
+	{
+		return;
+	}
+	
+	// console.log('INCOMING ----- ' + n);
+	//Si il y a plus d'un snapshot à afficher, on entre dans le mode INCOMING avec en paramètre le nombre à afficher.
+	if(n > 1 && n < this.config['imagesToShow'])
 	{
 		this.currentMode = "INCOMING-" + n;
 		this.unzoom();
+		this.currentSearchGesture = '';
+		$('.notifications').remove();
+		this.isMosaicFiltered = false;
+		this.isCurrentlyInASearchByGesture = false;
+		$('#mainPointer').fadeTo(this.config['timePrezoom'], 0);
+		$('#secondPointer').fadeTo(this.config['timePrezoom'], 0);
+		$('#spinner').remove();
+		this.deselectAllNeighbours();
+		$('.prezoomContainers').remove();
+	}
+	// console.log('n : ' + n);
+	if(n >= this.config['imagesToShow'])
+	{
+		// this.unzoom();
+		if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING-") > -1)
+		{
+			this.currentMode = "INCOMING-20";
+			this.unzoom();
+			this.currentMode = "MOSAIC";
+			$('.notifications').remove();
+			this.mosaicSelectionAndSearch();
+			clearTimeout(this.nouserTimeout);
+			console.log('OK');
+		}
+		//On affiche les notifications.
+		// this.notifySelectionSearchMosaicFull();
+	
+		// $('#mainPointer').fadeTo(this.config['timePrezoom'], 1);
+		// $('#secondPointer').fadeTo(this.config['timePrezoom'], 1);
 	}
 	
+	//Pour les snapshots à afficher.
 	for(var i = 0 ; i < n ; i++)
 	{
-		if($('#snapshotDiv-' + i).css('opacity') < 1)
+		//Si les snapshots ne sont pas affichés.
+		if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') < 1)
 		{
-			$('#snapshotDiv-' + i).fadeTo(this.config['timeFilling'], 1);
+			//On les fait apparaître.
+			$('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config['timeFilling'], '1');
 		}
 	}
-}
-
-/*
- * Affiche les pointeurs.
-*/
-mosaic.prototype.addPointers = function()
-{
-	var _this = this;
-	
-	var mainPointer = '<div id="mainPointer" class="pointers"></div>';
-	$('body').append(mainPointer);
-	$('body').mousemove(function(evt)
+	//Pour ceux à masquer.
+	for(var i = n ; i < this.config['imagesToShow'] ; i++)
 	{
-		$('#mainPointer').css(
+		//Si les snapshots ne sont pas masqués et qu'il ne s'agit pas du dernier snapshot en lecture aléatoire (mode NO-USER).
+		if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') > 0 && this.fillingIds[i] != this.currentRandomVideoIdx)
 		{
-			top: evt.pageY - $('#mainPointer').height()/2,
-			left: evt.pageX - $('#mainPointer').width()/2
-		});
-	});
+			//On les masque.
+			$('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config['timeFilling'], '0');
+		}
+	}
 }
 
 /*
@@ -375,9 +596,20 @@
 */
 mosaic.prototype.manageControlEvents = function(event)
 {
-	console.log('manage');
+	// console.log('manage');
+	
+	var _this = this;
+	
+	if(typeof event === 'undefined')
+	{
+		return;
+	}
+	
+	var gestureReceived = '';
+	
 	//Sinon si on a appuyé sur 'g' ou 'G'.
-	if(event.which == 103 || event.which == 71)
+	// if(event.which == 103 || event.which == 71)
+	/*if(event == "CURVES")
 	{
 		//Si on est déjà en recherche par courbes.
 		if(this.currentMode == "SEARCH" || this.currentMode == "FILTER")
@@ -415,7 +647,8 @@
 		}
 	}
 	//Si c'est a ou A.
-	else if(event.which == 65 || event.which == 97)
+	// else if(event.which == 65 || event.which == 97)
+	else if(event == "HELP")
 	{
 		if(!this.helpDisplayed)
 		{
@@ -427,307 +660,218 @@
 		}
 	}
 	//Si c'est v ou V.
-	else if(event.which == 86 || event.which == 118)
+	// else if(event.which == 86 || event.which == 118)
+	else if(event == "NOTIFY-SEARCH")
 	{
 		this.notifySearchMarkers('run;jump;fall');
 	}
 	//Si c'est b ou B.
-	else if(event.which == 66 || event.which == 98)
+	// else if(event.which == 66 || event.which == 98)
+	else if(event == "REMOVE-SEARCH")
 	{
 		this.removeSearchMarkers();
 	}
 	//Si c'est k ou K.
-	else if(event.which == 75 || event.which == 107)
+	// else if(event.which == 75 || event.which == 107)
+	else if(event == "FILTER")
 	{
 		this.searchFilter('circle');
 	}
 	//Si c'est l ou L.
-	else if(event.which == 76 || event.which == 108)
+	// else if(event.which == 76 || event.which == 108)
+	else if(event == "REMOVE-FILTER")
 	{
 		this.removeFilter();
 	}
 	//Si on a appuié sur la touche 'q' ou 'Q';
-	else if(event.which == 113 || event.which == 81)
+	// else if(event.which == 113 || event.which == 81)
+	else if(event == "UNZOOM")
 	{
 		this.unzoom();
-	}
-	else if(event.which == 111 || event.which == 79)
+	}*/
+	// else if(event.which == 111 || event.which == 79)
+	if(event.indexOf("INCOMING-") != -1 && this.prephaseEnabled)
 	{
-		if(this.snapshotsToShow > this.imagesToShow)
+		// console.log(this.date() + ' ' + event);
+		// console.log('CAN START : ' + this.canStart);
+		if(this.canStart)
 		{
-			this.snapshotsToShow = this.imagesToShow;
-		}
-		else
-		{
-			this.snapshotsToShow += 5;
+			if(this.snapshotsToShow > this.config['imagesToShow'])
+			{
+				this.snapshotsToShow = this.config['imagesToShow'];
+			}
+			else
+			{
+				var params = event.split('-');
+				// console.log(event);
+				this.snapshotsToShow = params[1];
+			}
+			
+			//Si la position de l'utilisateur a changé.
+			if(event != this.lastIncomingMessage)
+			{
+				console.log(this.snapshotsToShow);
+				this.lastIncomingMessage = event;
+				this.showNImages(this.snapshotsToShow);
+			}
 		}
 		
-		this.showNImages(this.snapshotsToShow);
+		clearTimeout(this.nouserTimeout);
+		this.nouserTimeout = setTimeout(function()
+		{
+			/*_this.showNImages(0);
+			_this.init();
+			_this.canStart = false;
+			_this.currentMode = "NO-USER";*/
+			
+				window.location.reload();
+			// mos = new mosaic('./config.json', default_parameters);
+			
+			console.log('NOUSER');
+		}, this.config['timeoutNouser']);
 	}
-}
-
-/*
- * 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.
- * 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.
- */
-mosaic.prototype.preZoom = function(snapshot)
-{
-    if(this.fullscreen)
+	else if((event == "NO-USER" || event == "INCOMING-0" || event == "INCOMING-1") && this.prephaseEnabled)
 	{
-        return;
+		/*this.showNImages(0);
+		this.init();
+		this.canStart = false;
+		this.currentMode = "NO-USER";*/
+		
+			window.location.reload();
+		// mos = new mosaic('./config.json', default_parameters);
+		
+		console.log('NOUSER');
+		
+		/*this.currentMode = "NO-USER";
+		this.showNImages(0);
+		this.canStart = false;
+		this.init();*/
 	}
-	
-	//On enlève les notifications initiales si elles existent.
-	this.removeSelectionSearchMosaicFull();
-	
-    //Mosaïque.
-    var _this = this;
-    //Dimensions de la mosaïque.
-    var h = this.height, w = this.width;
-    //Longueur en images, nombre d'images et taille de bordure de la mosaïque.
-    var len = this.config['length'], imgs = this.config['imagesToShow'], margin = this.marginWidth;
-    //Dimensions et position d'un snapshot dans la mosaïque.
-    var snHeight = this.snapshotHeight, snWidth = this.snapshotWidth;
-    var sTop = snapshot.position().top, sLeft = snapshot.position().left;
-    var prezoomPercentage = this.config['prezoomPercentage'];
-    
-    //ID de l'image actuelle.
-    var currentId = $('img', snapshot).attr('id');
-    
-    //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.
-    if(this.zoomed)
+	// /!\/!\ //
+	else if(event.indexOf("SWIPE") != -1)
 	{
-        if($('#preZoomContainer-' + currentId) != $(this) && this.previousZoomedSN != '' && this.previousId != '')
+		if(this.player && this.player.widgets && this.playerIsReady && !this.isSwipe)
 		{
-            this.preUnzoom();
-		}
-        else
-		{
-            return;
+			this.isSwipe = true;
+			
+			if(this.currentMode == 'SEARCH' && this.isMosaicFiltered && !this.player.widgets[0].isAMarkerAhead(this.currentSearchGesture))
+			{
+				this.playNextVideo();
+			}
+			
+			//L'utilisateur a fait un swipe left.
+			if(event.indexOf("LEFT") != -1)
+			{
+				this.player.widgets[0].switchToMarker(true, this.currentSearchGesture);
+				if(this.currentMode == 'VIDEO')
+				{
+					$('.notifications').remove();
+					this.videoSwipe('left');
+				}
+				else if(this.currentMode == 'SEARCH' && !this.currentSearchGesture)
+				{
+					$('.notifications').remove();
+					this.searchSearchAndSwipe('left');
+				}
+				else if(this.currentMode == 'SEARCH' && this.currentSearchGesture)
+				{
+					$('.notifications').remove();
+					this.searchGestureAndSwipe(this.currentSearchGesture, 'valid', 'left');
+				}
+			}
+			//L'utilisateur a fait un swipe right.
+			else if(event.indexOf("RIGHT") != -1)
+			{
+				this.player.widgets[0].switchToMarker(false, this.currentSearchGesture);
+				if(this.currentMode == 'VIDEO')
+				{
+					$('.notifications').remove();
+					this.videoSwipe('right');
+				}
+				else if(this.currentMode == 'SEARCH' && !this.currentSearchGesture)
+				{
+					$('.notifications').remove();
+					this.searchSearchAndSwipe('right');
+				}
+				else if(this.currentMode == 'SEARCH' && this.currentSearchGesture)
+				{
+					$('.notifications').remove();
+					this.searchGestureAndSwipe(this.currentSearchGesture, 'valid', 'right');
+				}
+			}
+			
+			//On le fait disparaitre au bout d'un certain temps.
+			this.notifySwipeTimeout = setTimeout(function()
+			{
+				_this.isSwipe = false;
+				
+				// /!\ //
+				$('.notifications').remove();
+				
+				if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture)
+				{
+					_this.searchSearch();
+				}
+				else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture)
+				{
+					_this.searchGesture(_this.currentSearchGesture, 'valid');
+				}
+				
+			}, this.config['timeoutNotifySwipe']);
 		}
 	}
-    
-    //On indique qu'on a zoomé et on spécifie le snapshot sur lequel on a zoomé.
-    this.zoomed = true;
-    this.previousZoomedSN = snapshot;
-    this.previousId = currentId;
-    
-    //On récupère les attributs de l'image.
-    var fakeImg = $('img', snapshot);
-    //On forme la balise de la fausse image et on passe son url pour les grands snapshots.
-    fakeImg = '<img id="fake-' + currentId + '" class="snapshots" src="' + fakeImg.attr('src').replace('-little/', '/') + '" />';
-    //On génère un faux snapshot identique au précédent et qu'on va coller dessus.
-    var fakeSnapshot = '<div id="prezoomContainer-' + currentId + '" class="prezoomContainers"><div id="prezoomSnapshot-' + currentId + '" class="snapshotDivs">' + fakeImg + '</div></div>';
-    
-    //On l'ajoute à la mosaïque.
-    $('#mainPanel').append(fakeSnapshot);
-    //On modifie ses attributs.
-    $('#fake-' + currentId).load(function()
-    {
-        $('#prezoomContainer-' + currentId).css('display', 'block');
-        $('#prezoomContainer-' + currentId).css('top', sTop).css('left', sLeft).css('width', (snWidth + margin)).css('height', (snHeight + margin));
-        $('#prezoomSnapshot-' + currentId).css('width', (snWidth)).css('height', (snHeight));
-        
-        //Dimensions et coordonnées initiales du div sur lequel on zoom.
-        var initialDivWidth = $('#prezoomContainer-' + currentId).width(), initialDivHeight = $('#prezoomContainer-' + currentId).height();
-        var initialDivTop = $('#prezoomContainer-' + currentId).position().top, initialDivLeft = $('#prezoomContainer-' + currentId).position().left;
-        //Dimensions et coordonnées finales du div.
-        var finalDivWidth = initialDivWidth * (prezoomPercentage+1), diffWidth = finalDivWidth - initialDivWidth, finalDivHeight = initialDivHeight + diffWidth;
-        var finalDivTop = (initialDivTop - (finalDivHeight - snHeight)/2), finalDivLeft = (initialDivLeft - (finalDivWidth - snWidth)/2);
-        
-        //CAS PARTICULIER pour la position du snapshot zoomé : les bordures.
-        if(finalDivTop < 0)
+	else if(event.indexOf("BEND") != -1 || event.indexOf('KNEE-UP') != -1 || event.indexOf('FALL') != -1 || event.indexOf('JUMP') != -1)
+	{
+		gestureReceived = event.toLowerCase();
+		gestureReceived = gestureReceived.replace('wave', 'hello');
+		this.currentSearchGesture = gestureReceived;
+	}
+	else if(event.indexOf("HELLO") != -1 && this.canNotifyHelp && !this.areBothPointersHere)
+	{
+		if(this.currentMode == 'SEARCH')
 		{
-            finalDivTop = -margin;
-		}
-        if(finalDivTop + finalDivHeight > h)
-		{
-            finalDivTop = h - finalDivHeight;
-		}
-        if(finalDivLeft < 0)
-		{
-            finalDivLeft = 0;
-		}
-        if(finalDivLeft + finalDivWidth + margin*2 > w)
-		{
-            finalDivLeft = w - finalDivWidth - margin*2;
+			this.notifyHelp(false);
 		}
-        
-        ////Code de debug.
-        ////CAUTION////
-        /*var red = '<div id="red"></div>';
-        if($('#red') != null || $('#red') != undefined)
-            $('body').append(red);
-        $('#red').css('background-color', '#FF0000').css('position', 'absolute').css('top', '0px').css('left', '0px').css('width', '100px').css('height', '100px');
-        $('#red').css('top', finalDivTop).css('left', finalDivLeft).css('width', finalDivWidth).css('height', finalDivHeight);*/
-        //alert("initial : " + initialDivWidth + " " + initialDivHeight + " ; final : " + finalDivWidth + " " + finalDivHeight);
-        ////CAUTION////
-        
-        //On prézoom le div en le centrant sur le milieu du snapshot pointé.
-        $('#prezoomSnapshot-' + currentId).animate(
-        {
-            width: finalDivWidth + margin,
-            height: finalDivHeight - margin*2,
-            top: finalDivTop + margin,
-            left: finalDivLeft + margin
-        }, _this.config['timePrezoom']);
-        $('#prezoomContainer-' + currentId).animate(
-        {
-            width: finalDivWidth + margin*2,
-            height: finalDivHeight - margin,
-            top: finalDivTop + margin,
-            left: finalDivLeft
-        }, _this.config['timePrezoom'], function()
+		else if(this.currentMode == 'FILTER')
 		{
-			_this.notifyPointMosaicPrezoom();
-		});
-    });
-    
-    //Si on clique sur le snapshot prézoomé, on enclenche un zoom total sur ce snapshot.
-    $('#prezoomContainer-' + currentId).click(function ()
-    {
-        if(this.previousZoomedSN != '')
-		{
-            _this.zoom();
+			this.notifyHelp(true);
 		}
-    });
-}
-
-/*
- * Dézoome sur la position de l'image. Il est à noter que ce dézoome diffère du dézoom global dans la mesure où celui-ci ne concerne que l'image sur laquelle on a zoomé.
- */
-mosaic.prototype.preUnzoom = function()
-{
-    //Si on n'a pas zoomé, on quitte la fonction.
-    if(!this.zoomed)
-	{
-        return;
 	}
 	
-	this.removePointMosaicPrezoom();
-    
-    //On spécifie la marge afin de centrer le prédézoom.
-    var margin = this.marginWidth;
-    //ID du snapshot précédemment pointé.
-    var id = this.previousId;
-    //On ne zoom plus.
-    this.zoomed = false;
-    //On rétrécit le snapshot de prézoom, puis on le supprime en donnant l'illusion qu'il s'agissait du véritable snapshot, alors qu'en fait c'était un clone.
-    $('#prezoomSnapshot-' + id).animate(
-    {
-        width: this.snapshotWidth,
-        height: this.snapshotHeight,
-        top: this.previousZoomedSN.position().top,
-        left: this.previousZoomedSN.position().left
-    }, this.config['preUnzoomTime']);
-    $('#prezoomContainer-' + id).animate(
-    {
-        width: this.snapshotWidth + margin,
-        height: this.snapshotHeight + margin,
-        top: this.previousZoomedSN.position().top,
-        left: this.previousZoomedSN.position().left
-    }, this.config['preUnzoomTime'], function(){ $(this).remove(); this.zoomed = false; });
-}
-
-
-/*
- * Zoom d'un snapshot en plein écran.
- */
-mosaic.prototype.zoom = function()
-{
-    var _this = this;
-    
-    //Si la mosaïque est en pleine écran, pas la peine de zoomer.
-    if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH")
+	if(gestureReceived != '')
 	{
-        return;
-	}
-	
-	this.removePointMosaicPrezoom();
-    
-    //On prend les attributs nécessaires au calculs.
-    var margin = this.marginWidth, len = this.config['length'], imgs = this.config['imagesToShow'], zoomedMargin = this.config['zoomedMargin'];
-	var zoomPercentage = this.config['zoomPercentage'];
-    var initMPWidth = this.previousZoomedSN.width() * len + margin*len, initMPHeight = this.previousZoomedSN.height() * (imgs / len) + margin*(imgs / len);
-    var newMPWidth = initMPWidth * len + zoomedMargin * (len), newMPHeight = initMPHeight * (imgs / len) + zoomedMargin * ((imgs / len));
-    var newPreMPWidth = initMPWidth * len * zoomPercentage + zoomedMargin * (len), newPreMPHeight = initMPHeight * (imgs / len) * zoomPercentage + zoomedMargin * ((imgs / len));
-    
-    //Dimensions et coordonnées initiales du div sur lequel on zoom.
-    var initialDivWidth = this.previousZoomedSN.width(), initialDivHeight = this.previousZoomedSN.height();
-    var initialDivTop = this.previousZoomedSN.position().top, initialDivLeft = this.previousZoomedSN.position().left;
-    //Dimensions et coordonnées finales du div.
-    var finalDivWidth = initialDivWidth * (zoomPercentage+1), finalDivHeight = initialDivHeight * (zoomPercentage+1);
-    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;
-    var newSnWidth = initMPWidth * zoomPercentage, newSnHeight = initMPHeight * zoomPercentage;
-    
-    this.preUnzoom(this);
-    /*SINGULARITE*/
-    this.fullscreen = true;
-    
-    //On passe l'image du snapshot pointé en HD.
-    var zoomedImg = $('img', this.previousZoomedSN);
-    var src = zoomedImg.attr('src');
-    zoomedImg.attr('src', src.replace('-little/', '/'));
-    
-    //On récupère son ID.
-    var tab, zoomedImgId;
-    tab = _this.previousId.split('-');
-    zoomedImgId = tab[1];
-	
-	//On donne les dimensions des snapshots.
-	$('.snapshotDivs').animate(
-	{
-		width: newSnWidth,
-		height: newSnHeight,
-		margin: zoomedMargin/2 + 'px',
-	}, this.config['zoomTime']);
-	
-	if(this.currentMode != 'NO-USER')
-	{
-		//Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
-		$('.snapshotDivs').animate(
+		if(this.currentMode == "SEARCH" && this.playerIsReady)
 		{
-			opacity: '0.4'
-		}, this.config['zoomTime']);
-		//Le snapshot du milieu revient à une opacité optimale, ce qui attire l'attention de l'utilisateur.
-		$(this.previousZoomedSN).animate(
+			this.player.widgets[0].searchByGesture(gestureReceived);
+			this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture;
+			
+			$('.notifications').remove();
+			this.searchGesture(gestureReceived, 'valid');
+		}
+		else if(this.currentMode == "FILTER")
 		{
-			opacity: '1'
-		}, this.config['zoomTime']);
-	}
-	
-    //On zoome sur la mosaïque.
-    $('#mainPanel').animate(
-    {
-        width: newPreMPWidth,
-        height: newPreMPHeight,
-        top: newZoomTop,
-        left: newZoomLeft
-    }, this.config['zoomTime'], function()
-    {
-        //On charge les interactions avec les voisins.
-        _this.centerId = zoomedImgId;
-		
-		if(_this.currentMode != "NO-USER")
-		{
-			_this.currentMode = 'VIDEO';
-			_this.listenToNeighbours();
+			if(this.isMosaicFiltered)
+			{
+				// console.log('FILTER !!!');
+				// this.notifySearch1Gesture(gestureReceived, 'valid');
+				$('.notifications').remove();
+				this.filterGesture(gestureReceived, 'valid');
+				this.searchFilter(gestureReceived);
+			}
 		}
 		
-		_this.snTop = (zoomedImg.position().top + newZoomTop + _this.MPTop_margin), _this.snLeft = (zoomedImg.position().left + newZoomLeft);
-		_this.snWidth = newSnWidth + 1, _this.snHeight = newSnHeight + 1;
-		
-		_this.notifyTopVideo = newZoomTop;
-		_this.notifyLeftVideo = newZoomLeft;
-		
-		_this.loadPlayer(_this.snTop, _this.snLeft, _this.snWidth, _this.snHeight, newZoomTop, newZoomLeft);
-    });
+		if(this.helpDisplayed)
+		{
+			this.removeHelp();
+		}
+	}
+	// /!\/!\ //
 }
 
 /*
  * Chargement du player basé sur le metadataplayer.
 */
-mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft)
+mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft, timeToGo)
 {
 	var _this = this;
 	
@@ -782,376 +926,112 @@
 	
 	//On démarre le player.
 	this.player = null;
+	
 	this.player = new IriSP.Metadataplayer(_config, _metadata);
 	
-	if(this.currentMode == 'NO-USER')
-	{
-		this.player.onLoad(function()
-		{
-			console.log(_this.player);
-			console.log(_this.player.popcorn);
-			//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
-			if(_this.player.popcorn != undefined)
-			{
-				_this.player.popcorn.listen('pause', function()
-				{
-					_this.unzoom();
-				});
-			}
-		});
-	}
-}
-
-/*
- * Retour à la taille normale de la mosaïque.
- */
-mosaic.prototype.unzoom = function()
-{
-    //Si on n'est pas en plein écran, on quitte.
-	console.log("'" + this.currentMode + "'");
-    if(this.currentMode != "SEARCH" && this.currentMode != "VIDEO" && this.currentMode != "NO-USER" && this.currentMode.indexOf("INCOMING") == -1)
+	this.player.onLoad(function()
 	{
-        return;
-	}
-	
-	this.snTop = 0;
-	this.snLeft = 0;
-	this.Width = 0;
-	this.snHeight = 0;
-    
-    //On charge les attributs nécessaires aux calculs.
-    var sWidth = this.snapshotWidth, sHeight = this.snapshotHeight;
-    var mpWidth = this.width, mpHeight = this.height;
-    var _this = this;
-    
-    //On passe le snapshot sur lequel on a zoomé en SD.
-    var zoomedImg = $('img', this.previousZoomedSN);
-    var src = zoomedImg.attr('src');
-    zoomedImg.attr('src', src.replace('snapshots/', 'snapshots-little/'));
-	
-	_this.player.widgets[0].freePlayer();
-	$('.LdtPlayer').remove();
-	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
-	_this.reaffectKeyPress();
-    
-    //On rend leur opacité aux snapshots. Qui ne sont alors plus grisés.
-    $('.snapshotDivs').animate(
-    {
-        width: sWidth,
-        height: sHeight,
-        margin: this.marginWidth/2 + 'px'
-    }, this.config['unzoomTime']);
-	
-	if(this.currentMode != 'NO-USER')
-	{
-		if(this.currentMode.indexOf("INCOMING") == -1)
+		if(_this.currentMode == 'NO-USER')
 		{
-			$('.snapshotDivs').animate(
-			{
-				opacity: '1'
-			}, this.config['unzoomTime']);
+			//On peut s'approcher de la kinect.
+			_this.canStart = true;
+			console.log('CAN START !');
+			// console.log(_this.player);
+			// console.log(_this.player.popcorn);
 		}
-	}
-	else
-	{
-		console.log('init');
-		this.previousZoomedSN.fadeTo(this.config['unzoomTime'], 0, function()
+		//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
+		if(_this.player.popcorn)
 		{
-			_this.init();
-		});
-	}
-	
-    //On dézoom sur la mosaïque.
-    $('#mainPanel').animate(
-    {
-        width: mpWidth,
-        height: mpHeight,
-        top: '0px',
-        left: '0px'
-    }, this.config['unzoomTime'], function()
-    {
-        //On n'est plus en plein écran, et on ne peut plus se déplacer vers le prochain voisin.
-        _this.fullscreen = false;
-        _this.canMoveToNeighbour = false;
-		
-		if(_this.currentMode != 'NO-USER')
-		{
-			//On revient en mode MOSAIC.
-			_this.currentMode = 'MOSAIC';
-			//On ne permet plus le déplacement vers les voisins.
-			$('.snapshotDivs').unbind('mouseover', function()
+			_this.player.popcorn.listen('pause', function()
 			{
-				_this.selectNeighbour();
+				//Si l'utilisateur a mis en pause.
+				if(_this.userPaused)
+				{
+				
+				}
+				//Si la pause est naturelle (fin de la timeline, dézoom, déplacement vers un voisin).
+				else
+				{
+					//Si c'est en mode sans utilisateur.
+					if(_this.currentMode == 'NO-USER')
+					{
+						//On dézoome.
+						_this.unzoom();
+					}
+					//Sinon.
+					else
+					{
+						//Si ce n'est pas causé par un déplacement ou un dézoom.
+						if(!_this.currentlyMoving && !_this.currentlyUnzooming)
+						{
+							//On réinitialise la position du curseur à la prochaine lecture de la vidéo.
+							console.log('REINIT');
+							//On passe a la video suivante.
+							console.log('AUTOMOVE');
+							
+							//Si on est en mode timeline et qu'on est en pause, c'est probablement que l'user a placé le curseur à la fin.
+							if(_this.currentMode != 'TIMELINE')
+							{
+								_this.playNextVideo();
+							}
+							//_this.timeToGoAt[parseInt(_this.centerId)] = 0;
+							console.log('time to go at to 0');
+							// return;
+						}
+					}
+				}
 			});
-			//On remet les notifications initiales.
-			_this.notifySelectionSearchMosaicFull();
+			// console.log('mosaic filtered : ' + _this.isMosaicFiltered);
+			
+			_this.player.popcorn.on("markersready", function()
+			{
+				_this.playerIsReady = true;
+				
+				if(_this.currentMode == 'VIDEO' || _this.currentMode == 'SEARCH' || _this.currentMode == 'TIMELINE')
+				{
+					_this.canSwipe = true;
+				}
+				
+				console.log('TIME TO GO AT : ' + _this.timeToGoAt[_this.centerId], _this.centerId, _this.imgs[_this.centerId]);
+				
+				if(_this.isMosaicFiltered)
+				{
+					if(_this.currentSearchGesture == '')
+					{
+						_this.removeFilter();
+					}
+					else
+					{
+						_this.currentMode = 'SEARCH';
+						// console.log(_this.currentSearchGesture);
+						_this.player.widgets[0].searchByGesture(_this.currentSearchGesture);
+						_this.isCurrentlyInASearchByGesture = _this.player.widgets[0].isCurrentlyInASearchByGesture;
+						
+						if(_this.timeToGoAt[_this.centerId] === 0 && _this.player.widgets[0].atLeastOneSearchMarker(_this.currentSearchGesture))
+						{
+							_this.player.widgets[0].goToFirstSearchedMarker(_this.currentSearchGesture);
+						}
+						else
+						{
+							_this.player.popcorn.currentTime(_this.timeToGoAt[_this.centerId]);
+						}
+					}
+				}
+				// /!\ //
+				else
+				{
+					if(_this.player.popcorn)
+					{
+						_this.player.popcorn.currentTime(_this.timeToGoAt[_this.centerId]);
+					}
+				}
+			});
 		}
-    });
-}
-
-/*
- * Affecte les listeners mouseenter aux voisins lors d'une vue en plein écran.
- */
-mosaic.prototype.listenToNeighbours = function()
-{
-    ////TEST
-    //$('.test').empty();
-    var _this = this;
-    
-	this.canMoveToNeighbour = false;
-    var currentLine = Math.floor(this.centerId / this.config['length']), currentColumn = this.centerId % this.config['length'];
-    var zoomedImg = $('img', this.previousZoomedSN);
-    
-    //On cherche l'ID des voisins.
-    //Si le voisin de gauche est sur la même ligne, on n'est pas sur la bordure de gauche.
-    this.neighboursIds[0] = (currentColumn > 0) ? (this.centerId - 1) : -1;
-    //Si le voisin de droite est sur la même ligne, on n'est pas sur la bordure de droite.
-    this.neighboursIds[1] = (currentColumn < this.config['length']) ? (+this.centerId + 1) : -1;
-    //Si le voisin du haut est sur la même colonne, on n'est pas sur la bordure du haut.
-    this.neighboursIds[2] = (currentLine > 0) ? (this.centerId - this.config['length']) : -1;
-    //Si le voisin du bas est sur la même colonne, on n'est pas sur la bordure du bas.
-    this.neighboursIds[3] = (currentLine < (this.config['imagesToShow'] / this.config['length'])) ? (+this.centerId + this.config['length']) : -1;
-    
-	//ID du cadre voisin.
-	var preId;
-	
-    for(var i = 0 ; i < this.neighboursIds.length ; i++)
-    {
-        if(this.neighboursIds[i] != -1)
-        {
-			preId = '#neighbourFrameBorder-' + this.neighboursIds[i];
-            //On permet le déplacement vers les voisins.
-            // $('#snapshotDiv-' + this.neighboursIds[i] + ', ' + preId + '-left,' + preId + '-right,' + preId + '-up,' + preId + '-down').mouseenter(mos.selectNeighbour);
-			
-            $('#snapshotDiv-' + this.neighboursIds[i]).mouseover(function()
-			{
-				_this.selectNeighbour($(this));
-			});
-        }
-    }
+	});
 }
 
 /*
- * Change la coloration d'une bordure où on se positionne lors d'une vue en plein écran.
- */
-mosaic.prototype.selectNeighbour = function(neighbour)
-{
-    ////TEST
-    //$('.test').append(mos.currentMode + " " + $(this).attr('id') + " " + 'snapshotDiv-' + mos.centerId + ',');
-	var _this = this;
-	
-    //Si on est en mode VIDEO (plein écran) ET si le snapshot pointé est un voisin.
-    
-    if((this.currentMode == 'VIDEO') && (neighbour.attr('id') != 'snapshotDiv-' + this.centerId))
-    {
-        //On crée le cadre qui va être superposé au voisin.
-        //On le colle au voisin.
-		var tab = neighbour.attr('id').split('-');
-		var snapshotId = tab[1];
-        var neighbourFrame = '';
-		var marginValue = parseFloat(neighbour.css('margin'));
-		
-		neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"><div class="neighbourImgBg" id="neighbourImgBg-' + snapshotId + '"><div class="neighbourImg" id="neighbourImg-' + snapshotId + '"></div></div></div>';
-		
-        $('#mainPanel').append(neighbourFrame);
-		
-		//On positionne le div de background juste au niveau du voisin.
-        $('#neighbourFrame-' + snapshotId).css(
-		{
-			'top': (+neighbour.position().top + marginValue),
-			'left': (+neighbour.position().left + marginValue),
-			'width': neighbour.width(),
-			'height': neighbour.height()
-		});
-		//On positionne le div de background noir juste au niveau de l'image du voisin.
-        $('#neighbourImgBg-' + snapshotId).css(
-		{
-			'top': marginValue,
-			'left': marginValue,
-			'width': neighbour.width() - marginValue*2,
-			'height': neighbour.height() - marginValue*2,
-		});
-		//On met par dessus le div de l'image clonée du voisin.
-		$('#neighbourImg-' + snapshotId).css(
-		{
-			'top': 0,
-			'left': 0,
-			'width': neighbour.width() - marginValue*2,
-			'height': neighbour.height() - marginValue*2,
-			'background-image': 'url("' + $('img', neighbour).attr('src') + '")',
-			'background-size': neighbour.width() + 'px ' + neighbour.height() + 'px',
-			'background-position': -marginValue + 'px ' + -marginValue + 'px',
-			'opacity': '0.4'
-		});
-		
-		var fId = '#neighbourFrame-' + snapshotId;
-		
-		$(fId).animate(
-        {
-            //On le fait apparaître.
-            opacity: '1'
-        }, _this.config['timeNeighbourGlowing'], function()
-        {
-            //On peut désormais se déplacer vers ce voisin.
-            _this.canMoveToNeighbour = true;
-        });
-		//Lorsqu'on quitte un des snapshots (bien entendu le voisin en question), on retire le cadre.
-		//Si on clique sur le voisin ou son cadre, on passe au voisin suivant.
-		$(fId).mouseout(function()
-		{
-			_this.deselectNeighbour($(this))
-		}).click(function()
-		{
-			_this.moveToNeighbour($(this))
-		});
-    }
-}
-
-/*
- * Change la coloration d'une bordure quittée lors d'une vue en plein écran.
- */
-mosaic.prototype.deselectNeighbour = function(neighbour)
-{
-    ////TEST
-    //$('.test').append('un,');
-	
-    //On ne peut plus se déplacer vers les voisins.
-    this.canMoveToNeighbour = false;
-    
-	//On récupère le voisin.
-	var neighbourFrame = neighbour;
-	
-    //Si on est en mode VIDEO.
-    if(this.currentMode == 'VIDEO')
-    {
-        //On le fait disparaître progressivement.
-        neighbourFrame.animate(
-        {
-            opacity: '0'
-        }, this.config['timeNeighbourUnglowing'], function()
-        {
-            //Une fois invisible, on le supprime.
-            neighbourFrame.remove();
-        });
-    }
-}
-
-/*
- * 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.
- */
-mosaic.prototype.moveToNeighbour = function(neighbour)
-{
-	var _this = this;
-    //Si on ne peut pas se déplacer vers les voisins, on quitte.
-    if(!_this.canMoveToNeighbour)
-	{
-        return;
-	}
-    
-    //On obtient l'ID de destination.
-    var tab = neighbour.attr('id').split('-');
-    var destinationId = tab[1];
-    
-    //On charge les attributs nécessaires aux calculs.
-	var length = _this.config['length'];
-    var MPCurrentTop = $('#mainPanel').position().top, MPCurrentLeft = $('#mainPanel').position().left;
-    var divideCoeffTop = Math.floor(destinationId / length) == 0 ? 1 : Math.floor(destinationId / length);
-    var divideCoeffLeft = destinationId % length == 0 ? 1 : destinationId % length;
-    var neighbourFrameTop = $('#snapshotDiv-' + destinationId).position().top, neighbourFrameLeft = $('#snapshotDiv-' + destinationId).position().left;
-    
-    //On définit pour le déplacement vertical s'il est nécessaire de se déplacer en haut ou en bas.
-    if(_this.previousZoomedSN.position().top > neighbourFrameTop)
-        MPCurrentTop += Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
-    else if(_this.previousZoomedSN.position().top < neighbourFrameTop)
-        MPCurrentTop -= Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
-    //On définit pour le déplacement horizontal s'il est nécessaire de se déplacer à gauche ou à droite.
-    if(_this.previousZoomedSN.position().left > neighbourFrameLeft)
-        MPCurrentLeft += Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
-    else if(_this.previousZoomedSN.position().left < neighbourFrameLeft)
-        MPCurrentLeft -= Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
-    
-    //On passe le snapshot de destination en HD.
-    var destinationImg = $('#snapshot-' + destinationId);
-    var destinationImgSrc = destinationImg.attr('src');
-    destinationImg.attr('src', destinationImgSrc.replace('snapshots-little/', 'snapshots/'));
-    
-    //On passe l'ancien snapshot en SD.
-    var currentImgSrc = $('img', _this.previousZoomedSN).attr('src');
-    $('img', _this.previousZoomedSN).attr('src', currentImgSrc.replace('snapshots/', 'snapshots-little/'));
-    
-    //On obtient l'ID du div de coloration du snapshot vers lequel on se déplace afin de le supprimer.
-    var neighbourFrame = neighbour;
-    var tab = neighbourFrame.attr('id').split('-');
-    _this.centerId = tab[1];
-    $(this).css('opacity', '0');
-    neighbourFrame.remove();
-    
-	_this.player.widgets[0].freePlayer();
-	$('.LdtPlayer').remove();
-	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
-	_this.reaffectKeyPress();
-	
-    //On grise le snapshot qu'on vient de quitter.
-    _this.previousZoomedSN.animate(
-    {
-        opacity: '0.4'
-    });
-    
-    //On se déplace.
-    $('#mainPanel').animate(
-    {
-        top: MPCurrentTop,
-        left: MPCurrentLeft
-    }, _this.config['timeMovingToNeighbour'], function()
-    {
-        //On fait apparaître le snapshot vers lequel on s'est déplacé.
-        $('#snapshotDiv-' + destinationId).animate(
-        {
-            opacity: '1'
-        }, _this.config['zoomTime'], function()
-        {
-            //On recharge les voisins.
-            $('.snapshotDivs').unbind('mouseenter', _this.selectNeighbour);
-            _this.previousZoomedSN = $('#snapshotDiv-' + _this.centerId);
-            _this.listenToNeighbours();
-			
-			_this.notifyTopVideo = MPCurrentTop;
-			_this.notifyLeftVideo = MPCurrentLeft;
-			
-			_this.loadPlayer((destinationImg.position().top + MPCurrentTop + _this.MPTop_margin), (destinationImg.position().left + MPCurrentLeft), destinationImg.width(), destinationImg.height(), MPCurrentTop, MPCurrentLeft);
-        });
-    });
-}
-
-/*
- * Déchargement du contenu de la mosaïque pour le chargement de la mosaïque locale.
- */
-mosaic.prototype.unload = function()
-{
-    //On supprime les event listeners des objets de la mosaïque.
-    $('.snapshotDivs').unbind();
-    $('.snapshots').unbind();
-    $('.prezoomContainers').unbind();
-    //On supprime physiquement les objets.
-    $('#mainPanel').empty();
-}
-
-/*
- * Centre verticalement un snapshot.
- */
-/*function verticalCenterImg(mosaic, img)
-{
-    //On récupère sa hauteur.
-    var image_height = img.height();
-    //Calcule la marge du haut de chaque div pour le centrage.
-    if(mosaic.top_margin == undefined)
-        mosaic.top_margin = (mosaic.snapshotHeight > image_height) ? (mosaic.snapshotHeight - image_height)/2 : (image_height - mosaic.snapshotHeight)/2;
-    //On centre le snapshot.
-    img.css('margin-top', mosaic.top_margin).css('margin-bottom', mosaic.top_margin);
-}*/
-
-/*
- * Permet de tester l'égalité des éléments de deux objets.
+ * Permet de tester l'égalité des éléments de deux objets.
  * Pour ce faire on compare les éléments définissant ces objets.
  */
 $.fn.equals = function(compareTo)
@@ -1189,21 +1069,23 @@
 					if(_this.config['local'] == 'true')
 					{
 						_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'));
-						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'));
+						// 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'));
 					}
 					else
 					{
 						_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
-						console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
+						// console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
 					}
 				});
 				_this.imgs[_this.ids[i]] = val_video.snapshot;
 				_this.urls[_this.ids[i]] = val_video.metadata;
-				console.log('ids : ' + _this.ids[i]);
+				//Au départ, on commence à 0 ms dans les vidéos.
+				_this.timeToGoAt[_this.ids[i]] = 0;
+				// console.log('ids : ' + _this.ids[i]);
 				i++;
 			});
 		});
-		console.log('rdy');
+		// console.log('rdy');
 		_this.loadMosaic();
 	});
 }
@@ -1224,476 +1106,6 @@
 }
 
 /*
- * Lance une recherche par courbes.
- */
-mosaic.prototype.startSearch = function()
-{
-	var top, left, width, height, margin_top, inMosaic;
-	//Si on est dans le cas d'un filtrage de mosaïque.
-	if(this.currentMode == "FILTER")
-	{
-		var mainPanel = $('#mainPanel');
-		top = mainPanel.position().top;
-		left = mainPanel.position().left;
-		width = mainPanel.width();
-		height = mainPanel.height();
-		margin_top = this.MPTop_margin;
-		inMosaic = true;
-	}
-	//Sinon si c'est une recherche dans la vidéo.
-	else if(this.currentMode == "SEARCH")
-	{
-		top = this.snTop;
-		left = this.snLeft;
-		width = this.snWidth;
-		height = this.snHeight;
-		margin_top = '0px';
-		inMosaic = false;
-	}
-	
-	this.searchCanvas = new searchCanvas(top, left, width, height, margin_top, this.timeSearchFade, inMosaic);
-	this.searchCanvas.create();
-}
-
-/*
- * Quitte une recherche par courbes.
- */
-mosaic.prototype.leaveSearch = function()
-{
-	this.searchCanvas.leaveSearch();
-}
-
-/* ===============================================
- *												   *
- *		      ZONE DES NOTIFICATIONS			   *
- *												   *
-   =============================================== */
-
-/*
- * Affiche la notification de sélection/recherche lorsque la mosaique est complète.
-*/
-mosaic.prototype.notifySelectionSearchMosaicFull = function()
-{
-	if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") == -1)
-	{
-		return;
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('#mainPanel').append(notification_selection + notification_search);
-
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var selection_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var search_left = selection_left + notify_width + notify_margin;
-	
-	//On les positionne.
-	$('#notify_selection').css(
-	{
-		left: selection_left
-	});
-	$('#notify_search').css(
-	{
-		left: search_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de sélection/recherche lorsque la mosaique est complète.
-*/
-mosaic.prototype.removeSelectionSearchMosaicFull = function()
-{
-	$('#notify_selection, #notify_search').remove();
-}
-
-/*
- * Affiche la notification de maintient du pointage lors d'une phase de prézoom.
-*/
-mosaic.prototype.notifyPointMosaicPrezoom = function()
-{
-	if($('#notify_point').length > 0 || this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") == -1)
-	{
-		return;
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_point = "<div id='notify_point' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('#mainPanel').append(notification_point);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	//On les positionne.
-	$('#notify_point').css(
-	{
-		left: point_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de maintient du pointage.
-*/
-mosaic.prototype.removePointMosaicPrezoom = function()
-{	
-	$('#notify_point').remove();
-}
-
-/*
- * Affiche l'aide.
-*/
-mosaic.prototype.notifyHelp = function()
-{
-	if(this.helpDisplayed)
-	{
-		return;
-	}
-	
-	this.removeSelectionSearchMosaicFull();
-	this.removePointMosaicPrezoom();
-	
-	this.helpDisplayed = true;
-	
-	var search_2hands_tab = ['no_motion', 'right_angle', 'contact', 'grand_jete', 'circle', 'screw', 'arc', 'rythme', 'slow', 'up_down', 'wave', 'wheel'];
-	var search_body_tab = ['bend', 'fall', 'jump', 'hello', 'knee_up'];
-	var controls_1hand_tab = ['selection'];
-	
-	//On spécifie les notifications en div.
-	var search_title = "<div id='search_title'></div>";
-	var search_img = "<div id='search_img' class='notify_imgs'></div>";
-	var search_2hands_text = "<div id='search_2hands_text'></div>";
-	var search_2hands_imgs = "<div id='search_2hands_imgs' class='notify_imgs_big'>";
-	
-	for(var i = 0 ; i < search_2hands_tab.length ; i++)
-	{
-		search_2hands_imgs += "<div id='2hands_" + search_2hands_tab[i] + "' class='notify_imgs_small'></div>";
-	}
-	search_2hands_imgs += "</div>";
-	
-	var search_body_text = "<div id='search_body_text'></div>";
-	var search_body_imgs = "<div id='search_2hands_imgs' class='notify_imgs'>"
-	
-	for(var i = 0 ; i < search_body_tab.length ; i++)
-	{
-		search_body_imgs += "<div id='body_" + search_body_tab[i] + "' class='notify_imgs_small'></div>";
-	}
-	search_body_imgs += "</div>";
-	
-	var controls_title = "<div id='controls_title'></div>";
-	var controls_img = "<div id='controls_img' class='notify_imgs'></div>";
-	var controls_1hand_text = "<div id='controls_1hand_text'></div>";
-	var controls_1hand_imgs = "<div id='controls_1hand_imgs' class='notify_imgs'>";
-	
-	for(var i = 0 ; i < controls_1hand_tab.length ; i++)
-	{
-		controls_1hand_imgs += "<div id='1hand_" + controls_1hand_tab[i] + "' class='notify_imgs_small'></div>";
-	}
-	controls_1hand_imgs += "</div>";
-	
-	var help_search = "<div id='help_search'>" + search_title + search_img + search_2hands_text + search_2hands_imgs + search_body_text + search_body_imgs + "</div>";
-	var help_controls = "<div id='help_controls'>" + controls_title + controls_img + controls_1hand_text + controls_1hand_imgs + "</div>";
-	
-	var notification_help = "<div id='notify_help'>" + help_search + "<div id='help_sep'></div>" + help_controls + "</div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_help);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $(window).width(), notify_height = $(window).height();
-	var notify_margin = parseInt($('#notify_help').css('margin'));
-	var notify_ = 10;
-	
-	//On les positionne.
-	$('#notify_help').css(
-	{
-		left: "0px",
-		top: "0px",
-		width: notify_width - notify_margin * 2,
-		height: notify_height - notify_margin * 2
-	});
-	
-	var search_width = $('#help_search').width();
-	
-	$('#search_title').html('Recherche');
-	$('#search_2hands_text').html('Gestes à effectuer avec les deux mains');
-	$('#search_body_text').html('Gestes à effectuer avec le corps entier');
-	
-	for(var i = 0 ; i < search_2hands_tab.length ; i++)
-	{
-		$("#2hands_" + search_2hands_tab[i]).css("background-image", "url('./pictos/help/" + search_2hands_tab[i] + ".png')");
-		//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
-	}
-	
-	for(var i = 0 ; i < search_body_tab.length ; i++)
-	{
-		$("#body_" + search_body_tab[i]).css("background-image", "url('./pictos/help/" + search_body_tab[i] + ".png')");
-		//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
-	}
-	
-	$('#controls_title').html('Contrôles');
-	$('#controls_1hand_text').html('Gestes à effectuer avec une seule main');
-	
-	for(var i = 0 ; i < controls_1hand_tab.length ; i++)
-	{
-		$("#1hand_" + controls_1hand_tab[i]).css("background-image", "url('./pictos/help/" + controls_1hand_tab[i] + ".png')");
-		//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
-	}
-	
-	//On les fait apparaître.
-	$('#notify_help').css(
-	{
-		opacity: "1"
-	});
-	
-	$('.notify_imgs_big').css(
-	{
-		opacity: "1"
-	});
-}
-
-/*
- * Supprime l'aide.
-*/
-mosaic.prototype.removeHelp = function()
-{
-	if(!this.helpDisplayed)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	$('#notify_help').fadeOut(this.timeNotifyFade, function()
-	{
-		_this.helpDisplayed = false;
-		$('#notify_help').remove();
-	});
-}
-
-/*
- * Affiche les types de marqueurs correspondants à ce qu'on a commencé à tracer lors d'une recherche.
-*/
- mosaic.prototype.notifySearchMarkers = function(markersStr)
-{
-	if($('.notifications_inSearch_container').length > 0)
-	{
-		return;
-	}
-	
-	console.log(markersStr);
-	
-	var markersList = markersStr.split(new RegExp(';'));
-	
-	var notification_search_markers = "<div class='notifications_inSearch_container'>";
-	
-	//On spécifie les notifications en div.
-	for(var i = 0 ; i < markersList.length ; i++)
-	{
-		notification_search_markers += "<div class='notifications_inSearch' style='background-image: url(./pictos/big/normal/" + markersList[i] + ".png);'></div>";
-	}
-	
-	notification_search_markers += "</div>";
-	
-	//On les ajoute à la mosaïque.
-	$('#mainPanel').append(notification_search_markers);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications_inSearch_container').width(), notify_height = $('.notifications_inSearch_container').height();
-	var notify_margin = parseInt($('.notifications_inSearch').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	var point_top = 0;
-	
-	if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH")
-	{
-		point_top = -this.notifyTopVideo,
-		point_left = -this.notifyLeftVideo + ($(window).width() - notify_width) / 2
-	}
-	
-	//On les positionne.
-	$('.notifications_inSearch_container').css(
-	{
-		left: point_left,
-		top: point_top
-	});
-	
-	//On les fait apparaître.
-	$('.notifications_inSearch').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de maintient du pointage.
-*/
-mosaic.prototype.removeSearchMarkers = function()
-{	
-	$('.notifications_inSearch_container').remove();
-}
-
-/*
- * Effectuer un filtrage de la mosaïque par rapport à un type de marqueurs.
-*/
-mosaic.prototype.searchFilter = function(type)
-{
-	var _this = this;
-	
-	if(this.currentMode == "MOSAIC")
-	{
-		this.currentMode = "FILTER";
-		
-		if(this.annotations.length > 0)
-		{
-			var gestureNumberByVideo = new Object();
-			var maxAnnotationNumber = 0;
-			// for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
-			for(var i = 0 ; i < this.annotations.length ; i++)
-			{
-				var current = this.annotations[i];
-				if(current.annotationType.contents.title == type)
-				{
-					if(gestureNumberByVideo[current.source.url] == undefined || gestureNumberByVideo[current.source.url] == '')
-					{
-						gestureNumberByVideo[current.source.url] = 0;
-					}
-					
-					gestureNumberByVideo[current.source.url]++;
-				}
-			}
-			
-			for(var i = 0 ; i < this.urls.length ; i++)
-			{
-				if(gestureNumberByVideo[this.urls[i]] == undefined || gestureNumberByVideo[this.urls[i]] == '')
-				{
-					gestureNumberByVideo[this.urls[i]] = 0;
-				}
-			}
-			
-			//On récupère la vidéo qui score le nombre d'occurences de la gesture le plus haut.
-			for(i in gestureNumberByVideo)
-			{	
-				// console.log(i + " " + gestureNumberByVideo[i]);
-				if(maxAnnotationNumber < gestureNumberByVideo[i])
-				{
-					maxAnnotationNumber = gestureNumberByVideo[i];
-				}
-			}
-			
-			var snMargin = parseInt($('.snapshotDivs').css('margin'));
-			
-			//On affiche l'opacité résultante pour chaque vidéo.
-			for(i in gestureNumberByVideo)
-			{
-				//Opacité conventionelle.
-				var opacity = gestureNumberByVideo[i] / maxAnnotationNumber;
-				// console.log('opacity b : ' + opacity + ' for ' + gestureNumberByVideo[i]);
-				//Ce qui est à zéro le restera (par conséquent le snapshot associé sera invisible).
-				if(opacity > 0)
-				{
-					//On réhausse l'opacité de 50%.
-					opacity = this.scaleIntervals(0., 1., 0.5, 1., opacity);
-				}
-				
-				var filterIndex = this.getIdxFromMetadata(i);
-				
-				if(filterIndex >= 0)
-				{
-					console.log('#snapshotDiv-' + filterIndex + " " + _this.config['timeFilterFade'] + " " + opacity);
-					$('#snapshotDiv-' + filterIndex).fadeTo(_this.config['timeFilterFade'], opacity);
-					
-					if(opacity == 0)
-					{
-						var filteredSnapshot = $('#snapshotDiv-' + filterIndex);
-						
-						if(filteredSnapshot.length > 0)
-						{
-							var hider = '<div id="filterHider-' + filterIndex + '" class="filterHiders"></div>';
-							$('#mainPanel').append(hider);
-							
-							$('#filterHider-' + filterIndex).css(
-							{
-								width: +filteredSnapshot.width() + 4 * snMargin,
-								height: +filteredSnapshot.height() + 4 * snMargin,
-								top: filteredSnapshot.position().top - snMargin,
-								left: filteredSnapshot.position().left - snMargin
-							});
-						}
-					}
-				}
-			}
-		}
-	}
-}
-
-/*
- * Passe une valeur de l'intervalle [A, B] à l'intervalle [C, D].
-*/
-mosaic.prototype.scaleIntervals = function(A, B, C, D, val)
-{
-	return (D - C + A) * val + (C - A);
-}
-
-/*
- * Retourne l'index d'un snapshot en fonction de ses metadonnées.
-*/
-mosaic.prototype.getIdxFromMetadata = function(metadata)
-{
-	var _this = this;
-	
-	for(idx in this.urls)
-	{
-		if(this.urls[idx] == metadata)
-		{
-			for(id in this.ids)
-			{
-				if(this.ids[id] == idx)
-				{
-					return id;
-				}
-			}
-		}
-	}
-	
-	return -1;
-}
-
-/*
- * Enlève une recherche par filtre.
-*/
-mosaic.prototype.removeFilter = function()
-{
-	if(this.currentMode == "FILTER")
-	{
-		this.currentMode = "MOSAIC";
-		
-		var _this = this;
-		
-		$('.filterHiders').remove();
-		$('.snapshotDivs').fadeTo(_this.config['timeFilterFade'], 1);
-	}
-}
-
-/*
  * Rebind keypress pour body.
 */
 mosaic.prototype.reaffectKeyPress = function()
@@ -1704,4 +1116,20 @@
 	{
 		_this.manageControlEvents(event);
 	});
-}
\ No newline at end of file
+}
+
+mosaic.prototype.date = function()
+{
+   var date, h, min, s;
+   date = new Date();
+   h = date.getHours();
+   min = date.getMinutes();
+   s = date.getSeconds();
+   if (h < 10)
+      h = "0" + h;
+   if (min < 10)
+      min = "0" + min;
+   if (s < 10)
+      s = "0" + s;
+   return (h + ":" + min + ":" + s);
+};
\ No newline at end of file