front_idill/src/mosaic/js/mosaic.js
changeset 44 8393d3473b98
parent 35 4267d6d27a7d
child 45 0e29ae4568a0
equal deleted inserted replaced
43:cefce0845ac5 44:8393d3473b98
    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(config, default_conf)
    25 function mosaic(config, default_conf)
    26 {
    26 {
       
    27 	//Interactions souris/kinect.
       
    28 	this.mouseInteractions = false;
       
    29 	//Interactions avec/sans préphase.
       
    30 	this.prephaseEnabled = true;
       
    31 	
       
    32 	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run"];
       
    33 
    27 	//Chemin du fichier de configuration.
    34 	//Chemin du fichier de configuration.
    28 	this.config_path = config;
    35 	this.config_path = config;
    29 	//Configuration par défaut en cas de valeur erronnée.
    36 	//Configuration par défaut en cas de valeur erronnée.
    30 	this.default_config = default_conf;
    37 	this.default_config = default_conf;
    31 	this.config = new Object();
    38 	this.config = new Object();
    32 	//Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
    39 	//Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
    33 	this.videos = [];
    40 	this.videos = [];
    34 	this.urls = [];
    41 	this.urls = [];
       
    42 	this.sources = [];
    35 	this.imgs = [];
    43 	this.imgs = [];
       
    44 	this.opacities = [];
       
    45 	this.timeToGoAt = [];
    36 	this.ids = [];
    46 	this.ids = [];
    37 	this.fillingIds = [];
    47 	this.fillingIds = [];
    38 	this.currentRandomVideoIdx = 0;
    48 	this.currentRandomVideoIdx = 0;
       
    49 	
       
    50 	//Dernières positions des pointeurs.
       
    51 	this.mainPointerLastX;
       
    52 	this.mainPointerLastY;
       
    53 	this.secondPointerLastX;
       
    54 	this.secondPointerLastY;
       
    55 	//Dernières positions avant le lancement de la fonction d'idle.
       
    56 	this.mainPointerIdleStartX;
       
    57 	this.mainPointerIdleStartY;
       
    58 	this.secondPointerIdleStartX;
       
    59 	this.secondPointerIdleStartY;
    39 	
    60 	
    40 	//Dimensions de la mosaïque en pixels.
    61 	//Dimensions de la mosaïque en pixels.
    41 	this.width;
    62 	this.width;
    42 	this.height;
    63 	this.height;
    43 	//Dimensions d'un snapshot en pixels.
    64 	//Dimensions d'un snapshot en pixels.
    48 	
    69 	
    49 	//Booléens permettant ou non certaines intéractions selon le contexte.
    70 	//Booléens permettant ou non certaines intéractions selon le contexte.
    50 	this.zoomed;
    71 	this.zoomed;
    51 	this.fullscreen;
    72 	this.fullscreen;
    52 	this.canMoveToNeighbour;
    73 	this.canMoveToNeighbour;
       
    74 	this.mainPointerExitBorder;
       
    75 	this.secondPointerExitBorder;
       
    76 	this.isMainPointerDisplayed;
       
    77 	this.isSecondPointerDisplayed;
    53 	this.helpDisplayed;
    78 	this.helpDisplayed;
       
    79 	//Indique si l'utilisateur a manuellement pausé la vidéo.
       
    80 	this.userPaused;
       
    81 	//Indique si on est en train de se déplacer vers un voisin.
       
    82 	this.currentlyMoving;
       
    83 	//Indique si on est en train de dézoomer vers la mosaïque.
       
    84 	this.currentlyUnzooming;
       
    85 	//Indique si on peut s'approcher de kinect.
       
    86 	this.canStart;
       
    87 	//Indique si on est actuellement sur un snapshot.
       
    88 	this.isOnASnapshot;
       
    89 	//Indique si l'idle des pointeurs est disponible (deux mains détectées).
       
    90 	this.pointersIdleAvailable;
       
    91 	//Indique si le timeout pour l'idle des pointeurs à besoin d'être lancé.
       
    92 	this.pointersIdleNeedLaunch;
       
    93 	//Indique si les deux mains sont là.
       
    94 	this.areBothPointersHere;
       
    95 	//Indique si le timeout pour la détection de deux pointeurs a été lancé.
       
    96 	this.areBothPointersTimeoutLaunched;
       
    97 	//Indique si la mosaïque a été filtrée.
       
    98 	this.isMosaicFiltered;
       
    99 	//Indique si on est actuellement dans une recherche par gesture.
       
   100 	this.isCurrentlyInASearchByGesture;
       
   101 	//Indique si un pointeur est déjà sur une notification de recherche par gesture.
       
   102 	this.alreadyOnNotification;
       
   103 	//Si on a fait un swipe.
       
   104 	this.isSwipe;
       
   105 	//On peut swiper.
       
   106 	this.canSwipe;
       
   107 	//On passe vers une autre video automatiquement à la fin d'une lecture.
       
   108 	this.autoMove;
       
   109 	//Si l'utilisateur a demandé à sélectionner la TL.
       
   110 	this.isTLRequested;
       
   111 	//Le pointeur gauche a sélectionné la TL.
       
   112 	this.isTLSelectedBySecondPointer;
       
   113 	//Le pointeur droit a sélectionné la TL.
       
   114 	this.isTLSelectedByMainPointer;
       
   115 	//On peut afficher l'aide.
       
   116 	this.canNotifyHelp;
       
   117 	//Indique si la mosaique est en train d'être filtrée.
       
   118 	this.isMosaicFiltering;
       
   119 	this.arrowLeftLoading = false;
       
   120 	this.arrowRightLoading = false;
       
   121 	this.arrowUpLoading = false;
       
   122 	this.arrowDownLoading = false;
       
   123 	//On est dans une recherche par courbes.
       
   124 	this.isSearchByCurvesOn;
       
   125 	this.canDrawNextCurve = false;
       
   126 	
       
   127 	//Timeout (attente) pour le zoom après un préZoom.
       
   128 	this.zoomTimeout;
       
   129 	//Timeout (attente) pour le passage vers un voisin.
       
   130 	this.moveToNeighbourTimeout;
       
   131 	this.mainPointerExitBorderTimeout;
       
   132 	this.secondPointerExitBorderTimeout;
       
   133 	//Idle time pour les pointeurs afin d'informer le front qu'on souhaite faire une recherche.
       
   134 	this.pointersSearchIdleTimeout;
       
   135 	//Vérifie toutes les N ms que les deux pointeurs sont détectés.
       
   136 	this.areBothPointersHereTimeout;
       
   137 	//Délai de suppression d'une notification de recherche par gesture.
       
   138 	this.removeNotificationByGestureTimeout;
       
   139 	//Délai de suppression d'une notification de recherche par gesture infructueuse.
       
   140 	this.removeFailedNotificationByGestureTimeout;
       
   141 	//Délai avant la suppression de notification swipe.
       
   142 	this.notifySwipeTimeout;
       
   143 	//Délai pour la sélection de la TL.
       
   144 	this.selectTLTimeout;
       
   145 	//Délai pour slider sur la TL.
       
   146 	this.canSlideInTLTimeout;
       
   147 	//Délai pour afficher l'aide.
       
   148 	this.canNotifyHelpTimeout;
       
   149 	this.arrowLeftTimeout;
       
   150 	this.arrowRightTimeout;
       
   151 	this.arrowUpTimeout;
       
   152 	this.arrowDownTimeout;
       
   153 	
       
   154 	this.arrowSpinnerTimeout;
       
   155 	this.nouserTimeout;
       
   156 	this.nextDrawCurveTimeout;
       
   157 	
       
   158 	//Dernier message INCOMING (pour éviter d'effectuer n fois la même action.
       
   159 	this.lastIncomingMessage;
    54 	
   160 	
    55 	//Type de marqueur recherché dans la mosaïque (en mode filter).
   161 	//Type de marqueur recherché dans la mosaïque (en mode filter).
    56 	this.filterSearchedType = "";
   162 	this.filterSearchedType = "";
    57 	
   163 	
    58 	//Mode actuel.
   164 	//Mode actuel.
    59 	this.currentMode = "MOSAIC";
   165 	this.currentMode = "NO-USER";
    60 	//Snapshot sur lequel on a zoomé.
   166 	//Snapshot sur lequel on a zoomé.
    61 	this.previousZoomedSN;
   167 	this.previousZoomedSN = null;
    62 	//Son ID.
   168 	//Son ID.
    63 	this.previousId;
   169 	this.previousId;
       
   170 	//Dernier snapshot prézoomé non null.
       
   171 	this.lastNonNullSN = null;
    64 	//Largeur de la marge pour le centrage vertical de la mosaïque.
   172 	//Largeur de la marge pour le centrage vertical de la mosaïque.
    65 	this.MPTop_margin;
   173 	this.MPTop_margin;
    66 	this.top_margin;
   174 	this.top_margin;
       
   175 	
       
   176 	//Gesture actuellement cherchée.
       
   177 	this.currentSearchGesture;
    67 
   178 
    68 	//Mosaïque locale.
   179 	//Mosaïque locale.
    69 	this.localMos;
   180 	this.localMos;
    70 	//Position des voisins lors d'un zoom.
   181 	//Position des voisins lors d'un zoom.
    71 	this.neighboursIds = [];
   182 	this.neighboursIds = [];
    72 	//ID du snapshot du milieu lors d'un zoom.
   183 	//ID du snapshot du milieu lors d'un zoom.
    73 	this.centerId;
   184 	this.centerId;
    74 	
   185 	
       
   186 	//Voisins sélectionnés par les pointeurs.
       
   187 	this.mainPointerNeighbourSelectedId = null;
       
   188 	this.secondPointerNeighbourSelectedId = null;
       
   189 	
    75 	//Snapshots a afficher.
   190 	//Snapshots a afficher.
    76 	this.snapshotsToShow = 1;
   191 	this.snapshotsToShow = 1;
    77 	
   192 	
    78 	//Lecteur.
   193 	//Lecteur.
    79 	this.player;
   194 	this.player;
       
   195 	//Si le lecteur est prêt.
       
   196 	this.playerIsReady;
       
   197 	
    80 	//Annotations (pour les marqueurs los d'un filtrage).
   198 	//Annotations (pour les marqueurs los d'un filtrage).
    81 	this.annotations = [];
   199 	this.annotations = [];
       
   200 	
       
   201 	//Client websocket pour recevoir les notifications du Middleware.
       
   202 	this.client;
    82 	
   203 	
    83 	//Coordonnées et dimensions d'un snapshot zoomé.
   204 	//Coordonnées et dimensions d'un snapshot zoomé.
    84 	this.snTop = 0;
   205 	this.snTop = 0;
    85 	this.snLeft = 0;
   206 	this.snLeft = 0;
    86 	this.snWidth = 0;
   207 	this.snWidth = 0;
    97  * Méthode d'affichage de la mosaïque.
   218  * Méthode d'affichage de la mosaïque.
    98  * Génère une matrice de imgs.
   219  * Génère une matrice de imgs.
    99  */
   220  */
   100 mosaic.prototype.createMosaic = function()
   221 mosaic.prototype.createMosaic = function()
   101 {
   222 {
   102 	console.log('CREATE');
   223 	// console.log('CREATE');
   103 	this.currentMode = "NO-USER";
   224 	// this.currentMode = "NO-USER";
   104 	var initPanel = '<div id="initPanel"></div>';
   225 	var initPanel = '<div id="initPanel"></div>';
   105 	var mp = $('#mainPanel');
   226 	var mp = $('#mainPanel');
   106 	mp.append(initPanel);
   227 	mp.append(initPanel);
   107 	$('#initPanel').css(
   228 	$('#initPanel').css(
   108 	{
   229 	{
   117 	var len = this.config['length'], imgs = this.config['imagesToShow'], imgsTotal = this.config['imagesTotal'];
   238 	var len = this.config['length'], imgs = this.config['imagesToShow'], imgsTotal = this.config['imagesTotal'];
   118 	
   239 	
   119 	//S'il s'agit d'un rectangle.
   240 	//S'il s'agit d'un rectangle.
   120     if(imgs % len == 0)
   241     if(imgs % len == 0)
   121     {
   242     {
   122 		this.previousZoomedSN = '';
   243 		this.previousZoomedSN = null;
   123 		this.previousPrezoomDiv = '';
   244 		this.previousPrezoomDiv = null;
   124 		this.fullscreen = false;
   245 		this.fullscreen = false;
   125 		this.canMoveToNeighbour = false;
   246 		this.canMoveToNeighbour = false;
       
   247 		this.currentlyZooming = false;
       
   248 		this.currentlyUnzooming = false;
   126 		this.helpDisplayed = false;
   249 		this.helpDisplayed = false;
       
   250 		this.canStart = false;
       
   251 		this.isOnASnapshot = false;
       
   252 		this.isMosaicFiltered = false;
       
   253 		this.areBothPointersHere = false;
       
   254 		this.areBothPointersTimeoutLaunched = false;
       
   255 		this.isCurrentlyInASearchByGesture = false;
       
   256 		this.alreadyOnNotification = false;
       
   257 		this.playerIsReady = false;
       
   258 		this.currentSearchGesture = '';
       
   259 		this.isMainPointerDisplayed = false;
       
   260 		this.isSecondPointerDisplayed = false;
       
   261 		this.isSwipe = false;
       
   262 		this.canSwipe = false;
       
   263 		this.autoMove = false;
       
   264 		this.isTLRequested = false;
       
   265 		this.isTLSelectedByMainPointer = false;
       
   266 		this.isTLSelectedBySecondPointer = false;
       
   267 		this.canNotifyHelp = false;
       
   268 		this.isMosaicFiltering = false;
       
   269 		this.isSearchByCurvesOn = false;
       
   270 		
       
   271 		this.lastIncomingMessage = 'INCOMING-0';
       
   272 		
   127 		var str = '';
   273 		var str = '';
   128 		
   274 		
   129 		if(this.imgs.length >= imgs)
   275 		if(this.imgs.length >= imgs)
   130 		{
   276 		{
   131 			for(var i = 0 ; i < imgs ; i++)
   277 			for(var i = 0 ; i < imgs ; i++)
   146 /*
   292 /*
   147  * Permet de raffraichir la mosaïque.
   293  * Permet de raffraichir la mosaïque.
   148  */
   294  */
   149 mosaic.prototype.loadMosaic = function()
   295 mosaic.prototype.loadMosaic = function()
   150 {
   296 {
   151 	console.log('LOAD');
   297 	// console.log('LOAD');
   152 	var createMosaic = this.createMosaic();
   298 	var createMosaic = this.createMosaic();
   153 	
   299 	
   154 	if(createMosaic == '')
   300 	if(createMosaic == '')
   155 	{
   301 	{
   156 		return;
   302 		return;
   176     this.height = $('#mainPanel').innerHeight();
   322     this.height = $('#mainPanel').innerHeight();
   177     //On centre verticalement la mosaïque.
   323     //On centre verticalement la mosaïque.
   178     this.MPTop_margin = ($(document).height() - $('#mainPanel').height())/2;
   324     this.MPTop_margin = ($(document).height() - $('#mainPanel').height())/2;
   179     $('#mainPanel').css('margin-top', this.MPTop_margin).css('margin-bottom', this.MPTop_margin);
   325     $('#mainPanel').css('margin-top', this.MPTop_margin).css('margin-bottom', this.MPTop_margin);
   180 	
   326 	
   181 	//On affiche les notifications.
   327 	//On fait coincider le background du body avec celui de la mosaïque.
   182 	this.notifySelectionSearchMosaicFull();
   328 	$('body').css('background-position', '0px ' + this.MPTop_margin + 'px');
   183 	
   329 	console.log(this.MPTop_margin);
   184 	$('.snapshotDivs').mouseenter(function ()
   330 	
       
   331 	/*$('.snapshotDivs').mouseover(function ()
   185 	{
   332 	{
   186 		//On effectue un prézoom dès qu'on va sur une image.
   333 		//On effectue un prézoom dès qu'on va sur une image.
   187 		_this.preZoom($(this));
   334 		_this.preZoom($(this));
   188 	});
   335 	});*/
   189 	
   336 	
   190 	this.addPointers();
   337 	this.addPointers();
   191 	
   338 	
   192 	//Si dans le metadata player _ n'est pas déclaré, on le déclare.
   339 	//Si dans le metadata player _ n'est pas déclaré, on le déclare.
   193 	if(typeof _ !== "undefined" && typeof IriSP._ === "undefined")
   340 	if(typeof _ !== "undefined" && typeof IriSP._ === "undefined")
   206 	nbFichiers = _this.urls.length,
   353 	nbFichiers = _this.urls.length,
   207 	fichiersCharges = 0;
   354 	fichiersCharges = 0;
   208 	
   355 	
   209 	for (var i = 0; i < nbFichiers; i++)
   356 	for (var i = 0; i < nbFichiers; i++)
   210 	{
   357 	{
   211 		console.log('url : ' + _this.urls[i]);
   358 		// console.log('url : ' + _this.urls[i]);
   212 		var source = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt});
   359 		_this.sources[i] = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt});
   213 		source.onLoad(function()
   360 		_this.sources[i].onLoad(function()
   214 		{
   361 		{
       
   362 			var source = this;
       
   363 			// console.log(source);
   215 			globalAnnotations.addElements(source.getAnnotations());
   364 			globalAnnotations.addElements(source.getAnnotations());
       
   365 			// console.log(source.url + ' ' + source.getAnnotations().length);
   216 			fichiersCharges++;
   366 			fichiersCharges++;
   217 			if (fichiersCharges == nbFichiers)
   367 			if (fichiersCharges == nbFichiers)
   218 			{
   368 			{
   219 				// instructions à exécuter quand tout est chargé
   369 				// instructions à exécuter quand tout est chargé
   220 				_this.annotations = globalAnnotations;
   370 				_this.annotations = globalAnnotations;
   221 				console.log('annotations loaded');
   371 				// console.log(_this.annotations.length + ' ' + nbFichiers);
   222 				_this.init();
   372 				console.log(_this.annotations.length + ' annotations loaded from ' + nbFichiers + ' files.');
       
   373 				
       
   374 				//Si on gère les interactions à la souris.
       
   375 				if(_this.mouseInteractions)
       
   376 				{
       
   377 					$('body').mousemove(function(e){_this.refreshMainPointer(e.pageX, e.pageY, _this)});
       
   378 				}
       
   379 				
       
   380 				// if(false)
       
   381 				// {
       
   382 				if(_this.prephaseEnabled)
       
   383 				{
       
   384 					_this.init();
       
   385 					_this.showNImages(0);
       
   386 					_this.currentMode = "NO-USER";
       
   387 				}
       
   388 				else
       
   389 				{
       
   390 					_this.showNImages(20);
       
   391 					_this.currentMode = "MOSAIC";
       
   392 				}
       
   393 				// }
       
   394 				
       
   395 				// /!\ //
       
   396 				// _this.currentMode = "FILTER";
       
   397 				// _this.showNImages(20);
       
   398 				//_this.isSearchByCurvesOn = true;
       
   399 				// _this.startSearch();
       
   400 				// console.log('CANVAS READY');
       
   401 				// /!\ //
       
   402 				
       
   403 				/*_this.currentSearchGesture = 'bend';
       
   404 				_this.currentMode = 'FILTER';
       
   405 				_this.searchFilter('bend');*/
       
   406 				
       
   407 				_this.previousZoomedSN = $('#snapshotDiv-' + _this.fillingIds[0]);
   223 			}
   408 			}
   224 		});
   409 		});
   225 	}
   410 	}
   226 }
   411 }
   227 
   412 
   230 */
   415 */
   231 mosaic.prototype.loadParameters = function(file_path)
   416 mosaic.prototype.loadParameters = function(file_path)
   232 {
   417 {
   233 	var _this = this;
   418 	var _this = this;
   234 	
   419 	
   235 	var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeFilling', 'zoomedMargin'];
   420 	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'];
   236 	var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage'];
   421 	var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage'];
   237 	
   422 	
   238 	$.getJSON(file_path, function(data)
   423 	$.getJSON(file_path, function(data)
   239 	{
   424 	{
   240 		for(key in data)
   425 		for(key in data)
   244 			if(_.include(supposedToBeInt, key))
   429 			if(_.include(supposedToBeInt, key))
   245 			{
   430 			{
   246 				var intVal = parseInt(val);
   431 				var intVal = parseInt(val);
   247 				if(isNaN(intVal))
   432 				if(isNaN(intVal))
   248 				{
   433 				{
   249 					console.log(_this.default_config);
   434 					// console.log(_this.default_config);
   250 					_this.config[key] = _this.default_config[key];
   435 					_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.");
   436 					console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Int). Valeur par défaut " + _this.default_config[key] + " chargée à la place.");
   252 				}
   437 				}
   253 				else
   438 				else
   254 				{
   439 				{
   292 			return 0.5 - Math.random()
   477 			return 0.5 - Math.random()
   293 		});
   478 		});
   294 		
   479 		
   295 		if(_this.config['local'] == 'true')
   480 		if(_this.config['local'] == 'true')
   296 		{
   481 		{
   297 			console.log("Loading local metadata.");
   482 			// console.log("Loading local metadata.");
   298 			_this.loadFromJson('./player/json/local_videos.json');
   483 			_this.loadFromJson('./player/json/local_videos.json');
   299 		}
   484 		}
   300 		else
   485 		else
   301 		{
   486 		{
   302 			console.log("Loading online metadata.");
   487 			// console.log("Loading online metadata.");
   303 			_this.loadFromJson('./player/json/online_videos.json');
   488 			_this.loadFromJson('./player/json/online_videos.json');
   304 		}
   489 		}
       
   490 		
       
   491 		//On initialise le client.
       
   492 		_this.client = new client(_this.config['host'], _this.config['port'], _this);
   305 	});
   493 	});
   306 }
   494 }
   307 
   495 
   308 /*
   496 /*
   309  * Phase principale (utilisateur non détecté). Une vidéo se lance aléatoirement.
   497  * Phase principale (utilisateur non détecté). Une vidéo se lance aléatoirement.
   311  * Lors de la fin d'une lecture, on dézoome vers la mosaïque, puis on rezoome vers un autre snapshot (aléatoire).
   499  * Lors de la fin d'une lecture, on dézoome vers la mosaïque, puis on rezoome vers un autre snapshot (aléatoire).
   312 */
   500 */
   313 mosaic.prototype.init = function()
   501 mosaic.prototype.init = function()
   314 {
   502 {
   315 	var _this = this;
   503 	var _this = this;
   316 	
   504 
   317 	if(this.currentRandomVideoIdx > this.config['imagesToShow'])
   505 	if(this.currentRandomVideoIdx > this.config['imagesToShow'])
   318 	{
   506 	{
   319 		this.currentRandomVideoIdx = 0;
   507 		this.currentRandomVideoIdx = 0;
   320 	}
   508 	}
       
   509 	
   321 	
   510 	
   322 	this.previousZoomedSN = $('#snapshotDiv-' + this.fillingIds[this.currentRandomVideoIdx]);
   511 	this.previousZoomedSN = $('#snapshotDiv-' + this.fillingIds[this.currentRandomVideoIdx]);
   323 	this.previousId = $('img', this.previousZoomedSN).attr('id');
   512 	this.previousId = $('img', this.previousZoomedSN).attr('id');
   324 	
   513 	
   325 	console.log('ids', this.fillingIds[this.currentRandomVideoIdx]);
   514 	// console.log('CURRENT MODE : ' + _this.currentMode);
       
   515 	// console.log('ids', this.fillingIds[this.currentRandomVideoIdx]);
   326 	
   516 	
   327 	this.previousZoomedSN.fadeTo(this.config['timePrezoom'], 1, function()
   517 	this.previousZoomedSN.fadeTo(this.config['timePrezoom'], 1, function()
   328 	{
   518 	{
       
   519 		// console.log('CURRENT MODE : ' + _this.currentMode);
   329 		_this.zoom();
   520 		_this.zoom();
   330 		_this.currentRandomVideoIdx++;
   521 		_this.currentRandomVideoIdx++;
   331 	});
   522 	});
   332 }
   523 }
   333 
   524 
   334 /*
   525 /*
   335  * Remplissage de la mosaïque en fonction du nombre d'images à afficher.
   526  * Remplissage de la mosaïque en fonction du nombre d'images à afficher.
   336 */
   527 */
   337 mosaic.prototype.showNImages = function(n)
   528 mosaic.prototype.showNImages = function(n)
   338 {
   529 {
   339 	if(n > 1)
   530 	if(this.currentlyMoving)
       
   531 	{
       
   532 		return;
       
   533 	}
       
   534 	
       
   535 	// console.log('INCOMING ----- ' + n);
       
   536 	//Si il y a plus d'un snapshot à afficher, on entre dans le mode INCOMING avec en paramètre le nombre à afficher.
       
   537 	if(n > 1 && n < this.config['imagesToShow'])
   340 	{
   538 	{
   341 		this.currentMode = "INCOMING-" + n;
   539 		this.currentMode = "INCOMING-" + n;
   342 		this.unzoom();
   540 		this.unzoom();
   343 	}
   541 		this.currentSearchGesture = '';
   344 	
   542 		$('.notifications').remove();
       
   543 		this.isMosaicFiltered = false;
       
   544 		this.isCurrentlyInASearchByGesture = false;
       
   545 		$('#mainPointer').fadeTo(this.config['timePrezoom'], 0);
       
   546 		$('#secondPointer').fadeTo(this.config['timePrezoom'], 0);
       
   547 		$('#spinner').remove();
       
   548 		this.deselectAllNeighbours();
       
   549 		$('.prezoomContainers').remove();
       
   550 	}
       
   551 	// console.log('n : ' + n);
       
   552 	if(n >= this.config['imagesToShow'])
       
   553 	{
       
   554 		// this.unzoom();
       
   555 		if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING-") > -1)
       
   556 		{
       
   557 			this.currentMode = "INCOMING-20";
       
   558 			this.unzoom();
       
   559 			this.currentMode = "MOSAIC";
       
   560 			$('.notifications').remove();
       
   561 			this.mosaicSelectionAndSearch();
       
   562 			clearTimeout(this.nouserTimeout);
       
   563 			console.log('OK');
       
   564 		}
       
   565 		//On affiche les notifications.
       
   566 		// this.notifySelectionSearchMosaicFull();
       
   567 	
       
   568 		// $('#mainPointer').fadeTo(this.config['timePrezoom'], 1);
       
   569 		// $('#secondPointer').fadeTo(this.config['timePrezoom'], 1);
       
   570 	}
       
   571 	
       
   572 	//Pour les snapshots à afficher.
   345 	for(var i = 0 ; i < n ; i++)
   573 	for(var i = 0 ; i < n ; i++)
   346 	{
   574 	{
   347 		if($('#snapshotDiv-' + i).css('opacity') < 1)
   575 		//Si les snapshots ne sont pas affichés.
   348 		{
   576 		if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') < 1)
   349 			$('#snapshotDiv-' + i).fadeTo(this.config['timeFilling'], 1);
   577 		{
   350 		}
   578 			//On les fait apparaître.
   351 	}
   579 			$('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config['timeFilling'], '1');
   352 }
   580 		}
   353 
   581 	}
   354 /*
   582 	//Pour ceux à masquer.
   355  * Affiche les pointeurs.
   583 	for(var i = n ; i < this.config['imagesToShow'] ; i++)
   356 */
   584 	{
   357 mosaic.prototype.addPointers = function()
   585 		//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).
   358 {
   586 		if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') > 0 && this.fillingIds[i] != this.currentRandomVideoIdx)
   359 	var _this = this;
   587 		{
   360 	
   588 			//On les masque.
   361 	var mainPointer = '<div id="mainPointer" class="pointers"></div>';
   589 			$('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config['timeFilling'], '0');
   362 	$('body').append(mainPointer);
   590 		}
   363 	$('body').mousemove(function(evt)
   591 	}
   364 	{
       
   365 		$('#mainPointer').css(
       
   366 		{
       
   367 			top: evt.pageY - $('#mainPointer').height()/2,
       
   368 			left: evt.pageX - $('#mainPointer').width()/2
       
   369 		});
       
   370 	});
       
   371 }
   592 }
   372 
   593 
   373 /*
   594 /*
   374  * Gère les événements de contrôle dans la mosaïque.
   595  * Gère les événements de contrôle dans la mosaïque.
   375 */
   596 */
   376 mosaic.prototype.manageControlEvents = function(event)
   597 mosaic.prototype.manageControlEvents = function(event)
   377 {
   598 {
   378 	console.log('manage');
   599 	// console.log('manage');
       
   600 	
       
   601 	var _this = this;
       
   602 	
       
   603 	if(typeof event === 'undefined')
       
   604 	{
       
   605 		return;
       
   606 	}
       
   607 	
       
   608 	var gestureReceived = '';
       
   609 	
   379 	//Sinon si on a appuyé sur 'g' ou 'G'.
   610 	//Sinon si on a appuyé sur 'g' ou 'G'.
   380 	if(event.which == 103 || event.which == 71)
   611 	// if(event.which == 103 || event.which == 71)
       
   612 	/*if(event == "CURVES")
   381 	{
   613 	{
   382 		//Si on est déjà en recherche par courbes.
   614 		//Si on est déjà en recherche par courbes.
   383 		if(this.currentMode == "SEARCH" || this.currentMode == "FILTER")
   615 		if(this.currentMode == "SEARCH" || this.currentMode == "FILTER")
   384 		{
   616 		{
   385 			//On quitte cette recherche.
   617 			//On quitte cette recherche.
   413 			
   645 			
   414 			this.startSearch();
   646 			this.startSearch();
   415 		}
   647 		}
   416 	}
   648 	}
   417 	//Si c'est a ou A.
   649 	//Si c'est a ou A.
   418 	else if(event.which == 65 || event.which == 97)
   650 	// else if(event.which == 65 || event.which == 97)
       
   651 	else if(event == "HELP")
   419 	{
   652 	{
   420 		if(!this.helpDisplayed)
   653 		if(!this.helpDisplayed)
   421 		{
   654 		{
   422 			this.notifyHelp();
   655 			this.notifyHelp();
   423 		}
   656 		}
   425 		{
   658 		{
   426 			this.removeHelp();
   659 			this.removeHelp();
   427 		}
   660 		}
   428 	}
   661 	}
   429 	//Si c'est v ou V.
   662 	//Si c'est v ou V.
   430 	else if(event.which == 86 || event.which == 118)
   663 	// else if(event.which == 86 || event.which == 118)
       
   664 	else if(event == "NOTIFY-SEARCH")
   431 	{
   665 	{
   432 		this.notifySearchMarkers('run;jump;fall');
   666 		this.notifySearchMarkers('run;jump;fall');
   433 	}
   667 	}
   434 	//Si c'est b ou B.
   668 	//Si c'est b ou B.
   435 	else if(event.which == 66 || event.which == 98)
   669 	// else if(event.which == 66 || event.which == 98)
       
   670 	else if(event == "REMOVE-SEARCH")
   436 	{
   671 	{
   437 		this.removeSearchMarkers();
   672 		this.removeSearchMarkers();
   438 	}
   673 	}
   439 	//Si c'est k ou K.
   674 	//Si c'est k ou K.
   440 	else if(event.which == 75 || event.which == 107)
   675 	// else if(event.which == 75 || event.which == 107)
       
   676 	else if(event == "FILTER")
   441 	{
   677 	{
   442 		this.searchFilter('circle');
   678 		this.searchFilter('circle');
   443 	}
   679 	}
   444 	//Si c'est l ou L.
   680 	//Si c'est l ou L.
   445 	else if(event.which == 76 || event.which == 108)
   681 	// else if(event.which == 76 || event.which == 108)
       
   682 	else if(event == "REMOVE-FILTER")
   446 	{
   683 	{
   447 		this.removeFilter();
   684 		this.removeFilter();
   448 	}
   685 	}
   449 	//Si on a appuié sur la touche 'q' ou 'Q';
   686 	//Si on a appuié sur la touche 'q' ou 'Q';
   450 	else if(event.which == 113 || event.which == 81)
   687 	// else if(event.which == 113 || event.which == 81)
       
   688 	else if(event == "UNZOOM")
   451 	{
   689 	{
   452 		this.unzoom();
   690 		this.unzoom();
   453 	}
   691 	}*/
   454 	else if(event.which == 111 || event.which == 79)
   692 	// else if(event.which == 111 || event.which == 79)
   455 	{
   693 	if(event.indexOf("INCOMING-") != -1 && this.prephaseEnabled)
   456 		if(this.snapshotsToShow > this.imagesToShow)
   694 	{
   457 		{
   695 		// console.log(this.date() + ' ' + event);
   458 			this.snapshotsToShow = this.imagesToShow;
   696 		// console.log('CAN START : ' + this.canStart);
   459 		}
   697 		if(this.canStart)
   460 		else
   698 		{
   461 		{
   699 			if(this.snapshotsToShow > this.config['imagesToShow'])
   462 			this.snapshotsToShow += 5;
   700 			{
   463 		}
   701 				this.snapshotsToShow = this.config['imagesToShow'];
   464 		
   702 			}
   465 		this.showNImages(this.snapshotsToShow);
   703 			else
   466 	}
   704 			{
   467 }
   705 				var params = event.split('-');
   468 
   706 				// console.log(event);
   469 /*
   707 				this.snapshotsToShow = params[1];
   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.
   708 			}
   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.
   709 			
   472  */
   710 			//Si la position de l'utilisateur a changé.
   473 mosaic.prototype.preZoom = function(snapshot)
   711 			if(event != this.lastIncomingMessage)
   474 {
   712 			{
   475     if(this.fullscreen)
   713 				console.log(this.snapshotsToShow);
   476 	{
   714 				this.lastIncomingMessage = event;
   477         return;
   715 				this.showNImages(this.snapshotsToShow);
   478 	}
   716 			}
   479 	
   717 		}
   480 	//On enlève les notifications initiales si elles existent.
   718 		
   481 	this.removeSelectionSearchMosaicFull();
   719 		clearTimeout(this.nouserTimeout);
   482 	
   720 		this.nouserTimeout = setTimeout(function()
   483     //Mosaïque.
   721 		{
   484     var _this = this;
   722 			/*_this.showNImages(0);
   485     //Dimensions de la mosaïque.
   723 			_this.init();
   486     var h = this.height, w = this.width;
   724 			_this.canStart = false;
   487     //Longueur en images, nombre d'images et taille de bordure de la mosaïque.
   725 			_this.currentMode = "NO-USER";*/
   488     var len = this.config['length'], imgs = this.config['imagesToShow'], margin = this.marginWidth;
   726 			
   489     //Dimensions et position d'un snapshot dans la mosaïque.
   727 				window.location.reload();
   490     var snHeight = this.snapshotHeight, snWidth = this.snapshotWidth;
   728 			// mos = new mosaic('./config.json', default_parameters);
   491     var sTop = snapshot.position().top, sLeft = snapshot.position().left;
   729 			
   492     var prezoomPercentage = this.config['prezoomPercentage'];
   730 			console.log('NOUSER');
   493     
   731 		}, this.config['timeoutNouser']);
   494     //ID de l'image actuelle.
   732 	}
   495     var currentId = $('img', snapshot).attr('id');
   733 	else if((event == "NO-USER" || event == "INCOMING-0" || event == "INCOMING-1") && this.prephaseEnabled)
   496     
   734 	{
   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.
   735 		/*this.showNImages(0);
   498     if(this.zoomed)
   736 		this.init();
   499 	{
   737 		this.canStart = false;
   500         if($('#preZoomContainer-' + currentId) != $(this) && this.previousZoomedSN != '' && this.previousId != '')
   738 		this.currentMode = "NO-USER";*/
   501 		{
   739 		
   502             this.preUnzoom();
   740 			window.location.reload();
   503 		}
   741 		// mos = new mosaic('./config.json', default_parameters);
   504         else
   742 		
   505 		{
   743 		console.log('NOUSER');
   506             return;
   744 		
   507 		}
   745 		/*this.currentMode = "NO-USER";
   508 	}
   746 		this.showNImages(0);
   509     
   747 		this.canStart = false;
   510     //On indique qu'on a zoomé et on spécifie le snapshot sur lequel on a zoomé.
   748 		this.init();*/
   511     this.zoomed = true;
   749 	}
   512     this.previousZoomedSN = snapshot;
   750 	// /!\/!\ //
   513     this.previousId = currentId;
   751 	else if(event.indexOf("SWIPE") != -1)
   514     
   752 	{
   515     //On récupère les attributs de l'image.
   753 		if(this.player && this.player.widgets && this.playerIsReady && !this.isSwipe)
   516     var fakeImg = $('img', snapshot);
   754 		{
   517     //On forme la balise de la fausse image et on passe son url pour les grands snapshots.
   755 			this.isSwipe = true;
   518     fakeImg = '<img id="fake-' + currentId + '" class="snapshots" src="' + fakeImg.attr('src').replace('-little/', '/') + '" />';
   756 			
   519     //On génère un faux snapshot identique au précédent et qu'on va coller dessus.
   757 			if(this.currentMode == 'SEARCH' && this.isMosaicFiltered && !this.player.widgets[0].isAMarkerAhead(this.currentSearchGesture))
   520     var fakeSnapshot = '<div id="prezoomContainer-' + currentId + '" class="prezoomContainers"><div id="prezoomSnapshot-' + currentId + '" class="snapshotDivs">' + fakeImg + '</div></div>';
   758 			{
   521     
   759 				this.playNextVideo();
   522     //On l'ajoute à la mosaïque.
   760 			}
   523     $('#mainPanel').append(fakeSnapshot);
   761 			
   524     //On modifie ses attributs.
   762 			//L'utilisateur a fait un swipe left.
   525     $('#fake-' + currentId).load(function()
   763 			if(event.indexOf("LEFT") != -1)
   526     {
   764 			{
   527         $('#prezoomContainer-' + currentId).css('display', 'block');
   765 				this.player.widgets[0].switchToMarker(true, this.currentSearchGesture);
   528         $('#prezoomContainer-' + currentId).css('top', sTop).css('left', sLeft).css('width', (snWidth + margin)).css('height', (snHeight + margin));
   766 				if(this.currentMode == 'VIDEO')
   529         $('#prezoomSnapshot-' + currentId).css('width', (snWidth)).css('height', (snHeight));
   767 				{
   530         
   768 					$('.notifications').remove();
   531         //Dimensions et coordonnées initiales du div sur lequel on zoom.
   769 					this.videoSwipe('left');
   532         var initialDivWidth = $('#prezoomContainer-' + currentId).width(), initialDivHeight = $('#prezoomContainer-' + currentId).height();
   770 				}
   533         var initialDivTop = $('#prezoomContainer-' + currentId).position().top, initialDivLeft = $('#prezoomContainer-' + currentId).position().left;
   771 				else if(this.currentMode == 'SEARCH' && !this.currentSearchGesture)
   534         //Dimensions et coordonnées finales du div.
   772 				{
   535         var finalDivWidth = initialDivWidth * (prezoomPercentage+1), diffWidth = finalDivWidth - initialDivWidth, finalDivHeight = initialDivHeight + diffWidth;
   773 					$('.notifications').remove();
   536         var finalDivTop = (initialDivTop - (finalDivHeight - snHeight)/2), finalDivLeft = (initialDivLeft - (finalDivWidth - snWidth)/2);
   774 					this.searchSearchAndSwipe('left');
   537         
   775 				}
   538         //CAS PARTICULIER pour la position du snapshot zoomé : les bordures.
   776 				else if(this.currentMode == 'SEARCH' && this.currentSearchGesture)
   539         if(finalDivTop < 0)
   777 				{
   540 		{
   778 					$('.notifications').remove();
   541             finalDivTop = -margin;
   779 					this.searchGestureAndSwipe(this.currentSearchGesture, 'valid', 'left');
   542 		}
   780 				}
   543         if(finalDivTop + finalDivHeight > h)
   781 			}
   544 		{
   782 			//L'utilisateur a fait un swipe right.
   545             finalDivTop = h - finalDivHeight;
   783 			else if(event.indexOf("RIGHT") != -1)
   546 		}
   784 			{
   547         if(finalDivLeft < 0)
   785 				this.player.widgets[0].switchToMarker(false, this.currentSearchGesture);
   548 		{
   786 				if(this.currentMode == 'VIDEO')
   549             finalDivLeft = 0;
   787 				{
   550 		}
   788 					$('.notifications').remove();
   551         if(finalDivLeft + finalDivWidth + margin*2 > w)
   789 					this.videoSwipe('right');
   552 		{
   790 				}
   553             finalDivLeft = w - finalDivWidth - margin*2;
   791 				else if(this.currentMode == 'SEARCH' && !this.currentSearchGesture)
   554 		}
   792 				{
   555         
   793 					$('.notifications').remove();
   556         ////Code de debug.
   794 					this.searchSearchAndSwipe('right');
   557         ////CAUTION////
   795 				}
   558         /*var red = '<div id="red"></div>';
   796 				else if(this.currentMode == 'SEARCH' && this.currentSearchGesture)
   559         if($('#red') != null || $('#red') != undefined)
   797 				{
   560             $('body').append(red);
   798 					$('.notifications').remove();
   561         $('#red').css('background-color', '#FF0000').css('position', 'absolute').css('top', '0px').css('left', '0px').css('width', '100px').css('height', '100px');
   799 					this.searchGestureAndSwipe(this.currentSearchGesture, 'valid', 'right');
   562         $('#red').css('top', finalDivTop).css('left', finalDivLeft).css('width', finalDivWidth).css('height', finalDivHeight);*/
   800 				}
   563         //alert("initial : " + initialDivWidth + " " + initialDivHeight + " ; final : " + finalDivWidth + " " + finalDivHeight);
   801 			}
   564         ////CAUTION////
   802 			
   565         
   803 			//On le fait disparaitre au bout d'un certain temps.
   566         //On prézoom le div en le centrant sur le milieu du snapshot pointé.
   804 			this.notifySwipeTimeout = setTimeout(function()
   567         $('#prezoomSnapshot-' + currentId).animate(
   805 			{
   568         {
   806 				_this.isSwipe = false;
   569             width: finalDivWidth + margin,
   807 				
   570             height: finalDivHeight - margin*2,
   808 				// /!\ //
   571             top: finalDivTop + margin,
   809 				$('.notifications').remove();
   572             left: finalDivLeft + margin
   810 				
   573         }, _this.config['timePrezoom']);
   811 				if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture)
   574         $('#prezoomContainer-' + currentId).animate(
   812 				{
   575         {
   813 					_this.searchSearch();
   576             width: finalDivWidth + margin*2,
   814 				}
   577             height: finalDivHeight - margin,
   815 				else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture)
   578             top: finalDivTop + margin,
   816 				{
   579             left: finalDivLeft
   817 					_this.searchGesture(_this.currentSearchGesture, 'valid');
   580         }, _this.config['timePrezoom'], function()
   818 				}
   581 		{
   819 				
   582 			_this.notifyPointMosaicPrezoom();
   820 			}, this.config['timeoutNotifySwipe']);
   583 		});
   821 		}
   584     });
   822 	}
   585     
   823 	else if(event.indexOf("BEND") != -1 || event.indexOf('KNEE-UP') != -1 || event.indexOf('FALL') != -1 || event.indexOf('JUMP') != -1)
   586     //Si on clique sur le snapshot prézoomé, on enclenche un zoom total sur ce snapshot.
   824 	{
   587     $('#prezoomContainer-' + currentId).click(function ()
   825 		gestureReceived = event.toLowerCase();
   588     {
   826 		gestureReceived = gestureReceived.replace('wave', 'hello');
   589         if(this.previousZoomedSN != '')
   827 		this.currentSearchGesture = gestureReceived;
   590 		{
   828 	}
   591             _this.zoom();
   829 	else if(event.indexOf("HELLO") != -1 && this.canNotifyHelp && !this.areBothPointersHere)
   592 		}
   830 	{
   593     });
   831 		if(this.currentMode == 'SEARCH')
   594 }
   832 		{
   595 
   833 			this.notifyHelp(false);
   596 /*
   834 		}
   597  * 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é.
   835 		else if(this.currentMode == 'FILTER')
   598  */
   836 		{
   599 mosaic.prototype.preUnzoom = function()
   837 			this.notifyHelp(true);
   600 {
   838 		}
   601     //Si on n'a pas zoomé, on quitte la fonction.
   839 	}
   602     if(!this.zoomed)
   840 	
   603 	{
   841 	if(gestureReceived != '')
   604         return;
   842 	{
   605 	}
   843 		if(this.currentMode == "SEARCH" && this.playerIsReady)
   606 	
   844 		{
   607 	this.removePointMosaicPrezoom();
   845 			this.player.widgets[0].searchByGesture(gestureReceived);
   608     
   846 			this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture;
   609     //On spécifie la marge afin de centrer le prédézoom.
   847 			
   610     var margin = this.marginWidth;
   848 			$('.notifications').remove();
   611     //ID du snapshot précédemment pointé.
   849 			this.searchGesture(gestureReceived, 'valid');
   612     var id = this.previousId;
   850 		}
   613     //On ne zoom plus.
   851 		else if(this.currentMode == "FILTER")
   614     this.zoomed = false;
   852 		{
   615     //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.
   853 			if(this.isMosaicFiltered)
   616     $('#prezoomSnapshot-' + id).animate(
   854 			{
   617     {
   855 				// console.log('FILTER !!!');
   618         width: this.snapshotWidth,
   856 				// this.notifySearch1Gesture(gestureReceived, 'valid');
   619         height: this.snapshotHeight,
   857 				$('.notifications').remove();
   620         top: this.previousZoomedSN.position().top,
   858 				this.filterGesture(gestureReceived, 'valid');
   621         left: this.previousZoomedSN.position().left
   859 				this.searchFilter(gestureReceived);
   622     }, this.config['preUnzoomTime']);
   860 			}
   623     $('#prezoomContainer-' + id).animate(
   861 		}
   624     {
   862 		
   625         width: this.snapshotWidth + margin,
   863 		if(this.helpDisplayed)
   626         height: this.snapshotHeight + margin,
   864 		{
   627         top: this.previousZoomedSN.position().top,
   865 			this.removeHelp();
   628         left: this.previousZoomedSN.position().left
   866 		}
   629     }, this.config['preUnzoomTime'], function(){ $(this).remove(); this.zoomed = false; });
   867 	}
   630 }
   868 	// /!\/!\ //
   631 
       
   632 
       
   633 /*
       
   634  * Zoom d'un snapshot en plein écran.
       
   635  */
       
   636 mosaic.prototype.zoom = function()
       
   637 {
       
   638     var _this = this;
       
   639     
       
   640     //Si la mosaïque est en pleine écran, pas la peine de zoomer.
       
   641     if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH")
       
   642 	{
       
   643         return;
       
   644 	}
       
   645 	
       
   646 	this.removePointMosaicPrezoom();
       
   647     
       
   648     //On prend les attributs nécessaires au calculs.
       
   649     var margin = this.marginWidth, len = this.config['length'], imgs = this.config['imagesToShow'], zoomedMargin = this.config['zoomedMargin'];
       
   650 	var zoomPercentage = this.config['zoomPercentage'];
       
   651     var initMPWidth = this.previousZoomedSN.width() * len + margin*len, initMPHeight = this.previousZoomedSN.height() * (imgs / len) + margin*(imgs / len);
       
   652     var newMPWidth = initMPWidth * len + zoomedMargin * (len), newMPHeight = initMPHeight * (imgs / len) + zoomedMargin * ((imgs / len));
       
   653     var newPreMPWidth = initMPWidth * len * zoomPercentage + zoomedMargin * (len), newPreMPHeight = initMPHeight * (imgs / len) * zoomPercentage + zoomedMargin * ((imgs / len));
       
   654     
       
   655     //Dimensions et coordonnées initiales du div sur lequel on zoom.
       
   656     var initialDivWidth = this.previousZoomedSN.width(), initialDivHeight = this.previousZoomedSN.height();
       
   657     var initialDivTop = this.previousZoomedSN.position().top, initialDivLeft = this.previousZoomedSN.position().left;
       
   658     //Dimensions et coordonnées finales du div.
       
   659     var finalDivWidth = initialDivWidth * (zoomPercentage+1), finalDivHeight = initialDivHeight * (zoomPercentage+1);
       
   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;
       
   661     var newSnWidth = initMPWidth * zoomPercentage, newSnHeight = initMPHeight * zoomPercentage;
       
   662     
       
   663     this.preUnzoom(this);
       
   664     /*SINGULARITE*/
       
   665     this.fullscreen = true;
       
   666     
       
   667     //On passe l'image du snapshot pointé en HD.
       
   668     var zoomedImg = $('img', this.previousZoomedSN);
       
   669     var src = zoomedImg.attr('src');
       
   670     zoomedImg.attr('src', src.replace('-little/', '/'));
       
   671     
       
   672     //On récupère son ID.
       
   673     var tab, zoomedImgId;
       
   674     tab = _this.previousId.split('-');
       
   675     zoomedImgId = tab[1];
       
   676 	
       
   677 	//On donne les dimensions des snapshots.
       
   678 	$('.snapshotDivs').animate(
       
   679 	{
       
   680 		width: newSnWidth,
       
   681 		height: newSnHeight,
       
   682 		margin: zoomedMargin/2 + 'px',
       
   683 	}, this.config['zoomTime']);
       
   684 	
       
   685 	if(this.currentMode != 'NO-USER')
       
   686 	{
       
   687 		//Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
       
   688 		$('.snapshotDivs').animate(
       
   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 	
       
   699     //On zoome sur la mosaïque.
       
   700     $('#mainPanel').animate(
       
   701     {
       
   702         width: newPreMPWidth,
       
   703         height: newPreMPHeight,
       
   704         top: newZoomTop,
       
   705         left: newZoomLeft
       
   706     }, this.config['zoomTime'], function()
       
   707     {
       
   708         //On charge les interactions avec les voisins.
       
   709         _this.centerId = zoomedImgId;
       
   710 		
       
   711 		if(_this.currentMode != "NO-USER")
       
   712 		{
       
   713 			_this.currentMode = 'VIDEO';
       
   714 			_this.listenToNeighbours();
       
   715 		}
       
   716 		
       
   717 		_this.snTop = (zoomedImg.position().top + newZoomTop + _this.MPTop_margin), _this.snLeft = (zoomedImg.position().left + newZoomLeft);
       
   718 		_this.snWidth = newSnWidth + 1, _this.snHeight = newSnHeight + 1;
       
   719 		
       
   720 		_this.notifyTopVideo = newZoomTop;
       
   721 		_this.notifyLeftVideo = newZoomLeft;
       
   722 		
       
   723 		_this.loadPlayer(_this.snTop, _this.snLeft, _this.snWidth, _this.snHeight, newZoomTop, newZoomLeft);
       
   724     });
       
   725 }
   869 }
   726 
   870 
   727 /*
   871 /*
   728  * Chargement du player basé sur le metadataplayer.
   872  * Chargement du player basé sur le metadataplayer.
   729 */
   873 */
   730 mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft)
   874 mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft, timeToGo)
   731 {
   875 {
   732 	var _this = this;
   876 	var _this = this;
   733 	
   877 	
   734 	//On configure les options de lancement.
   878 	//On configure les options de lancement.
   735 	IriSP.libFiles.defaultDir = "../lib/";
   879 	IriSP.libFiles.defaultDir = "../lib/";
   780 		left: newZoomLeft
   924 		left: newZoomLeft
   781 	});
   925 	});
   782 	
   926 	
   783 	//On démarre le player.
   927 	//On démarre le player.
   784 	this.player = null;
   928 	this.player = null;
       
   929 	
   785 	this.player = new IriSP.Metadataplayer(_config, _metadata);
   930 	this.player = new IriSP.Metadataplayer(_config, _metadata);
   786 	
   931 	
   787 	if(this.currentMode == 'NO-USER')
   932 	this.player.onLoad(function()
   788 	{
   933 	{
   789 		this.player.onLoad(function()
   934 		if(_this.currentMode == 'NO-USER')
   790 		{
   935 		{
   791 			console.log(_this.player);
   936 			//On peut s'approcher de la kinect.
   792 			console.log(_this.player.popcorn);
   937 			_this.canStart = true;
   793 			//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
   938 			console.log('CAN START !');
   794 			if(_this.player.popcorn != undefined)
   939 			// console.log(_this.player);
   795 			{
   940 			// console.log(_this.player.popcorn);
   796 				_this.player.popcorn.listen('pause', function()
   941 		}
   797 				{
   942 		//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
   798 					_this.unzoom();
   943 		if(_this.player.popcorn)
   799 				});
   944 		{
   800 			}
   945 			_this.player.popcorn.listen('pause', function()
   801 		});
   946 			{
   802 	}
   947 				//Si l'utilisateur a mis en pause.
       
   948 				if(_this.userPaused)
       
   949 				{
       
   950 				
       
   951 				}
       
   952 				//Si la pause est naturelle (fin de la timeline, dézoom, déplacement vers un voisin).
       
   953 				else
       
   954 				{
       
   955 					//Si c'est en mode sans utilisateur.
       
   956 					if(_this.currentMode == 'NO-USER')
       
   957 					{
       
   958 						//On dézoome.
       
   959 						_this.unzoom();
       
   960 					}
       
   961 					//Sinon.
       
   962 					else
       
   963 					{
       
   964 						//Si ce n'est pas causé par un déplacement ou un dézoom.
       
   965 						if(!_this.currentlyMoving && !_this.currentlyUnzooming)
       
   966 						{
       
   967 							//On réinitialise la position du curseur à la prochaine lecture de la vidéo.
       
   968 							console.log('REINIT');
       
   969 							//On passe a la video suivante.
       
   970 							console.log('AUTOMOVE');
       
   971 							
       
   972 							//Si on est en mode timeline et qu'on est en pause, c'est probablement que l'user a placé le curseur à la fin.
       
   973 							if(_this.currentMode != 'TIMELINE')
       
   974 							{
       
   975 								_this.playNextVideo();
       
   976 							}
       
   977 							//_this.timeToGoAt[parseInt(_this.centerId)] = 0;
       
   978 							console.log('time to go at to 0');
       
   979 							// return;
       
   980 						}
       
   981 					}
       
   982 				}
       
   983 			});
       
   984 			// console.log('mosaic filtered : ' + _this.isMosaicFiltered);
       
   985 			
       
   986 			_this.player.popcorn.on("markersready", function()
       
   987 			{
       
   988 				_this.playerIsReady = true;
       
   989 				
       
   990 				if(_this.currentMode == 'VIDEO' || _this.currentMode == 'SEARCH' || _this.currentMode == 'TIMELINE')
       
   991 				{
       
   992 					_this.canSwipe = true;
       
   993 				}
       
   994 				
       
   995 				console.log('TIME TO GO AT : ' + _this.timeToGoAt[_this.centerId], _this.centerId, _this.imgs[_this.centerId]);
       
   996 				
       
   997 				if(_this.isMosaicFiltered)
       
   998 				{
       
   999 					if(_this.currentSearchGesture == '')
       
  1000 					{
       
  1001 						_this.removeFilter();
       
  1002 					}
       
  1003 					else
       
  1004 					{
       
  1005 						_this.currentMode = 'SEARCH';
       
  1006 						// console.log(_this.currentSearchGesture);
       
  1007 						_this.player.widgets[0].searchByGesture(_this.currentSearchGesture);
       
  1008 						_this.isCurrentlyInASearchByGesture = _this.player.widgets[0].isCurrentlyInASearchByGesture;
       
  1009 						
       
  1010 						if(_this.timeToGoAt[_this.centerId] === 0 && _this.player.widgets[0].atLeastOneSearchMarker(_this.currentSearchGesture))
       
  1011 						{
       
  1012 							_this.player.widgets[0].goToFirstSearchedMarker(_this.currentSearchGesture);
       
  1013 						}
       
  1014 						else
       
  1015 						{
       
  1016 							_this.player.popcorn.currentTime(_this.timeToGoAt[_this.centerId]);
       
  1017 						}
       
  1018 					}
       
  1019 				}
       
  1020 				// /!\ //
       
  1021 				else
       
  1022 				{
       
  1023 					if(_this.player.popcorn)
       
  1024 					{
       
  1025 						_this.player.popcorn.currentTime(_this.timeToGoAt[_this.centerId]);
       
  1026 					}
       
  1027 				}
       
  1028 			});
       
  1029 		}
       
  1030 	});
   803 }
  1031 }
   804 
       
   805 /*
       
   806  * Retour à la taille normale de la mosaïque.
       
   807  */
       
   808 mosaic.prototype.unzoom = function()
       
   809 {
       
   810     //Si on n'est pas en plein écran, on quitte.
       
   811 	console.log("'" + this.currentMode + "'");
       
   812     if(this.currentMode != "SEARCH" && this.currentMode != "VIDEO" && this.currentMode != "NO-USER" && this.currentMode.indexOf("INCOMING") == -1)
       
   813 	{
       
   814         return;
       
   815 	}
       
   816 	
       
   817 	this.snTop = 0;
       
   818 	this.snLeft = 0;
       
   819 	this.Width = 0;
       
   820 	this.snHeight = 0;
       
   821     
       
   822     //On charge les attributs nécessaires aux calculs.
       
   823     var sWidth = this.snapshotWidth, sHeight = this.snapshotHeight;
       
   824     var mpWidth = this.width, mpHeight = this.height;
       
   825     var _this = this;
       
   826     
       
   827     //On passe le snapshot sur lequel on a zoomé en SD.
       
   828     var zoomedImg = $('img', this.previousZoomedSN);
       
   829     var src = zoomedImg.attr('src');
       
   830     zoomedImg.attr('src', src.replace('snapshots/', 'snapshots-little/'));
       
   831 	
       
   832 	_this.player.widgets[0].freePlayer();
       
   833 	$('.LdtPlayer').remove();
       
   834 	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
       
   835 	_this.reaffectKeyPress();
       
   836     
       
   837     //On rend leur opacité aux snapshots. Qui ne sont alors plus grisés.
       
   838     $('.snapshotDivs').animate(
       
   839     {
       
   840         width: sWidth,
       
   841         height: sHeight,
       
   842         margin: this.marginWidth/2 + 'px'
       
   843     }, this.config['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 	
       
   864     //On dézoom sur la mosaïque.
       
   865     $('#mainPanel').animate(
       
   866     {
       
   867         width: mpWidth,
       
   868         height: mpHeight,
       
   869         top: '0px',
       
   870         left: '0px'
       
   871     }, this.config['unzoomTime'], function()
       
   872     {
       
   873         //On n'est plus en plein écran, et on ne peut plus se déplacer vers le prochain voisin.
       
   874         _this.fullscreen = false;
       
   875         _this.canMoveToNeighbour = false;
       
   876 		
       
   877 		if(_this.currentMode != 'NO-USER')
       
   878 		{
       
   879 			//On revient en mode MOSAIC.
       
   880 			_this.currentMode = 'MOSAIC';
       
   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 		}
       
   889     });
       
   890 }
       
   891 
       
   892 /*
       
   893  * Affecte les listeners mouseenter aux voisins lors d'une vue en plein écran.
       
   894  */
       
   895 mosaic.prototype.listenToNeighbours = function()
       
   896 {
       
   897     ////TEST
       
   898     //$('.test').empty();
       
   899     var _this = this;
       
   900     
       
   901 	this.canMoveToNeighbour = false;
       
   902     var currentLine = Math.floor(this.centerId / this.config['length']), currentColumn = this.centerId % this.config['length'];
       
   903     var zoomedImg = $('img', this.previousZoomedSN);
       
   904     
       
   905     //On cherche l'ID des voisins.
       
   906     //Si le voisin de gauche est sur la même ligne, on n'est pas sur la bordure de gauche.
       
   907     this.neighboursIds[0] = (currentColumn > 0) ? (this.centerId - 1) : -1;
       
   908     //Si le voisin de droite est sur la même ligne, on n'est pas sur la bordure de droite.
       
   909     this.neighboursIds[1] = (currentColumn < this.config['length']) ? (+this.centerId + 1) : -1;
       
   910     //Si le voisin du haut est sur la même colonne, on n'est pas sur la bordure du haut.
       
   911     this.neighboursIds[2] = (currentLine > 0) ? (this.centerId - this.config['length']) : -1;
       
   912     //Si le voisin du bas est sur la même colonne, on n'est pas sur la bordure du bas.
       
   913     this.neighboursIds[3] = (currentLine < (this.config['imagesToShow'] / this.config['length'])) ? (+this.centerId + this.config['length']) : -1;
       
   914     
       
   915 	//ID du cadre voisin.
       
   916 	var preId;
       
   917 	
       
   918     for(var i = 0 ; i < this.neighboursIds.length ; i++)
       
   919     {
       
   920         if(this.neighboursIds[i] != -1)
       
   921         {
       
   922 			preId = '#neighbourFrameBorder-' + this.neighboursIds[i];
       
   923             //On permet le déplacement vers les voisins.
       
   924             // $('#snapshotDiv-' + this.neighboursIds[i] + ', ' + preId + '-left,' + preId + '-right,' + preId + '-up,' + preId + '-down').mouseenter(mos.selectNeighbour);
       
   925 			
       
   926             $('#snapshotDiv-' + this.neighboursIds[i]).mouseover(function()
       
   927 			{
       
   928 				_this.selectNeighbour($(this));
       
   929 			});
       
   930         }
       
   931     }
       
   932 }
       
   933 
       
   934 /*
       
   935  * Change la coloration d'une bordure où on se positionne lors d'une vue en plein écran.
       
   936  */
       
   937 mosaic.prototype.selectNeighbour = function(neighbour)
       
   938 {
       
   939     ////TEST
       
   940     //$('.test').append(mos.currentMode + " " + $(this).attr('id') + " " + 'snapshotDiv-' + mos.centerId + ',');
       
   941 	var _this = this;
       
   942 	
       
   943     //Si on est en mode VIDEO (plein écran) ET si le snapshot pointé est un voisin.
       
   944     
       
   945     if((this.currentMode == 'VIDEO') && (neighbour.attr('id') != 'snapshotDiv-' + this.centerId))
       
   946     {
       
   947         //On crée le cadre qui va être superposé au voisin.
       
   948         //On le colle au voisin.
       
   949 		var tab = neighbour.attr('id').split('-');
       
   950 		var snapshotId = tab[1];
       
   951         var neighbourFrame = '';
       
   952 		var marginValue = parseFloat(neighbour.css('margin'));
       
   953 		
       
   954 		neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"><div class="neighbourImgBg" id="neighbourImgBg-' + snapshotId + '"><div class="neighbourImg" id="neighbourImg-' + snapshotId + '"></div></div></div>';
       
   955 		
       
   956         $('#mainPanel').append(neighbourFrame);
       
   957 		
       
   958 		//On positionne le div de background juste au niveau du voisin.
       
   959         $('#neighbourFrame-' + snapshotId).css(
       
   960 		{
       
   961 			'top': (+neighbour.position().top + marginValue),
       
   962 			'left': (+neighbour.position().left + marginValue),
       
   963 			'width': neighbour.width(),
       
   964 			'height': neighbour.height()
       
   965 		});
       
   966 		//On positionne le div de background noir juste au niveau de l'image du voisin.
       
   967         $('#neighbourImgBg-' + snapshotId).css(
       
   968 		{
       
   969 			'top': marginValue,
       
   970 			'left': marginValue,
       
   971 			'width': neighbour.width() - marginValue*2,
       
   972 			'height': neighbour.height() - marginValue*2,
       
   973 		});
       
   974 		//On met par dessus le div de l'image clonée du voisin.
       
   975 		$('#neighbourImg-' + snapshotId).css(
       
   976 		{
       
   977 			'top': 0,
       
   978 			'left': 0,
       
   979 			'width': neighbour.width() - marginValue*2,
       
   980 			'height': neighbour.height() - marginValue*2,
       
   981 			'background-image': 'url("' + $('img', neighbour).attr('src') + '")',
       
   982 			'background-size': neighbour.width() + 'px ' + neighbour.height() + 'px',
       
   983 			'background-position': -marginValue + 'px ' + -marginValue + 'px',
       
   984 			'opacity': '0.4'
       
   985 		});
       
   986 		
       
   987 		var fId = '#neighbourFrame-' + snapshotId;
       
   988 		
       
   989 		$(fId).animate(
       
   990         {
       
   991             //On le fait apparaître.
       
   992             opacity: '1'
       
   993         }, _this.config['timeNeighbourGlowing'], function()
       
   994         {
       
   995             //On peut désormais se déplacer vers ce voisin.
       
   996             _this.canMoveToNeighbour = true;
       
   997         });
       
   998 		//Lorsqu'on quitte un des snapshots (bien entendu le voisin en question), on retire le cadre.
       
   999 		//Si on clique sur le voisin ou son cadre, on passe au voisin suivant.
       
  1000 		$(fId).mouseout(function()
       
  1001 		{
       
  1002 			_this.deselectNeighbour($(this))
       
  1003 		}).click(function()
       
  1004 		{
       
  1005 			_this.moveToNeighbour($(this))
       
  1006 		});
       
  1007     }
       
  1008 }
       
  1009 
       
  1010 /*
       
  1011  * Change la coloration d'une bordure quittée lors d'une vue en plein écran.
       
  1012  */
       
  1013 mosaic.prototype.deselectNeighbour = function(neighbour)
       
  1014 {
       
  1015     ////TEST
       
  1016     //$('.test').append('un,');
       
  1017 	
       
  1018     //On ne peut plus se déplacer vers les voisins.
       
  1019     this.canMoveToNeighbour = false;
       
  1020     
       
  1021 	//On récupère le voisin.
       
  1022 	var neighbourFrame = neighbour;
       
  1023 	
       
  1024     //Si on est en mode VIDEO.
       
  1025     if(this.currentMode == 'VIDEO')
       
  1026     {
       
  1027         //On le fait disparaître progressivement.
       
  1028         neighbourFrame.animate(
       
  1029         {
       
  1030             opacity: '0'
       
  1031         }, this.config['timeNeighbourUnglowing'], function()
       
  1032         {
       
  1033             //Une fois invisible, on le supprime.
       
  1034             neighbourFrame.remove();
       
  1035         });
       
  1036     }
       
  1037 }
       
  1038 
       
  1039 /*
       
  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.
       
  1041  */
       
  1042 mosaic.prototype.moveToNeighbour = function(neighbour)
       
  1043 {
       
  1044 	var _this = this;
       
  1045     //Si on ne peut pas se déplacer vers les voisins, on quitte.
       
  1046     if(!_this.canMoveToNeighbour)
       
  1047 	{
       
  1048         return;
       
  1049 	}
       
  1050     
       
  1051     //On obtient l'ID de destination.
       
  1052     var tab = neighbour.attr('id').split('-');
       
  1053     var destinationId = tab[1];
       
  1054     
       
  1055     //On charge les attributs nécessaires aux calculs.
       
  1056 	var length = _this.config['length'];
       
  1057     var MPCurrentTop = $('#mainPanel').position().top, MPCurrentLeft = $('#mainPanel').position().left;
       
  1058     var divideCoeffTop = Math.floor(destinationId / length) == 0 ? 1 : Math.floor(destinationId / length);
       
  1059     var divideCoeffLeft = destinationId % length == 0 ? 1 : destinationId % length;
       
  1060     var neighbourFrameTop = $('#snapshotDiv-' + destinationId).position().top, neighbourFrameLeft = $('#snapshotDiv-' + destinationId).position().left;
       
  1061     
       
  1062     //On définit pour le déplacement vertical s'il est nécessaire de se déplacer en haut ou en bas.
       
  1063     if(_this.previousZoomedSN.position().top > neighbourFrameTop)
       
  1064         MPCurrentTop += Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
       
  1065     else if(_this.previousZoomedSN.position().top < neighbourFrameTop)
       
  1066         MPCurrentTop -= Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
       
  1067     //On définit pour le déplacement horizontal s'il est nécessaire de se déplacer à gauche ou à droite.
       
  1068     if(_this.previousZoomedSN.position().left > neighbourFrameLeft)
       
  1069         MPCurrentLeft += Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
       
  1070     else if(_this.previousZoomedSN.position().left < neighbourFrameLeft)
       
  1071         MPCurrentLeft -= Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
       
  1072     
       
  1073     //On passe le snapshot de destination en HD.
       
  1074     var destinationImg = $('#snapshot-' + destinationId);
       
  1075     var destinationImgSrc = destinationImg.attr('src');
       
  1076     destinationImg.attr('src', destinationImgSrc.replace('snapshots-little/', 'snapshots/'));
       
  1077     
       
  1078     //On passe l'ancien snapshot en SD.
       
  1079     var currentImgSrc = $('img', _this.previousZoomedSN).attr('src');
       
  1080     $('img', _this.previousZoomedSN).attr('src', currentImgSrc.replace('snapshots/', 'snapshots-little/'));
       
  1081     
       
  1082     //On obtient l'ID du div de coloration du snapshot vers lequel on se déplace afin de le supprimer.
       
  1083     var neighbourFrame = neighbour;
       
  1084     var tab = neighbourFrame.attr('id').split('-');
       
  1085     _this.centerId = tab[1];
       
  1086     $(this).css('opacity', '0');
       
  1087     neighbourFrame.remove();
       
  1088     
       
  1089 	_this.player.widgets[0].freePlayer();
       
  1090 	$('.LdtPlayer').remove();
       
  1091 	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
       
  1092 	_this.reaffectKeyPress();
       
  1093 	
       
  1094     //On grise le snapshot qu'on vient de quitter.
       
  1095     _this.previousZoomedSN.animate(
       
  1096     {
       
  1097         opacity: '0.4'
       
  1098     });
       
  1099     
       
  1100     //On se déplace.
       
  1101     $('#mainPanel').animate(
       
  1102     {
       
  1103         top: MPCurrentTop,
       
  1104         left: MPCurrentLeft
       
  1105     }, _this.config['timeMovingToNeighbour'], function()
       
  1106     {
       
  1107         //On fait apparaître le snapshot vers lequel on s'est déplacé.
       
  1108         $('#snapshotDiv-' + destinationId).animate(
       
  1109         {
       
  1110             opacity: '1'
       
  1111         }, _this.config['zoomTime'], function()
       
  1112         {
       
  1113             //On recharge les voisins.
       
  1114             $('.snapshotDivs').unbind('mouseenter', _this.selectNeighbour);
       
  1115             _this.previousZoomedSN = $('#snapshotDiv-' + _this.centerId);
       
  1116             _this.listenToNeighbours();
       
  1117 			
       
  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);
       
  1122         });
       
  1123     });
       
  1124 }
       
  1125 
       
  1126 /*
       
  1127  * Déchargement du contenu de la mosaïque pour le chargement de la mosaïque locale.
       
  1128  */
       
  1129 mosaic.prototype.unload = function()
       
  1130 {
       
  1131     //On supprime les event listeners des objets de la mosaïque.
       
  1132     $('.snapshotDivs').unbind();
       
  1133     $('.snapshots').unbind();
       
  1134     $('.prezoomContainers').unbind();
       
  1135     //On supprime physiquement les objets.
       
  1136     $('#mainPanel').empty();
       
  1137 }
       
  1138 
       
  1139 /*
       
  1140  * Centre verticalement un snapshot.
       
  1141  */
       
  1142 /*function verticalCenterImg(mosaic, img)
       
  1143 {
       
  1144     //On récupère sa hauteur.
       
  1145     var image_height = img.height();
       
  1146     //Calcule la marge du haut de chaque div pour le centrage.
       
  1147     if(mosaic.top_margin == undefined)
       
  1148         mosaic.top_margin = (mosaic.snapshotHeight > image_height) ? (mosaic.snapshotHeight - image_height)/2 : (image_height - mosaic.snapshotHeight)/2;
       
  1149     //On centre le snapshot.
       
  1150     img.css('margin-top', mosaic.top_margin).css('margin-bottom', mosaic.top_margin);
       
  1151 }*/
       
  1152 
  1032 
  1153 /*
  1033 /*
  1154  * Permet de tester l'égalité des éléments de deux objets.
  1034  * Permet de tester l'égalité des éléments de deux objets.
  1155  * Pour ce faire on compare les éléments définissant ces objets.
  1035  * Pour ce faire on compare les éléments définissant ces objets.
  1156  */
  1036  */
  1187 				$.getJSON(val_video.metadata, function(meta)
  1067 				$.getJSON(val_video.metadata, function(meta)
  1188 				{
  1068 				{
  1189 					if(_this.config['local'] == 'true')
  1069 					if(_this.config['local'] == 'true')
  1190 					{
  1070 					{
  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'));
  1071 						_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'));
  1072 						// 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 					}
  1073 					}
  1194 					else
  1074 					else
  1195 					{
  1075 					{
  1196 						_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
  1076 						_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'));
  1077 						// console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
  1198 					}
  1078 					}
  1199 				});
  1079 				});
  1200 				_this.imgs[_this.ids[i]] = val_video.snapshot;
  1080 				_this.imgs[_this.ids[i]] = val_video.snapshot;
  1201 				_this.urls[_this.ids[i]] = val_video.metadata;
  1081 				_this.urls[_this.ids[i]] = val_video.metadata;
  1202 				console.log('ids : ' + _this.ids[i]);
  1082 				//Au départ, on commence à 0 ms dans les vidéos.
       
  1083 				_this.timeToGoAt[_this.ids[i]] = 0;
       
  1084 				// console.log('ids : ' + _this.ids[i]);
  1203 				i++;
  1085 				i++;
  1204 			});
  1086 			});
  1205 		});
  1087 		});
  1206 		console.log('rdy');
  1088 		// console.log('rdy');
  1207 		_this.loadMosaic();
  1089 		_this.loadMosaic();
  1208 	});
  1090 	});
  1209 }
  1091 }
  1210 
  1092 
  1211 /*
  1093 /*
  1222 		}
  1104 		}
  1223 	}
  1105 	}
  1224 }
  1106 }
  1225 
  1107 
  1226 /*
  1108 /*
  1227  * Lance une recherche par courbes.
       
  1228  */
       
  1229 mosaic.prototype.startSearch = function()
       
  1230 {
       
  1231 	var top, left, width, height, margin_top, inMosaic;
       
  1232 	//Si on est dans le cas d'un filtrage de mosaïque.
       
  1233 	if(this.currentMode == "FILTER")
       
  1234 	{
       
  1235 		var mainPanel = $('#mainPanel');
       
  1236 		top = mainPanel.position().top;
       
  1237 		left = mainPanel.position().left;
       
  1238 		width = mainPanel.width();
       
  1239 		height = mainPanel.height();
       
  1240 		margin_top = this.MPTop_margin;
       
  1241 		inMosaic = true;
       
  1242 	}
       
  1243 	//Sinon si c'est une recherche dans la vidéo.
       
  1244 	else if(this.currentMode == "SEARCH")
       
  1245 	{
       
  1246 		top = this.snTop;
       
  1247 		left = this.snLeft;
       
  1248 		width = this.snWidth;
       
  1249 		height = this.snHeight;
       
  1250 		margin_top = '0px';
       
  1251 		inMosaic = false;
       
  1252 	}
       
  1253 	
       
  1254 	this.searchCanvas = new searchCanvas(top, left, width, height, margin_top, this.timeSearchFade, inMosaic);
       
  1255 	this.searchCanvas.create();
       
  1256 }
       
  1257 
       
  1258 /*
       
  1259  * Quitte une recherche par courbes.
       
  1260  */
       
  1261 mosaic.prototype.leaveSearch = function()
       
  1262 {
       
  1263 	this.searchCanvas.leaveSearch();
       
  1264 }
       
  1265 
       
  1266 /* ===============================================
       
  1267  *												   *
       
  1268  *		      ZONE DES NOTIFICATIONS			   *
       
  1269  *												   *
       
  1270    =============================================== */
       
  1271 
       
  1272 /*
       
  1273  * Affiche la notification de sélection/recherche lorsque la mosaique est complète.
       
  1274 */
       
  1275 mosaic.prototype.notifySelectionSearchMosaicFull = function()
       
  1276 {
       
  1277 	if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") == -1)
       
  1278 	{
       
  1279 		return;
       
  1280 	}
       
  1281 	
       
  1282 	//On spécifie les notifications en div.
       
  1283 	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
       
  1284 	var notification_search = "<div id='notify_search' class='notifications'></div>";
       
  1285 	
       
  1286 	//On les ajoute à la mosaïque.
       
  1287 	$('#mainPanel').append(notification_selection + notification_search);
       
  1288 
       
  1289 	//On calcule leurs coordonnées et dimensions.
       
  1290 	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
       
  1291 	var notify_margin = parseInt($('.notifications').css('margin'));
       
  1292 	var selection_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
       
  1293 	var search_left = selection_left + notify_width + notify_margin;
       
  1294 	
       
  1295 	//On les positionne.
       
  1296 	$('#notify_selection').css(
       
  1297 	{
       
  1298 		left: selection_left
       
  1299 	});
       
  1300 	$('#notify_search').css(
       
  1301 	{
       
  1302 		left: search_left
       
  1303 	});
       
  1304 	
       
  1305 	//On les fait apparaître.
       
  1306 	$('.notifications').css(
       
  1307 	{
       
  1308 		opacity: "0.9"
       
  1309 	});
       
  1310 }
       
  1311 
       
  1312 /*
       
  1313  * Supprime la notification de sélection/recherche lorsque la mosaique est complète.
       
  1314 */
       
  1315 mosaic.prototype.removeSelectionSearchMosaicFull = function()
       
  1316 {
       
  1317 	$('#notify_selection, #notify_search').remove();
       
  1318 }
       
  1319 
       
  1320 /*
       
  1321  * Affiche la notification de maintient du pointage lors d'une phase de prézoom.
       
  1322 */
       
  1323 mosaic.prototype.notifyPointMosaicPrezoom = function()
       
  1324 {
       
  1325 	if($('#notify_point').length > 0 || this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") == -1)
       
  1326 	{
       
  1327 		return;
       
  1328 	}
       
  1329 	
       
  1330 	//On spécifie les notifications en div.
       
  1331 	var notification_point = "<div id='notify_point' class='notifications'></div>";
       
  1332 	
       
  1333 	//On les ajoute à la mosaïque.
       
  1334 	$('#mainPanel').append(notification_point);
       
  1335 	
       
  1336 	//On calcule leurs coordonnées et dimensions.
       
  1337 	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
       
  1338 	var notify_margin = parseInt($('.notifications').css('margin'));
       
  1339 	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
       
  1340 	
       
  1341 	//On les positionne.
       
  1342 	$('#notify_point').css(
       
  1343 	{
       
  1344 		left: point_left
       
  1345 	});
       
  1346 	
       
  1347 	//On les fait apparaître.
       
  1348 	$('.notifications').css(
       
  1349 	{
       
  1350 		opacity: "0.9"
       
  1351 	});
       
  1352 }
       
  1353 
       
  1354 /*
       
  1355  * Supprime la notification de maintient du pointage.
       
  1356 */
       
  1357 mosaic.prototype.removePointMosaicPrezoom = function()
       
  1358 {	
       
  1359 	$('#notify_point').remove();
       
  1360 }
       
  1361 
       
  1362 /*
       
  1363  * Affiche l'aide.
       
  1364 */
       
  1365 mosaic.prototype.notifyHelp = function()
       
  1366 {
       
  1367 	if(this.helpDisplayed)
       
  1368 	{
       
  1369 		return;
       
  1370 	}
       
  1371 	
       
  1372 	this.removeSelectionSearchMosaicFull();
       
  1373 	this.removePointMosaicPrezoom();
       
  1374 	
       
  1375 	this.helpDisplayed = true;
       
  1376 	
       
  1377 	var search_2hands_tab = ['no_motion', 'right_angle', 'contact', 'grand_jete', 'circle', 'screw', 'arc', 'rythme', 'slow', 'up_down', 'wave', 'wheel'];
       
  1378 	var search_body_tab = ['bend', 'fall', 'jump', 'hello', 'knee_up'];
       
  1379 	var controls_1hand_tab = ['selection'];
       
  1380 	
       
  1381 	//On spécifie les notifications en div.
       
  1382 	var search_title = "<div id='search_title'></div>";
       
  1383 	var search_img = "<div id='search_img' class='notify_imgs'></div>";
       
  1384 	var search_2hands_text = "<div id='search_2hands_text'></div>";
       
  1385 	var search_2hands_imgs = "<div id='search_2hands_imgs' class='notify_imgs_big'>";
       
  1386 	
       
  1387 	for(var i = 0 ; i < search_2hands_tab.length ; i++)
       
  1388 	{
       
  1389 		search_2hands_imgs += "<div id='2hands_" + search_2hands_tab[i] + "' class='notify_imgs_small'></div>";
       
  1390 	}
       
  1391 	search_2hands_imgs += "</div>";
       
  1392 	
       
  1393 	var search_body_text = "<div id='search_body_text'></div>";
       
  1394 	var search_body_imgs = "<div id='search_2hands_imgs' class='notify_imgs'>"
       
  1395 	
       
  1396 	for(var i = 0 ; i < search_body_tab.length ; i++)
       
  1397 	{
       
  1398 		search_body_imgs += "<div id='body_" + search_body_tab[i] + "' class='notify_imgs_small'></div>";
       
  1399 	}
       
  1400 	search_body_imgs += "</div>";
       
  1401 	
       
  1402 	var controls_title = "<div id='controls_title'></div>";
       
  1403 	var controls_img = "<div id='controls_img' class='notify_imgs'></div>";
       
  1404 	var controls_1hand_text = "<div id='controls_1hand_text'></div>";
       
  1405 	var controls_1hand_imgs = "<div id='controls_1hand_imgs' class='notify_imgs'>";
       
  1406 	
       
  1407 	for(var i = 0 ; i < controls_1hand_tab.length ; i++)
       
  1408 	{
       
  1409 		controls_1hand_imgs += "<div id='1hand_" + controls_1hand_tab[i] + "' class='notify_imgs_small'></div>";
       
  1410 	}
       
  1411 	controls_1hand_imgs += "</div>";
       
  1412 	
       
  1413 	var help_search = "<div id='help_search'>" + search_title + search_img + search_2hands_text + search_2hands_imgs + search_body_text + search_body_imgs + "</div>";
       
  1414 	var help_controls = "<div id='help_controls'>" + controls_title + controls_img + controls_1hand_text + controls_1hand_imgs + "</div>";
       
  1415 	
       
  1416 	var notification_help = "<div id='notify_help'>" + help_search + "<div id='help_sep'></div>" + help_controls + "</div>";
       
  1417 	
       
  1418 	//On les ajoute à la mosaïque.
       
  1419 	$('body').append(notification_help);
       
  1420 	
       
  1421 	//On calcule leurs coordonnées et dimensions.
       
  1422 	var notify_width = $(window).width(), notify_height = $(window).height();
       
  1423 	var notify_margin = parseInt($('#notify_help').css('margin'));
       
  1424 	var notify_ = 10;
       
  1425 	
       
  1426 	//On les positionne.
       
  1427 	$('#notify_help').css(
       
  1428 	{
       
  1429 		left: "0px",
       
  1430 		top: "0px",
       
  1431 		width: notify_width - notify_margin * 2,
       
  1432 		height: notify_height - notify_margin * 2
       
  1433 	});
       
  1434 	
       
  1435 	var search_width = $('#help_search').width();
       
  1436 	
       
  1437 	$('#search_title').html('Recherche');
       
  1438 	$('#search_2hands_text').html('Gestes à effectuer avec les deux mains');
       
  1439 	$('#search_body_text').html('Gestes à effectuer avec le corps entier');
       
  1440 	
       
  1441 	for(var i = 0 ; i < search_2hands_tab.length ; i++)
       
  1442 	{
       
  1443 		$("#2hands_" + search_2hands_tab[i]).css("background-image", "url('./pictos/help/" + search_2hands_tab[i] + ".png')");
       
  1444 		//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
       
  1445 	}
       
  1446 	
       
  1447 	for(var i = 0 ; i < search_body_tab.length ; i++)
       
  1448 	{
       
  1449 		$("#body_" + search_body_tab[i]).css("background-image", "url('./pictos/help/" + search_body_tab[i] + ".png')");
       
  1450 		//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
       
  1451 	}
       
  1452 	
       
  1453 	$('#controls_title').html('Contrôles');
       
  1454 	$('#controls_1hand_text').html('Gestes à effectuer avec une seule main');
       
  1455 	
       
  1456 	for(var i = 0 ; i < controls_1hand_tab.length ; i++)
       
  1457 	{
       
  1458 		$("#1hand_" + controls_1hand_tab[i]).css("background-image", "url('./pictos/help/" + controls_1hand_tab[i] + ".png')");
       
  1459 		//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
       
  1460 	}
       
  1461 	
       
  1462 	//On les fait apparaître.
       
  1463 	$('#notify_help').css(
       
  1464 	{
       
  1465 		opacity: "1"
       
  1466 	});
       
  1467 	
       
  1468 	$('.notify_imgs_big').css(
       
  1469 	{
       
  1470 		opacity: "1"
       
  1471 	});
       
  1472 }
       
  1473 
       
  1474 /*
       
  1475  * Supprime l'aide.
       
  1476 */
       
  1477 mosaic.prototype.removeHelp = function()
       
  1478 {
       
  1479 	if(!this.helpDisplayed)
       
  1480 	{
       
  1481 		return;
       
  1482 	}
       
  1483 	
       
  1484 	var _this = this;
       
  1485 	
       
  1486 	$('#notify_help').fadeOut(this.timeNotifyFade, function()
       
  1487 	{
       
  1488 		_this.helpDisplayed = false;
       
  1489 		$('#notify_help').remove();
       
  1490 	});
       
  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.
  1109  * Rebind keypress pour body.
  1698 */
  1110 */
  1699 mosaic.prototype.reaffectKeyPress = function()
  1111 mosaic.prototype.reaffectKeyPress = function()
  1700 {
  1112 {
  1701 	var _this = this;
  1113 	var _this = this;
  1703 	$('body').keypress(function (event)
  1115 	$('body').keypress(function (event)
  1704 	{
  1116 	{
  1705 		_this.manageControlEvents(event);
  1117 		_this.manageControlEvents(event);
  1706 	});
  1118 	});
  1707 }
  1119 }
       
  1120 
       
  1121 mosaic.prototype.date = function()
       
  1122 {
       
  1123    var date, h, min, s;
       
  1124    date = new Date();
       
  1125    h = date.getHours();
       
  1126    min = date.getMinutes();
       
  1127    s = date.getSeconds();
       
  1128    if (h < 10)
       
  1129       h = "0" + h;
       
  1130    if (min < 10)
       
  1131       min = "0" + min;
       
  1132    if (s < 10)
       
  1133       s = "0" + s;
       
  1134    return (h + ":" + min + ":" + s);
       
  1135 };