Front IDILL :
authorbastiena
Mon, 23 Jul 2012 16:59:35 +0200
changeset 52 277c94533395
parent 51 03ea3d7ddbe1
child 53 5df462180423
Front IDILL : doc updated swipe factorized search bug fixed : when a search is not complete
front_idill/doc/Documentation - Front IDILL.html
front_idill/lib/jquery.mousewheel-2.0.0.js
front_idill/lib/jquery.mousewheel-2.0.0.min.js
front_idill/src/communication/js/client.js
front_idill/src/config.json
front_idill/src/defaults.js
front_idill/src/dico.json
front_idill/src/index.html
front_idill/src/mosaic/css/mosaic.less
front_idill/src/mosaic/js/mosaic.js
front_idill/src/mosaic/js/neighbours.js
front_idill/src/mosaic/js/notifications.js
front_idill/src/mosaic/js/playerControl.js
front_idill/src/mosaic/js/pointers.js
front_idill/src/mosaic/js/search.js
front_idill/src/mosaic/js/zoomInteractions.js
front_idill/src/player/metadataplayer/Timeline.css
front_idill/src/player/metadataplayer/Timeline.js
front_idill/src/search/css/searchCanvas.css
front_idill/src/search/js/curvesDetector.js
front_idill/src/search/js/searchCanvas.js
front_processing/doc/tutorial front processing.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/doc/Documentation - Front IDILL.html	Mon Jul 23 16:59:35 2012 +0200
@@ -0,0 +1,220 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" class="has_sidebar fixed-header earthrise">
+    <head>
+        <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
+        <meta name="description" content="Tutoriel sur le développement et l'utilisation de code Processing utilisant le Middleware TraKERS."/>
+        <meta name="keywords" content="TraKERS, TraKERS Processing, TraKERS Front Processing, TraKERS Front, Kinect Processing"/>
+        <title>BROWSE BY MOTION - Documentation Front IDILL</title>
+    </head>
+    
+    <body>
+		<h2>Sommaire</h2>
+        
+        <ol type="I">
+            <a href="#I"><li>Introduction</li></a>
+            <a href="#II"><li>Lancement</li></a>
+            <a href="#III"><li>Fonctionnalités</li></a>
+            <a href="#IV"><li>Configuration</li></a>
+            <a href="#V"><li>Notices à prendre en compte</li></a>
+        </ol>
+		
+		<hr />
+        
+        <ol type="I" start="1">
+            <h3><a name="#I"><li>Introduction</li></a></h3>
+        </ol>
+        
+		<p>Ce front est un prototype sous forme d'application web développée en javascript permettant de naviguer au sein d'une mosaïque de vidéos indexées.</p>
+
+		<p>Elements requis :
+			<ul>
+				<li>Google Chrome 20 ou supérieur est nécessaire pour lancer ce prototype.</li>
+				<li>WampServer 2 doit être installé.</li>
+				<li>Le dossier Front IDILL doit être copié à la racine du dossier www de Wamp (par défaut dans C:\wamp\www).</li>
+			</ul>
+		</p>
+
+		<p>Si vous souhaitez utiliser le prototype en mode d'interaction Kinect :
+			<ul>
+				<li>Kinect for Xbox 360.</li>
+				<li>Kinect SDK 1.5 de Microsoft.</li>
+				<li>.NET Framework 4.0.</li>
+			</ul>
+		</p>
+		
+        <hr />
+        
+        <ol type="I" start="2">
+            <h3><a name="#II"><li>Lancement</li></a></h3>
+        </ol>
+        
+		<p>
+			<ol type="1" start="1">
+				<li>Lancer wamp.</li>
+				<li>Aller sur Google Chrome à l'adresse : http://localhost/Front%20IDILL</li>
+				<li>Par défaut, le prototype est réglé pour les interactions à la souris. Vous pouvez néanmoins le configurer (voir Configuration) pour qu'il puisse se connecter à un Middleware utilisant Kinect.</li>
+			</ol>
+		</p>
+
+		<p>Lancement en mode Kinect (après avoir réglé le paramètre dans la configuration).</p>
+
+		<p>
+			<ol type="1" start="4">
+				<li>Après avoir lancé le Front, il faut cliquer sur le raccourci l'exécutable "BBM - Middleware.exe". Si vous l'avez supprimé, vous pouvez le retrouvé ainsi : dossier d'installation de BBM\Browse by Motion\Middleware\MainModule.exe.</li>
+				<li>La fenêtre s'ouvre. Dès que vous voyez la sortie vidéo de la Kinect apparaître à l'écran, vous avez connecté le Middleware.</li>
+				<li>Relancez le Front en cliquant dessus et en appuyant sur F5 afin de raffraichir la fenêtre du navigateur.</li>
+			</ol>
+		</p>
+		
+        <hr />
+        
+        <ol type="I" start="3">
+            <h3><a name="#III"><li>Fonctionnalités</li></a></h3>
+        </ol>
+        
+		<p>Dans cette partie, on déclinera les fonctionnalités selon le mode d'interaction utilisé (Souris/Kinect).</p>
+
+		<u><h3><p>Mode d'interaction souris :</p></h3></u>
+		
+		<ol type="1" start="1">
+			<h3><li>Actions de contrôle de l'interface.</li></h3>
+			
+			<ol type="A" start="1">
+				<h4><li>Sélection de la vidéo dans la mosaïque.</li></h4>
+				
+				<p>Lorsque vous vous trouvez dans la mosaïque, vous pouvez survoler les images, qui zoomeront légèrement. Un clic sur une image zoomée vous permettra d'accéder à sa vidéo.</p>
+			</ol>
+			
+			<ol type="A" start="2">
+				<h4><li>Revenir à la mosaïque.</li></h4>
+				
+				<p>Il y a deux interactions possibles pour revenir à la mosaïque.</p>
+				<ul>
+					<li>Le fait de cliquer en dehors de la vidéo centrale.</li>
+					<li>Le fait de tirer la molette de la souris vers vous.</li>
+				</ul>
+			</ol>
+			
+			<ol type="A" start="3">
+				<h4><li>Aller d'une vidéo à une autre.</li></h4>
+				
+				<p>Dans une vidéo, vous pourrez voir 4 bordures, respectivement en haut, en bas, à droite et à gauche de la vidéo centrale. Il y en a 4, sauf si vous vous trouvez sur une extrémité de la mosaïque.
+				Pour passer à une vidéo voisine, il faut mettre la souris sur la vidéo voulue, attendre qu'elle bleuisse et que la notification de changement de vidéo apparaisse en haut de la fenêtre. Ensuite, vous pouvez :</p>
+				
+				<ul>
+					<li>Cliquer sur cette vidéo.</li>
+					<li>Déplacer rapidement le curseur vers la bordure opposée.</li>
+				</ul>
+			</ol>
+		</ol>
+		
+		<ol type="1" start="2">
+			<h3><li>Recherche par courbes.</li></h3>
+			
+			<ol type="A" start="1">
+				<h4><li>Tracé de courbes.</li></h4>
+				
+				<p>Lorsque vous vous trouvez dans la mosaïque, ou sur le lecteur vidéo (au dessus de la timeline), il vous est possible d'effectuer une recherche par courbe en maintenant le bouton gauche de la souris et en la déplaçant. La courbe sera alors tracée par le mouvement du curseur.<br />Dès que l'utilisateur lâche le bouton, la courbe disparaît.</p>
+			</ol>
+			
+			<ol type="A" start="2">
+				<h4><li>Reconnaissance de courbes.</li></h4>
+				
+				<p>Durant le tracé, il peut arriver 4 choses :</p>
+				<ul>
+					<li>Le tracé correspond à plusieurs courbes : Leurs macarons sont affichés en haut de la fenêtre.</li>
+					<li>Le tracé correspond à une seule courbe : Le macaron de la courbe est affiché en haut de la fenêtre et on effectue une recherche sur les marqueurs correspondants à cette courbe.</li>
+					<li>Le tracé correspond à plusieurs courbes, mais le tracé actuel permet de définir une courbe : Si on relâche le bouton de la souris, on valide la courbe qu'on a tracé et on entre dans une recherche.</li>
+					<li>Le tracé ne correspond à aucune courbe répertoriée. Un macaron de geste inconnu s'affiche et le panneau d'aide apparaît. Il est possible de cliquer ou de tracer une nouvelle courbe pour faire disparaître le panneau d'aide.</li>
+				</ul>
+				<p>Une recherche par courbes dans la mosaïque résulte en un filtrage. Plus les vidéos sont opaques et plus le nombre de marqueurs trouvés dans celles-ci sont importants.<br />Une recherche dans une vidéo mettra en surbrillance les marqueurs correspondant au type de marqueur recherché.</p>
+				<p>Une nouvelle requête de recherche écrase la précédente.</p>
+				<p>Si une recherche est effectuée dans la mosaïque, la recherche s'étend à toutes les vidéos contenues.</p>
+				<p>A l'inverse, une recherche dans une vidéo n'affecte pas la mosaïque.</p>
+			</ol>
+			
+			<ol type="A" start="2">
+				<h4><li>Quitter la recherche.</li></h4>
+				
+				<p>Pour quitter une recherche en cours, il suffit de placer le curseur sur le macaron de recherche, qui apparaîtra alors barré. Ensuite, un clic le fait disparaître et quitte la recherche.</p>
+			</ol>
+		</ol>
+
+		<u><h3><p>Mode d'interaction Kinect :</p></h3></u>
+		
+		<p>Deux pointeurs sont affichées lorsque les mains se situent à un certain intervalle de profondeur par rapport à la Kinect. Cet intervalle peut être modifié dans la configuration. Il s'agit de la zone de recherche.</p>
+		
+		<ol type="1" start="1">
+			<h3><li>Actions de contrôle de l'interface.</li></h3>
+			
+			<ol type="A" start="1">
+				<h4><li>Sélection de la vidéo dans la mosaïque.</li></h4>
+				
+				<p>Lorsque vous vous trouvez dans la mosaïque, vous pouvez pointer les images avec un bras, l'image sur laquelle le pointeur correspondant à une de vos mains se trouve zoomera légèrement. Lorsque vous maintenez le pointeur sur une image, une mire se remplira progressivement. Lorsqu'elle sera entièrement remplie, un zoom s'effectuera sur l'image afin de donner l'accès à sa vidéo.</p>
+			</ol>
+			
+			<ol type="A" start="2">
+				<h4><li>Revenir à la mosaïque.</li></h4>
+				
+				<p>Il faut placer les deux pointeurs correspondants aux mains sur les bordures des voisins de la vidéo centrale pour revenir à la mosaïque. Il est possible de le faire horizontalement ou verticalement.</p>
+			</ol>
+			
+			<ol type="A" start="3">
+				<h4><li>Aller d'une vidéo à une autre.</li></h4>
+				
+				<p>Dans une vidéo, vous pourrez voir 4 bordures, respectivement en haut, en bas, à droite et à gauche de la vidéo centrale. Il y en a 4, sauf si vous vous trouvez sur une extrémité de la mosaïque.
+				Pour passer à une vidéo voisine, il faut mettre le pointeur sur la vidéo voulue, attendre qu'elle bleuisse et que la notification de changement de vidéo apparaisse en haut de la fenêtre. Ensuite, vous pouvez déplacer rapidement le pointeur vers la bordure opposée</p>
+			</ol>
+		</ol>
+		
+		<ol type="1" start="2">
+			<h3><li>Recherche par courbes.</li></h3>
+			
+			<p>La recherche dans le mode d'interaction Kinect diffère de celle du mode d'interaction souris dans la mesure où il faut effectuer une demande de recherche. Celle-ci se fait en placant les deux mains dans la zone de recherche et en ne les bougeant plus jusqu'à ce qu'une notification de recherche apparaisse. Dans la mosaïque, les mains peuvent se placer à n'importe quel endroit, alors que dans une vidéo, il faut les placer sur la vidéo centrale.</p>
+			
+			<ol type="A" start="1">
+				<h4><li>Tracé de courbes.</li></h4>
+				
+				<p>Lorsque vous vous trouvez dans la mosaïque, ou sur le lecteur vidéo (au dessus de la timeline), il vous est possible d'effectuer une recherche par courbe en demandant une recherche, puis en déplacant les deux mains dans la zone de recherche. Seul les débuts de courbes valides seront pris en compte (afin d'éviter que le positionnement des mains ne génère trop d'erreurs de reconnaissance). La courbe sera alors tracée par le mouvement du curseur.<br />Dès que l'utilisateur enlève au moins une main de la zone de recherche, la courbe disparaît.</p>
+				<p>Chaque pointeur génère une courbe. L'analyse de courbes est donc double.</p>
+			</ol>
+			
+			<ol type="A" start="2">
+				<h4><li>Reconnaissance de courbes.</li></h4>
+				
+				<p>Durant le tracé, il peut arriver 4 choses :</p>
+				<ul>
+					<li>Le tracé correspond à plusieurs courbes : Leurs macarons sont affichés en haut de la fenêtre.</li>
+					<li>Le tracé correspond à une seule courbe : Le macaron de la courbe est affiché en haut de la fenêtre et on effectue une recherche sur les marqueurs correspondants à cette courbe.</li>
+					<li>Le tracé correspond à plusieurs courbes, mais le tracé actuel permet de définir une courbe : Si on enlève les mains de la zone de recherche, on valide la courbe qu'on a tracé et on entre dans une recherche.</li>
+					<li>Le tracé ne correspond à aucune courbe répertoriée. Un macaron de geste inconnu s'affiche et le panneau d'aide apparaît. Il est possible d'effectuer une recherche gestuelle (voir plus bas) ou de tracer une nouvelle courbe pour faire disparaître le panneau d'aide.</li>
+				</ul>
+				<p>Il est possible aussi d'afficher l'aide en effectuant le geste wave (secouer la main droite horizontalement, le coude formant un angle droit). Au préalable il faut avoir effectué une demande de recherche.</p>
+				<p>Une recherche par courbes dans la mosaïque résulte en un filtrage. Plus les vidéos sont opaques et plus le nombre de marqueurs trouvés dans celles-ci sont importants.<br />Une recherche dans une vidéo mettra en surbrillance les marqueurs correspondant au type de marqueur recherché.</p>
+				<p>Une nouvelle requête de recherche écrase la précédente.</p>
+				<p>Si une recherche est effectuée dans la mosaïque, la recherche s'étend à toutes les vidéos contenues.</p>
+				<p>A l'inverse, une recherche dans une vidéo n'affecte pas la mosaïque.</p>
+			</ol>
+			
+			<ol type="A" start="2">
+				<h4><li>Quitter la recherche.</li></h4>
+				
+				<p>Pour quitter une recherche en cours, il suffit de placer un pointeur sur le macaron de recherche, qui apparaîtra alors barré. Ensuite, une mire se remplit au fur et à mesure. Lorsque la mire est pleine, la notification et la recherche sont enlevées.</p>
+			</ol>
+		</ol>
+		
+		<hr />
+		
+		<ol type="I" start="4">
+            <h3><a name="#IV"><li>Configuration</li></a></h3>
+        </ol>
+		
+		<hr />
+		
+		<ol type="I" start="5">
+            <h3><a name="#V"><li>Notices à prendre en compte</li></a></h3>
+        </ol>
+        
+        <p>Si vous expérimentez des difficultés ou souhaitez nous soumettre une requête, veuillez consulter le fichier contact.txt à la racine du projet.</p>
+    </body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/lib/jquery.mousewheel-2.0.0.js	Mon Jul 23 16:59:35 2012 +0200
@@ -0,0 +1,93 @@
+/* Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Thanks to: Andrew Cobby (@andrewcobby http://github.com/cobbweb)
+ *              - Refactored for jQuery 1.7+ only
+ *              - Use MozMousePixelScroll for new Gecko browsers
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
+ *
+ * Version: 2.0.0
+ *
+ * Recommended for jQuery 1.7+
+ * Should work with older versions though
+ */
+
+(function($,undefined) {
+
+    var types = ['DOMMouseScroll', 'mousewheel', 'MozMousePixelScroll'];
+
+    if ($.event.fixHooks) {
+        for (var i=types.length; i;) {
+            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
+        }
+    }
+
+    $.event.special.mousewheel = {
+        setup: function() {
+            if (this.addEventListener) {
+                for (var i=types.length; i;) {
+                    this.addEventListener(types[--i], handler, false);
+                }
+            } else {
+                this.onmousewheel = handler;
+            }
+        },
+
+        teardown: function() {
+            if (this.removeEventListener) {
+                for (var i=types.length; i;) {
+                    this.removeEventListener(types[--i], handler, false);
+                }
+            } else {
+                this.onmousewheel = null;
+            }
+        }
+    };
+
+    function handler(event) {
+        var orgEvent = event || window.event, args = [].slice.call(arguments, 1), delta = 0, deltaX = 0, deltaY = 0;
+        event = $.event.fix(orgEvent);
+        event.type = "mousewheel";
+
+        // Old school scrollwheel delta
+        if (orgEvent.wheelDelta) {
+            delta = orgEvent.wheelDelta / 120;
+        }
+
+        if (orgEvent.detail) {
+            if (orgEvent.type == types[2]) {
+                // Firefox 4+, unbind old DOMMouseScroll event
+                this.removeEventListener(types[0], handler, false);
+                delta = -orgEvent.detail / 42;
+            } else {
+                delta = -orgEvent.detail / 3;
+            }
+        }
+
+        // New school multidimensional scroll (touchpads) deltas
+        deltaY = delta;
+
+        // Gecko
+        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
+            deltaY = 0;
+            deltaX = -1 * delta;
+        }
+
+        // Webkit
+        if (orgEvent.wheelDeltaY !== undefined) {
+            deltaY = orgEvent.wheelDeltaY / 120;
+        }
+
+        if (orgEvent.wheelDeltaX !== undefined) {
+            deltaX = -1 * orgEvent.wheelDeltaX / 120;
+        }
+
+        // Add event and delta to the front of the arguments
+        args.unshift(event, delta, deltaX, deltaY);
+
+        return ($.event.dispatch || $.event.handle).apply(this, args);
+    }
+
+})(jQuery);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/lib/jquery.mousewheel-2.0.0.min.js	Mon Jul 23 16:59:35 2012 +0200
@@ -0,0 +1,14 @@
+/* Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Thanks to: Andrew Cobby (@andrewcobby http://github.com/cobbweb)
+ *              - Refactored for jQuery 1.7+ only
+ *              - Use MozMousePixelScroll for new Gecko browsers
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
+ *
+ * Version: 2.0.0
+ *
+ * Requires jQuery: 1.7+
+ */(function(a,b){function e(d){var f=d||window.event,g=[].slice.call(arguments,1),h=0,i=0,j=0;return d=a.event.fix(f),d.type="mousewheel",f.wheelDelta&&(h=f.wheelDelta/120),f.detail&&(f.type==c[2]?(this.removeEventListener(c[0],e,!1),h=-f.detail/42):h=-f.detail/3),j=h,f.axis!==b&&f.axis===f.HORIZONTAL_AXIS&&(j=0,i=-1*h),f.wheelDeltaY!==b&&(j=f.wheelDeltaY/120),f.wheelDeltaX!==b&&(i=-1*f.wheelDeltaX/120),g.unshift(d,h,i,j),(a.event.dispatch||a.event.handle).apply(this,g)}var c=["DOMMouseScroll","mousewheel","MozMousePixelScroll"];if(a.event.fixHooks)for(var d=c.length;d;)a.event.fixHooks[c[--d]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,!1);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,!1);else this.onmousewheel=null}}})(jQuery);
\ No newline at end of file
--- a/front_idill/src/communication/js/client.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/communication/js/client.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,17 +1,38 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : client.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit la "classe" client permettant de recevoir les instructions du Middleware, sous forme de sockets (via le serveur WebSocket du Middleware).
+ */
+
 /*
  * Un client est défini par une socket, qui permettra de recevoir les données du server websocket du Middleware.
  * On accède aussi à la mosaïque.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadParameters.
 */
-function client(host, port, _mosaic)
+function Client(host, port, _mosaic)
 {
-	this.socket;
+	this.socket = null;
 	this.mosaic = _mosaic;
 	
 	this.pointerLeft = false;
 	this.pointerRight = false;
 	this.timePointers = 100;
-	this.pointerLeftTimeout;
-	this.pointerRightTimeout;
+	this.pointerLeftTimeout = null;
+	this.pointerRightTimeout = null;
 	this.isLeftHanded = false;
 	
 	this.createWebSocket('ws://' + host + ':' + port + '/');
@@ -19,8 +40,10 @@
 
 /*
  * Création et Initialisation des sockets et listeners permettant d'écouter le server.
+ * Est appelé dans le fichier :
+ * client > fonction Client.
 */
-client.prototype.createWebSocket = function(host)
+Client.prototype.createWebSocket = function(host)
 {
 	var _this = this;
 	
@@ -67,8 +90,10 @@
 
 /*
  * Traite un message reçu du Middleware.
+ * Est appelé dans le fichier :
+ * client > fonction createWebSocket.
 */
-client.prototype.processMsg = function(msg)
+Client.prototype.processMsg = function(msg)
 {
 	if(typeof msg === 'undefined' || typeof msg.data === 'undefined')
 	{
@@ -103,7 +128,7 @@
 		if(!this.mosaic.mouseInteractions && this.mosaic.currentMode != 'NO-USER' && this.mosaic.currentMode.indexOf('INCOMING') == -1)
 		{
 			// console.log('pt');
-			this.mosaic.refreshMainPointer(x, y);
+			this.mosaic.refreshPointers(x, y, true);
 		}
 		
 		// /!\ //
@@ -138,7 +163,7 @@
 		
 		if(!this.mosaic.mouseInteractions && this.mosaic.currentMode != 'NO-USER' && this.mosaic.currentMode.indexOf('INCOMING') == -1)
 		{
-			this.mosaic.refreshSecondPointer(x, y);
+			this.mosaic.refreshPointers(x, y, false);
 		}
 		
 		if(!this.mosaic.isSecondPointerDisplayed)
@@ -239,7 +264,7 @@
 						this.mosaic.nextDrawCurveTimeout = setTimeout(function()
 						{
 							_this.mosaic.canDrawNextCurve = true;
-						}, this.mosaic.config['timeoutNextDrawCurve']);
+						}, this.mosaic.config.timeoutNextDrawCurve);
 					}
 				}
 			}
@@ -271,17 +296,4 @@
 		this.mosaic.pointersIdleNeedLaunch = true;
 	}
 	// /!\/!\ //
-}
-
-/*
- * Permet d'envoyer un message au Middleware (optionnel).
-*/
-client.prototype.sendMessage = function(data)
-{
-	//Si data est un objet, on le change en chaine.
-	if(typeof data === 'object')
-	{
-		data = JSON.stringify(data);
-	}
-	this.socket.send(data);
 }
\ No newline at end of file
--- a/front_idill/src/config.json	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/config.json	Mon Jul 23 16:59:35 2012 +0200
@@ -1,40 +1,45 @@
-{
-	"local":"true",
-	"length":"5",
-	"imagesToShow":"20",
-	"totalImages":"22",
-	"timePrezoom":"500",
-	"timePreUnzoom":"200",
-	"timeZoom":"2000",
-	"zoomTime":"500",
-	"timeUnzoom":"400",
-	"timeNeighbourGlowing":"1000",
-	"timeNeighbourUnglowing":"1000",
-	"timeMovingToNeighbour":"1000",
-	"timeSearchFade":"2000",
-	"timeNotifyFade":"2000",
-	"timeFilterFade":"2000",
-	"timeANFade":"500",
-	"timeoutZoom":"2000",
-	"timeoutUnzoom":"1000",
-	"timeoutMoveToNeighbour":"250",
-	"timeoutPointersIdle":"2000",
-	"timeoutAreBothPointersHere":"500",
-	"timeoutRemoveNotificationByGesture":"1500",
-	"timeoutRemoveFailedNotificationByGesture":"1500",
-	"timeoutNotifySwipe":"1000",
-	"timeoutSelectTL":"100",
-	"timeoutSlideTL":"1000",
-	"timeoutCanNotifyHelp":"1000",
-	"timeoutRemoveSpinner":"1000",
-	"timeoutNouser":"3000",
-	"timeoutNextDrawCurve":"500",
-	"zoomPercentage":"0.80",
-	"prezoomPercentage":"0.25",
-	"zoomedMargin":"42",
-	"host":"127.0.0.1",
-	"port":"8090",
-	"mouseUpDownDeltaTreshold":"15",
-	"dico":"./dico.json",
-	"lang":"en"
+{
+    "local":true,
+	"videoConfigFileLocal":"./player/json/local_videos.json",
+	"videoConfigFileOnline":"./player/json/online_videos.json",
+	"mouseInteractions":true,
+	"noUserModeEnabled":true,
+    "length":"5",
+    "imagesToShow":"20",
+    "totalImages":"22",
+	"timeReloadAfterResize":"1000",
+    "timePrezoom":"500",
+    "timePreUnzoom":"200",
+    "timeZoom":"2000",
+    "zoomTime":"500",
+    "timeUnzoom":"400",
+    "timeNeighbourGlowing":"1000",
+    "timeNeighbourUnglowing":"1000",
+    "timeMovingToNeighbour":"1000",
+    "timeSearchFade":"2000",
+    "timeNotifyFade":"2000",
+    "timeFilterFade":"2000",
+    "timeANFade":"500",
+    "timeoutZoom":"2000",
+    "timeoutUnzoom":"1000",
+    "timeoutMoveToNeighbour":"250",
+    "timeoutPointersIdle":"2000",
+    "timeoutAreBothPointersHere":"500",
+    "timeoutRemoveNotificationByGesture":"1500",
+    "timeoutRemoveFailedNotificationByGesture":"1500",
+    "timeoutNotifySwipe":"1000",
+    "timeoutSelectTL":"100",
+    "timeoutSlideTL":"1000",
+    "timeoutCanNotifyHelp":"1000",
+    "timeoutRemoveSpinner":"1000",
+    "timeoutNouser":"3000",
+    "timeoutNextDrawCurve":"500",
+    "zoomPercentage":"0.80",
+    "prezoomPercentage":"0.25",
+    "zoomedMargin":"42",
+    "host":"127.0.0.1",
+    "port":"8090",
+    "mouseUpDownDeltaTreshold":"15",
+    "curveDictionary":"./dico.json",
+    "lang":""
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/defaults.js	Mon Jul 23 16:59:35 2012 +0200
@@ -0,0 +1,65 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : defaults.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Ce fichier contient la configuration par défaut du Front IDILL.
+ */
+ 
+ var default_parameters = {
+	local : true,
+	mouseInteractions : true,
+	noUserModeEnabled : true,
+	videoConfigFileLocal : "./player/json/local_videos.json",
+	videoConfigFileOnline : "./player/json/online_videos.json",
+	timeReloadAfterResize : 1000,
+	imagesByLine : 5,
+	imagesToShow : 20,
+	totalImages : 23,
+	timePrezoom : 500,
+	timePreUnzoom : 200,
+	timeZoom : 2000,
+	zoomTime : 500,
+	timeUnzoom : 400,
+	timeNeighbourGlowing : 1000,
+	timeNeighbourUnglowing : 1000,
+	timeMovingToNeighbour : 1000,
+	timeSearchFade : 2000,
+	timeNotifyFade : 2000,
+	timeFilterFade : 2000,
+	timeANFade : 500,
+	timeFilling : 500,
+	timeoutZoom : 2000,
+	timeoutUnzoom : 1000,
+	timeoutMoveToNeighbour : 250,
+	timeoutPointersIdle : 2000,
+	timeoutAreBothPointersHere : 500,
+	timeoutRemoveNotificationByGesture : 1500,
+	timeoutRemoveFailedNotificationByGesture : 1500,
+	timeoutNotifySwipe : 1000,
+	timeoutSelectTL : 100,
+	timeoutSlideTL : 1000,
+	timeoutCanNotifyHelp : 1000,
+	timeoutRemoveSpinner : 1000,
+	timeoutNouser : 3000,
+	timeoutNexrDrawCurve : 500,
+	zoomPercentage : 0.80,
+	prezoomPercentage : 0.25,
+	zoomedMargin : 42,
+	host : '127.0.0.1',
+	port : '8080',
+	mouseUpDownDeltaTreshold : 15,
+	curveDictionary : './dico.json',
+	lang : navigator.language
+}
\ No newline at end of file
--- a/front_idill/src/dico.json	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/dico.json	Mon Jul 23 16:59:35 2012 +0200
@@ -1,54 +1,54 @@
-{
-	"divisions":"6",
-	"gestures":
-	[
-		{
-			"name":"contact",
-			"codes":["D1D0D1", "D1D0D2"]
-		},
-		{
-			"name":"right-angle",
-			"codes":["D1D0D1D3D1", "D1D0D1D2D1"]
-		},
-		{
-			"name":"up-down",
-			"codes":["D0D1", "D0D2"]
-		},
-		{
-			"name":"fall",
-			"codes":["D3"]
-		},
-		{
-			"name":"jump",
-			"codes":["D0"]
-		},
-		{
-			"name":"grand-jete",
-			"codes":["D1D0", "D2D0"]
-		},
-		{
-			"name":"wave",
-			"codes":["D0D1D0D1D0D1D0D1", "D0D2D0D2D0D2D0D2"]
-		},
-		{
-			"name":"bend",
-			"codes":["D1D3", "D1D2"]
-		},
-		{
-			"name":"knee-up",
-			"codes":["D3D0D3", "D3D2D3"]
-		},
-		{
-			"name":"no-motion",
-			"codes":["D2D1D0D5D4D3D4"]
-		},
-		{
-			"name":"circle",
-			"codes":["D4D5D0D1D2"]
-		},
-		{
-			"name":"screw",
-			"codes":["D4D5D0D1D2D3D4D1D2", "D4D5D0D1D2D0D1D2"]
-		}
-	]
+{
+    "divisions":"6",
+    "gestures":
+    [
+        {
+            "name":"contact",
+            "codes":["D1D0D1", "D1D0D2"]
+        },
+        {
+            "name":"right-angle",
+            "codes":["D1D0D1D3D1", "D1D0D1D2D1"]
+        },
+        {
+            "name":"up-down",
+            "codes":["D0D1", "D0D2"]
+        },
+        {
+            "name":"fall",
+            "codes":["D3"]
+        },
+        {
+            "name":"jump",
+            "codes":["D0"]
+        },
+        {
+            "name":"grand-jete",
+            "codes":["D1D0", "D2D0"]
+        },
+        {
+            "name":"wave",
+            "codes":["D0D1D0D1D0D1D0D1", "D0D2D0D2D0D2D0D2"]
+        },
+        {
+            "name":"bend",
+            "codes":["D1D3", "D1D2"]
+        },
+        {
+            "name":"knee-up",
+            "codes":["D3D0D3", "D3D2D3"]
+        },
+        {
+            "name":"no-motion",
+            "codes":["D2D1D0D5D4D3D4"]
+        },
+        {
+            "name":"circle",
+            "codes":["D4D5D0D1D2"]
+        },
+        {
+            "name":"screw",
+            "codes":["D4D5D0D1D2D3D4D1D2", "D4D5D0D1D2D0D1D2"]
+        }
+    ]
 }
\ No newline at end of file
--- a/front_idill/src/index.html	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/index.html	Mon Jul 23 16:59:35 2012 +0200
@@ -32,6 +32,7 @@
         <script type="text/javascript" src="../lib/jquery.min.js"></script>
         <script type="text/javascript" src="../lib/jquery-ui.min.js"></script>
         <script type="text/javascript" src="../lib/jquery.mousewheel-2.0.0.min.js"></script>
+        <script type="text/javascript" src="./defaults.js"></script>
         <script type="text/javascript" src="./mosaic/js/mosaic.js"></script>
         <script type="text/javascript" src="./mosaic/js/notifications.js"></script>
         <script type="text/javascript" src="./mosaic/js/pointers.js"></script>
@@ -40,112 +41,30 @@
         <script type="text/javascript" src="./mosaic/js/search.js"></script>
         <script type="text/javascript" src="./mosaic/js/playerControl.js"></script>
         <script type="text/javascript" src="./mosaic/js/localMosaic.js"></script>
-		<script type="text/javascript" src="./player/metadataplayer/LdtPlayer-core.js"></script>
-		<script type="text/javascript" src="../lib/paper.js"></script>
-		<link rel="stylesheet" type="text/css" href="./search/css/searchCanvas.css" />
-		<script type="text/javascript" src="./search/js/searchCanvas.js"></script>
-		<script type="text/javascript" src="./search/js/curvesDetector.js"></script>
-		<script type="text/javascript" src="./communication/js/client.js"></script>
+        <script type="text/javascript" src="./player/metadataplayer/LdtPlayer-core.js"></script>
+        <script type="text/javascript" src="../lib/paper.js"></script>
+        <link rel="stylesheet" type="text/css" href="./search/css/searchCanvas.css" />
+        <script type="text/javascript" src="./search/js/searchCanvas.js"></script>
+        <script type="text/javascript" src="./search/js/curvesDetector.js"></script>
+        <script type="text/javascript" src="./communication/js/client.js"></script>
     </head>
     
     <body>
+		<!-- /!\ ATTENTION : Si vous souhaitez modifier la configuration, veuillez modifier les valeurs de config.json situé à la racine du dossier Front IDILL. /!\ -->
+		
         <!-- Ce div stocke la mosaïque. -->
         <div id="mainPanel"></div>
-		<div class="player" id="video"></div>
-		<div class="LdtPlayer" id="LdtPlayer"></div>
 
         <!-- SET AN EMPTY DIV TO BE POPULATED WITH CONTENT VIA JQUERY -->
         <div class="test" style="color: #FFFFFF"></div>
         
         <!-- Scripts principaux. -->
         <script type="text/javascript">
-            //Longueur de la mosaïques et nombre d'images à afficher (seront importés des paramètres du Middleware).
-			var default_parameters = new Object();
-			default_parameters['local'] = true;
-			default_parameters['length'] = 5;
-			default_parameters['imagesToShow'] = 20;
-			default_parameters['totalImages'] = 23;
-			default_parameters['timePrezoom'] = 500;
-			default_parameters['timePreUnzoom'] = 200;
-			default_parameters['timeZoom'] = 2000;
-			default_parameters['zoomTime'] = 500;
-			default_parameters['timeUnzoom'] = 400;
-			default_parameters['timeNeighbourGlowing'] = 1000;
-			default_parameters['timeNeighbourUnglowing'] = 1000;
-			default_parameters['timeMovingToNeighbour'] = 1000;
-			default_parameters['timeSearchFade'] = 2000;
-			default_parameters['timeNotifyFade'] = 2000;
-			default_parameters['timeFilterFade'] = 2000;
-			default_parameters['timeANFade'] = 500;
-			default_parameters['timeFilling'] = 500;
-			default_parameters['timeoutZoom'] = 2000;
-			default_parameters['timeoutUnzoom'] = 1000;
-			default_parameters['timeoutMoveToNeighbour'] = 250;
-			default_parameters['timeoutPointersIdle'] = 2000;
-			default_parameters['timeoutAreBothPointersHere'] = 500;
-			default_parameters['timeoutRemoveNotificationByGesture'] = 1500;
-			default_parameters['timeoutRemoveFailedNotificationByGesture'] = 1500;
-			default_parameters['timeoutNotifySwipe'] = 1000;
-			default_parameters['timeoutSelectTL'] = 100;
-			default_parameters['timeoutSlideTL'] = 1000;
-			default_parameters['timeoutCanNotifyHelp'] = 1000;
-			default_parameters['timeoutRemoveSpinner'] = 1000;
-			default_parameters['timeoutNouser'] = 3000;
-			default_parameters['timeoutNexrDrawCurve'] = 500;
-			default_parameters['zoomPercentage'] = 0.80;
-			default_parameters['prezoomPercentage'] = 0.25;
-			default_parameters['zoomedMargin'] = 42;
-			default_parameters['host'] = '127.0.0.1';
-			default_parameters['port'] = '80';
-			default_parameters['mouseUpDownDeltaTreshold'] = 15;
-			default_parameters['dico'] = './dico.json';
-			default_parameters['lang'] = 'en';
-			
-            /*var length = 5, imagesToShow = 20, totalImages = 23;
-            //Temps de chargement du prezoom en ms (seront importés des paramètres du Middleware).
-            var timePrezoom = 500, timePreUnzoom = 200, timeZoom = 500, timeUnzoom = 400;
-            var timeNeighbourGlowing = 1000, timeNeighbourUnglowing = 1000, timeMovingToNeighbour = 1000;
-			var timeSearchFade = 2000;
-			var timeNotifyFade = 2000;
-            var zoomPercentage = 0.80, prezoomPercentage = 0.25;
-            var zoomedMargin = 42;*/
-            //On instancie la mosaïque.
-            
-            //On spécifie les attributs de temps.
-            /*mos.zoomTime = timeZoom;
-            mos.unzoomTime = timeUnzoom;
-            mos.preZoomTime = timePrezoom;
-            mos.preUnzoomTime = timePreUnzoom;
-            mos.timeNeighbourGlowing = timeNeighbourGlowing;
-            mos.timeNeighbourUnglowing = timeNeighbourUnglowing;
-            mos.timeMovingToNeighbour = timeMovingToNeighbour;
-			mos.timeSearchFade = timeSearchFade;
-			mos.timeNotifyFade = timeNotifyFade;*/
-            //On instancie une mosaïque locale pour le zoom total (pas encore implémenté).
-            //var lMos = new localMosaic(length, imagesToShow, zoomedMargin);
-            //mos.localMos = lMos;
-            //Tableau d'images de test pour peupler la mosaïque.
-            /*var imgs = [];
-            for(var i = 0 ; i < 42 ; i++)
-			{
-                imgs[i] = i + '.jpg';
-			}*/
             var mos;
             //Si la page a chargé, on raffraichit la mosaïque.
             $(document).ready(function ()
             {
-				mos = new mosaic('./config.json', default_parameters);
-                //mos.loadMosaic();
-                
-                /*$('.snapshotDivs').mouseenter(function ()
-                {
-                    //On effectue un prézoom dès qu'on va sur une image.
-                    mos.preZoom($(this));
-                });*/
-                /*$('body').keypress(function (event)
-                {
-					mos.manageControlEvents(event);
-                });*/
+                mos = new Mosaic('./config.json', default_parameters);
             });
         </script>
     </body>
--- a/front_idill/src/mosaic/css/mosaic.less	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/mosaic/css/mosaic.less	Mon Jul 23 16:59:35 2012 +0200
@@ -20,24 +20,43 @@
  * C'est pourquoi j'utilise WAMP pour le lancer.
  */
 
+/* Epaisseur de la bordure de la mosaique. */
 @mosaic-border-tickness: 1px;
+/* Couleur de fond de la mosaique. */
 @mosaic-background-color: #202020;
+/* Image de fond de la mosaique. */
 @mosaic-background-image-path: url("../../img/background.png");
+/* Image de fond de prezoom ou de sélection de voisin. */
 @selected-snapshot-background-image-path: url("../../img/selected_background.png");
+/* Couleur de fond des snapshots. */
 @snapshots-background-color: #8D8D8D;
+/* Valeur de la marge des snapshots dans la mosaique. */
 @snapshots-margin-value: 8px;
+/* Marges des snapshots. */
 @snapshots-margin: @snapshots-margin-value @snapshots-margin-value @snapshots-margin-value @snapshots-margin-value;
+/* Couleur noire. */
 @black: #000000;
+/* Image de notification de sélection. */
 @notify-selection-background-image-path: url("../../pictos/notifications/selectionner.png");
+/* Image de notification de recherche. */
 @notify-search-background-image-path: url("../../pictos/notifications/rechercher.png");
+/* Image de notification de confirmation. */
 @notify-point-background-image-path: url("../../pictos/notifications/confirmer.png");
+/* Image de notification de déplacement dans la timeline. */
 @notify-timeline-background-image-path: url("../../pictos/notifications/deplacer.png");
+/* Couleur de fond du panneau d'aide. */
 @notify-help-background-color: rgba(100, 100, 100, 0.9);
+/* Epaisseur de bordure du panneau d'aide. */
 @notify-help-border-width: 2px;
+/* Valeur de marge du panneau d'aide. */
 @notify-help-margin: 15px;
+/* Image de recherche du panneau d'aide. */
 @notify-help-search-background-image-path: url("../../pictos/help/recherche.png");
+/* Image de controle du panneau d'aide. */
 @notify-help-controls-background-image-path: url("../../pictos/help/controles.png");
+/* Image du pointeur principal. */
 @mainPointer-background-image-path: url("../../img/cursors/pointer.png");
+/* Image du pointeur secondaire. */
 @secondPointer-background-image-path: url("../../img/cursors/pointer2.png");
 
 html
@@ -45,6 +64,9 @@
 	//cursor: none;
 }
 
+/*
+ * Style du corps.
+*/
 body
 {
     overflow: hidden;
@@ -79,7 +101,7 @@
 	opacity: 0;
 	width: 100%;
 	height: 100%;
-	z-index: 1000;
+	z-index: 2000;
 }
 
 /*
@@ -141,7 +163,7 @@
 }
 
 /*
- * 
+ * Style du fond d'un snapshot de voisin.
  */
 .neighbourImgBg
 {
@@ -150,18 +172,16 @@
 }
 
 /*
- * 
+ * Style d'un snapshot de voisin.
  */
 .neighbourImg
 {
     position: absolute;
 }
 
-video
-{
-	//position: absolute;
-}
-
+/*
+ * Style commun aux notifications.
+*/
 .notifications
 {
 	position: absolute;
@@ -175,6 +195,9 @@
 	z-index: 400;
 }
 
+/*
+ * Style commun aux notifications lors d'une recherche par courbes en cours.
+*/
 .notifications_inSearch
 {
 	position: relative;
@@ -189,6 +212,9 @@
 	z-index: 400;
 }
 
+/*
+ * Div contenant les notifications lors d'une recherche par courbes en cours.
+*/
 .notifications_inSearch_container
 {
 	position: absolute;
@@ -196,28 +222,40 @@
 	background: transparent;
 }
 
+/*
+ * Notification de sélection.
+*/
 #notify_selection
 {
 	background-image: @notify-selection-background-image-path;
 }
 
+/*
+ * Notification de recherche.
+*/
 #notify_search
 {
 	background-image: @notify-search-background-image-path;
 }
 
+/*
+ * Notification de confirmation.
+*/
 #notify_point
 {
 	background-image: @notify-point-background-image-path;
 }
 
+/*
+ * Notification de déplacement dans la timeline.
+*/
 #notify_timeline
 {
 	background-image: @notify-timeline-background-image-path;
 }
 
 /*
- * Aide
+ * Panneau d'aide
  */
 #notify_help
 {
@@ -229,6 +267,9 @@
 	background-color: @notify-help-background-color;
 }
 
+/*
+ * Colonne de recherche du panneau d'aide.
+*/
 #help_search
 {
 	float: left;
@@ -238,6 +279,9 @@
 	background: transparent;
 }
 
+/*
+ * Colonne des controles du panneau d'aide.
+*/
 #help_controls
 {
 	float: left;
@@ -247,6 +291,9 @@
 	background: transparent;
 }
 
+/*
+ * Séparateur vertical du panneau d'aide.
+*/
 #help_sep
 {
 	position: absolute;
@@ -257,6 +304,9 @@
 	background-color: #fff;
 }
 
+/*
+ * Titres des colonnes du panneau d'aide.
+*/
 #search_title, #controls_title
 {
 	position: relative;
@@ -269,6 +319,9 @@
 	margin-bottom: 15px;
 }
 
+/*
+ * Image de recherche du panneau d'aide.
+*/
 #search_img
 {
 	background-image: @notify-help-search-background-image-path;
@@ -278,6 +331,9 @@
 	height: 225px;
 }
 
+/*
+ * Image des controles du panneau d'aide.
+*/
 #controls_img
 {
 	background-image: @notify-help-controls-background-image-path;
@@ -287,6 +343,9 @@
 	height: 225px;
 }
 
+/*
+ * Textes des zones de recherche et controles du panneau d'aide.
+*/
 #search_2hands_text, #search_body_text, #controls_1hand_text
 {
 	position: relative;
@@ -300,11 +359,9 @@
 	margin-bottom: 10px;
 }
 
-/*#search_2hands_imgs, #controls_1hand_imgs
-{
-	padding-left: 40px;
-}*/
-
+/*
+ * Images des gestures de recherche et controles du panneau d'aide.
+*/
 .notify_imgs_small
 {
 	float: left;
@@ -312,13 +369,12 @@
 	height: 130px;
 	background-position: 0px 0px;
 	background-repeat: no-repeat;
-}
-
-.notify_imgs_small
-{
 	margin: 4px;
 }
 
+/*
+ * Masques de non sélection qui s'appliquent sur une mosaique filtrée.
+*/
 .filterHiders
 {
 	position: absolute;
@@ -326,6 +382,9 @@
 	background: transparent;
 }
 
+/*
+ * Style du pointeur principal.
+*/
 #mainPointer
 {
 	position: absolute;
@@ -338,6 +397,9 @@
 	opacity: 0;
 }
 
+/*
+ * Style du pointeur secondaire.
+*/
 #secondPointer
 {
 	position: absolute;
@@ -350,6 +412,9 @@
 	opacity: 0;
 }
 
+/*
+ * Style des voisins additionnels.
+*/
 .borderNeighbours
 {
 	position: absolute;
--- a/front_idill/src/mosaic/js/mosaic.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/mosaic/js/mosaic.js	Mon Jul 23 16:59:35 2012 +0200
@@ -21,291 +21,584 @@
  * Classe définissant la mosaïque.
  * Elle contient sa longueur, le nombre d'images total, une liste d'urls pour les vidéos, leurs snapshots principaux et leur position.
  * Contient également les dimensions en px de la mosaïque.
+ * Est appelé dans :
+ * la page d'index, afin de créer la mosaique.
  */
-function mosaic(config, default_conf)
+function Mosaic(config, default_conf)
 {
-	//Interactions souris/kinect.
-	this.mouseInteractions = true;
-	//Interactions avec/sans préphase.
-	this.prephaseEnabled = true;
-	
-	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run", "up-down", "grand-jete"];
+    this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run", "up-down", "grand-jete"];
 
-	//Chemin du fichier de configuration.
-	this.config_path = config;
-	//Configuration par défaut en cas de valeur erronnée.
-	this.default_config = default_conf;
-	this.config = new Object();
-	//Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
-	this.videos = [];
-	this.urls = [];
-	this.sources = [];
-	this.imgs = [];
-	this.opacities = [];
-	this.timeToGoAt = [];
-	this.ids = [];
-	this.fillingIds = [];
-	this.currentRandomVideoIdx = 0;
-	
-	//Dictionnaire pour les courbes de recherche.
-	this.dictionary = [];
-	
-	//Dernières positions des pointeurs.
-	this.mainPointerLastX;
-	this.mainPointerLastY;
-	this.secondPointerLastX;
-	this.secondPointerLastY;
-	//Dernières positions avant le lancement de la fonction d'idle.
-	this.mainPointerIdleStartX;
-	this.mainPointerIdleStartY;
-	this.secondPointerIdleStartX;
-	this.secondPointerIdleStartY;
-	
-	//Coordonnées de la souris dans le mode d'interaction souris.
-	this.mousePosX;
-	this.mousePosY;
-	//Coordonnées précédentes de la souris dans le mode d'interaction souris.
-	this.mousePosLastX;
-	this.mousePosLastY;
-	//Valeur du déplacement entre un mouse up et un mouse down.
-	this.mouseUpDownDelta = 0;
-	
-	//Dimensions de la mosaïque en pixels.
-	this.width;
-	this.height;
-	//Dimensions d'un snapshot en pixels.
-	this.snapshotWidth;
-	this.snapshotHeight;
-	//Espacement entre les snapshots en pixels.
-	this.marginWidth;
-	
-	//Booléens permettant ou non certaines intéractions selon le contexte.
-	this.zoomed = false;
-	this.fullscreen = false;
-	this.canMoveToNeighbour = false;
-	this.mainPointerExitBorder = false;
-	this.secondPointerExitBorder = false;
-	this.isMainPointerDisplayed = false;
-	this.isSecondPointerDisplayed = false;
-	this.helpDisplayed = false;
-	//Indique si l'utilisateur a manuellement pausé la vidéo.
-	this.userPaused = false;
-	//Indique si on est en train de se déplacer vers un voisin.
-	this.currentlyMoving = false;
-	//Indique si on est en train de dézoomer vers la mosaïque.
-	this.currentlyUnzooming = false;
-	//Indique si on peut s'approcher de kinect.
-	this.canStart = false;
-	//Indique si on est actuellement sur un snapshot.
-	this.isOnASnapshot = false;
-	//Indique si l'idle des pointeurs est disponible (deux mains détectées).
-	this.pointersIdleAvailable = false;
-	//Indique si le timeout pour l'idle des pointeurs à besoin d'être lancé.
-	this.pointersIdleNeedLaunch = false;
-	//Indique si les deux mains sont là.
-	this.areBothPointersHere = false;
-	//Indique si le timeout pour la détection de deux pointeurs a été lancé.
-	this.areBothPointersTimeoutLaunched = false;
-	//Indique si la mosaïque a été filtrée.
-	this.isMosaicFiltered = false;
-	//Indique si on est actuellement dans une recherche par gesture.
-	this.isCurrentlyInASearchByGesture = false;
-	//Indique si un pointeur est déjà sur une notification de recherche par gesture.
-	this.alreadyOnNotification = false;
-	//Si on a fait un swipe.
-	this.isSwipe = false;
-	//On peut swiper.
-	this.canSwipe = false;
-	//On passe vers une autre video automatiquement à la fin d'une lecture.
-	this.autoMove = false;
-	//Si l'utilisateur a demandé à sélectionner la TL.
-	this.isTLRequested = false;
-	//Le pointeur gauche a sélectionné la TL.
-	this.isTLSelectedBySecondPointer = false;
-	//Le pointeur droit a sélectionné la TL.
-	this.isTLSelectedByMainPointer = false;
-	//On peut afficher l'aide.
-	this.canNotifyHelp = false;
-	//Indique si la mosaique est en train d'être filtrée.
-	this.isMosaicFiltering = false;
-	this.arrowLeftLoading = false;
-	this.arrowRightLoading = false;
-	this.arrowUpLoading = false;
-	this.arrowDownLoading = false;
-	//On est dans une recherche par courbes.
-	this.isSearchByCurvesOn = false;
-	this.canDrawNextCurve = false;
-	//Dans le mode d'interaction souris, indique si on se situe actuellement sur un snapshot entièrement prézoomé.
-	this.isOnAPrezoomSN = false;
-	//Indique si une courbe de recherche donne au moins un résultat.
-	this.curvesGesturesFound = false;
-	//Indique si on souhaite supprimer la recherche en cours.
-	this.gestureDelRequested = false;
-	//Code de gesture actuellement calculé par les détecteurs de courbes.
-	this.actualCode = '';
-	//Indique si l'utilisateur est entré dans la zone de recherche.
-	this.isUserInSearchZone = false;
-	
-	//Timeout (attente) pour le zoom après un préZoom.
-	this.zoomTimeout = null;
-	//Timeout (attente) pour le passage vers un voisin.
-	this.moveToNeighbourTimeout = null;
-	this.mainPointerExitBorderTimeout = null;
-	this.secondPointerExitBorderTimeout = null;
-	//Idle time pour les pointeurs afin d'informer le front qu'on souhaite faire une recherche.
-	this.pointersSearchIdleTimeout = null;
-	//Vérifie toutes les N ms que les deux pointeurs sont détectés.
-	this.areBothPointersHereTimeout = null;
-	//Délai de suppression d'une notification de recherche par gesture.
-	this.removeNotificationByGestureTimeout = null;
-	//Délai de suppression d'une notification de recherche par gesture infructueuse.
-	this.removeFailedNotificationByGestureTimeout = null;
-	//Délai avant la suppression de notification swipe.
-	this.notifySwipeTimeout = null;
-	//Délai pour la sélection de la TL.
-	this.selectTLTimeout = null;
-	//Délai pour slider sur la TL.
-	this.canSlideInTLTimeout = null;
-	//Délai pour afficher l'aide.
-	this.canNotifyHelpTimeout = null;
-	this.arrowLeftTimeout = null;
-	this.arrowRightTimeout = null;
-	this.arrowUpTimeout = null;
-	this.arrowDownTimeout = null;
-	
-	this.arrowSpinnerTimeout = null;
-	this.nouserTimeout = null;
-	this.nextDrawCurveTimeout = null;
-	
-	//Dernier message INCOMING (pour éviter d'effectuer n fois la même action.
-	this.lastIncomingMessage = '';
-	
-	//Type de marqueur recherché dans la mosaïque (en mode filter).
-	this.filterSearchedType = "";
-	
-	//Mode actuel.
-	this.currentMode = "NO-USER";
-	//Snapshot sur lequel on a zoomé.
-	this.previousZoomedSN = null;
-	//Snapshot sur lequel on a prezoomé.
-	this.previousPrezoomDiv = null;
-	//Son ID.
-	this.previousId = null;
-	//Dernier snapshot prézoomé non null.
-	this.lastNonNullSN = null;
-	//Largeur de la marge pour le centrage vertical de la mosaïque.
-	this.MPTop_margin;
-	this.top_margin;
-	
-	//Gestures actuellement cherchées dans les vidéos.
-	this.currentSearchGesture = [];
-	
-	//Mosaïque locale.
-	this.localMos;
-	//Position des voisins lors d'un zoom.
-	this.neighboursIds = [];
-	//ID du snapshot du milieu lors d'un zoom.
-	this.centerId;
-	
-	//Voisins sélectionnés par les pointeurs.
-	this.mainPointerNeighbourSelectedId = null;
-	this.secondPointerNeighbourSelectedId = null;
-	
-	//Snapshots a afficher.
-	this.snapshotsToShow = 1;
-	
-	//Lecteur.
-	this.player = null;
-	//Si le lecteur est prêt.
-	this.playerIsReady = false;
-	
-	//Annotations (pour les marqueurs los d'un filtrage).
-	this.annotations = [];
-	
-	//Client websocket pour recevoir les notifications du Middleware.
-	this.client;
-	
-	//Coordonnées et dimensions d'un snapshot zoomé.
-	this.snTop = 0;
-	this.snLeft = 0;
-	this.snWidth = 0;
-	this.snHeight = 0;
-	
-	this.searchCanvas;
-	//Position actuelle de la vidéo zoomée.
-	this.notifyTopVideo;
-	this.notifyLeftVideo;
-	this.loadParameters(this.config_path);
+    //Chemin du fichier de configuration.
+    this.config_path = config;
+    //Configuration par défaut en cas de valeur erronnée.
+    this.default_config = default_conf;
+    this.config = new Object();
+    //Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
+    this.videos = [];
+    this.urls = [];
+    this.sources = [];
+    this.imgs = [];
+    this.opacities = [];
+    this.timeToGoAt = [];
+    this.ids = [];
+    this.fillingIds = [];
+    this.currentRandomVideoIdx = 0;
+    
+    //Dictionnaire pour les courbes de recherche.
+    this.dictionary = [];
+    
+    //Dernières positions des pointeurs.
+    this.mainPointerLastX = null;
+    this.mainPointerLastY = null;
+    this.secondPointerLastX = null;
+    this.secondPointerLastY = null;
+    //Dernières positions avant le lancement de la fonction d'idle.
+    this.mainPointerIdleStartX = null;
+    this.mainPointerIdleStartY = null;
+    this.secondPointerIdleStartX = null;
+    this.secondPointerIdleStartY = null;
+    
+    //Coordonnées de la souris dans le mode d'interaction souris.
+    this.mousePosX = null;
+    this.mousePosY = null;
+    //Coordonnées précédentes de la souris dans le mode d'interaction souris.
+    this.mousePosLastX = null;
+    this.mousePosLastY = null;
+    //Valeur du déplacement entre un mouse up et un mouse down.
+    this.mouseUpDownDelta = 0;
+	//Coordonnées de la souris au dernier mouse down.
+	this.mouseDownPosX = null;
+	this.mouseDownPosY = null;
+    
+    //Dimensions de la mosaïque en pixels.
+    this.width = null;
+    this.height = null;
+    //Dimensions d'un snapshot en pixels.
+    this.snapshotWidth = null;
+    this.snapshotHeight = null;
+    //Espacement entre les snapshots en pixels.
+    this.marginWidth = null;
+    
+    //Booléens permettant ou non certaines intéractions selon le contexte.
+    this.zoomed = false;
+    this.fullscreen = false;
+    this.canMoveToNeighbour = false;
+    this.mainPointerExitBorder = false;
+    this.secondPointerExitBorder = false;
+    this.isMainPointerDisplayed = false;
+    this.isSecondPointerDisplayed = false;
+    this.helpDisplayed = false;
+    //Indique si l'utilisateur a manuellement pausé la vidéo.
+    this.userPaused = false;
+    //Indique si on est en train de se déplacer vers un voisin.
+    this.currentlyMoving = false;
+    //Indique si on est en train de dézoomer vers la mosaïque.
+    this.currentlyUnzooming = false;
+    //Indique si on peut s'approcher de kinect.
+    this.canStart = false;
+    //Indique si on est actuellement sur un snapshot.
+    this.isOnASnapshot = false;
+    //Indique si l'idle des pointeurs est disponible (deux mains détectées).
+    this.pointersIdleAvailable = false;
+    //Indique si le timeout pour l'idle des pointeurs à besoin d'être lancé.
+    this.pointersIdleNeedLaunch = false;
+    //Indique si les deux mains sont là.
+    this.areBothPointersHere = false;
+    //Indique si le timeout pour la détection de deux pointeurs a été lancé.
+    this.areBothPointersTimeoutLaunched = false;
+    //Indique si la mosaïque a été filtrée.
+    this.isMosaicFiltered = false;
+    //Indique si on est actuellement dans une recherche par gesture.
+    this.isCurrentlyInASearchByGesture = false;
+    //Indique si un pointeur est déjà sur une notification de recherche par gesture.
+    this.alreadyOnNotification = false;
+    //Si on a fait un swipe.
+    this.isSwipe = false;
+    //On peut swiper.
+    this.canSwipe = false;
+    //On passe vers une autre video automatiquement à la fin d'une lecture.
+    this.autoMove = false;
+    //Si l'utilisateur a demandé à sélectionner la TL.
+    this.isTLRequested = false;
+    //Le pointeur gauche a sélectionné la TL.
+    this.isTLSelectedBySecondPointer = false;
+    //Le pointeur droit a sélectionné la TL.
+    this.isTLSelectedByMainPointer = false;
+    //On peut afficher l'aide.
+    this.canNotifyHelp = false;
+    //Indique si la mosaique est en train d'être filtrée.
+    this.isMosaicFiltering = false;
+    this.arrowLeftLoading = false;
+    this.arrowRightLoading = false;
+    this.arrowUpLoading = false;
+    this.arrowDownLoading = false;
+    //On est dans une recherche par courbes.
+    this.isSearchByCurvesOn = false;
+    this.canDrawNextCurve = false;
+    //Dans le mode d'interaction souris, indique si on se situe actuellement sur un snapshot entièrement prézoomé.
+    this.isOnAPrezoomSN = false;
+    //Indique si une courbe de recherche donne au moins un résultat.
+    this.curvesGesturesFound = false;
+    //Indique si on souhaite supprimer la recherche en cours.
+    this.gestureDelRequested = false;
+    //Code de gesture actuellement calculé par les détecteurs de courbes.
+    this.actualCode = '';
+    //Indique si l'utilisateur est entré dans la zone de recherche.
+    this.isUserInSearchZone = false;
+	this.isMouseDown = false;
+	//Indique si on est en train de prézoomer.
+	this.isPrezooming = false;
+    
+    //Timeout (attente) pour le zoom après un préZoom.
+    this.zoomTimeout = null;
+    //Timeout (attente) pour le passage vers un voisin.
+    this.moveToNeighbourTimeout = null;
+    this.mainPointerExitBorderTimeout = null;
+    this.secondPointerExitBorderTimeout = null;
+    //Idle time pour les pointeurs afin d'informer le front qu'on souhaite faire une recherche.
+    this.pointersSearchIdleTimeout = null;
+    //Vérifie toutes les N ms que les deux pointeurs sont détectés.
+    this.areBothPointersHereTimeout = null;
+    //Délai de suppression d'une notification de recherche par gesture.
+    this.removeNotificationByGestureTimeout = null;
+    //Délai de suppression d'une notification de recherche par gesture infructueuse.
+    this.removeFailedNotificationByGestureTimeout = null;
+    //Délai avant la suppression de notification swipe.
+    this.notifySwipeTimeout = null;
+    //Délai pour la sélection de la TL.
+    this.selectTLTimeout = null;
+    //Délai pour slider sur la TL.
+    this.canSlideInTLTimeout = null;
+    //Délai pour afficher l'aide.
+    this.canNotifyHelpTimeout = null;
+    this.arrowLeftTimeout = null;
+    this.arrowRightTimeout = null;
+    this.arrowUpTimeout = null;
+    this.arrowDownTimeout = null;
+    
+    this.arrowSpinnerTimeout = null;
+    this.nouserTimeout = null;
+    this.nextDrawCurveTimeout = null;
+    
+    //Dernier message INCOMING (pour éviter d'effectuer n fois la même action.
+    this.lastIncomingMessage = '';
+    
+    //Type de marqueur recherché dans la mosaïque (en mode filter).
+    this.filterSearchedType = "";
+    
+    //Mode actuel.
+    this.currentMode = "NO-USER";
+    //Snapshot sur lequel on a zoomé.
+    this.previousZoomedSN = null;
+    //Snapshot sur lequel on a prezoomé.
+    this.previousPrezoomDiv = null;
+    //Son ID.
+    this.previousId = null;
+    //Dernier snapshot prézoomé non null.
+    this.lastNonNullSN = null;
+    //Largeur de la marge pour le centrage vertical de la mosaïque.
+    this.MPTop_margin = null;
+    this.top_margin = null;
+    
+    //Gestures actuellement cherchées dans les vidéos.
+    this.currentSearchGesture = [];
+    
+    //Position des voisins lors d'un zoom.
+    this.neighboursIds = [];
+    //ID du snapshot du milieu lors d'un zoom.
+    this.centerId = null;
+    
+    //Voisins sélectionnés par les pointeurs.
+    this.mainPointerNeighbourSelectedId = null;
+    this.secondPointerNeighbourSelectedId = null;
+    
+    //Snapshots a afficher.
+    this.snapshotsToShow = 1;
+    
+    //Lecteur.
+    this.player = null;
+    //Si le lecteur est prêt.
+    this.playerIsReady = false;
+    
+    //Annotations (pour les marqueurs los d'un filtrage).
+    this.annotations = [];
+    
+    //Client websocket pour recevoir les notifications du Middleware.
+    this.client = null;
+    
+    //Coordonnées et dimensions d'un snapshot zoomé.
+    this.snTop = 0;
+    this.snLeft = 0;
+    this.snWidth = 0;
+    this.snHeight = 0;
+    
+    this.searchCanvas = null;
+    //Position actuelle de la vidéo zoomée.
+    this.notifyTopVideo = null;
+    this.notifyLeftVideo = null;
+    this.loadParameters(this.config_path);
 }
 
 /*
  * Méthode d'affichage de la mosaïque.
  * Génère une matrice de imgs.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadMosaic, afin de créer les éléments visuels de la mosaique.
  */
-mosaic.prototype.createMosaic = function()
+Mosaic.prototype.createMosaic = function()
 {
-	// console.log('CREATE');
-	// this.currentMode = "NO-USER";
-	var initPanel = '<div id="initPanel"></div>';
-	var mp = $('#mainPanel');
-	mp.append(initPanel);
-	$('#initPanel').css(
+	var _this = this;
+	
+    //On ajoute le player au body pour le lancer la première fois qu'on zoom.
+	$('body').append('<div class="player" id="video"></div><div class="LdtPlayer" id="LdtPlayer"></div>');
+	
+	//On recharge la fenêtre si sa taille a changé.
+	$(window).resize(function()
 	{
-		background: 'transparent',
-		width: mp.width(),
-		height: mp.height(),
-		top: mp.position().top,
-		left: mp.position().left,
-		'margin-top': this.MPTop_margin
+		_.debounce(window.location.reload(), _this.config.timeReloadAfterResize);
 	});
 	
-	var len = this.config['length'], imgs = this.config['imagesToShow'], imgsTotal = this.config['imagesTotal'];
-	
-	//S'il s'agit d'un rectangle.
+    var initPanel = '<div id="initPanel"></div>';
+    var mp = $('#mainPanel');
+    mp.append(initPanel);
+    $('#initPanel').css(
+    {
+        background: 'transparent',
+        width: mp.width(),
+        height: mp.height(),
+        top: mp.position().top,
+        left: mp.position().left,
+        'margin-top': this.MPTop_margin
+    });
+    
+    var len = this.config.length, imgs = this.config.imagesToShow, imgsTotal = this.config.imagesTotal;
+    
+    //S'il s'agit d'un rectangle.
     if(imgs % len == 0)
     {
-		this.lastIncomingMessage = 'INCOMING-0';
-		
-		var str = '';
-		
-		if(this.imgs.length >= imgs)
-		{
-			for(var i = 0 ; i < imgs ; i++)
-			{
-				//On charge les images de petite taille pour ne pas surcharger la mosaïque lors de l'affichage global.
-				str += '<div id="snapshotDiv-' + i + '" class="snapshotDivs" style="opacity: 0;"><img id="snapshot-' + i + '" class="snapshots" src="snapshots-little/' + this.imgs[i] + '" /></div>';
-				//Au départ aucune vidéo n'a de gesture de recherche.
-				this.currentSearchGesture[i] = '';
-			}
-		}
-		
-		return str + '<div id="ghostPanel"></div>';
-	}
-	else
+        this.lastIncomingMessage = 'INCOMING-0';
+        
+        var str = '';
+        
+        if(this.imgs.length >= imgs)
+        {
+            for(var i = 0 ; i < imgs ; i++)
+            {
+                //On charge les images de petite taille pour ne pas surcharger la mosaïque lors de l'affichage global.
+                str += '<div id="snapshotDiv-' + i + '" class="snapshotDivs" style="opacity: 0;"><img id="snapshot-' + i + '" class="snapshots" src="snapshots-little/' + this.imgs[i] + '" /></div>';
+                //Au départ aucune vidéo n'a de gesture de recherche.
+                this.currentSearchGesture[i] = '';
+            }
+        }
+        
+        return str + '<div id="ghostPanel"></div>';
+    }
+    else
+    {
+        alert("Le nombre d'images a afficher doit être divisible par la longueur de la mosaïque !");
+    }
+}
+
+/*
+ * Fonction appelée lors d'un mouse down en mode d'interaction souris.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadMosaic, attachée à l'événement jQuery mousedown.
+*/
+Mosaic.prototype.onMouseDown = function(e)
+{
+	this.isMouseDown = true;
+	
+	//On met à jour les coordonnées de la souris au dernier mouse down.
+	this.mouseDownPosX = e.pageX;
+	this.mouseDownPosY = e.pageY;
+	
+	//Si on est sur une notification de gesture de recherche.
+	this.removeSearchNotificationIfOnIt(e.pageX, e.pageY);
+	this.isUserInSearchZone = true;
+	
+	//Si on est en mode de tracé de courbes, on indique qu'on a commencé à tracer au canvas.
+	if(this.isSearchByCurvesOn)
 	{
-		alert("Le nombre d'images a afficher doit être divisible par la longueur de la mosaïque !");
+		this.searchCanvas.onPointerIn(this.mousePosX, this.mousePosY, null, null);
 	}
 }
 
 /*
- * Permet de raffraichir la mosaïque.
- */
-mosaic.prototype.loadMosaic = function()
+ * Fonction appelée lors d'un mouse move en mode d'interaction souris.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadMosaic, attachée à l'événement jQuery mousemove.
+*/
+Mosaic.prototype.onMouseMove = function(e)
 {
-	// console.log('LOAD');
-	var createMosaic = this.createMosaic();
-	
-	if(createMosaic == '')
+	//Si on n'a pas appuyé sur la souris avant, on part.
+	if(!this.isMouseDown)
 	{
 		return;
 	}
 	
 	var _this = this;
 	
+	//Si on est en mode de tracé de courbes, on met à jour la courbe.
+	if(this.isSearchByCurvesOn)
+	{
+		this.searchCanvas.onPointerMove(this.mousePosX, this.mousePosY - this.MPTop_margin, null, null);
+	}
+	
+	//On met à jour l'ancienne position de la souris si elle est nulle.
+	if(!this.mousePosLastX && this.mousePosLastX != 0)
+	{
+		this.mousePosLastX = this.mousePosX;
+	}
+	if(!this.mousePosLastY && this.mousePosLastY != 0)
+	{
+		this.mousePosLastY = this.mousePosY;
+	}
+	
+	//Le delta s'accroît si la souris bouge.
+	this.mouseUpDownDelta += Math.floor(Math.sqrt((this.mousePosLastX - e.pageX) * (this.mousePosLastX - e.pageX) + (this.mousePosLastY - e.pageY) * (this.mousePosLastY - e.pageY)));
+	
+	//On met à jour l'ancienne position de la souris.
+	if(this.mousePosLastX != this.mousePosX)
+	{
+		this.mousePosLastX = this.mousePosX;
+	}
+	if(this.mousePosLastY != this.mousePosY)
+	{
+		this.mousePosLastY = this.mousePosY;
+	}
+	
+	//Si la souris a parcouru une trop grande distance, on entre en recherche.
+	if(this.mouseUpDownDelta > this.config.mouseUpDownDeltaTreshold)
+	{
+		//Si on est en mosaique, on entre en filtrage.
+		if(this.currentMode == "MOSAIC")
+		{
+			this.preUnzoom();
+			this.currentMode = "FILTER";
+			this.isMosaicFiltered = true;
+		}
+		//Si on est en mode de filtrage, mais qu'on n'est pas en tracé de courbes.
+		else if(this.currentMode == "FILTER" && !this.isSearchByCurvesOn && this.isUserInSearchZone)
+		{
+			//On lance une nouvelle recherche pas courbes.
+			this.preUnzoom();
+		}
+		//Si on est dans une vidéo, on entre en recherche.
+		else if(this.currentMode == "VIDEO" || this.currentMode == "TIMELINE")
+		{
+			this.currentMode = "SEARCH";
+		}
+		//Si on est en mode recherche dans une vidéo, mais qu'on n'est pas en tracé de courbes.
+		/*else if(this.currentMode == "SEARCH" && !this.isSearchByCurvesOn)
+		{
+			//On lance une nouvelle recherche pas courbes.
+		}*/
+		
+		if(this.currentMode != "NO-USER" && this.currentMode.indexOf("INCOMING") == -1 && !this.isSearchByCurvesOn)
+		{
+			this.isSearchByCurvesOn = true;
+			this.startSearch();
+			this.searchCanvas.onPointerIn(this.mousePosX, this.mousePosY - this.MPTop_margin, null, null);
+		}
+		
+		//S'il n'est pas possible d'afficher l'aide.
+		if(!this.canNotifyHelp)
+		{
+			//On rend son affichage possible après un certain délai.
+			this.canNotifyHelpTimeout = setTimeout(function()
+			{
+				_this.canNotifyHelp = true;
+			}, this.config.timeoutCanNotifyHelp);
+		}
+	}
+}
+
+/*
+ * Fonction appelée lors d'un mouse up en mode d'interaction souris.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadMosaic, attachée à l'événement jQuery mousemove.
+*/
+Mosaic.prototype.onMouseUp = function()
+{
+	this.isMouseDown = false;
+	
+	//Si on était en train de tracer une courbe.
+	if(this.isSearchByCurvesOn)
+	{
+		//On quitte la zone de recherche.
+		this.isUserInSearchZone = false;
+		
+		//On regarde si ce qu'on a tracé correspond à une courbe en particulier.
+		var gesture_match = this.gestureWithSameCode(this.actualCode);
+		this.actualCode = '';
+		
+		//Si oui.
+		if(gesture_match.length > 0)
+		{
+			//Si on est en mode recherche dans une vidéo et que le player est prêt.
+			if(this.currentMode == "SEARCH" && this.playerIsReady)
+			{
+				//On effectue une recherche dans cette vidéo.
+				this.player.widgets[0].searchByGesture(gesture_match);
+				this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture;
+				
+				//On va au premier marqueur trouvé.
+				if(this.player && this.player.widgets[0] && this.timeToGoAt[this.centerId] === 0 && this.player.widgets[0].atLeastOneSearchMarker(this.currentSearchGesture[this.centerId]))
+				{
+					this.player.widgets[0].goToFirstSearchedMarker(this.currentSearchGesture[this.centerId]);
+				}
+				
+				//On affiche la notification de gesture de recherche.
+				this.removeNotifications();
+				this.currentSearchGesture[this.centerId] = gesture_match;
+				this.searchGesture(gesture_match, 'valid');
+				this.curvesGesturesFound = false;
+			}
+			//Si on est en mode de filtrage de mosaique.
+			else if(this.currentMode == "FILTER")
+			{
+				if(this.isMosaicFiltered)
+				{
+					//On notifie la recherche par filtrage.
+					this.removeNotifications();
+					this.filterSearchedType = gesture_match;
+					this.filterGesture(gesture_match, 'valid');
+					//On filtre la mosaique.
+					this.searchFilter(gesture_match);
+					this.curvesGesturesFound = false;
+				}
+			}
+		}
+		//Si aucune gesture ne matche dans le dictionnaire.
+		else
+		{
+			//Si on était en mode filtrage de la mosaïque et qu'aucune gesture de filtrage n'avait été détectée avant ca, on revient en mode mosaïque.
+			if(this.currentMode == "FILTER" && this.filterSearchedType == "")
+			{
+				this.currentMode = "MOSAIC";
+				this.isMosaicFiltered = false;
+			}
+			//Sinon si on était en mode recherche dans une video et qu'aucune gesture n'avait été détectée avant ca, on revient en mode video.
+			if(this.currentMode == "SEARCH" && this.currentSearchGesture[this.centerId] == "")
+			{
+				this.currentMode = "VIDEO";
+			}
+		}
+		//On dit au module de recherche qu'on arrête de tracer des courbes.
+		this.searchCanvas.onPointerOut();
+	}
+	
+	this.mousePosLastX = null;
+	this.mousePosLastY = null;
+	
+	//Si la distance parcourue par la souris entre le mouse down et le mouse up est inférieure ou égale au seuil.
+	if(this.mouseUpDownDelta <= this.config.mouseUpDownDeltaTreshold)
+	{
+		//Si on est sur un snapshot prézoomé.
+		if(this.isOnAPrezoomSN && this.previousZoomedSN != '' && (this.currentMode == 'MOSAIC' || this.currentMode == 'FILTER') && !this.isPrezooming)
+		{
+			this.zoom();
+		}
+	}
+	
+	//On réinitialise le delta, on quitte la recherche par courbes.
+	this.mouseUpDownDelta = 0;
+	this.isSearchByCurvesOn = false;
+	this.leaveSearch();
+	
+	//Si on est en mode de filtrage et qu'on a une gesture de filtrage trouvée.
+	if(this.currentMode == 'FILTER' && this.filterSearchedType != '')
+	{
+		//On notifie.
+		this.removeNotifications();
+		this.filterGesture(this.filterSearchedType, 'valid');
+	}
+}
+
+/*
+ * Fonction appelée lors d'un clic en mode d'interaction souris.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadMosaic.
+*/
+Mosaic.prototype.onClick = function(x, y)
+{
+	//Si la position de la souris entre le mouse down et le mouse up change de plus de 10px, on part.
+	if(!this.mouseDownPosX || !this.mouseDownPosY || Math.sqrt((this.mouseDownPosX - x) * (this.mouseDownPosX - x) + (this.mouseDownPosY - y) * (this.mouseDownPosY - y)) > 10)
+	{
+		return;
+	}
+	
+	//Si on est dans un mode autre qu'un mode zoomé et qu'on n'affiche pas l'aide, on part.
+	if(this.currentMode != "VIDEO" && this.currentMode != "SEARCH" && this.currentMode != "TIMELINE" && !this.helpDisplayed)
+	{
+		return;
+	}
+	
+	//Si on clique en dehors de la video centrale, alors on dézoome.
+	var TL = $('.Ldt-Timeline');
+	var TLwidth = TL.width(), TLheight = TL.height();
+	var Ptop = $('.LdtPlayer').position().top, Pleft = $('.LdtPlayer').position().left;
+	var Pheight = $('.LdtPlayer').height();
+	var MPx = this.mousePosX, MPy = this.mousePosY;
+	
+	//On regarde si on a cliqué sur un snapshot.
+	var SN = this.pointerPositionToSN(MPx - this.notifyLeftVideo, MPy - this.notifyTopVideo, true);
+	var SNId;
+	if(SN)
+	{
+		SNId = parseInt(SN.attr('id').replace('snapshotDiv-', ''));
+	}
+	
+	//Si on n'a pas demandé à supprimé la notification de gesture.
+	if(!this.gestureDelRequested && !this.helpDisplayed)
+	{
+		//Si non, ou s'il ne fait pas partie des voisins.
+		if(!SNId || !_.include(this.neighboursIds, SNId))
+		{
+			//Si le clic a lieu en dehors du player et que l'aide n'est pas affichée, on dezoom.
+			if(MPx < Pleft || MPx > (+Pleft + TLwidth) || MPy < Ptop || MPy > (+Ptop + Pheight - TLheight))
+			{
+				this.unzoom();
+			}
+		}
+		//Si on se trouve sur un voisin, on bouge.
+		else if(SNId && _.include(this.neighboursIds, SNId) && this.canMoveToNeighbour)
+		{
+			this.moveToNeighbour($('#snapshotDiv-' + SNId));
+		}
+	}
+	//Si on l'a demandé, on enlève la demande de suppression.
+	else
+	{
+		this.gestureDelRequested = false;
+	}
+	
+	//Si l'aide est affichée, un clic la ferme.
+	if(this.helpDisplayed)
+	{
+		this.removeHelp();
+	}
+}
+
+/*
+ * Permet de raffraichir la mosaïque.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadFromJson, afin de charger la mosaique une fois que les fichiers de métadonnées ont été lus.
+ */
+Mosaic.prototype.loadMosaic = function()
+{
+    // console.log('LOAD');
+    var createMosaic = this.createMosaic();
+    
+    if(createMosaic == '')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
     //On affecte les chemins vers les images à la mosaïque.
     this.previousZoomedSN;
-    //this.width = 
-	// console.log(createMosaic);
     //On met à jour la mosaïque.
     $('#mainPanel').html(createMosaic);
     //On récupère la taille des bordures.
@@ -314,7 +607,7 @@
     //On calcule la taille des divs contenant les snapshots.
     this.width = $('#mainPanel').innerWidth();
     //On ne calculera pas tout de suite la hauteur de la mosaique étant donnée qu'elle est calculée par la suite dynamiquement.
-    this.snapshotWidth = this.width / this.config['length'] - this.marginWidth;
+    this.snapshotWidth = this.width / this.config.length - this.marginWidth;
     this.snapshotHeight = this.snapshotWidth*9/16;
     $('.snapshotDivs').css('width', this.snapshotWidth).css('height', this.snapshotHeight).css('margin', this.marginWidth/2);
     
@@ -322,936 +615,774 @@
     //On centre verticalement la mosaïque.
     this.MPTop_margin = ($(document).height() - $('#mainPanel').height())/2;
     $('#mainPanel').css('margin-top', this.MPTop_margin).css('margin-bottom', this.MPTop_margin);
-	
-	//On fait coincider le background du body avec celui de la mosaïque.
-	$('body').css('background-position', '0px ' + this.MPTop_margin + 'px');
-	
-	/*$('.snapshotDivs').mouseover(function ()
-	{
-		//On effectue un prézoom dès qu'on va sur une image.
-		_this.preZoom($(this));
-	});*/
-	
-	this.addPointers();
-	
-	//Si dans le metadata player _ n'est pas déclaré, on le déclare.
-	if(typeof _ !== "undefined" && typeof IriSP._ === "undefined")
-	{
-		IriSP._ = _;
-	}
-	
-	if(typeof $ !== "undefined" && typeof IriSP.jQuery === "undefined")
-	{
-		IriSP.jQuery = $;
-	}
-	
-	//On charge les marqueurs.
-	var sourceManager = new IriSP.Model.Directory(),
-	globalAnnotations = new IriSP.Model.List(sourceManager),
-	nbFichiers = _this.urls.length,
-	fichiersCharges = 0;
-	
-	for (var i = 0; i < nbFichiers; i++)
-	{
-		// console.log('url : ' + _this.urls[i]);
-		_this.sources[i] = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt});
-		_this.sources[i].onLoad(function()
+    
+    //On fait coincider le background du body avec celui de la mosaïque.
+    $('body').css('background-position', '0px ' + this.MPTop_margin + 'px');
+    
+    this.addPointers();
+    
+    //Si dans le metadata player _ n'est pas déclaré, on le déclare.
+    if(typeof _ !== "undefined" && typeof IriSP._ === "undefined")
+    {
+        IriSP._ = _;
+    }
+    
+    if(typeof $ !== "undefined" && typeof IriSP.jQuery === "undefined")
+    {
+        IriSP.jQuery = $;
+    }
+    
+    //On charge les marqueurs.
+    var sourceManager = new IriSP.Model.Directory(),
+    globalAnnotations = new IriSP.Model.List(sourceManager),
+    nbFichiers = _this.urls.length,
+    fichiersCharges = 0;
+    
+    //Récupère les annotations.
+    for (var i = 0; i < nbFichiers; i++)
+    {
+        _this.sources[i] = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt});
+        _this.sources[i].onLoad(function()
+        {
+            var source = this;
+            globalAnnotations.addElements(source.getAnnotations());
+            fichiersCharges++;
+            if (fichiersCharges == nbFichiers)
+            {
+                //Instructions à exécuter quand tout est chargé.
+                _this.annotations = globalAnnotations;
+                // console.log(_this.annotations.length + ' annotations loaded from ' + nbFichiers + ' files.');
+                
+                //Si on gère les interactions à la souris.
+                if(_this.config.mouseInteractions)
+                {
+                    //On met à jour la position estimée de la souris.
+                    $(window).mousemove(function(e)
+                    {
+                        // _this.refreshPointers(e.pageX, e.pageY, _this, true);
+                        _this.refreshPointers(e.pageX, e.pageY, true);
+                        _this.mousePosX = e.pageX;
+                        _this.mousePosY = e.pageY;
+                    });
+                }
+                
+                //Si on a activé la préphase mais qu'on est en mode Kinect.
+                if(_this.config.noUserModeEnabled && !_this.config.mouseInteractions)
+                {
+                    //On active la préphase.
+                    _this.init();
+                    _this.showNImages(0);
+                    _this.currentMode = "NO-USER";
+                }
+                else
+                {
+                    //Sinon on affiche directement la mosaique.
+                    _this.showNImages(20);
+                    _this.currentMode = "MOSAIC";
+                }
+                
+                //Le premier snapshot sur lequel on zoom en préphase.
+                _this.previousZoomedSN = $('#snapshotDiv-' + _this.fillingIds[0]);
+            }
+        });
+    }
+    
+    //Si on est en mode d'intéraction souris.
+    if(this.config.mouseInteractions)
+    {
+        //Si on fait un mouse down sur le body, on vérifie enregistre le déplacement de la souris jusqu'au prochain mouse up.
+        $(window).mousedown(function (e)
+        {
+			_this.onMouseDown(e);
+			return false;
+        });
+		
+		//On écoute le déplacement de la souris.
+		$(window).mousemove(function(e)
 		{
-			var source = this;
-			// console.log(source);
-			globalAnnotations.addElements(source.getAnnotations());
-			// console.log(source.url + ' ' + source.getAnnotations().length);
-			fichiersCharges++;
-			if (fichiersCharges == nbFichiers)
+			_this.onMouseMove(e);
+			return false;
+		});
+		
+		//Si on fait un mouse up après ce mouse down.
+		$(window).mouseup(function()
+		{
+			_this.onMouseUp();
+			return false;
+		});
+		
+		//Si on fait un clic.
+		$(window).click(function(e)
+		{
+			_this.onClick(e.pageX, e.pageY);
+			_this.removeSearchNotificationIfOnIt(e.pageX, e.pageY);
+			return false;
+		});
+		
+		$(window).on('mousewheel', function(event, delta, deltaX, deltaY)
+        {
+			//Si on est dans un mode autre qu'on mode zoomé ou que l'aide est affichée, on part.
+			if(_this.currentMode != "VIDEO" && _this.currentMode != "SEARCH" && _this.currentMode != "TIMELINE" || _this.helpDisplayed)
 			{
-				// instructions à exécuter quand tout est chargé
-				_this.annotations = globalAnnotations;
-				// console.log(_this.annotations.length + ' ' + nbFichiers);
-				console.log(_this.annotations.length + ' annotations loaded from ' + nbFichiers + ' files.');
-				
-				//Si on gère les interactions à la souris.
-				if(_this.mouseInteractions)
-				{
-					$(window).mousemove(function(e)
-					{
-						_this.refreshMainPointer(e.pageX, e.pageY, _this);
-						_this.mousePosX = e.pageX;
-						_this.mousePosY = e.pageY;
-					});
-				}
-				
-				if(_this.prephaseEnabled && !_this.mouseInteractions)
-				{
-					_this.init();
-					_this.showNImages(0);
-					_this.currentMode = "NO-USER";
-				}
-				else
-				{
-					_this.showNImages(20);
-					_this.currentMode = "MOSAIC";
-				}
-				
-				// /!\ //
-				// _this.currentMode = "FILTER";
-				// _this.showNImages(20);
-				//_this.isSearchByCurvesOn = true;
-				// _this.startSearch();
-				// console.log('CANVAS READY');
-				// /!\ //
-				
-				_this.previousZoomedSN = $('#snapshotDiv-' + _this.fillingIds[0]);
-			}
-		});
-	}
-	
-	if(this.mouseInteractions)
-	{
-		//Si on fait un mouse down sur le body, on vérifie enregistre le déplacement de la souris jusqu'au prochain mouse up.
-		$(window).mousedown(function (e)
-		{
-			_this.removeSearchNotificationIfOnIt(e.pageX, e.pageY);
-			
-			_this.isUserInSearchZone = true;
-			if(_this.isSearchByCurvesOn)
-			{
-				_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY, null, null);
+				return;
 			}
 			
-			console.log('mdown');
-			//On écoute le déplacement de la souris.
-			$(window).mousemove(function(e)
-			{
-				if(_this.isSearchByCurvesOn)
-				{
-					_this.searchCanvas.onPointerMove(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
-				}
-				
-				//On met à jour l'ancienne position de la souris si elle est nulle.
-				if(!_this.mousePosLastX && _this.mousePosLastX != 0)
-				{
-					_this.mousePosLastX = _this.mousePosX;
-				}
-				if(!_this.mousePosLastY && _this.mousePosLastY != 0)
-				{
-					_this.mousePosLastY = _this.mousePosY;
-				}
-				
-				//Le delta s'accroît si la souris bouge.
-				_this.mouseUpDownDelta += Math.floor(Math.sqrt((_this.mousePosLastX - e.pageX) * (_this.mousePosLastX - e.pageX) + (_this.mousePosLastY - e.pageY) * (_this.mousePosLastY - e.pageY)));
-				
-				// console.log(_this.mouseUpDownDelta, _this.mousePosLastX, e.pageX);
-				
-				if(_this.mousePosLastX != _this.mousePosX)
-				{
-					_this.mousePosLastX = _this.mousePosX;
-				}
-				if(_this.mousePosLastY != _this.mousePosY)
-				{
-					_this.mousePosLastY = _this.mousePosY;
-				}
-				
-				//Si la souris a parcouru une trop grande distance, on entre en recherche.
-				if(_this.mouseUpDownDelta > _this.config['mouseUpDownDeltaTreshold'])
-				{
-					//Si on est en mosaique, on entre en filtrage.
-					if(_this.currentMode == "MOSAIC")
-					{
-						_this.preUnzoom();
-						_this.currentMode = "FILTER";
-						_this.isMosaicFiltered = true;
-						
-						console.log(_this.date() + ' - ENTRE EN MODE FILTRAGE');
-						
-						_this.isSearchByCurvesOn = true;
-						_this.startSearch();
-						
-						/*if(!_this.curvesGesturesFound)
-						{
-							this.removeNotifications();
-							_this.filterSearch();
-						}*/
-						
-						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
-					}
-					else if(_this.currentMode == "FILTER" && !_this.isSearchByCurvesOn && _this.isUserInSearchZone)
-					{
-						console.log('after search');
-						_this.preUnzoom();
-						_this.isSearchByCurvesOn = true;
-						_this.startSearch();
-						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
-					}
-					//Si on est dans une vidéo, on entre en recherche.
-					else if(_this.currentMode == "VIDEO" || _this.currentMode == "TIMELINE")
-					{
-						_this.currentMode = "SEARCH";
-						
-						console.log(_this.date() + ' - ENTRE EN MODE RECHERCHE');
-						
-						_this.isSearchByCurvesOn = true;
-						_this.startSearch();
-						
-						/*if(!_this.curvesGesturesFound)
-						{
-							this.removeNotifications();
-							_this.searchSearch();
-						}*/
-						
-						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
-					}
-					else if(_this.currentMode == "SEARCH" && !_this.isSearchByCurvesOn)
-					{
-						_this.isSearchByCurvesOn = true;
-						_this.startSearch();
-						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
-					}
-					
-					//Il est possible d'afficher l'aide.
-					if(!_this.canNotifyHelp)
-					{
-						_this.canNotifyHelpTimeout = setTimeout(function()
-						{
-							_this.canNotifyHelp = true;
-						}, _this.config['timeoutCanNotifyHelp']);
-					}
-				}
-			});
-			
-			//Si on fait un mouse up après ce mouse down.
-			$(window).mouseup(function()
-			{
-				console.log('mup');
-				
-				if(_this.isSearchByCurvesOn)
-				{
-					_this.isUserInSearchZone = false;
-					
-					var gesture_match = _this.gestureWithSameCode(_this.actualCode);
-					_this.actualCode = '';
-					
-					if(gesture_match.length > 0)
-					{
-						if(_this.currentMode == "SEARCH" && _this.playerIsReady)
-						{
-							_this.player.widgets[0].searchByGesture(gesture_match);
-							_this.isCurrentlyInASearchByGesture = _this.player.widgets[0].isCurrentlyInASearchByGesture;
-							
-							if(_this.player && _this.player.widgets[0] && _this.timeToGoAt[_this.centerId] === 0 && _this.player.widgets[0].atLeastOneSearchMarker(_this.currentSearchGesture[_this.centerId]))
-							{
-								_this.player.widgets[0].goToFirstSearchedMarker(_this.currentSearchGesture[_this.centerId]);
-							}
-							
-							_this.removeNotifications();
-							_this.currentSearchGesture[_this.centerId] = gesture_match;
-							_this.searchGesture(gesture_match, 'valid');
-							_this.curvesGesturesFound = false;
-						}
-						else if(_this.currentMode == "FILTER")
-						{
-							if(_this.isMosaicFiltered)
-							{
-								_this.removeNotifications();
-								_this.filterSearchedType = gesture_match;
-								_this.filterGesture(gesture_match, 'valid');
-								_this.searchFilter(gesture_match);
-								_this.curvesGesturesFound = false;
-							}
-						}
-					}
-					
-					_this.searchCanvas.onPointerOut();
-				}
-				
-				//On unbind ce qui a été bindé après le mouse up.
-				$(window).unbind('mousemove');
-				$(window).unbind('mouseup');
-				//On rebind le mousemove principal du body, car ils ont tous été unbindés.
-				$(window).mousemove(function(e)
-				{
-					_this.refreshMainPointer(e.pageX, e.pageY, _this);
-					_this.mousePosX = e.pageX;
-					_this.mousePosY = e.pageY;
-				});
-				
-				_this.mousePosLastX = null;
-				_this.mousePosLastY = null;
-				
-				//Si la distance parcourue par la souris entre le mouse down et le mouse up est inférieure ou égale au seuil.
-				if(_this.mouseUpDownDelta <= _this.config['mouseUpDownDeltaTreshold'])
-				{
-					//Si on est sur un snapshot prézoomé.
-					if(_this.isOnAPrezoomSN && _this.previousZoomedSN != '' && (_this.currentMode == 'MOSAIC' || _this.currentMode == 'FILTER'))
-					{
-						_this.zoom();
-					}
-				}
-				
-				_this.mouseUpDownDelta = 0;
-				_this.isSearchByCurvesOn = false;
-				_this.leaveSearch();
-				
-				if(_this.currentMode == 'FILTER' && _this.filterSearchedType != '')
-				{
-					_this.removeNotifications();
-					_this.filterGesture(_this.filterSearchedType, 'valid');
-				}
-			});
-		});
-	}
+            //Quand on "tire" la molette vers soi, on dezoom.
+            if (delta < 0)
+            {
+                _this.unzoom();
+            }
+        });
+    }
 }
 
 /*
  * Charge les paramètres du Front. Local (true/false) est le mode de chargement des données.
+ * Est appelé dans le fichier :
+ * mosaic > fonction Mosaic, est appelée dans le constructeur de manière à charger les paramètres de configuration avant la création de la mosaique.
 */
-mosaic.prototype.loadParameters = function(file_path)
+Mosaic.prototype.loadParameters = function(file_path)
 {
-	var _this = this;
-	
-	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', 'mouseUpDownDeltaTreshold'];
-	var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage'];
-	
-	$.getJSON(file_path, function(data)
-	{
-		for(key in data)
-		{
-			var val = data[key];
-			
-			if(_.include(supposedToBeInt, key))
-			{
-				var intVal = parseInt(val);
-				if(isNaN(intVal))
-				{
-					// console.log(_this.default_config);
-					_this.config[key] = _this.default_config[key];
-					console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Int). Valeur par défaut " + _this.default_config[key] + " chargée à la place.");
-				}
-				else
-				{
-					_this.config[key] = intVal;
-				}
-			}
-			else if(_.include(supposedToBeFloat, key))
-			{
-				var floatVal = parseFloat(val);
-				if(isNaN(floatVal))
+    var _this = this;
+    
+    //Variables censées être des ints.
+    var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timeReloadAfterResize', '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', 'mouseUpDownDeltaTreshold'];
+    //Variables censées êtres des floats.
+    var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage'];
+    
+    //On lit le fichier de configuration.
+    $.getJSON(file_path, function(data)
+    {
+        //Pour chaque ligne du fichier.
+        for(key in data)
+        {
+            var val = data[key];
+            
+            //Si la valeur est prise pour un int.
+            if(_.include(supposedToBeInt, key))
+            {
+                //On la parse et s'il y a une erreur, on l'indique dans la console avant d'affecter la valeur par défaut.
+                //Sinon on lui affecte la valeur lue.
+                var intVal = parseInt(val);
+                if(isNaN(intVal))
+                {
+                    _this.config[key] = _this.default_config[key];
+                    console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Int). Valeur par défaut " + _this.default_config[key] + " chargée à la place.");
+                }
+                else
+                {
+                    _this.config[key] = intVal;
+                }
+            }
+            //Si la valeur est prise pour un float.
+            else if(_.include(supposedToBeFloat, key))
+            {
+                //On la parse et s'il y a une erreur, on l'indique dans la console avant d'affecter la valeur par défaut.
+                //Sinon on lui affecte la valeur lue.
+                var floatVal = parseFloat(val);
+                if(isNaN(floatVal))
+                {
+                    _this.config[key] = _this.default_config[key];
+                    console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Float). Valeur par défaut " + _this.default_config[key] + " chargée à la place.");
+                }
+                else
+                {
+                    _this.config[key] = floatVal;
+                }
+            }
+            else
+            {
+				//S'il s'agit de la langue, on met par défaut si la valeur est nulle.
+				if(key == 'lang' && val == '')
 				{
 					_this.config[key] = _this.default_config[key];
-					console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Float). Valeur par défaut " + _this.default_config[key] + " chargée à la place.");
 				}
+                //Sinon si c'est une string, on l'affecte.
 				else
 				{
-					_this.config[key] = floatVal;
+					_this.config[key] = val;
 				}
-			}
-			else
-			{
-				_this.config[key] = val;
-			}
-		}
-		
-		//On remplit le tableau d'ids.
-		for(var i = 0 ; i < _this.config['totalImages'] ; i++)
-			_this.ids.push(i);
-		//On les mélange.
-		_this.ids.sort(function()
-		{
-			return 0.5 - Math.random()
-		});
-		
-		//On remplit le tableau d'ids destiné à afficher les snapshots au fur et à mesure.
-		for(var i = 0 ; i < _this.config['imagesToShow'] ; i++)
-			_this.fillingIds.push(i);
-		//On les mélange.
-		_this.fillingIds.sort(function()
-		{
-			return 0.5 - Math.random()
-		});
-		
-		if(_this.config['local'] == 'true')
-		{
-			// console.log("Loading local metadata.");
-			_this.loadFromJson('./player/json/local_videos.json');
-		}
-		else
-		{
-			// console.log("Loading online metadata.");
-			_this.loadFromJson('./player/json/online_videos.json');
-		}
-		
-		//On initialise le client.
-		if(!_this.mouseInteractions)
-		{
-			_this.client = new client(_this.config['host'], _this.config['port'], _this);
-		}
-		
-		_this.getDictionary();
-		_this.getLang();
-	});
+            }
+        }
+        
+        //On remplit le tableau d'ids.
+        for(var i = 0 ; i < _this.config.totalImages ; i++)
+            _this.ids.push(i);
+        //On les mélange.
+        _this.ids = _.shuffle(_this.ids);
+        
+        //On remplit le tableau d'ids destiné à afficher les snapshots au fur et à mesure.
+        for(var i = 0 ; i < _this.config.imagesToShow ; i++)
+            _this.fillingIds.push(i);
+        //On les mélange.
+        _this.fillingIds = _.shuffle(_this.fillingIds);
+        
+        //Si la config spécifie le chargement comme étant local/en ligne, on charge le fichier des vidéos approprié.
+        if(_this.config.local)
+        {
+            _this.loadFromJson(_this.config.videoConfigFileLocal);
+        }
+        else
+        {
+            _this.loadFromJson(_this.config.videoConfigFileOnline);
+        }
+        
+        //On initialise le client dans le cas d'intéractions Kinect.
+        if(!_this.config.mouseInteractions)
+        {
+            _this.client = new Client(_this.config.host, _this.config.port, _this);
+        }
+        
+        //On prend le dictionnaire stockant les codes des courbes de recherche.
+        _this.getDictionary();
+        //On charge le fichier des langues.
+        _this.getLang();
+    });
 }
 
 /*
  * Phase principale (utilisateur non détecté). Une vidéo se lance aléatoirement.
  * L'interface est identique à celle du zoom, mais sans interaction possible avec les voisins, ni les controles timeline.
  * Lors de la fin d'une lecture, on dézoome vers la mosaïque, puis on rezoome vers un autre snapshot (aléatoire).
+ * Est appelé dans les fichiers :
+ * mosaic > fonction loadMosaic.
+ * zoomInteractions > fonction unzoom.
 */
-mosaic.prototype.init = function()
+Mosaic.prototype.init = function()
 {
-	var _this = this;
-
-	if(this.currentRandomVideoIdx > this.config['imagesToShow'])
-	{
-		this.currentRandomVideoIdx = 0;
-	}
-	
-	
-	this.previousZoomedSN = $('#snapshotDiv-' + this.fillingIds[this.currentRandomVideoIdx]);
-	this.previousId = $('img', this.previousZoomedSN).attr('id');
-	
-	// console.log('CURRENT MODE : ' + _this.currentMode);
-	// console.log('ids', this.fillingIds[this.currentRandomVideoIdx]);
-	
-	this.previousZoomedSN.fadeTo(this.config['timePrezoom'], 1, function()
-	{
-		// console.log('CURRENT MODE : ' + _this.currentMode);
-		_this.zoom();
-		_this.currentRandomVideoIdx++;
-	});
+    var _this = this;
+    
+    //Si l'index de lecture des vidéos en mode sans utilisateur excède le nombre maximal de vidéos, il est remis à 0 pour tourner en boucle.
+    if(this.currentRandomVideoIdx > this.config.imagesToShow)
+    {
+        this.currentRandomVideoIdx = 0;
+    }
+    
+    //Le snapshot sur lequel on doit zoomé a pour id le tableau de lecture aléatoire à l'index de lecture.
+    this.previousZoomedSN = $('#snapshotDiv-' + this.fillingIds[this.currentRandomVideoIdx]);
+    this.previousId = $('img', this.previousZoomedSN).attr('id');
+    
+    //On fait apparaître le snapshot avant de zoomer dessus.
+    this.previousZoomedSN.fadeTo(this.config.timePrezoom, 1, function()
+    {
+        _this.zoom();
+        _this.currentRandomVideoIdx++;
+    });
 }
 
 /*
  * Remplissage de la mosaïque en fonction du nombre d'images à afficher.
+ * Est appelé dans le fichier :
+ * mosaic > fonctions loadMosaic et manageControlEvents.
 */
-mosaic.prototype.showNImages = function(n)
+Mosaic.prototype.showNImages = function(n)
+{
+    //Si on bouge vers un voisin, on n'utilise pas cette fonction.
+    if(this.currentlyMoving)
+    {
+        return;
+    }
+    
+    //Si il y a plus d'un snapshot à afficher, on entre dans le mode INCOMING avec en paramètre le nombre à afficher.
+    if(n > 1 && n < this.config.imagesToShow)
+    {
+        //On met en mode incoming avec le nombre de snapshots à afficher.
+        this.currentMode = "INCOMING-" + n;
+        //On dézoom.
+        this.unzoom();
+        
+        //On initialise les gestures de recherche.
+        for(var i = 0 ; i < this.config.imagesToShow ; i++)
+        {
+            this.currentSearchGesture[i] = '';
+        }
+        
+        //On enlève les notifications.
+        this.removeNotifications();
+        //On annule les recherches.
+        this.isMosaicFiltered = false;
+        this.isCurrentlyInASearchByGesture = false;
+        //On masque les pointeurs.
+        $('#mainPointer').fadeTo(this.config.timePrezoom, 0);
+        $('#secondPointer').fadeTo(this.config.timePrezoom, 0);
+        //On enlève le spinner.
+        $('#spinner').remove();
+        //On déselectionne tous les voisins.
+        this.deselectAllNeighbours();
+        //On enlève tous les prézooms en cours.
+        $('.prezoomContainers').remove();
+    }
+    
+    //Si on doit afficher la mosaique complète.
+    if(n >= this.config.imagesToShow)
+    {
+        //Si on est en mode sans utilisateur ou bien en mode d'utilisateur approchant.
+        if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING-") > -1)
+        {
+            //Si on est en intéractions Kinect.
+            if(!this.config.mouseInteractions)
+            {
+                //On met le mode à jour.
+                this.currentMode = "INCOMING-20";
+                //On dézoom.
+                this.unzoom();
+            }
+            
+            //On passe en mode mosaique.
+            this.currentMode = "MOSAIC";
+            //On enlève les notifications, et on met les notifications de sélection et de recherche.
+            this.removeNotifications();
+            this.mosaicSelectionAndSearch();
+            //On retarde le mécanisme de redémarrage.
+            clearTimeout(this.nouserTimeout);
+        }
+    }
+    
+    //Pour les snapshots à afficher.
+    for(var i = 0 ; i < n ; i++)
+    {
+        //Si les snapshots ne sont pas affichés.
+        if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') < 1)
+        {
+            //On les fait apparaître.
+            $('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config.timeFilling, '1');
+        }
+    }
+    //Pour ceux à masquer.
+    for(var i = n ; i < this.config.imagesToShow ; i++)
+    {
+        //Si les snapshots ne sont pas masqués et qu'il ne s'agit pas du dernier snapshot en lecture aléatoire (mode NO-USER).
+        if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') > 0 && this.fillingIds[i] != this.currentRandomVideoIdx)
+        {
+            //On les masque.
+            $('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config.timeFilling, '0');
+        }
+    }
+}
+
+/*
+ * Gère les événements de contrôle dans la mosaïque.
+ * Est appelé dans le fichier :
+ * client > fonction processMsg.
+*/
+Mosaic.prototype.manageControlEvents = function(event)
 {
-	if(this.currentlyMoving)
+    var _this = this;
+    
+    if(typeof event === 'undefined')
+    {
+        return;
+    }
+    
+    var gestureReceived = '';
+    
+    //Si l'utilisateur arrive et qu'on a la préphase activée.
+    if(event.indexOf("INCOMING-") != -1 && this.config.noUserModeEnabled)
+    {
+        //Si on peut démarrer.
+        if(this.canStart)
+        {
+            //Si on veut afficher plus de snapshots que disponibles, on affiche le maximum.
+            if(this.snapshotsToShow > this.config.imagesToShow)
+            {
+                this.snapshotsToShow = this.config.imagesToShow;
+            }
+            else
+            {
+                //On récupère le nombre de snapshots à afficher.
+                var params = event.split('-');
+                this.snapshotsToShow = params[1];
+            }
+            
+            //Si la position de l'utilisateur a changé.
+            if(event != this.lastIncomingMessage)
+            {
+                //On la met à jour et on affiche la mosaique en conséquence.
+                this.lastIncomingMessage = event;
+                this.showNImages(this.snapshotsToShow);
+            }
+        }
+        
+        //On retarde le mécanisme de redémarrage.
+        clearTimeout(this.nouserTimeout);
+        
+        //Après un délai d'absence de l'utilisateur on redémarre.
+        this.nouserTimeout = setTimeout(function()
+        {
+            window.location.reload();
+        }, this.config.timeoutNouser);
+    }
+    //S'il n'y a qu'un snapshot à afficher et qu'on est en préphase, on redémarre.
+    else if((event == "NO-USER" || event == "INCOMING-0" || event == "INCOMING-1") && this.config.noUserModeEnabled)
+    {
+        window.location.reload();
+    }
+    //Si on a fait un swipe.
+    else if(event.indexOf("SWIPE") != -1)
+    {
+        //Si le player est près et qu'on n'est pas en train de faire un swipe.
+        if(this.player && this.player.widgets && this.playerIsReady && !this.isSwipe)
+        {
+            //On est en train de faire un swipe.
+            this.isSwipe = true;
+            
+            //Si on est en mode de recherche, que la mosaique est filtrée et qu'on est arrivé au dernier marqueur.
+            if(this.currentMode == 'SEARCH' && this.isMosaicFiltered && !this.player.widgets[0].isAMarkerAhead(this.currentSearchGesture[this.centerId]))
+            {
+                //On passe à la prochaine vidéo qui contient des résultats.
+                this.playNextVideo();
+            }
+            
+			//On spécifie s'il s'agit d'un swipe left ou right.
+			var swipeType = ((event.indexOf("LEFT") != -1) ? 'left' : 'right');
+			var isSwipeLeft = ((event.indexOf("LEFT") != -1) ? true : false);
+			
+			//On passe au marqueur suivant/précédent en fonction du type de swipe.
+			this.player.widgets[0].switchToMarker(isSwipeLeft, this.currentSearchGesture[this.centerId]);
+			//Si on est en mode vidéo.
+			if(this.currentMode == 'VIDEO')
+			{
+				//On affiche la notification.
+				this.removeNotifications();
+				this.videoSwipe(swipeType);
+			}
+			//Si on est en mode recherche dans une vidéo et qu'on n'a pas de gesture de recherche.
+			else if(this.currentMode == 'SEARCH' && this.currentSearchGesture[this.centerId] == '')
+			{
+				//On affiche la notification.
+				this.removeNotifications();
+				this.searchSearchAndSwipe(swipeType);
+			}
+			//Si on est en mode recherche dans une vidéo et qu'on a une gesture de recherche.
+			else if(this.currentMode == 'SEARCH' && this.currentSearchGesture[this.centerId] != '')
+			{
+				//On affiche la notification.
+				this.removeNotifications();
+				this.searchGestureAndSwipe(this.currentSearchGesture[this.centerId], 'valid', swipeType);
+			}
+            
+            //On le fait disparaitre au bout d'un certain temps.
+            this.notifySwipeTimeout = setTimeout(function()
+            {
+                _this.isSwipe = false;
+                _this.removeNotifications();
+                
+                //Si on est en mode de recherche dans une vidéo et qu'aucune gesture n'est recherchée.
+                if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] == '')
+                {
+                    _this.searchSearch();
+                }
+                //Si on est en mode de recherche dans une vidéo et qu'on a une recherche par gesture.
+                else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] != '')
+                {
+                    _this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid');
+                }
+                
+            }, this.config.timeoutNotifySwipe);
+        }
+    }
+    //Si on reçoit l'instruction correspondant à une des quatre gestures de recherche corporelle.
+    else if(event.indexOf("BEND") != -1 || event.indexOf('KNEE-UP') != -1 || event.indexOf('FALL') != -1 || event.indexOf('JUMP') != -1)
+    {
+        //On la met en minuscule.
+        gestureReceived = event.toLowerCase();
+        //On met à jour la gesture recherchée.
+        this.currentSearchGesture[centerId] = gestureReceived;
+    }
+    //Si on a effectué un hello, qu'on peut notifier l'aide et que les deux mains ne sont pas dans la zone de recherche.
+    else if(event.indexOf("HELLO") != -1 && this.canNotifyHelp && !this.areBothPointersHere)
+    {
+        //On affiche différentes aides en fonction de si on se trouve dans une vidéo ou non.
+        if(this.currentMode == 'SEARCH')
+        {
+            this.notifyHelp(false);
+        }
+        else if(this.currentMode == 'FILTER')
+        {
+            this.notifyHelp(true);
+        }
+    }
+    
+    //Si on a reçu une gesture.
+    if(gestureReceived != '')
+    {
+        //Si on est en mode recherche et que le player est prêt.
+        if(this.currentMode == "SEARCH" && this.playerIsReady)
+        {
+            //On recherche dans la vidéo.
+            this.player.widgets[0].searchByGesture(gestureReceived);
+            this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture;
+            //On notifie.
+            this.removeNotifications();
+            this.searchGesture(gestureReceived, 'valid');
+        }
+        //Si on est dans un filtrage.
+        else if(this.currentMode == "FILTER")
+        {
+            if(this.isMosaicFiltered)
+            {
+                //On notifie et on filtre.
+                this.removeNotifications();
+                this.filterGesture(gestureReceived, 'valid');
+                this.searchFilter(gestureReceived);
+            }
+        }
+        
+        //Si l'aide est affichée, on l'enlève.
+        if(this.helpDisplayed)
+        {
+            this.removeHelp();
+        }
+    }
+}
+
+/*
+ * Fonction qui s'exécute lorsque le player a chargé.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadPlayer.
+*/
+Mosaic.prototype.onPlayerLoad = function()
+{
+	var _this = this;
+	
+	if(this.currentMode == 'NO-USER')
 	{
-		return;
+		//On peut s'approcher de la kinect.
+		this.canStart = true;
 	}
 	
-	// console.log('INCOMING ----- ' + n);
-	//Si il y a plus d'un snapshot à afficher, on entre dans le mode INCOMING avec en paramètre le nombre à afficher.
-	if(n > 1 && n < this.config['imagesToShow'])
+	//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
+	if(this.player.popcorn)
 	{
-		this.currentMode = "INCOMING-" + n;
-		this.unzoom();
-		
-		for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
+		this.player.popcorn.listen('pause', function()
 		{
-			this.currentSearchGesture[i] = '';
-		}
+			//Si la pause est naturelle (fin de la timeline, dézoom, déplacement vers un voisin).
+			if(!_this.userPaused)
+			{
+				//Si c'est en mode sans utilisateur.
+				if(_this.currentMode == 'NO-USER')
+				{
+					//On dézoome.
+					_this.unzoom();
+				}
+				//Sinon, si ce n'est pas causé par un déplacement ou un dézoom.
+				else if(!_this.currentlyMoving && !_this.currentlyUnzooming)
+				{
+					//Si on est en mode timeline et qu'on est en pause, c'est probablement que l'user a placé le curseur à la fin.
+					if(_this.currentMode != 'TIMELINE')
+					{
+						_this.playNextVideo();
+					}
+				}
+			}
+		});
 		
-		this.removeNotifications();
-		this.isMosaicFiltered = false;
-		this.isCurrentlyInASearchByGesture = false;
-		$('#mainPointer').fadeTo(this.config['timePrezoom'], 0);
-		$('#secondPointer').fadeTo(this.config['timePrezoom'], 0);
-		$('#spinner').remove();
-		this.deselectAllNeighbours();
-		$('.prezoomContainers').remove();
+		//Si les marqueurs ont été chargés.
+		this.player.popcorn.on("markersready", function()
+		{
+			_this.onMarkersReady();
+		});
 	}
-	// console.log('n : ' + n);
-	if(n >= this.config['imagesToShow'])
+}
+
+/*
+ * Fonction qui s'exécute lorsque les marqueurs d'une video on été placés.
+ * Est appelé dans le fichier :
+ * mosaic > fonction onPlayerLoad.
+*/
+Mosaic.prototype.onMarkersReady = function()
+{
+	var _this = this;
+	
+	//Le player est prêt.
+	this.playerIsReady = true;
+	
+	if(this.player.widgets[0])
 	{
-		// this.unzoom();
-		if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING-") > -1)
+		//On spécifie à la timeline dans quel mode d'intéraction on est.
+		this.player.widgets[0].setMouseInteractions(this.config.mouseInteractions);
+		//Idem pour la langue.
+		if(this.gesturesText.length > 0)
 		{
-			if(!this.mouseInteractions)
-			{
-				this.currentMode = "INCOMING-20";
-				this.unzoom();
-			}
-			
-			this.currentMode = "MOSAIC";
-			this.removeNotifications();
-			this.mosaicSelectionAndSearch();
-			clearTimeout(this.nouserTimeout);
-			console.log('OK');
+			this.player.widgets[0].setLang(this.gesturesText);
 		}
-		//On affiche les notifications.
-		// this.notifySelectionSearchMosaicFull();
-	
-		//$('#mainPointer').fadeTo(this.config['timePrezoom'], 1);
-		//$('#secondPointer').fadeTo(this.config['timePrezoom'], 1);
 	}
 	
-	//Pour les snapshots à afficher.
-	for(var i = 0 ; i < n ; i++)
+	//Si on est en mode video ou recherche ou timeline.
+	if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH' || this.currentMode == 'TIMELINE')
+	{
+		//On peut faire des swipes.
+		this.canSwipe = true;
+	}
+	
+	//Si aucune recherche par gesture n'est effectuée.
+	if(this.currentSearchGesture[this.centerId] == '')
 	{
-		//Si les snapshots ne sont pas affichés.
-		if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') < 1)
+		//On enlève le filtre.
+		this.removeFilter();
+	}
+	//Sinon.
+	else
+	{
+		//On entre en mode recherche dans une vidéo.
+		this.currentMode = 'SEARCH';
+		//On recherche la gesture.
+		this.player.widgets[0].searchByGesture(this.currentSearchGesture[this.centerId]);
+		this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture;
+		
+		//On va au premier marqueur trouvé.
+		if(this.timeToGoAt[this.centerId] === 0 && this.player.widgets[0].atLeastOneSearchMarker(this.currentSearchGesture[this.centerId]))
 		{
-			//On les fait apparaître.
-			$('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config['timeFilling'], '1');
+			this.player.widgets[0].goToFirstSearchedMarker(this.currentSearchGesture[this.centerId]);
 		}
-	}
-	//Pour ceux à masquer.
-	for(var i = n ; i < this.config['imagesToShow'] ; i++)
-	{
-		//Si les snapshots ne sont pas masqués et qu'il ne s'agit pas du dernier snapshot en lecture aléatoire (mode NO-USER).
-		if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') > 0 && this.fillingIds[i] != this.currentRandomVideoIdx)
+		//Si aucun marqueur n'est trouvé.
+		else
 		{
-			//On les masque.
-			$('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config['timeFilling'], '0');
+			//On va juste là où on était la dernière fois qu'on a joué la vidéo.
+			this.player.popcorn.currentTime(this.timeToGoAt[this.centerId]);
 		}
 	}
 }
 
 /*
- * Gère les événements de contrôle dans la mosaïque.
+ * Chargement du player basé sur le metadataplayer.
+ * Est appelé dans les fichiers :
+ * neighbours > fonction moveToNeighbour.
+ * zoomInteractions > zoom.
 */
-mosaic.prototype.manageControlEvents = function(event)
+Mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft, timeToGo)
 {
-	// console.log('manage');
-	
-	var _this = this;
-	
-	if(typeof event === 'undefined')
-	{
-		return;
-	}
-	
-	var gestureReceived = '';
-	
-	if(event.indexOf("INCOMING-") != -1 && this.prephaseEnabled)
-	{
-		// console.log(this.date() + ' ' + event);
-		// console.log('CAN START : ' + this.canStart);
-		if(this.canStart)
-		{
-			if(this.snapshotsToShow > this.config['imagesToShow'])
-			{
-				this.snapshotsToShow = this.config['imagesToShow'];
-			}
-			else
-			{
-				var params = event.split('-');
-				// console.log(event);
-				this.snapshotsToShow = params[1];
-			}
-			
-			//Si la position de l'utilisateur a changé.
-			if(event != this.lastIncomingMessage)
-			{
-				console.log(this.snapshotsToShow);
-				this.lastIncomingMessage = event;
-				this.showNImages(this.snapshotsToShow);
-			}
-		}
-		
-		clearTimeout(this.nouserTimeout);
-		this.nouserTimeout = setTimeout(function()
-		{
-			/*_this.showNImages(0);
-			_this.init();
-			_this.canStart = false;
-			_this.currentMode = "NO-USER";*/
-			
-				window.location.reload();
-			// mos = new mosaic('./config.json', default_parameters);
-			
-			console.log('NOUSER');
-		}, this.config['timeoutNouser']);
-	}
-	else if((event == "NO-USER" || event == "INCOMING-0" || event == "INCOMING-1") && this.prephaseEnabled)
-	{
-		/*this.showNImages(0);
-		this.init();
-		this.canStart = false;
-		this.currentMode = "NO-USER";*/
-		
-			window.location.reload();
-		// mos = new mosaic('./config.json', default_parameters);
-		
-		console.log('NOUSER');
-		
-		/*this.currentMode = "NO-USER";
-		this.showNImages(0);
-		this.canStart = false;
-		this.init();*/
-	}
-	// /!\/!\ //
-	else if(event.indexOf("SWIPE") != -1)
-	{
-		if(this.player && this.player.widgets && this.playerIsReady && !this.isSwipe)
-		{
-			this.isSwipe = true;
-			
-			if(this.currentMode == 'SEARCH' && this.isMosaicFiltered && !this.player.widgets[0].isAMarkerAhead(this.currentSearchGesture[this.centerId]))
-			{
-				this.playNextVideo();
-			}
-			
-			//L'utilisateur a fait un swipe left.
-			if(event.indexOf("LEFT") != -1)
-			{
-				this.player.widgets[0].switchToMarker(true, this.currentSearchGesture[this.centerId]);
-				if(this.currentMode == 'VIDEO')
-				{
-					this.removeNotifications();
-					this.videoSwipe('left');
-				}
-				else if(this.currentMode == 'SEARCH' && !this.currentSearchGesture[this.centerId])
-				{
-					this.removeNotifications();
-					this.searchSearchAndSwipe('left');
-				}
-				else if(this.currentMode == 'SEARCH' && this.currentSearchGesture[this.centerId])
-				{
-					this.removeNotifications();
-					this.searchGestureAndSwipe(this.currentSearchGesture[this.centerId], 'valid', 'left');
-				}
-			}
-			//L'utilisateur a fait un swipe right.
-			else if(event.indexOf("RIGHT") != -1)
-			{
-				this.player.widgets[0].switchToMarker(false, this.currentSearchGesture[this.centerId]);
-				if(this.currentMode == 'VIDEO')
-				{
-					this.removeNotifications();
-					this.videoSwipe('right');
-				}
-				else if(this.currentMode == 'SEARCH' && !this.currentSearchGesture[this.centerId])
-				{
-					this.removeNotifications();
-					this.searchSearchAndSwipe('right');
-				}
-				else if(this.currentMode == 'SEARCH' && this.currentSearchGesture[this.centerId])
-				{
-					this.removeNotifications();
-					this.searchGestureAndSwipe(this.currentSearchGesture[this.centerId], 'valid', 'right');
-				}
-			}
-			
-			//On le fait disparaitre au bout d'un certain temps.
-			this.notifySwipeTimeout = setTimeout(function()
-			{
-				_this.isSwipe = false;
-				
-				// /!\ //
-				_this.removeNotifications();
-				
-				if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture[_this.centerId])
-				{
-					_this.searchSearch();
-				}
-				else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId])
-				{
-					_this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid');
-				}
-				
-			}, this.config['timeoutNotifySwipe']);
-		}
-	}
-	else if(event.indexOf("BEND") != -1 || event.indexOf('KNEE-UP') != -1 || event.indexOf('FALL') != -1 || event.indexOf('JUMP') != -1)
-	{
-		gestureReceived = event.toLowerCase();
-		gestureReceived = gestureReceived.replace('wave', 'hello');
-		this.currentSearchGesture[centerId] = gestureReceived;
-	}
-	else if(event.indexOf("HELLO") != -1 && this.canNotifyHelp && !this.areBothPointersHere)
-	{
-		if(this.currentMode == 'SEARCH')
-		{
-			this.notifyHelp(false);
-		}
-		else if(this.currentMode == 'FILTER')
-		{
-			this.notifyHelp(true);
-		}
-	}
-	
-	if(gestureReceived != '')
-	{
-		if(this.currentMode == "SEARCH" && this.playerIsReady)
-		{
-			this.player.widgets[0].searchByGesture(gestureReceived);
-			this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture;
-			
-			this.removeNotifications();
-			this.searchGesture(gestureReceived, 'valid');
-		}
-		else if(this.currentMode == "FILTER")
-		{
-			if(this.isMosaicFiltered)
-			{
-				// console.log('FILTER !!!');
-				// this.notifySearch1Gesture(gestureReceived, 'valid');
-				this.removeNotifications();
-				this.filterGesture(gestureReceived, 'valid');
-				this.searchFilter(gestureReceived);
-			}
-		}
-		
-		if(this.helpDisplayed)
-		{
-			this.removeHelp();
-		}
-	}
-	// /!\/!\ //
-}
-
-/*
- * Chargement du player basé sur le metadataplayer.
-*/
-mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft, timeToGo)
-{
-	var _this = this;
-	
-	//On configure les options de lancement.
-	IriSP.libFiles.defaultDir = "../lib/";
-	IriSP.widgetsDir = "./player/metadataplayer/"
-	
-	var videoToPlay = this.videos[this.centerId];
-	var currentMetadata = this.urls[this.centerId];
-	
-	var _metadata = {
-		url: currentMetadata,
-		format: 'ldt'
-	};
-	
-	var _config = {
-		gui: {
-			zoomTop: zoomTop - this.marginWidth*2,
-			zoomLeft: zoomLeft,
-			width: newSnWidth,
-			height: newSnHeight,
-			container: 'LdtPlayer',
-			default_options: {
-				metadata: _metadata
-			},
-			css:'./player/metadataplayer/LdtPlayer-core.css',
-			widgets: [
-				{
-					type: "Timeline"
-				}
-			]
-		},
-		player:{
-			type: 'html5', // player type
-			video: videoToPlay,
-			live: true,
-			height: newSnHeight,
-			width: newSnWidth,
-			autostart: true
-		}
-	};
-	
-	//On positionne le player.
-	$('.LdtPlayer').css(
-	{
-		//display: 'none',
-		position: 'absolute',
-		'background-color': '#000000',
-		top: newZoomTop,
-		left: newZoomLeft
-	});
-	
-	//On démarre le player.
-	this.player = null;
-	
-	this.player = new IriSP.Metadataplayer(_config, _metadata);
-	
-	this.player.onLoad(function()
-	{
-		if(_this.currentMode == 'NO-USER')
-		{
-			//On peut s'approcher de la kinect.
-			_this.canStart = true;
-			console.log('CAN START !');
-			// console.log(_this.player);
-			// console.log(_this.player.popcorn);
-		}
-		
-		//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
-		if(_this.player.popcorn)
-		{
-			_this.player.popcorn.listen('pause', function()
-			{
-				//Si l'utilisateur a mis en pause.
-				if(_this.userPaused)
-				{
-				
-				}
-				//Si la pause est naturelle (fin de la timeline, dézoom, déplacement vers un voisin).
-				else
-				{
-					//Si c'est en mode sans utilisateur.
-					if(_this.currentMode == 'NO-USER')
-					{
-						//On dézoome.
-						_this.unzoom();
-					}
-					//Sinon.
-					else
-					{
-						//Si ce n'est pas causé par un déplacement ou un dézoom.
-						if(!_this.currentlyMoving && !_this.currentlyUnzooming)
-						{
-							//On réinitialise la position du curseur à la prochaine lecture de la vidéo.
-							console.log('REINIT');
-							//On passe a la video suivante.
-							console.log('AUTOMOVE');
-							
-							//Si on est en mode timeline et qu'on est en pause, c'est probablement que l'user a placé le curseur à la fin.
-							if(_this.currentMode != 'TIMELINE')
-							{
-								_this.playNextVideo();
-							}
-							//_this.timeToGoAt[parseInt(_this.centerId)] = 0;
-							console.log('time to go at to 0');
-							// return;
-						}
-					}
-				}
-			});
-			// console.log('mosaic filtered : ' + _this.isMosaicFiltered);
-			
-			_this.player.popcorn.on("markersready", function()
-			{
-				_this.playerIsReady = true;
-				
-				if(_this.player.widgets[0])
-				{
-					_this.player.widgets[0].setMouseInteractions(_this.mouseInteractions);
-					if(_this.gesturesText.length > 0)
-					{
-						_this.player.widgets[0].setLang(_this.gesturesText);
-					}
-				}
-				
-				if(_this.currentMode == 'VIDEO' || _this.currentMode == 'SEARCH' || _this.currentMode == 'TIMELINE')
-				{
-					_this.canSwipe = true;
-				}
-				
-				console.log('TIME TO GO AT : ' + _this.timeToGoAt[_this.centerId], _this.centerId, _this.imgs[_this.centerId]);
-				
-				// if(_this.isMosaicFiltered)
-				// {
-					if(_this.currentSearchGesture[_this.centerId] == '')
-					{
-						_this.removeFilter();
-					}
-					else
-					{
-						_this.currentMode = 'SEARCH';
-						// console.log(_this.currentSearchGesture);
-						_this.player.widgets[0].searchByGesture(_this.currentSearchGesture[_this.centerId]);
-						_this.isCurrentlyInASearchByGesture = _this.player.widgets[0].isCurrentlyInASearchByGesture;
-						
-						if(_this.timeToGoAt[_this.centerId] === 0 && _this.player.widgets[0].atLeastOneSearchMarker(_this.currentSearchGesture[_this.centerId]))
-						{
-							_this.player.widgets[0].goToFirstSearchedMarker(_this.currentSearchGesture[_this.centerId]);
-						}
-						else
-						{
-							_this.player.popcorn.currentTime(_this.timeToGoAt[_this.centerId]);
-						}
-					}
-				// }
-				// /!\ //
-				/*else
-				{
-					if(_this.player.popcorn)
-					{
-						_this.player.popcorn.currentTime(_this.timeToGoAt[_this.centerId]);
-					}
-				}*/
-			});
-		}
-	});
-}
-
-/*
- * Permet de tester l'égalité des éléments de deux objets.
- * Pour ce faire on compare les éléments définissant ces objets.
- */
-$.fn.equals = function(compareTo)
-{
-    if (!compareTo || !compareTo.length || this.length!=compareTo.length)
+    var _this = this;
+    
+    //On configure les options de lancement.
+    IriSP.libFiles.defaultDir = "../lib/";
+    IriSP.widgetsDir = "./player/metadataplayer/"
+    
+    var videoToPlay = this.videos[this.centerId];
+    var currentMetadata = this.urls[this.centerId];
+    
+    var _metadata = {
+        url: currentMetadata,
+        format: 'ldt'
+    };
+    
+    var _config = {
+        gui: {
+            zoomTop: zoomTop - this.marginWidth*2,
+            zoomLeft: zoomLeft,
+            width: newSnWidth,
+            height: newSnHeight,
+            container: 'LdtPlayer',
+            default_options: {
+                metadata: _metadata
+            },
+            css:'./player/metadataplayer/LdtPlayer-core.css',
+            widgets: [
+                {
+                    type: "Timeline"
+                }
+            ]
+        },
+        player:{
+            type: 'html5', // player type
+            video: videoToPlay,
+            live: true,
+            height: newSnHeight,
+            width: newSnWidth,
+            autostart: true
+        }
+    };
+    
+    //On positionne le player.
+    $('.LdtPlayer').css(
     {
-        return false;
-    }
-    for (var i=0; i<this .length; i++)
+        position: 'absolute',
+        'background-color': '#000000',
+        top: newZoomTop,
+        left: newZoomLeft
+    });
+    
+    //On démarre le player.
+    this.player = null;
+    
+    this.player = new IriSP.Metadataplayer(_config, _metadata);
+    
+    this.player.onLoad(function()
     {
-        if (this[i]!==compareTo[i])
-        {
-            return false;
-        }
-    }
-    return true;
+        _this.onPlayerLoad();
+    });
 }
 
 /*
  * Charge les vidéos, les snapshots et les annotations depuis un fichier json.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadParameters.
 */
-mosaic.prototype.loadFromJson = function(path)
+Mosaic.prototype.loadFromJson = function(path)
 {
-	var _this = this;
-	var i = 0;
-
-	$.getJSON(path, function(data)
-	{
-		$.each(data, function(key, val)
-		{
-			$.each(val, function(key_video, val_video)
-			{
-				$.getJSON(val_video.metadata, function(meta)
-				{
-					if(_this.config['local'] == 'true')
-					{
-						_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://media.iri.centrepompidou.fr/ddc_player/', './player/videos/').replace('mp4:', '').replace('video/', '').replace('ldtplatform/', '').replace('.m4v', '.mp4'));
-						// console.log(meta.medias[0].url.replace('rtmp://media.iri.centrepompidou.fr/ddc_player/', './player/videos/').replace('mp4:', '').replace('video/', '').replace('ldtplatform/', '').replace('.m4v', '.mp4'));
-					}
-					else
-					{
-						_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
-						// console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
-					}
-				});
-				_this.imgs[_this.ids[i]] = val_video.snapshot;
-				_this.urls[_this.ids[i]] = val_video.metadata;
-				//Au départ, on commence à 0 ms dans les vidéos.
-				_this.timeToGoAt[_this.ids[i]] = 0;
-				// console.log('ids : ' + _this.ids[i]);
-				i++;
-			});
-		});
-		// console.log('rdy');
-		_this.loadMosaic();
-	});
+    var _this = this;
+    var i = 0;
+    
+    //On ouvre le fichier contenant les vidéos et les adresses des métadonnées.
+    $.getJSON(path, function(data)
+    {
+        $.each(data, function(key, val)
+        {
+            $.each(val, function(key_video, val_video)
+            {
+                //On extrait les métadonnées.
+                $.getJSON(val_video.metadata, function(meta)
+                {
+                    //Si on est en chargement local.
+                    if(_this.config.local)
+                    {
+                        //On cherche les vidéos dans les métadonnées.
+                        _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'));
+                    }
+                    //Si on est en chargement en ligne.
+                    else
+                    {
+                        //On met l'adresse des videos en ligne.
+                        _this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4'));
+                    }
+                });
+                
+                //On affecte les images et métadonnées.
+                _this.imgs[_this.ids[i]] = val_video.snapshot;
+                _this.urls[_this.ids[i]] = val_video.metadata;
+                //Au départ, on commence à 0 ms dans les vidéos.
+                _this.timeToGoAt[_this.ids[i]] = 0;
+                i++;
+            });
+        });
+        
+        //On charge la mosaique.
+        _this.loadMosaic();
+    });
 }
 
 /*
- * Affecte une vidéo au tableau des vidéos selon son id
+ * Affecte une vidéo au tableau des vidéos selon son id.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadFromJson.
 */
-mosaic.prototype.affectVideoById = function(metadata_id, video)
+Mosaic.prototype.affectVideoById = function(metadata_id, video)
 {
-	for (i = 0 ; i < this.urls.length ; i++)
-	{
-		if(this.urls[i] == metadata_id)
-		{
-			this.videos[i] = video;
-			break;
-		}
-	}
+    for (i = 0 ; i < this.urls.length ; i++)
+    {
+        if(this.urls[i] == metadata_id)
+        {
+            this.videos[i] = video;
+            break;
+        }
+    }
 }
 
 /*
- * Rebind keypress pour body.
+ * Affiche la date actuelle pour l'affichage de messages dans la console.
+ * Est appelé dans chaque console.log() où on veut afficher la date à laquelle l'instruction est exécutée.
 */
-mosaic.prototype.reaffectKeyPress = function()
-{
-	var _this = this;
-	
-	$('body').keypress(function (event)
-	{
-		_this.manageControlEvents(event);
-	});
-}
-
-mosaic.prototype.date = function()
+Mosaic.prototype.date = function()
 {
    var date, h, min, s;
    date = new Date();
--- a/front_idill/src/mosaic/js/neighbours.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/mosaic/js/neighbours.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,334 +1,362 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : neighbours.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les fonctions d'intéraction avec les voisins lors d'un zoom.
+ */
+
 /*
  * Affecte les listeners mouseenter aux voisins lors d'une vue en plein écran.
+ * Est appelé : dans les fichiers neighbours > fonction moveToNeighbour et zoomInteractions > fonction zoom.
  */
-mosaic.prototype.listenToNeighbours = function()
+Mosaic.prototype.listenToNeighbours = function()
 {
-    ////TEST
-    //$('.test').empty();
-	console.log('LISTEN TO NEIGHBOURS');
-	
-	if(this.currentMode != 'SEARCH')
-	{
-		this.removeNotifications();
-	}
-	
-	if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") != -1)
-	{
-		return;
-	}
-	
-	// console.log('MODE : ' + this.currentMode);
-	
-	if(this.neighboursIds == null || this.neighboursIds != null && this.neighboursIds.length > 0)
-	{
-		return;
-	}
-	
+    //Si on n'est pas en mode recherche, on enlève les notifications.
+    if(this.currentMode != 'SEARCH')
+    {
+        this.removeNotifications();
+    }
+    
+    //Si on est en mode sans utilisateur ou en mode utilisateur approche, on part.
+    if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") != -1)
+    {
+        return;
+    }
+    
+    //Si ils n'y a pas de voisins répertoriés, on part.
+    if(this.neighboursIds == null || this.neighboursIds != null && this.neighboursIds.length > 0)
+    {
+        return;
+    }
+    
     var _this = this;
     
-	this.canMoveToNeighbour = false;
-    var currentLine = Math.floor(this.centerId / this.config['length']), currentColumn = this.centerId % this.config['length'];
+    //On ne peut actuellement pas se déplacer vers un voisin.
+    this.canMoveToNeighbour = false;
+    //On calcule la ligne et colonne du snapshot du milieu.
+    var currentLine = Math.floor(this.centerId / this.config.length), currentColumn = this.centerId % this.config.length;
     var zoomedImg = $('img', this.previousZoomedSN);
-	
+    
     //On cherche l'ID des voisins.
     //Si le voisin de gauche est sur la même ligne, on n'est pas sur la bordure de gauche.
     this.neighboursIds[0] = (currentColumn > 0) ? (this.centerId - 1) : -1;
     //Si le voisin de droite est sur la même ligne, on n'est pas sur la bordure de droite.
-    this.neighboursIds[1] = (currentColumn < this.config['length'] - 1) ? (+this.centerId + 1) : -1;
+    this.neighboursIds[1] = (currentColumn < this.config.length - 1) ? (+this.centerId + 1) : -1;
     //Si le voisin du haut est sur la même colonne, on n'est pas sur la bordure du haut.
-    this.neighboursIds[2] = (currentLine > 0) ? (this.centerId - this.config['length']) : -1;
+    this.neighboursIds[2] = (currentLine > 0) ? (this.centerId - this.config.length) : -1;
     //Si le voisin du bas est sur la même colonne, on n'est pas sur la bordure du bas.
-    this.neighboursIds[3] = (currentLine < (this.config['imagesToShow'] / this.config['length'])) ? (+this.centerId + this.config['length']) : -1;
+    this.neighboursIds[3] = (currentLine < (this.config.imagesToShow / this.config.length)) ? (+this.centerId + this.config.length) : -1;
     
-	//ID du cadre voisin.
-	var preId;
-	
+    //ID du cadre voisin.
+    var preId;
+    
+    //Si les voisins ont un id supérieur au maximum, on les met à -1.
     for(var i = 0 ; i < this.neighboursIds.length ; i++)
     {
-		// console.log('pre : ' + this.neighboursIds[i]);
-		if(this.neighboursIds[i] >= this.config['imagesToShow'])
-		{
-			this.neighboursIds[i] = -1;
-		}
+        if(this.neighboursIds[i] >= this.config.imagesToShow)
+        {
+            this.neighboursIds[i] = -1;
+        }
     }
-	
-	// console.log('neighbours : ', this.neighboursIds);
-	
-	//Si on est sur une bordure.
-	//On crée des voisins supplémentaires.
-	if(_.include(this.neighboursIds, -1))
-	{
-		this.createAdditionalNeighbours();
-	}
+    
+    //Si on est sur une bordure.
+    //On crée des voisins supplémentaires.
+    if(_.include(this.neighboursIds, -1))
+    {
+        this.createAdditionalNeighbours();
+    }
 }
 
 /*
  * Crée des voisins supplémentaires pour garantir le déplacement / dézoom quand on arrive sur le bord de la mosaïque.
+ * Est appelé : dans le fichier neighbours > fonction listenToNeighbours.
 */
-mosaic.prototype.createAdditionalNeighbours = function()
+Mosaic.prototype.createAdditionalNeighbours = function()
 {
-	if(this.currentMode == "NO-USER")
-	{
-		return;
-	}
-	
-	// console.log('Create additional neighbours');
-	
-	var additionalNeighbours = '';
-	for(var i = 0 ; i < this.neighboursIds.length ; i++)
-	{
-		var sn = $('#snapshotDiv-' + this.centerId);
-		var m = parseInt(sn.css('margin'));
-		var centerTop = sn.position().top + this.notifyTopVideo + this.MPTop_margin, centerLeft = sn.position().left + this.notifyLeftVideo;
-		var centerWidth = sn.width(), centerHeight = sn.height();
-		
-		// console.log('top : ' + sn.position().top + ', left : ' + this.notifyTopVideo + ' ' + this.notifyLeftVideo + ' ' + this.centerId);
-		// console.log(this.neighboursIds[i]);
-		
-		var top, left;
-				
-		if(this.neighboursIds[i] == -1)
-		{
-			if(i == 0)
-			{
-				top = centerTop + m / 2;
-				left = centerLeft - centerWidth - 2 * m;
-			}
-			else if(i == 1)
-			{
-				top = centerTop + m / 2;
-				left = centerLeft + centerWidth + 3 * m;
-			}
-			else if(i == 2)
-			{
-				top = centerTop - centerHeight - 2 * m;
-				left = centerLeft + m / 2;
-			}
-			else if(i == 3)
-			{
-				top = centerTop + centerHeight + 3 * m;
-				left = centerLeft + m / 2;
-			}
-			
-			additionalNeighbours += '<div id="borderNeighbour-' + i + '" class="borderNeighbours" style="opacity: 0; width: ' + centerWidth + 'px; height: ' + centerHeight + 'px; top: ' + top + 'px; left: ' + left + 'px;"></div>';
-		}
-	}
-	// console.log(additionalNeighbours);
-	$('body').append(additionalNeighbours);
-	
-	$('.borderNeighbours').fadeTo(this.config['timeANFade'], '1');
+    //Si on est en mode sans utilisateur, on part.
+    if(this.currentMode == "NO-USER")
+    {
+        return;
+    }
+    
+    //Pour tous les voisins.
+    var additionalNeighbours = '';
+    for(var i = 0 ; i < this.neighboursIds.length ; i++)
+    {
+        //Snapshot du milieu.
+        var sn = $('#snapshotDiv-' + this.centerId);
+        //Marge de celui-ci.
+        var m = parseInt(sn.css('margin'));
+        //Ses coordonnées.
+        var centerTop = sn.position().top + this.notifyTopVideo + this.MPTop_margin, centerLeft = sn.position().left + this.notifyLeftVideo;
+        //Ses dimensions.
+        var centerWidth = sn.width(), centerHeight = sn.height();
+        
+        var top, left;
+        
+        //Si on est sur une bordure, on calcule les coordonnées du voisin à l'extérieur de la bordure en fonction de sa position dans le tableau des voisins.
+        if(this.neighboursIds[i] == -1)
+        {
+            if(i == 0)
+            {
+                top = centerTop + m / 2;
+                left = centerLeft - centerWidth - 2 * m;
+            }
+            else if(i == 1)
+            {
+                top = centerTop + m / 2;
+                left = centerLeft + centerWidth + 3 * m;
+            }
+            else if(i == 2)
+            {
+                top = centerTop - centerHeight - 2 * m;
+                left = centerLeft + m / 2;
+            }
+            else if(i == 3)
+            {
+                top = centerTop + centerHeight + 3 * m;
+                left = centerLeft + m / 2;
+            }
+            
+            //On place le voisin additionnel.
+            additionalNeighbours += '<div id="borderNeighbour-' + i + '" class="borderNeighbours" style="opacity: 0; width: ' + centerWidth + 'px; height: ' + centerHeight + 'px; top: ' + top + 'px; left: ' + left + 'px;"></div>';
+        }
+    }
+    
+    $('body').append(additionalNeighbours);
+    //On le fait apparaître.
+    $('.borderNeighbours').fadeTo(this.config.timeANFade, '1');
 }
 
 /*
  * Supprime les voisins supplémentaires.
+ * Est appelé : dans les fichiers neighbours > fonction moveToNeighbour et zoomInteractions > fonction unzoom.
 */
-mosaic.prototype.removeAdditionalNeighbours = function()
+Mosaic.prototype.removeAdditionalNeighbours = function()
 {
-	$('.borderNeighbours').fadeTo(this.config['timeANFade'], '0', function()
-	{
-		$('.borderNeighbours').remove();
-	});
-	this.deselectAllNeighbours();
+    $('.borderNeighbours').fadeTo(this.config.timeANFade, '0', function()
+    {
+        $('.borderNeighbours').remove();
+    });
+    this.deselectAllNeighbours();
 }
 
 /*
  * Déselectionne tous les voisins, même les additionnels.
+ * Est appelé : dans les fichier neighbours > fonction removeAdditionalNeighbours.
 */
-mosaic.prototype.deselectAllNeighbours = function()
+Mosaic.prototype.deselectAllNeighbours = function()
 {
-	$('.neighbourFrame').fadeTo(this.config['timeANFade'], '0', function()
-	{
-		$('.neighbourFrame').remove();
-	});
+    $('.neighbourFrame').fadeTo(this.config.timeANFade, '0', function()
+    {
+        $('.neighbourFrame').remove();
+    });
 }
 
 /*
  * Change la coloration d'une bordure où on se positionne lors d'une vue en plein écran.
+ * Est appelé : dans le fichier pointers > fonction pointersVideoInteractions.
  */
-mosaic.prototype.selectNeighbour = function(neighbour, pointer)
+Mosaic.prototype.selectNeighbour = function(neighbour, pointer)
 {
-    ////TEST
-    //$('.test').append(mos.currentMode + " " + $(this).attr('id') + " " + 'snapshotDiv-' + mos.centerId + ',');
-	
-	// console.log(this.currentlyMoving, this.currentlyUnzooming, this.helpDisplayed);
-	
-	if(this.currentlyMoving || this.currentlyUnzooming || this.helpDisplayed)
-	{
-		return;
-	}
-	
-	if(this.gestureDelRequested)
-	{
-		var tab = neighbour.attr('id').split('-');
-		var snapshotId = tab[1];
-		this.deselectNeighbour(snapshotId);
-		return;
-	}
-
-	// console.log('test (2)');
-	
-	this.canSwipe = false;
-	
-	var _this = this;
-	
-	// console.log('SEL NEI', this.neighbourIds);
-	
+    //Si on est en train de se déplacer vers un voisin ou dézoomer ou si l'aide est affichée, on part.
+    if(this.currentlyMoving || this.currentlyUnzooming || this.helpDisplayed)
+    {
+        return;
+    }
+    
+    //Si on est sur une notification de gesture de recherche.
+    if(this.gestureDelRequested)
+    {
+        //On récupère l'id du voisin.
+        var tab = neighbour.attr('id').split('-');
+        var snapshotId = tab[1];
+        //On le déselectionne.
+        this.deselectNeighbour(snapshotId);
+        //On part.
+        return;
+    }
+    
+    //On ne peut pas faire de swipes.
+    this.canSwipe = false;
+    
+    var _this = this;
+    
     //Si on est en mode VIDEO (plein écran) ET si le snapshot pointé est un voisin.
-
-	// console.log('test (3)');
-    
-    if((this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH') && (neighbour.attr('id') != 'snapshotDiv-' + this.centerId))
+	if((this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH') && (neighbour.attr('id') != 'snapshotDiv-' + this.centerId))
     {
         //On crée le cadre qui va être superposé au voisin.
         //On le colle au voisin.
-		var tab = neighbour.attr('id').split('-');
-		var snapshotId = tab[1];
+        var tab = neighbour.attr('id').split('-');
+        var snapshotId = tab[1];
         var neighbourFrame = '';
-		var marginValue = parseFloat(neighbour.css('margin'));
-		
-		//Si la frame existe déjà, on quitte.
-		if($('#neighbourFrame-' + snapshotId).length > 0)
-		{
-			return;
-		}
-		
-		//Si c'est un voisin additionnel.
-		if(neighbour.attr('id').indexOf('borderNeighbour') != -1)
-		{
-			snapshotId = +snapshotId + this.config['imagesToShow'];
-			neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"></div>';
-			if($('#neighbourFrame-' + snapshotId).length > 0)
-			{
-				return;
-			}
-			$('body').append(neighbourFrame);
-		}
-		else
-		{
-			neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"><div class="neighbourImgBg" id="neighbourImgBg-' + snapshotId + '"><div class="neighbourImg" id="neighbourImg-' + snapshotId + '"></div></div></div>';
-			if($('#neighbourFrame-' + snapshotId).length > 0)
-			{
-				return;
-			}
-			$('#mainPanel').append(neighbourFrame);
-		}
-		
-		//On positionne le div de background juste au niveau du voisin.
+        var marginValue = parseFloat(neighbour.css('margin'));
+        
+        //Si la frame existe déjà, on quitte.
+        if($('#neighbourFrame-' + snapshotId).length > 0)
+        {
+            return;
+        }
+        
+        //Si c'est un voisin additionnel.
+        if(neighbour.attr('id').indexOf('borderNeighbour') != -1)
+        {
+            //On le sélectionne quand même.
+            snapshotId = +snapshotId + this.config.imagesToShow;
+            neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"></div>';
+            if($('#neighbourFrame-' + snapshotId).length > 0)
+            {
+                return;
+            }
+            $('body').append(neighbourFrame);
+        }
+        //Si c'est un voisin normal.
+        else
+        {
+            //On le sélectionne.
+            neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"><div class="neighbourImgBg" id="neighbourImgBg-' + snapshotId + '"><div class="neighbourImg" id="neighbourImg-' + snapshotId + '"></div></div></div>';
+            if($('#neighbourFrame-' + snapshotId).length > 0)
+            {
+                return;
+            }
+            $('#mainPanel').append(neighbourFrame);
+        }
+        
+        //On positionne le div de background juste au niveau du voisin.
         $('#neighbourFrame-' + snapshotId).css(
-		{
-			'top': (+neighbour.position().top + marginValue),
-			'left': (+neighbour.position().left + marginValue),
-			'width': neighbour.width(),
-			'height': neighbour.height()
-		});
-		//On positionne le div de background noir juste au niveau de l'image du voisin.
+        {
+            'top': (+neighbour.position().top + marginValue),
+            'left': (+neighbour.position().left + marginValue),
+            'width': neighbour.width(),
+            'height': neighbour.height()
+        });
+        //On positionne le div de background noir juste au niveau de l'image du voisin.
         $('#neighbourImgBg-' + snapshotId).css(
-		{
-			'top': marginValue,
-			'left': marginValue,
-			'width': neighbour.width() - marginValue*2,
-			'height': neighbour.height() - marginValue*2,
-		});
-		//On met par dessus le div de l'image clonée du voisin.
-		$('#neighbourImg-' + snapshotId).css(
-		{
-			'top': 0,
-			'left': 0,
-			'width': neighbour.width() - marginValue*2,
-			'height': neighbour.height() - marginValue*2,
-			'background-image': 'url("' + $('img', neighbour).attr('src') + '")',
-			'background-size': neighbour.width() + 'px ' + neighbour.height() + 'px',
-			'background-position': -marginValue + 'px ' + -marginValue + 'px',
-			'opacity': '0.4'
-		});
-		
-		var fId = '#neighbourFrame-' + snapshotId;
-		
-		$(fId).animate(
+        {
+            'top': marginValue,
+            'left': marginValue,
+            'width': neighbour.width() - marginValue*2,
+            'height': neighbour.height() - marginValue*2,
+        });
+        //On met par dessus le div de l'image clonée du voisin.
+        $('#neighbourImg-' + snapshotId).css(
+        {
+            'top': 0,
+            'left': 0,
+            'width': neighbour.width() - marginValue*2,
+            'height': neighbour.height() - marginValue*2,
+            'background-image': 'url("' + $('img', neighbour).attr('src') + '")',
+            'background-size': neighbour.width() + 'px ' + neighbour.height() + 'px',
+            'background-position': -marginValue + 'px ' + -marginValue + 'px',
+            'opacity': '0.4'
+        });
+        
+        var fId = '#neighbourFrame-' + snapshotId;
+        
+        $(fId).animate(
         {
             //On le fait apparaître.
             opacity: '1'
-        }, _this.config['timeNeighbourGlowing'], function()
-		{
-			if(_this.mouseInteractions)
-			{
-				if(_this.currentMode == 'VIDEO')
-				{
-					_this.removeNotifications();
-					_this.videoMove(snapshotId);
-				}
-				else if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture[_this.centerId])
-				{
-					_this.removeNotifications();
-					_this.searchSearchAndMove(snapshotId);
-				}
-				else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId])
-				{
-					_this.removeNotifications();
-					_this.searchGestureAndMove(_this.currentSearchGesture[_this.centerId], 'valid', snapshotId);
-				}
-				
-				_this.canMoveToNeighbour = true;
-			}
-			else
-			{
-				if(_this.currentMode == 'VIDEO')
-				{
-					_this.removeNotifications();
-					_this.videoMoveAndUnzoom(snapshotId);
-				}
-				else if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture[_this.centerId])
-				{
-					_this.removeNotifications();
-					_this.searchSearchAndMoveAndUnzoom(snapshotId);
-				}
-				else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId])
-				{
-					_this.removeNotifications();
-					_this.searchGestureAndMoveAndUnzoom(_this.currentSearchGesture[_this.centerId], 'valid', snapshotId);
-				}
-			}
-		});
-		
-		var side = $.inArray(parseInt(snapshotId), this.neighboursIds);
-		
-		if(side == -1)
-		{
-			return;
-		}
-		
-		var sides = ['left', 'right', 'down', 'up'];
-		pointer.css('background-image', 'url(./img/cursors/' + sides[side] + '_gray.png)');
+        }, _this.config.timeNeighbourGlowing, function()
+        {
+            //Si on est en mode d'intéraction souris.
+            if(_this.config.mouseInteractions)
+            {
+                //Si on est en mode video.
+                if(_this.currentMode == 'VIDEO')
+                {
+                    //On notifie.
+                    _this.removeNotifications();
+                    _this.videoMove(snapshotId);
+                }
+                //Si on est en mode de recherche mais sans gesture encore.
+                else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] == '')
+                {
+                    //On notifie.
+                    _this.removeNotifications();
+                    _this.searchSearchAndMove(snapshotId);
+                }
+                //Si on est en mode de recherche avec une gesture.
+                else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] != '')
+                {
+                    //On notifie.
+                    _this.removeNotifications();
+                    _this.searchGestureAndMove(_this.currentSearchGesture[_this.centerId], 'valid', snapshotId);
+                }
+                
+                //On peut bouger vers un voisin.
+                _this.canMoveToNeighbour = true;
+            }
+            //Si on est en mode d'intéractions Kinect.
+            else
+            {
+                //Si on est en mode video, on notifie mais avec un dézoom possible.
+                if(_this.currentMode == 'VIDEO')
+                {
+                    _this.removeNotifications();
+                    _this.videoMoveAndUnzoom(snapshotId);
+                }
+                //Si on est en mode de recherche mais sans gesture encore, on notifie mais avec un dézoom possible.
+                else if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture[_this.centerId])
+                {
+                    _this.removeNotifications();
+                    _this.searchSearchAndMoveAndUnzoom(snapshotId);
+                }
+                //Si on est en mode de recherche avec une gesture, on notifie mais avec un dézoom possible.
+                else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId])
+                {
+                    _this.removeNotifications();
+                    _this.searchGestureAndMoveAndUnzoom(_this.currentSearchGesture[_this.centerId], 'valid', snapshotId);
+                }
+            }
+        });
+        
+        //On repère de quel côté le voisin se trouve en fonction du centre.
+        var side = $.inArray(parseInt(snapshotId), this.neighboursIds);
+        
+        //S'il n'est nulle part on part.
+        if(side == -1)
+        {
+            return;
+        }
+        
+        //On affecte l'image de la notification en fonction du côté.
+        var sides = ['left', 'right', 'down', 'up'];
+        pointer.css('background-image', 'url(./img/cursors/' + sides[side] + '_gray.png)');
     }
 }
 
-
-
 /*
  * Change la coloration d'une bordure quittée lors d'une vue en plein écran.
+ * Est appelé : dans les fichiers neighbours > fonction selectNeighbour et pointers > fonction pointersVideoInteractions.
  */
-mosaic.prototype.deselectNeighbour = function(neighbourId)
+Mosaic.prototype.deselectNeighbour = function(neighbourId)
 {
-    ////TEST
-    //$('.test').append('un,');
-	
-	//this.removeNotifyMoveUnzoom();
-	
-	if($('#neighbourFrame-' + neighbourId).length <= 0)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	// console.log('DES');
-	
+    if($('#neighbourFrame-' + neighbourId).length <= 0)
+    {
+        return;
+    }
+    
+    var _this = this;
+    
     //On ne peut plus se déplacer vers les voisins.
     this.canMoveToNeighbour = true;
     
-	//On récupère le voisin.
-	var neighbourFrame = $('#neighbourFrame-' + neighbourId);
-	
+    //On récupère le voisin.
+    var neighbourFrame = $('#neighbourFrame-' + neighbourId);
+    
     //Si on est en mode VIDEO.
     if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH')
     {
@@ -336,22 +364,22 @@
         neighbourFrame.animate(
         {
             opacity: '0'
-        }, this.config['timeNeighbourUnglowing'], function()
+        }, this.config.timeNeighbourUnglowing, function()
         {
             //Une fois invisible, on le supprime.
             neighbourFrame.remove();
-			_this.removeNotifications();
-			
-			if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] == '')
-			{
-				_this.searchSearch();
-			}
-			else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] != '')
-			{
-				_this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid');
-			}
-			
-			_this.canSwipe = true;
+            _this.removeNotifications();
+            
+            if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] == '')
+            {
+                _this.searchSearch();
+            }
+            else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] != '')
+            {
+                _this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid');
+            }
+            
+            _this.canSwipe = true;
         });
     }
 }
@@ -360,101 +388,95 @@
  * Permet de savoir si un déplacement est possible en fonction de l'id de snapshot entré.
  * x et y sont les positions du pointeur.
  * Déplace vers le voisin si possible.
+ * Est appelé : dans le fichier pointers > fonction pointersVideoInteractions.
 */
-mosaic.prototype.correctMoveToNeighbour = function(id, x, y)
+Mosaic.prototype.correctMoveToNeighbour = function(id, x, y)
 {
-	var _this = this;
-	
-	if(this.neighboursIds != null && this.neighboursIds.length > 0 && this.canMoveToNeighbour)
-	{
-		var idx = $.inArray(id, this.neighboursIds);
-		//Si l'id du snapshot qu'on vient de quitter fait partie des voisins.
-		if(idx > -1)
-		{
-			//Correspondance indices : position par rapport au snapshot du milieu.
-			//0 : gauche.
-			//1 : droite.
-			//2 : haut.
-			//3 : bas.
-			
-			//On cherche le symétrique de l'id du voisin quitté.
-			//Astuce : S'il est pair, cela signifie qu'on doit faire +1, sinon c'est -1.
-			//var sym = (idx % 2 == 0) ? (+idx + 1) : (idx - 1);
-			
-			//S'il est > -1 alors forcément il existe.
-			//Si on peut se déplacer vers un voisin, on le fait.
-			if(this.neighboursIds[idx] > -1)
-			{
-				var centerWidth = -this.notifyLeftVideo + $(window).width() / 2, centerHeight = -this.notifyTopVideo + $(window).height() / 2;
-				
-				// console.log('x : ' + x + ' cw : ' + centerWidth + ', y : ' + y + ' ch : ' + centerHeight);
-				
-				//Si l'id du tableau est pair, alors forcément le pointeur doit être plus à droite/plus en bas que le milieu de l'écran pour se déplacer vers le voisin.
-				//Sinon c'est l'inverse.
-				//(sym et idx on été échangés).
-				if(idx == 0 && x > centerWidth || idx == 2 && y > centerHeight || idx == 1 && x < centerWidth || idx == 3 && y < centerHeight)
-				{
-					// console.log('d to (' + idx + ' - ' + this.neighboursIds[idx] + '): ' + this.imgs[this.neighboursIds[idx]]);
-					
-					this.moveToNeighbour($('#snapshotDiv-' + this.neighboursIds[idx]));
-				}
-			}
-		}
-		else if(id >= this.config['imagesToShow'])
-		{
-			//On otbient le vrai ID du voisin additionnel.
-			var additionalNeighbourId = id - this.config['imagesToShow'];
-			var sym = (additionalNeighbourId % 2 == 0) ? (+additionalNeighbourId + 1) : (additionalNeighbourId - 1);
-		}
-	}
+    var _this = this;
+    
+    if(this.neighboursIds != null && this.neighboursIds.length > 0 && this.canMoveToNeighbour)
+    {
+        var idx = $.inArray(id, this.neighboursIds);
+        //Si l'id du snapshot qu'on vient de quitter fait partie des voisins.
+        if(idx > -1)
+        {
+            //Correspondance indices : position par rapport au snapshot du milieu.
+            //0 : gauche.
+            //1 : droite.
+            //2 : haut.
+            //3 : bas.
+            
+            //On cherche le symétrique de l'id du voisin quitté.
+            //Astuce : S'il est pair, cela signifie qu'on doit faire +1, sinon c'est -1.
+            //var sym = (idx % 2 == 0) ? (+idx + 1) : (idx - 1);
+            
+            //S'il est > -1 alors forcément il existe.
+            //Si on peut se déplacer vers un voisin, on le fait.
+            if(this.neighboursIds[idx] > -1)
+            {
+                var centerWidth = -this.notifyLeftVideo + $(window).width() / 2, centerHeight = -this.notifyTopVideo + $(window).height() / 2;
+                
+                //Si l'id du tableau est pair, alors forcément le pointeur doit être plus à droite/plus en bas que le milieu de l'écran pour se déplacer vers le voisin.
+                //Sinon c'est l'inverse.
+                //(sym et idx on été échangés).
+                if(idx == 0 && x > centerWidth || idx == 2 && y > centerHeight || idx == 1 && x < centerWidth || idx == 3 && y < centerHeight)
+                {
+                    this.moveToNeighbour($('#snapshotDiv-' + this.neighboursIds[idx]));
+                }
+            }
+        }
+        else if(id >= this.config.imagesToShow)
+        {
+            //On otbient le vrai ID du voisin additionnel.
+            var additionalNeighbourId = id - this.config.imagesToShow;
+            var sym = (additionalNeighbourId % 2 == 0) ? (+additionalNeighbourId + 1) : (additionalNeighbourId - 1);
+        }
+    }
 }
 
 /*
  * 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.
+ * Est appelé : dans les fichiers neighbours > fonction correctMoveToNeighbour, playerControl > fonction playNextVideo et zoomInteractions > zoom.
  */
-mosaic.prototype.moveToNeighbour = function(neighbour)
+Mosaic.prototype.moveToNeighbour = function(neighbour)
 {
-	var _this = this;
-	
-	console.log('automove : ' + this.autoMove);
-	
+    var _this = this;
+    
     //Si on ne peut pas se déplacer vers les voisins, on quitte.
     if((!this.canMoveToNeighbour || neighbour.length <= 0 || this.currentlyMoving) && !this.autoMove)
-	{
+    {
         return;
-	}
-	
-	console.log('MOVE');
-	this.canMoveToNeighbour = false;
-	this.currentlyMoving = true;
-	this.removeAdditionalNeighbours();
+    }
+    
+    this.canMoveToNeighbour = false;
+    this.currentlyMoving = true;
+    this.removeAdditionalNeighbours();
     
     //On obtient l'ID de destination.
     var tab = neighbour.attr('id').split('-');
     var destinationId = tab[1];
-	
-	var startId = this.previousZoomedSN.attr('id').replace('snapshotDiv-', '');
+    
+    var startId = this.previousZoomedSN.attr('id').replace('snapshotDiv-', '');
     
     //On charge les attributs nécessaires aux calculs.
-	var length = _this.config['length'];
+    var length = _this.config.length;
     var MPCurrentTop = $('#mainPanel').position().top, MPCurrentLeft = $('#mainPanel').position().left;
     var divideCoeffTop = Math.floor(destinationId / length) == 0 ? 1 : Math.floor(destinationId / length);
     var divideCoeffLeft = destinationId % length == 0 ? 1 : destinationId % length;
     var neighbourFrameTop = $('#snapshotDiv-' + destinationId).position().top, neighbourFrameLeft = $('#snapshotDiv-' + destinationId).position().left;
     
-	_this.previousZoomedSN = $('#snapshotDiv-' + this.centerId);
-	// var centerSN = $('#snapshotDiv-' + this.centerId);
-	
-	//On définit pour le déplacement vertical s'il est nécessaire de se déplacer en haut ou en bas.
-	if(_this.previousZoomedSN.position().top > neighbourFrameTop)
-		MPCurrentTop += Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
-	else if(_this.previousZoomedSN.position().top < neighbourFrameTop)
-		MPCurrentTop -= Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
-	//On définit pour le déplacement horizontal s'il est nécessaire de se déplacer à gauche ou à droite.
-	if(_this.previousZoomedSN.position().left > neighbourFrameLeft)
-		MPCurrentLeft += Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
-	else if(_this.previousZoomedSN.position().left < neighbourFrameLeft)
-		MPCurrentLeft -= Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
+    _this.previousZoomedSN = $('#snapshotDiv-' + this.centerId);
+    
+    //On définit pour le déplacement vertical s'il est nécessaire de se déplacer en haut ou en bas.
+    if(_this.previousZoomedSN.position().top > neighbourFrameTop)
+        MPCurrentTop += Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
+    else if(_this.previousZoomedSN.position().top < neighbourFrameTop)
+        MPCurrentTop -= Math.abs(neighbourFrameTop - _this.previousZoomedSN.position().top);
+    //On définit pour le déplacement horizontal s'il est nécessaire de se déplacer à gauche ou à droite.
+    if(_this.previousZoomedSN.position().left > neighbourFrameLeft)
+        MPCurrentLeft += Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
+    else if(_this.previousZoomedSN.position().left < neighbourFrameLeft)
+        MPCurrentLeft -= Math.abs(neighbourFrameLeft - _this.previousZoomedSN.position().left);
     
     //On passe le snapshot de destination en HD.
     var destinationImg = $('#snapshot-' + destinationId);
@@ -467,67 +489,72 @@
 
     $('#snapshotDiv-' + destinationId).css('opacity', '1');
     
-	if(_this.playerIsReady)
-	{
-		if(_this.currentMode == 'TIMELINE')
-		{
-			_this.exitTimeline('move');
-		}
-		
-		// console.log(Math.floor(_this.player.popcorn.currentTime()));
-		if(_this.autoMove)
-		{
-			_this.timeToGoAt[_this.centerId] = 0;
-			this.autoMove = false;
-		}
-		else
-		{
-			_this.timeToGoAt[_this.centerId] = Math.floor(_this.player.popcorn.currentTime());
-		}
-		_this.player.widgets[0].freePlayer();
-		_this.playerIsReady = false;
-		$('.LdtPlayer').remove();
-		$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
-	}
-	
-	//On obtient l'ID du div de coloration du snapshot vers lequel on se déplace afin de le supprimer.
+    //Si le player est prêt.
+    if(_this.playerIsReady)
+    {
+        //Si on est en mode timeline on la quitte.
+        if(_this.currentMode == 'TIMELINE')
+        {
+            _this.exitTimeline('move');
+        }
+        
+        //Si le move est automatique (fin de vidéo).
+        if(_this.autoMove)
+        {
+            //On remet à jour la position du curseur de la vidéo.
+            _this.timeToGoAt[_this.centerId] = 0;
+            _this.autoMove = false;
+        }
+        //Sinon on revient là où on était la dernière fois que la video a été jouée.
+        else
+        {
+            _this.timeToGoAt[_this.centerId] = Math.floor(_this.player.popcorn.currentTime());
+        }
+        //On libère le player.
+        _this.player.widgets[0].freePlayer();
+        _this.playerIsReady = false;
+        $('.LdtPlayer').remove();
+        $('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
+    }
+    
+    //On obtient l'ID du div de coloration du snapshot vers lequel on se déplace afin de le supprimer.
     _this.centerId = destinationId;
-	
+    
     //On grise le snapshot qu'on vient de quitter.
-    _this.previousZoomedSN.fadeTo(_this.config['zoomTime'], '0.4');
+    _this.previousZoomedSN.fadeTo(_this.config.zoomTime, '0.4');
     
-	//console.log(MPCurrentLeft);
-	
+    //console.log(MPCurrentLeft);
+    
     //On se déplace.
     $('#mainPanel').animate(
     {
         top: MPCurrentTop,
         left: MPCurrentLeft
-    }, _this.config['timeMovingToNeighbour'], function()
+    }, _this.config.timeMovingToNeighbour, function()
     {
-		if(_this.currentSearchGesture[_this.centerId] != '')
-		{
-			console.log('notify move');
-			_this.currentMode = 'SEARCH';
-			_this.isCurrentlyInASearchByGesture = true;
-			_this.removeNotifications();
-			_this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid');
-		}
-		
+        //On passe en mode recherche et on recherche dans la vidéo en fonction de la gesture de recherche enregistrée dans la nouvelle vidéo.
+        if(_this.currentSearchGesture[_this.centerId] != '')
+        {
+            _this.currentMode = 'SEARCH';
+            _this.isCurrentlyInASearchByGesture = true;
+            _this.removeNotifications();
+            _this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid');
+        }
+        
         //On fait apparaître le snapshot vers lequel on s'est déplacé.
-        $('#snapshotDiv-' + destinationId).fadeTo(_this.config['zoomTime'], '1', function()
+        $('#snapshotDiv-' + destinationId).fadeTo(_this.config.zoomTime, '1', function()
         {
             //On recharge les voisins.
             _this.previousZoomedSN = $('#snapshotDiv-' + _this.centerId);
             
-			_this.notifyTopVideo = MPCurrentTop;
-			_this.notifyLeftVideo = MPCurrentLeft;
-			_this.neighboursIds.length = 0;
-			_this.currentlyMoving = false;
-			_this.listenToNeighbours();
-			
-			
-			_this.loadPlayer((destinationImg.position().top + MPCurrentTop + _this.MPTop_margin), (destinationImg.position().left + MPCurrentLeft), destinationImg.width(), destinationImg.height(), MPCurrentTop, MPCurrentLeft, _this.timeToGoAt[_this.centerId]);
+            _this.notifyTopVideo = MPCurrentTop;
+            _this.notifyLeftVideo = MPCurrentLeft;
+            _this.neighboursIds.length = 0;
+            _this.currentlyMoving = false;
+            _this.listenToNeighbours();
+            
+            //On charge le player.
+            _this.loadPlayer((destinationImg.position().top + MPCurrentTop + _this.MPTop_margin), (destinationImg.position().left + MPCurrentLeft), destinationImg.width(), destinationImg.height(), MPCurrentTop, MPCurrentLeft, _this.timeToGoAt[_this.centerId]);
         });
     });
 }
@@ -535,182 +562,180 @@
 /*
  * Donne éventuellement un snapshot d'après les coordonnées du pointeur sur l'écran.
  * Renvoie null sinon.
+ * Est appelé : dans les fichiers pointers > fonction pointersMosaicInteractions et pointersVideoInteractions et zoomInteractions > zoom.
 */
-mosaic.prototype.pointerPositionToSN = function(x, y, isMainPointer)
+Mosaic.prototype.pointerPositionToSN = function(x, y, isMainPointer)
 {
-	if(this.helpDisplayed)
-	{
-		return;
-	}
-	
-	x += $('#mainPointer').width() / 2;
-	y += $('#mainPointer').height() / 2;
-	
-	// $('.snapshotDivs').css('opacity', '0.5');
-	//Taille de la marge des snapshots.
-	var m = parseInt($('.snapshotDivs').css('margin'));
-	
-	//Dimensions d'un snapshot de la mosaïque.
-	var W = $('.snapshotDivs').width() + m * 2, H = $('.snapshotDivs').height() + m * 2;
-	
-	//Position supposée du snapshot dans la mosaïque.
-	//Au départ on ne sélectionne rien.
-	var i = -1, j = -1;
-	
-	//Espace de centrage vertical de la mosaïque.
-	var top_margin = parseInt(this.MPTop_margin);
-	//Dimensions de la mosaïque en nombre de snapshots.
-	var mosW = this.config['length'], mosH = this.config['imagesToShow'] / mosW;
-	
-	//Si le pointeur se trouve au niveau de la mosaïque.
-	if(x < W * mosW && y >= top_margin && y < H * mosH + top_margin)
-	{
-		//Si le pointeur est sur une des bordures.
-		var xb = x % W;
-		var yb = y - top_margin;
-		yb %= H;
-		
-		if(xb < m || xb > W - m || yb < m || yb > H - m)
-		{
-			//On renvoie null.
-			return null;
-		}
-		//Sinon il est forcément sur un des snapshots.
-		else
-		{
-			i = Math.floor(x / W);
-			j = Math.floor((y - top_margin) / H);
-		}
-		
-		//On passe des coordonnées 2D en 1D.
-		var snapshot = $('#snapshotDiv-' + (j * mosW + i));
-		
-		//Si le snapshot a été filtré, on renvoie null si on se trouve dans la mosaïque.
-		if(this.isMosaicFiltered && (this.currentMode == "MOSAIC" || this.currentMode == "FILTER") && snapshot.css('opacity') == 0)
-		{
-			return null;
-		}
-		
-		//On renvoie le snapshot.
-		return snapshot;
-	}
-	
-	//Si on est arrivé là, c'est que le pointeur n'est pas dans la mosaïque.
-	return null;
+    if(this.helpDisplayed)
+    {
+        return;
+    }
+    
+    x += $('#mainPointer').width() / 2;
+    y += $('#mainPointer').height() / 2;
+    
+    //Taille de la marge des snapshots.
+    var m = parseInt($('.snapshotDivs').css('margin'));
+    
+    //Dimensions d'un snapshot de la mosaïque.
+    var W = $('.snapshotDivs').width() + m * 2, H = $('.snapshotDivs').height() + m * 2;
+    
+    //Position supposée du snapshot dans la mosaïque.
+    //Au départ on ne sélectionne rien.
+    var i = -1, j = -1;
+    
+    //Espace de centrage vertical de la mosaïque.
+    var top_margin = parseInt(this.MPTop_margin);
+    //Dimensions de la mosaïque en nombre de snapshots.
+    var mosW = this.config.length, mosH = this.config.imagesToShow / mosW;
+    
+    //Si le pointeur se trouve au niveau de la mosaïque.
+    if(x < W * mosW && y >= top_margin && y < H * mosH + top_margin)
+    {
+        //Si le pointeur est sur une des bordures.
+        var xb = x % W;
+        var yb = y - top_margin;
+        yb %= H;
+        
+        if(xb < m || xb > W - m || yb < m || yb > H - m)
+        {
+            //On renvoie null.
+            return null;
+        }
+        //Sinon il est forcément sur un des snapshots.
+        else
+        {
+            i = Math.floor(x / W);
+            j = Math.floor((y - top_margin) / H);
+        }
+        
+        //On passe des coordonnées 2D en 1D.
+        var snapshot = $('#snapshotDiv-' + (j * mosW + i));
+        
+        //Si le snapshot a été filtré, on renvoie null si on se trouve dans la mosaïque.
+        if(this.isMosaicFiltered && (this.currentMode == "MOSAIC" || this.currentMode == "FILTER") && snapshot.css('opacity') == 0)
+        {
+            return null;
+        }
+        
+        //On renvoie le snapshot.
+        return snapshot;
+    }
+    
+    //Si on est arrivé là, c'est que le pointeur n'est pas dans la mosaïque.
+    return null;
 }
 
 /*
  * Donne éventuellement un voisin additionnel d'après les coordonnées du pointeur sur l'écran.
  * Renvoie null sinon.
+ * Est appelé : dans le fichier pointers > fonction pointersVideoInteractions.
 */
-mosaic.prototype.pointerPositionToAN = function(x, y, isMainPointer)
+Mosaic.prototype.pointerPositionToAN = function(x, y, isMainPointer)
 {
-	if(this.helpDisplayed)
-	{
-		return;
-	}
-	
-	x += $('#mainPointer').width() / 2;
-	y += $('#mainPointer').height() / 2;
-	
-	//Pour tous les voisins.
-	for(var i = 0 ; i < this.neighboursIds.length ; i++)
-	{
-		//Si on est sur un bord.
-		if(this.neighboursIds[i] == -1)
-		{
-			//On récupère un voisin au delà du bord.
-			var neighbour = $('#borderNeighbour-' + i);
-			
-			if(neighbour == null || neighbour == undefined || neighbour.position() == null)
-			{
-				return;
-			}
-			
-			//Si le pointeur est sur le voisin, on le retourne.
-			if(x > neighbour.position().left && x < +neighbour.position().left + neighbour.width() && y > neighbour.position().top && y < +neighbour.position().top + neighbour.height())
-			{
-				return neighbour;
-			}
-		}
-	}
-	return null;
+    //Si l'aide est affichée, on part.
+    if(this.helpDisplayed)
+    {
+        return;
+    }
+    
+    x += $('#mainPointer').width() / 2;
+    y += $('#mainPointer').height() / 2;
+    
+    //Pour tous les voisins.
+    for(var i = 0 ; i < this.neighboursIds.length ; i++)
+    {
+        //Si on est sur un bord.
+        if(this.neighboursIds[i] == -1)
+        {
+            //On récupère un voisin au delà du bord.
+            var neighbour = $('#borderNeighbour-' + i);
+            
+            if(neighbour == null || neighbour == undefined || neighbour.position() == null)
+            {
+                return;
+            }
+            
+            //Si le pointeur est sur le voisin, on le retourne.
+            if(x > neighbour.position().left && x < +neighbour.position().left + neighbour.width() && y > neighbour.position().top && y < +neighbour.position().top + neighbour.height())
+            {
+                return neighbour;
+            }
+        }
+    }
+    return null;
 }
 
 /*
  * Vérifie l'intéraction dézoom.
+ * Est appelé : dans le fichier pointers > fonction pointersVideoInteractions.
 */
-mosaic.prototype.checkForDezoom = function()
+Mosaic.prototype.checkForDezoom = function()
 {
-	//Si on se trouve en mode VIDEO ou SEARCH.
-	if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH")
-	{
-		//Si les deux pointeurs sont allés puis ont quitté une bordure.
-		if(this.mainPointerExitBorder && this.secondPointerExitBorder)
-		{
-			//Si les voisins existent.
-			if(this.neighboursIds != null && this.neighboursIds.length > 0)
-			{
-				var localIdMainPointerNeighbour = $.inArray(this.mainPointerNeighbourSelectedId, this.neighboursIds);
-				var localIdSecondPointerNeighbour = $.inArray(this.secondPointerNeighbourSelectedId, this.neighboursIds);
-				
-				//Cas où on a des voisins additionnels.
-				if(this.mainPointerNeighbourSelectedId >= this.config['imagesToShow'])
-				{
-					localIdMainPointerNeighbour = this.mainPointerNeighbourSelectedId - this.config['imagesToShow'];
-				}
-				if(this.secondPointerNeighbourSelectedId >= this.config['imagesToShow'])
-				{
-					localIdSecondPointerNeighbour = this.secondPointerNeighbourSelectedId - this.config['imagesToShow'];
-				}
-				
-				// console.log(localIdMainPointerNeighbour + ' <=> ' + localIdSecondPointerNeighbour);
-				
-				if(localIdMainPointerNeighbour > -1 && localIdMainPointerNeighbour < 4 && localIdSecondPointerNeighbour > -1 && localIdSecondPointerNeighbour < 4)
-				{
-					var sym = (localIdMainPointerNeighbour % 2 == 0) ? (+localIdMainPointerNeighbour + 1) : (localIdMainPointerNeighbour - 1);
-					
-					//Si les voisins sélectionnés sont opposés.
-					if(sym == localIdSecondPointerNeighbour)
-					{
-						//Positions des pointeurs.
-						var xMain = $('#mainPointer').position().left - $('#mainPointer').width() / 2;
-						var yMain = $('#mainPointer').position().top - $('#mainPointer').height() / 2;
-						var xSecond = $('#secondPointer').position().left - $('#secondPointer').width() / 2;
-						var ySecond = $('#secondPointer').position().top - $('#secondPointer').height() / 2;
-						
-						//Snapshot central.
-						var centerSN = $('#snapshotDiv-' + this.centerId);
-						
-						//Quarts du snapshot central.
-						var center1QuartWidth = centerSN.position().left + this.notifyLeftVideo + centerSN.width() / 4;
-						var center3QuartsWidth = centerSN.position().left + this.notifyLeftVideo + centerSN.width() * 3 / 4;
-						var center1QuartHeight = centerSN.position().top + this.notifyTopVideo + centerSN.height() / 4;
-						var center3QuartsHeight = centerSN.position().top + this.notifyTopVideo + centerSN.height() * 3 / 4;
-						
-						//Pour activer le dézoom, il suffit que les pointeurs soient dans un rectangle délimité au centre de l'écran.
-						//Si les voisins sélectionnés sont de disposition horizontale.
-						if(sym == 0 || sym == 1)
-						{
-							if(xMain > center1QuartWidth && xSecond > center1QuartWidth && xMain < center3QuartsWidth && xSecond < center3QuartsWidth)
-							{
-								console.log('HORIZONTAL UNZOOM - ' + this.currentMode);
-								this.unzoom();
-								console.log('HORIZONTAL UNZOOM AFTER - ' + this.currentMode);
-							}
-						}
-						//Sinon s'ils sont de disposition verticale.
-						else if(sym == 2 || sym == 3)
-						{
-							if(yMain > center1QuartHeight && ySecond > center1QuartHeight && yMain < center3QuartsHeight && ySecond < center3QuartsHeight)
-							{
-								console.log('VERTICAL UNZOOM - ' + this.currentMode);
-								this.unzoom();
-							}
-						}
-					}
-				}
-			}
-		}
-	}
+    //Si on se trouve en mode VIDEO ou SEARCH.
+    if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH")
+    {
+        //Si les deux pointeurs sont allés puis ont quitté une bordure.
+        if(this.mainPointerExitBorder && this.secondPointerExitBorder)
+        {
+            //Si les voisins existent.
+            if(this.neighboursIds != null && this.neighboursIds.length > 0)
+            {
+                var localIdMainPointerNeighbour = $.inArray(this.mainPointerNeighbourSelectedId, this.neighboursIds);
+                var localIdSecondPointerNeighbour = $.inArray(this.secondPointerNeighbourSelectedId, this.neighboursIds);
+                
+                //Cas où on a des voisins additionnels.
+                if(this.mainPointerNeighbourSelectedId >= this.config.imagesToShow)
+                {
+                    localIdMainPointerNeighbour = this.mainPointerNeighbourSelectedId - this.config.imagesToShow;
+                }
+                if(this.secondPointerNeighbourSelectedId >= this.config.imagesToShow)
+                {
+                    localIdSecondPointerNeighbour = this.secondPointerNeighbourSelectedId - this.config.imagesToShow;
+                }
+                
+                if(localIdMainPointerNeighbour > -1 && localIdMainPointerNeighbour < 4 && localIdSecondPointerNeighbour > -1 && localIdSecondPointerNeighbour < 4)
+                {
+                    var sym = (localIdMainPointerNeighbour % 2 == 0) ? (+localIdMainPointerNeighbour + 1) : (localIdMainPointerNeighbour - 1);
+                    
+                    //Si les voisins sélectionnés sont opposés.
+                    if(sym == localIdSecondPointerNeighbour)
+                    {
+                        //Positions des pointeurs.
+                        var xMain = $('#mainPointer').position().left - $('#mainPointer').width() / 2;
+                        var yMain = $('#mainPointer').position().top - $('#mainPointer').height() / 2;
+                        var xSecond = $('#secondPointer').position().left - $('#secondPointer').width() / 2;
+                        var ySecond = $('#secondPointer').position().top - $('#secondPointer').height() / 2;
+                        
+                        //Snapshot central.
+                        var centerSN = $('#snapshotDiv-' + this.centerId);
+                        
+                        //Quarts du snapshot central.
+                        var center1QuartWidth = centerSN.position().left + this.notifyLeftVideo + centerSN.width() / 4;
+                        var center3QuartsWidth = centerSN.position().left + this.notifyLeftVideo + centerSN.width() * 3 / 4;
+                        var center1QuartHeight = centerSN.position().top + this.notifyTopVideo + centerSN.height() / 4;
+                        var center3QuartsHeight = centerSN.position().top + this.notifyTopVideo + centerSN.height() * 3 / 4;
+                        
+                        //Pour activer le dézoom, il suffit que les pointeurs soient dans un rectangle délimité au centre de l'écran.
+                        //Si les voisins sélectionnés sont de disposition horizontale.
+                        if(sym == 0 || sym == 1)
+                        {
+                            if(xMain > center1QuartWidth && xSecond > center1QuartWidth && xMain < center3QuartsWidth && xSecond < center3QuartsWidth)
+                            {
+                                this.unzoom();
+                            }
+                        }
+                        //Sinon s'ils sont de disposition verticale.
+                        else if(sym == 2 || sym == 3)
+                        {
+                            if(yMain > center1QuartHeight && ySecond > center1QuartHeight && yMain < center3QuartsHeight && ySecond < center3QuartsHeight)
+                            {
+                                this.unzoom();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
--- a/front_idill/src/mosaic/js/notifications.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/mosaic/js/notifications.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,1455 +1,1494 @@
-/* ===============================================
- *												   *
- *		      ZONE DES NOTIFICATIONS			   *
- *												   *
-   =============================================== */
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : notifications.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les fonctions de notification (images apparaissant en haut de la fenêtre).
+ */
 
 /*
  * Affiche l'aide.
+ * Est appelé dans les fichiers :
+ * mosaic > fonction manageControlEvents.
+ * curvesDetector > fonction updateDists.
 */
-mosaic.prototype.notifyHelp = function(inMosaic)
+Mosaic.prototype.notifyHelp = function(inMosaic)
 {
-	if(this.helpDisplayed)
-	{
-		return;
-	}
-	
-	console.log('HELP DISPLAYED');
-	
-	this.removeNotifications();
-	
-	this.helpDisplayed = true;
-	
-	var search_2hands_tab;
-	var search_2hands_tab_opacities;
-	var search_body_tab;
-	var search_body_tab_opacities;
-	var controls_1hand_tab;
-	var controls_1hand_tab;
-	var controls_1hand_tab_opacities;
-	var controls_1hand_tab_opacities;
-	
-	var img_directory = './pictos/help/';
-	
-	if(this.mouseInteractions)
-	{
-		search_2hands_tab = ['arret', 'contact', 'grandjete', 'group_spin', 'port_de_bras', 'spin', 'up_down', 'wave', 'chute', 'knee_up', 'jump', 'bend'];
-		search_2hands_tab_opacities = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
-	}
-	else
-	{
-		search_2hands_tab = ['arret', 'contact', 'grandjete', 'group_spin', 'port_de_bras', 'spin', 'up_down', 'wave'];
-		search_body_tab = ['chute', 'knee_up', 'jump', 'bend'];
-		search_2hands_tab_opacities = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5];
-		search_body_tab_opacities = [1, 1, 1, 1];
-	}
-	
-	if(inMosaic)
-	{
-		controls_1hand_tab = ['selection'];
-		controls_1hand_tab_opacities = [1];
-	}
-	else
-	{
-		controls_1hand_tab = ['deplacer', 'precedent', 'suivant', 'mosaique_horizontal', 'mosaique_vertical', 'move_down', 'move_up', 'move_right', 'move_left'];
-		controls_1hand_tab_opacities = [1, 1, 1, 1, 1, 1, 1, 1, 1];
-	}
-	
-	//On spécifie les notifications en div.
-	var search_title = "<div id='search_title'></div>";
-	var search_img = "<div id='search_img' class='notify_imgs'></div>";
-	var search_2hands_text = "<div id='search_2hands_text'></div>";
-	var search_2hands_imgs = "<div id='search_2hands_imgs' class='notify_imgs_big'>";
-	
-	for(var i = 0 ; i < search_2hands_tab.length ; i++)
-	{
-		search_2hands_imgs += "<div id='2hands_" + search_2hands_tab[i] + "' class='notify_imgs_small' style='opacity: " + search_2hands_tab_opacities[i] + ";'></div>";
-	}
-	search_2hands_imgs += "</div>";
-	
-	var search_body_text;
-	var search_body_imgs;
-	
-	if(!this.mouseInteractions)
-	{
-		search_body_text = "<div id='search_body_text'></div>";
-		search_body_imgs = "<div id='search_body_imgs' class='notify_imgs'>"
-		
-		for(var i = 0 ; i < search_body_tab.length ; i++)
-		{
-			search_body_imgs += "<div id='body_" + search_body_tab[i] + "' class='notify_imgs_small' style='opacity: " + search_body_tab_opacities[i] + ";'></div>";
-		}
-		search_body_imgs += "</div>";
-	}
-	
-	var controls_title = "<div id='controls_title'></div>";
-	var controls_img = "<div id='controls_img' class='notify_imgs'></div>";
-	var controls_1hand_text = "<div id='controls_1hand_text'></div>";
-	var controls_1hand_imgs;
-	var controls_1hand_imgs;
-	
-	controls_1hand_imgs = "<div id='controls_1hand_imgs' class='notify_imgs'>";
-	for(var i = 0 ; i < controls_1hand_tab.length ; i++)
-	{
-		controls_1hand_imgs += "<div id='1hand_" + controls_1hand_tab[i] + "' class='notify_imgs_small' style='opacity: " + controls_1hand_tab_opacities[i] + ";'></div>";
-	}
-	controls_1hand_imgs += "</div>";
-	
-	var help_search;
-	
-	if(this.mouseInteractions)
-	{
-		help_search = "<div id='help_search'>" + search_title + search_img + search_2hands_text + search_2hands_imgs + "</div>";
-	}
-	else
-	{
-		help_search = "<div id='help_search'>" + search_title + search_img + search_2hands_text + search_2hands_imgs + search_body_text + search_body_imgs + "</div>";
-	}
-	var help_controls;
+    //Si elle est déjà affichée on quitte.
+    if(this.helpDisplayed)
+    {
+        return;
+    }
+    
+    //On enlève les autres notifications.
+    this.removeNotifications();
+    
+    //On indique qu'elle est affiché.
+    this.helpDisplayed = true;
+    
+    //Section des courbes de recherche.
+    var search_2hands_tab;
+    //Section des recherches corporelles.
+    var search_body_tab;
+    //Section des actions de contrôle sur l'interface.
+    var controls_1hand_tab;
+    //Opacités (indique si elles sont actuellement implémentées).
+    var search_2hands_tab_opacities;
+    var search_body_tab_opacities;
+    var controls_1hand_tab_opacities;
+    var controls_1hand_tab_opacities;
+    
+    //Dossier contenant les images.
+    var img_directory = './pictos/help/';
+    
+    //Si on est en mode d'intéraction souris, la recherche corporelle se fait par des courbes. On les regroupes donc dans la section des courbes.
+    if(this.config.mouseInteractions)
+    {
+        search_2hands_tab = ['arret', 'contact', 'grandjete', 'group_spin', 'port_de_bras', 'spin', 'up_down', 'wave', 'chute', 'knee_up', 'jump', 'bend'];
+        search_2hands_tab_opacities = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+    }
+    else
+    {
+        search_2hands_tab = ['arret', 'contact', 'grandjete', 'group_spin', 'port_de_bras', 'spin', 'up_down', 'wave'];
+        search_body_tab = ['chute', 'knee_up', 'jump', 'bend'];
+        search_2hands_tab_opacities = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5];
+        search_body_tab_opacities = [1, 1, 1, 1];
+    }
+    
+    //Dans la mosaique, on ne peut que sélectionner un snapshot.
+    if(inMosaic)
+    {
+        controls_1hand_tab = ['selection'];
+        controls_1hand_tab_opacities = [1];
+    }
+    //Dans une vidéo, on peut aller d'un voisin à l'autre, bouger dans la timeline, dézoomer et swiper d'un marqueur à l'autre.
+    else
+    {
+        controls_1hand_tab = ['deplacer', 'precedent', 'suivant', 'mosaique_horizontal', 'mosaique_vertical', 'move_down', 'move_up', 'move_right', 'move_left'];
+        controls_1hand_tab_opacities = [1, 1, 1, 1, 1, 1, 1, 1, 1];
+    }
+    
+    //Colonne de recherche.
+    //Titre de la colonne de recherche.
+    var search_title = "<div id='search_title'></div>";
+    //Image de la colonne.
+    var search_img = "<div id='search_img' class='notify_imgs'></div>";
+    //Sous-titre.
+    var search_2hands_text = "<div id='search_2hands_text'></div>";
+    //Images de recherche par courbes.
+    var search_2hands_imgs = "<div id='search_2hands_imgs' class='notify_imgs_big'>";
+    
+    //On crée les images.
+    for(var i = 0 ; i < search_2hands_tab.length ; i++)
+    {
+        search_2hands_imgs += "<div id='2hands_" + search_2hands_tab[i] + "' class='notify_imgs_small' style='opacity: " + search_2hands_tab_opacities[i] + ";'></div>";
+    }
+    search_2hands_imgs += "</div>";
+    
+    //Sous-titre de la zone de recherche corporelle.
+    var search_body_text;
+    //Images de recherche corporelle.
+    var search_body_imgs;
+    
+    //Si on est en mode Kinect.
+    if(!this.config.mouseInteractions)
+    {
+        //On crée le texte et les images de la recherche corporelle.
+        search_body_text = "<div id='search_body_text'></div>";
+        search_body_imgs = "<div id='search_body_imgs' class='notify_imgs'>"
+        
+        for(var i = 0 ; i < search_body_tab.length ; i++)
+        {
+            search_body_imgs += "<div id='body_" + search_body_tab[i] + "' class='notify_imgs_small' style='opacity: " + search_body_tab_opacities[i] + ";'></div>";
+        }
+        search_body_imgs += "</div>";
+    }
+    
+    //Titre de la colonne des actions de contrôle.
+    var controls_title = "<div id='controls_title'></div>";
+    //Image de la colonne.
+    var controls_img = "<div id='controls_img' class='notify_imgs'></div>";
+    //Sous-titre de la zone de contrôle de l'interface.
+    var controls_1hand_text = "<div id='controls_1hand_text'></div>";
+    //Images des actions de contrôle de l'interface.
+    var controls_1hand_imgs;
+    
+    controls_1hand_imgs = "<div id='controls_1hand_imgs' class='notify_imgs'>";
+    for(var i = 0 ; i < controls_1hand_tab.length ; i++)
+    {
+        controls_1hand_imgs += "<div id='1hand_" + controls_1hand_tab[i] + "' class='notify_imgs_small' style='opacity: " + controls_1hand_tab_opacities[i] + ";'></div>";
+    }
+    controls_1hand_imgs += "</div>";
+    
+    //Colonne de recherche du panneau d'aide.
+    var help_search;
+    
+    //Dans le mode d'intéraction souris, les gestures de recherche corporelles ont été intégrées aux courbes.
+    if(this.config.mouseInteractions)
+    {
+        help_search = "<div id='help_search'>" + search_title + search_img + search_2hands_text + search_2hands_imgs + "</div>";
+    }
+    else
+    {
+        help_search = "<div id='help_search'>" + search_title + search_img + search_2hands_text + search_2hands_imgs + search_body_text + search_body_imgs + "</div>";
+    }
+    
+    //Colonne de contrôle du panneau d'aide.
+    var help_controls;
 
-	help_controls = "<div id='help_controls'>" + controls_title + controls_img + controls_1hand_text + controls_1hand_imgs + "</div>";
-	
-	var notification_help = "<div id='notify_help'>" + help_search + "<div id='help_sep'></div>" + help_controls + "</div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_help);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $(window).width(), notify_height = $(window).height();
-	var notify_margin = parseInt($('#notify_help').css('margin'));
-	var notify_ = 10;
-	
-	//On les positionne.
-	$('#notify_help').css(
-	{
-		left: "0px",
-		top: "0px",
-		width: notify_width - notify_margin * 2,
-		height: notify_height - notify_margin * 2,
-		'z-index': 2000
-	});
-	
-	// console.log(($('#help_search').width() - ($('.notify_imgs_small').width() * 5 + parseInt($('.notify_imgs_small').css('margin')))) / 2);
-	
-	var margins = parseInt($('.notify_imgs_small').css('margin'));
-	var widths = $('.notify_imgs_small').width();
-	var heights = $('.notify_imgs_small').height();
-	
-	var sep_left = $('#help_sep').position().left;
-	var help_margin = parseInt($('#notify_help').css('margin'));
-	
-	//On calcule la taille d'une zone de recherche (une des deux parties).
-	var help_column_width = sep_left - help_margin;
-	//Longueur d'une image.
-	var img_width = (margins * 2 + widths);
-	//Longueur totale des images de recherche à deux mains mises bout à bout.
-	// var search_2hands_total_width = search_2hands_tab.length * img_width;
-	
-	//On récupère le nombre d'images affichables horizontalement pour les gestures de recherche à deux mains dans une des parties de l'aide.
-	var search_2hands_n_imgs = Math.floor(help_column_width / img_width);
-	//Calcul du padding-left de cette section.
-	var search_2hands_padding_left = (help_column_width - search_2hands_n_imgs * img_width) / 2;
-	
-	$('#search_2hands_imgs').css(
-	{
-		// 'padding-left': ($('#help_search').width() - ($('.notify_imgs_small').width() * 5 + parseInt($('.notify_imgs_small').css('margin')))) / 2,
-		'padding-left': search_2hands_padding_left,
-		'height': ($('.notify_imgs_small').height() * 2 + parseInt($('.notify_imgs_small').css('margin')))
-	});
-	
-	//On récupère le nombre d'images affichables horizontalement pour les gestures de recherche corporelles dans une des parties de l'aide.
-	var search_body_n_imgs = Math.floor(help_column_width / img_width);
-	//Calcul du padding-left de cette section.
-	var search_body_padding_left = (help_column_width - search_body_n_imgs * img_width) / 2;
-	
-	$('#search_body_imgs').css(
-	{
-		// 'padding-left': ($('#help_search').width() - ($('.notify_imgs_small').width() * 4 + parseInt($('.notify_imgs_small').css('margin')))) / 2,
-		'padding-left': search_body_padding_left,
-		'height': ($('.notify_imgs_small').height() * 2 + parseInt($('.notify_imgs_small').css('margin')))
-	});
-	
-	//On récupère le nombre d'images affichables horizontalement pour les gestures de controle dans une des parties de l'aide.
-	var controls_1hand_n_imgs = Math.floor(help_column_width / img_width);
-	//Calcul du padding-left de cette section.
-	var controls_1hand_padding_left = (help_column_width - controls_1hand_n_imgs * img_width) / 2;
-	
-	$('#controls_1hand_imgs').css(
-	{
-		// 'padding-left': ($('#help_controls').width() - ($('.notify_imgs_small').width())) / 2,
-		'padding-left': controls_1hand_padding_left,
-		'height': ($('.notify_imgs_small').height())
-	});
-	
-	var search_width = $('#help_search').width();
-	
-	$('#search_title').html('Recherche');
-	
-	if(this.mouseInteractions)
-	{
-		$('#search_2hands_text').html('Courbes à effectuer avec la souris');
-	}
-	else
-	{
-		$('#search_2hands_text').html('Gestes à effectuer avec les deux mains');
-	}
-	
-	for(var i = 0 ; i < search_2hands_tab.length ; i++)
-	{
-		$("#2hands_" + search_2hands_tab[i]).css("background-image", "url('" + img_directory + 'MI/' + search_2hands_tab[i] + ".png')");
-		//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
-	}
-	
-	if(!this.mouseInteractions)
-	{
-		$('#search_body_text').html('Gestes à effectuer avec le corps entier');
-		
-		for(var i = 0 ; i < search_body_tab.length ; i++)
-		{
-			$("#body_" + search_body_tab[i]).css("background-image", "url('" + img_directory + search_body_tab[i] + ".png')");
-			//console.log("url('../../pictos/help/" + search_2hands_tab[i] + ".png')");
-		}
-	}
-	
-	$('#controls_title').html('Contrôles');
-	$('#controls_1hand_text').html('Gestes à effectuer avec une seule main');
-	
-	for(var i = 0 ; i < controls_1hand_tab.length ; i++)
-	{
-		$("#1hand_" + controls_1hand_tab[i]).css("background-image", "url('" + img_directory + controls_1hand_tab[i] + ".png')");
-	}
-	
-	//On les fait apparaître.
-	$('#notify_help').css(
-	{
-		opacity: "1"
-	});
-	
-	$('.notify_imgs_big').css(
-	{
-		opacity: "1"
-	});
+    help_controls = "<div id='help_controls'>" + controls_title + controls_img + controls_1hand_text + controls_1hand_imgs + "</div>";
+    
+    //Panneau d'aide.
+    var notification_help = "<div id='notify_help'>" + help_search + "<div id='help_sep'></div>" + help_controls + "</div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_help);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $(window).width(), notify_height = $(window).height();
+    var notify_margin = parseInt($('#notify_help').css('margin'));
+    var notify_ = 10;
+    
+    //On les positionne.
+    $('#notify_help').css(
+    {
+        left: "0px",
+        top: "0px",
+        width: notify_width - notify_margin * 2,
+        height: notify_height - notify_margin * 2,
+        'z-index': 1000
+    });
+    
+    //Taille des marges des images.
+    var margins = parseInt($('.notify_imgs_small').css('margin'));
+    //Largeur des images.
+    var widths = $('.notify_imgs_small').width();
+    //Hauteur des images.
+    var heights = $('.notify_imgs_small').height();
+    //Position horizontale du séparateur de colonnes.
+    var sep_left = $('#help_sep').position().left;
+    //Marge du panneau d'aide.
+    var help_margin = parseInt($('#notify_help').css('margin'));
+    
+    //On calcule la taille d'une zone de recherche (une des deux parties).
+    var help_column_width = sep_left - help_margin;
+    //Longueur d'une image.
+    var img_width = (margins * 2 + widths);
+    
+    //On récupère le nombre d'images affichables horizontalement pour les gestures de recherche à deux mains dans une des parties de l'aide.
+    var search_2hands_n_imgs = Math.floor(help_column_width / img_width);
+    //Calcul du padding-left de cette section.
+    var search_2hands_padding_left = (help_column_width - search_2hands_n_imgs * img_width) / 2;
+    
+    //On positionne la section de recherche par courbes.
+    $('#search_2hands_imgs').css(
+    {
+        'padding-left': search_2hands_padding_left,
+        'height': ($('.notify_imgs_small').height() * 2 + parseInt($('.notify_imgs_small').css('margin')))
+    });
+    
+    //On récupère le nombre d'images affichables horizontalement pour les gestures de recherche corporelles dans une des parties de l'aide.
+    var search_body_n_imgs = Math.floor(help_column_width / img_width);
+    //Calcul du padding-left de cette section.
+    var search_body_padding_left = (help_column_width - search_body_n_imgs * img_width) / 2;
+    
+    //On positionne la section de recherche par gestures corporelles.
+    $('#search_body_imgs').css(
+    {
+        'padding-left': search_body_padding_left,
+        'height': ($('.notify_imgs_small').height() * 2 + parseInt($('.notify_imgs_small').css('margin')))
+    });
+    
+    //On récupère le nombre d'images affichables horizontalement pour les gestures de controle dans une des parties de l'aide.
+    var controls_1hand_n_imgs = Math.floor(help_column_width / img_width);
+    //Calcul du padding-left de cette section.
+    var controls_1hand_padding_left = (help_column_width - controls_1hand_n_imgs * img_width) / 2;
+    
+    //On potisionne la section des actions de contrôle de l'interface.
+    $('#controls_1hand_imgs').css(
+    {
+        'padding-left': controls_1hand_padding_left,
+        'height': ($('.notify_imgs_small').height())
+    });
+    
+    //Longueur de la colonne de recherche.
+    var search_width = $('#help_search').width();
+    
+    $('#search_title').html('Recherche');
+    var MI = '';
+    
+    //Le texte de recherche et les images changent en fonction du mode d'intéraction (souris/Kinect).
+    if(this.config.mouseInteractions)
+    {
+        $('#search_2hands_text').html('Courbes à effectuer avec la souris');
+        MI = 'MI/';
+    }
+    else
+    {
+        $('#search_2hands_text').html('Gestes à effectuer avec les deux mains');
+    }
+    
+    //On affecte les images pour la recherche par courbes.
+    for(var i = 0 ; i < search_2hands_tab.length ; i++)
+    {
+        $("#2hands_" + search_2hands_tab[i]).css("background-image", "url('" + img_directory + MI + search_2hands_tab[i] + ".png')");
+    }
+    
+    //Si on est en mode Kinect, on affecte les images de recherche corporelle.
+    if(!this.config.mouseInteractions)
+    {
+        $('#search_body_text').html('Gestes à effectuer avec le corps entier');
+        
+        for(var i = 0 ; i < search_body_tab.length ; i++)
+        {
+            $("#body_" + search_body_tab[i]).css("background-image", "url('" + img_directory + search_body_tab[i] + ".png')");
+        }
+    }
+    
+    //Actions de contrôle de l'interface.
+    $('#controls_title').html('Contrôles');
+    $('#controls_1hand_text').html('Gestes à effectuer avec une seule main');
+    
+    //On affecte les images des actions de contrôle de l'interface.
+    for(var i = 0 ; i < controls_1hand_tab.length ; i++)
+    {
+        $("#1hand_" + controls_1hand_tab[i]).css("background-image", "url('" + img_directory + controls_1hand_tab[i] + ".png')");
+    }
+    
+    //On les fait apparaître.
+    $('#notify_help').css(
+    {
+        opacity: "1"
+    });
+    
+    $('.notify_imgs_big').css(
+    {
+        opacity: "1"
+    });
 }
 
 /*
  * Supprime l'aide.
+ * Est appelé dans les fichiers :
+ * pointers > fonction detectIdlePointers.
+ * mosaic > fonction manageControlEvents et onClick.
+ * curvesDetector > fonction updateDists.
 */
-mosaic.prototype.removeHelp = function()
+Mosaic.prototype.removeHelp = function()
 {
-	if(!this.helpDisplayed)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	$('#notify_help').fadeOut(this.timeNotifyFade, function()
-	{
-		_this.helpDisplayed = false;
-		// _this.canNotifyHelp = false;
-		_this.canNotifyHelp = true;
-		console.log('CAN NOT NOTIFY HELP');
-		$('#notify_help').remove();
-	});
+    //Si l'aide n'est pas affichée, on part.
+    if(!this.helpDisplayed)
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On fait disparaître l'aide.
+    $('#notify_help').fadeOut(this.timeNotifyFade, function()
+    {
+        //On indique que l'aide n'est plus affichée, et on détruit le panneau.
+        _this.helpDisplayed = false;
+        _this.canNotifyHelp = true;
+        $('#notify_help').remove();
+    });
 }
 
 /*
- * Affiche la notification de validation/survol de gesture de filtrage.
- * Mode prend pour valeurs : "valid" ou "hover".
+ * Affichage de la notification de sélection & recherche dans la mosaïque.
+ * Est appelé dans les fichiers :
+ * zoomInteractions > fonctions preUnzoom et unzoom.
+ * mosaic > fonction showNImages.
 */
-mosaic.prototype.notifySearch1Gesture = function(gestureName, mode)
+Mosaic.prototype.mosaicSelectionAndSearch = function()
 {
-	// console.log('C');
-	if($('#notify_search_1gesture').length > 0)
-	{
-		$('#notify_search_1gesture').remove();
-	}
-	
-	//Si on a effectué une demande de recherche auparavant, on supprime la notification de demande de recherche.
-	if($('#notify_search').length > 0)
-	{
-		this.removeNotifications();
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search_1gesture);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	if(_.include(this.gestures, gestureName))
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + mode + '/' + gestureName + '.png")');
-	}
-	else if(mode == 'none')
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
-	}
-	
-	//On les positionne.
-	$('#notify_search_1gesture').css(
-	{
-		top: 0,
-		left: ($(window).width() - notify_width) / 2
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
+    //Si on n'est pas en mode mosaic, on part.
+    if(this.currentMode != 'MOSAIC')
+    {
+        return;
+    }
+    
+    //On spécifie les notifications en div.
+    var notification_selection = "<div id='notify_selection' class='notifications'></div>";
+    var notification_search = "<div id='notify_search' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_selection + notification_search);
 
-// /!\/!\/!\ //
-
-/* NOUVELLES NOTIFICATIONS */
-
-// /!\/!\/!\ //
-
-/*
- * Affichage de la notification de sélection & recherche dans la mosaïque.
-*/
-mosaic.prototype.mosaicSelectionAndSearch = function()
-{
-	if(this.currentMode != 'MOSAIC')
-	{
-		return;
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_selection + notification_search);
-
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var selection_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var search_left = selection_left + notify_width + notify_margin;
-	
-	//On les positionne.
-	$('#notify_selection').css(
-	{
-		left: selection_left
-	});
-	$('#notify_search').css(
-	{
-		left: search_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var selection_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var search_left = selection_left + notify_width + notify_margin;
+    
+    //On les positionne.
+    $('#notify_selection').css(
+    {
+        left: selection_left
+    });
+    $('#notify_search').css(
+    {
+        left: search_left
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de sélection dans la mosaïque.
+ * Est appelé dans le fichier :
+ * zoomInteractions > fonction preZoom.
 */
-mosaic.prototype.mosaicSelection = function()
+Mosaic.prototype.mosaicSelection = function()
 {
-	if(this.currentMode != 'MOSAIC')
-	{
-		return;
-	}
-	
-	//On spécifie la notification en div.
-	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
-	
-	//On l'ajoute à la mosaïque.
-	$('body').append(notification_selection);
+    //Si on n'est pas en mode mosaic, on part.
+    if(this.currentMode != 'MOSAIC')
+    {
+        return;
+    }
+    
+    //On spécifie la notification en div.
+    var notification_selection = "<div id='notify_selection' class='notifications'></div>";
+    
+    //On l'ajoute à la mosaïque.
+    $('body').append(notification_selection);
 
-	//On calcule ses coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var selection_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	//On les positionne.
-	$('#notify_selection').css(
-	{
-		left: selection_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //On calcule ses coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var selection_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
+    
+    //On les positionne.
+    $('#notify_selection').css(
+    {
+        left: selection_left
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de recherche dans une demande de filtrage de la mosaïque.
+ * Est appelé dans les fichiers :
+ * pointers > fonction launchIdlePointers.
+ * zoomInteractions > fonction preUnzoom.
 */
-mosaic.prototype.filterSearch = function()
+Mosaic.prototype.filterSearch = function()
 {
-	if(this.currentMode != 'FILTER' || this.filterSearchedType)
-	{
-		return;
-	}
-	
-	// window.location.reload();
-	
-	//On spécifie la notification en div.
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	
-	//On l'ajoute à la mosaïque.
-	$('body').append(notification_search);
+    //Si on n'est pas en mode filtrage ou qu'aucune recherche n'est affectée au filtrage, on part.
+    if(this.currentMode != 'FILTER' || this.filterSearchedType)
+    {
+        return;
+    }
+    
+    //On spécifie la notification en div.
+    var notification_search = "<div id='notify_search' class='notifications'></div>";
+    
+    //On l'ajoute à la mosaïque.
+    $('body').append(notification_search);
 
-	//On calcule ses coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_left = $(window).width() / 2 - notify_width / 2 - notify_margin;
-	
-	//On la positionne.
-	$('#notify_search').css(
-	{
-		left: search_left
-	});
-	
-	//On la fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //On calcule ses coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_left = $(window).width() / 2 - notify_width / 2 - notify_margin;
+    
+    //On la positionne.
+    $('#notify_search').css(
+    {
+        left: search_left
+    });
+    
+    //On la fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de recherche & sélection dans une demande de filtrage de la mosaïque.
+ * Est appelé dans le fichier :
+ * zoomInteractions > fonction preZoom.
 */
-mosaic.prototype.filterSearchAndSelection = function()
+Mosaic.prototype.filterSearchAndSelection = function()
 {
-	if(this.currentMode != 'FILTER' || this.filterSearchedType)
-	{
-		return;
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_selection + notification_search);
+    //Si on n'est pas en mode filtrage ou qu'aucune recherche n'est affectée au filtrage, on part.
+    if(this.currentMode != 'FILTER' || this.filterSearchedType)
+    {
+        return;
+    }
+    
+    //On spécifie les notifications en div.
+    var notification_selection = "<div id='notify_selection' class='notifications'></div>";
+    var notification_search = "<div id='notify_search' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_selection + notification_search);
 
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var selection_left = search_left + notify_width + notify_margin;
-	
-	//On les positionne.
-	$('#notify_selection').css(
-	{
-		left: selection_left
-	});
-	$('#notify_search').css(
-	{
-		left: search_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var selection_left = search_left + notify_width + notify_margin;
+    
+    //On les positionne.
+    $('#notify_selection').css(
+    {
+        left: selection_left
+    });
+    $('#notify_search').css(
+    {
+        left: search_left
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat de gesture dans la mosaïque filtrée.
+ * Est appelé dans les fichiers :
+ * zoomInteractions > fonction preUnzoom.
+ * mosaic > onMouseUp et manageControlEvents.
+ * curvesDetector > updateDists.
 */
-mosaic.prototype.filterGesture = function(gestureName, mode)
+Mosaic.prototype.filterGesture = function(gestureName, mode)
 {
-	if(this.currentMode != 'FILTER' || !this.filterSearchedType)
-	{
-		return;
-	}
-	
-	// console.trace();
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search_1gesture);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	// console.log('url("./pictos/big/' + (this.mouseInteractions ? 'MI' : '') + '/' + mode + '/' + gestureName + '.png")');
-	
-	if(_.include(this.gestures, gestureName))
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI' : '') + '/' + (this.gestureDelRequested ? 'hover' : 'valid') + '/' + gestureName + '.png")');
-	}
-	else if(mode == 'none')
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
-	}
-	
-	//On les positionne.
-	$('#notify_search_1gesture').css(
-	{
-		top: 0,
-		left: ($(window).width() - notify_width) / 2
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode filtrage ou qu'aucune recherche n'est affectée au filtrage, on part.
+    if(this.currentMode != 'FILTER' || !this.filterSearchedType)
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search_1gesture);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
+    
+    if(_.include(this.gestures, gestureName))
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.config.mouseInteractions ? 'MI' : '') + '/' + (this.gestureDelRequested ? 'hover' : 'valid') + '/' + gestureName + '.png")');
+    }
+    else if(mode == 'none')
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
+    }
+    
+    //On les positionne.
+    $('#notify_search_1gesture').css(
+    {
+        top: 0,
+        left: ($(window).width() - notify_width) / 2
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat de gesture & de sélection dans la mosaïque filtrée.
+ * Est appelé dans le fichier :
+ * zoomInteractions > fonction preZoom.
 */
-mosaic.prototype.filterGestureAndSelection = function(gestureName, mode)
+Mosaic.prototype.filterGestureAndSelection = function(gestureName, mode)
 {
-	if(this.currentMode != 'FILTER' || !this.filterSearchedType)
-	{
-		return;
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
-	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search_1gesture + notification_selection);
+    //Si on n'est pas en mode filtrage ou qu'aucune recherche n'est affectée au filtrage, on part.
+    if(this.currentMode != 'FILTER' || !this.filterSearchedType)
+    {
+        return;
+    }
+    
+    //On spécifie les notifications en div.
+    var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
+    var notification_selection = "<div id='notify_selection' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search_1gesture + notification_selection);
 
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var selection_left = search_1gesture_left + notify_width + notify_margin;
-	
-	if(_.include(this.gestures, gestureName))
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI' : '') + '/' + mode + '/' + gestureName + '.png")');
-	}
-	else if(mode == 'none')
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
-	}
-	
-	//On les positionne.
-	$('#notify_search_1gesture').css(
-	{
-		left: search_1gesture_left
-	});
-	$('#notify_selection').css(
-	{
-		left: selection_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var selection_left = search_1gesture_left + notify_width + notify_margin;
+    
+    if(_.include(this.gestures, gestureName))
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.config.mouseInteractions ? 'MI' : '') + '/' + mode + '/' + gestureName + '.png")');
+    }
+    else if(mode == 'none')
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
+    }
+    
+    //On les positionne.
+    $('#notify_search_1gesture').css(
+    {
+        left: search_1gesture_left
+    });
+    $('#notify_selection').css(
+    {
+        left: selection_left
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affiche la notification de dezoom.
  * Direction vaut left ou right.
+ * Est appelé dans le fichier :
+ * mosaic > fonction manageControlEvents.
 */
-mosaic.prototype.videoSwipe = function(direction)
+Mosaic.prototype.videoSwipe = function(direction)
 {
-	if(this.currentMode != 'VIDEO' || !this.isSwipe)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_swipe = "<div id='notify_swipe' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_swipe);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_swipe').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + ($(window).width() - notify_width - notify_margin) / 2,
-		'background-image': 'url(./pictos/notifications/swipe_' + direction + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode video ou qu'on n'est pas en train d'effectuer un swipe, on part.
+    if(this.currentMode != 'VIDEO' || !this.isSwipe)
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_swipe = "<div id='notify_swipe' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_swipe);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On les positionne.
+    $('#notify_swipe').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + ($(window).width() - notify_width - notify_margin) / 2,
+        'background-image': 'url(./pictos/notifications/swipe_' + direction + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat de move vers un voisin.
+ * Est appelé dans le fichier :
+ * neighbours > fonction selectNeighbour.
 */
-mosaic.prototype.videoMove = function(targetId)
+Mosaic.prototype.videoMove = function(targetId)
 {
-	if(this.currentMode != 'VIDEO')
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_move = "<div id='notify_move' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_move);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var move_left = $(window).width() / 2 - (notify_width) / 2 + notify_margin;
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	// console.log(this.neighboursIds, parseInt(targetId), side);
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var sides = ['left', 'right', 'up', 'down'];
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_move').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + move_left,
-		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode video, on part.
+    if(this.currentMode != 'VIDEO')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_move = "<div id='notify_move' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_move);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var move_left = $(window).width() / 2 - (notify_width) / 2 + notify_margin;
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var sides = ['left', 'right', 'up', 'down'];
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On les positionne.
+    $('#notify_move').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + move_left,
+        'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat de move vers un voisin & de dézoom dans une vidéo.
+ * Est appelé dans le fichier :
+ * neighbours > fonction selectNeighbour.
 */
-mosaic.prototype.videoMoveAndUnzoom = function(targetId)
+Mosaic.prototype.videoMoveAndUnzoom = function(targetId)
 {
-	if(this.currentMode != 'VIDEO')
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_move = "<div id='notify_move' class='notifications'></div>";
-	var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_move + notification_unzoom);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var move_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var unzoom_left = move_left + notify_width + notify_margin;
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	// console.log(this.neighboursIds, parseInt(targetId), side);
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var sides = ['left', 'right', 'up', 'down'];
-	var unzooms = ['horizontal', 'vertical'];
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_move').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + move_left,
-		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
-	});
-	
-	$('#notify_unzoom').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + unzoom_left,
-		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode video, on part.
+    if(this.currentMode != 'VIDEO')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_move = "<div id='notify_move' class='notifications'></div>";
+    var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_move + notification_unzoom);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var move_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var unzoom_left = move_left + notify_width + notify_margin;
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var sides = ['left', 'right', 'up', 'down'];
+    var unzooms = ['horizontal', 'vertical'];
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On les positionne.
+    $('#notify_move').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + move_left,
+        'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+    });
+    
+    $('#notify_unzoom').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + unzoom_left,
+        'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat de dézoom dans une vidéo.
+ * Est appelé dans le fichier :
+ * neighbours > fonction selectNeighbour.
 */
-mosaic.prototype.videoUnzoom = function(targetId)
+Mosaic.prototype.videoUnzoom = function(targetId)
 {
-	if(this.currentMode != 'VIDEO')
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie la notifications en div.
-	var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
-	
-	//On l'ajoute à la mosaïque.
-	$('body').append(notification_unzoom);
-	
-	//On calcule ses coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var unzoom_left = $(window).width() / 2 - notify_width / 2 - notify_margin;
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var unzooms = ['horizontal', 'vertical'];
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On la positionne.
-	$('#notify_unzoom').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + unzoom_left,
-		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode video, on part.
+    if(this.currentMode != 'VIDEO')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie la notifications en div.
+    var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
+    
+    //On l'ajoute à la mosaïque.
+    $('body').append(notification_unzoom);
+    
+    //On calcule ses coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var unzoom_left = $(window).width() / 2 - notify_width / 2 - notify_margin;
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var unzooms = ['horizontal', 'vertical'];
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On la positionne.
+    $('#notify_unzoom').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + unzoom_left,
+        'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de timeline dans une vidéo/recherche.
+ * Est appelé dans le fichier :
+ * pointers > fonction pointersTimelineSelection.
 */
-mosaic.prototype.timelineTimeline = function()
+Mosaic.prototype.timelineTimeline = function()
 {
-	if(this.currentMode != 'TIMELINE')
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie la notifications en div.
-	var notification_timeline = "<div id='notify_timeline' class='notifications'></div>";
-	
-	//On l'ajoute à la mosaïque.
-	$('body').append(notification_timeline);
-	
-	//On calcule ses coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var timeline_left = $(window).width() / 2 - notify_width / 2 - notify_margin;
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On la positionne.
-	$('#notify_timeline').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + timeline_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode timeline, on part.
+    if(this.currentMode != 'TIMELINE')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie la notifications en div.
+    var notification_timeline = "<div id='notify_timeline' class='notifications'></div>";
+    
+    //On l'ajoute à la mosaïque.
+    $('body').append(notification_timeline);
+    
+    //On calcule ses coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var timeline_left = $(window).width() / 2 - notify_width / 2 - notify_margin;
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On la positionne.
+    $('#notify_timeline').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + timeline_left
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de recherche dans une vidéo de recherche.
+ * Est appelé dans les fichiers :
+ * neighbours > fonction deselectNeighbour.
+ * pointers > fonction launchIdlePointers.
+ * mosaic > fonction manageControlEvents.
 */
-mosaic.prototype.searchSearch = function()
+Mosaic.prototype.searchSearch = function()
 {
-	if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie la notifications en div.
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	
-	//On l'ajoute à la mosaïque.
-	$('body').append(notification_search);
-	
-	//On calcule ses coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_left = $(window).width() / 2 - notify_width / 2 - notify_margin;
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On la positionne.
-	$('#notify_search').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + search_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est effectuée, on part.
+    if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie la notifications en div.
+    var notification_search = "<div id='notify_search' class='notifications'></div>";
+    
+    //On l'ajoute à la mosaïque.
+    $('body').append(notification_search);
+    
+    //On calcule ses coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_left = $(window).width() / 2 - notify_width / 2 - notify_margin;
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On la positionne.
+    $('#notify_search').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + search_left
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de recherche & de swipe dans une vidéo de recherche.
+ * Est appelé dans le fichier :
+ * mosaic > fonction manageControlEvents.
 */
-mosaic.prototype.searchSearchAndSwipe = function(direction)
+Mosaic.prototype.searchSearchAndSwipe = function(direction)
 {
-	if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture || !this.isSwipe)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	var notification_swipe = "<div id='notify_swipe' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search + notification_swipe);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var swipe_left = search_left + notify_width + notify_margin;
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_search').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + search_left
-	});
-	$('#notify_swipe').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + swipe_left,
-		'background-image': 'url(./pictos/notifications/swipe_' + direction + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est effectuée ou qu'on n'est pas en train de faire un swipe, on part.
+    if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture || !this.isSwipe)
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_search = "<div id='notify_search' class='notifications'></div>";
+    var notification_swipe = "<div id='notify_swipe' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search + notification_swipe);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var swipe_left = search_left + notify_width + notify_margin;
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On les positionne.
+    $('#notify_search').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + search_left
+    });
+    $('#notify_swipe').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + swipe_left,
+        'background-image': 'url(./pictos/notifications/swipe_' + direction + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de recherche, de move vers un voisin.
+ * Est appelé dans le fichier :
+ * neighbours > fonction selectNeighbour.
 */
-mosaic.prototype.searchSearchAndMove = function(targetId)
+Mosaic.prototype.searchSearchAndMove = function(targetId)
 {
-	if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
-	{
-		return;
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	var notification_move = "<div id='notify_move' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search + notification_move);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var move_left = search_left + notify_width + notify_margin;
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var sides = ['left', 'right', 'up', 'down'];
-	
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_search').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + search_left
-	});
-	$('#notify_move').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + move_left,
-		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est effectuée, on part.
+    if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
+    {
+        return;
+    }
+    
+    //On spécifie les notifications en div.
+    var notification_search = "<div id='notify_search' class='notifications'></div>";
+    var notification_move = "<div id='notify_move' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search + notification_move);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var move_left = search_left + notify_width + notify_margin;
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var sides = ['left', 'right', 'up', 'down'];
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On les positionne.
+    $('#notify_search').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + search_left
+    });
+    $('#notify_move').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + move_left,
+        'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de recherche, de move vers un voisin & de dézoom dans une vidéo de recherche.
+ * Est appelé dans le fichier :
+ * neighbours > fonction selectNeighbour.
 */
-mosaic.prototype.searchSearchAndMoveAndUnzoom = function(targetId)
+Mosaic.prototype.searchSearchAndMoveAndUnzoom = function(targetId)
 {
-	if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
-	{
-		return;
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	var notification_move = "<div id='notify_move' class='notifications'></div>";
-	var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search + notification_move + notification_unzoom);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_left = $(window).width() / 2 - (notify_width * 3 + notify_margin * 4) / 2;
-	var move_left = search_left + notify_width + notify_margin;
-	var unzoom_left = move_left + notify_width + notify_margin;
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var sides = ['left', 'right', 'up', 'down'];
-	var unzooms = ['horizontal', 'vertical'];
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_search').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + search_left
-	});
-	$('#notify_move').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + move_left,
-		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
-	});
-	$('#notify_unzoom').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + unzoom_left,
-		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est effectuée, on part.
+    if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
+    {
+        return;
+    }
+    
+    //On spécifie les notifications en div.
+    var notification_search = "<div id='notify_search' class='notifications'></div>";
+    var notification_move = "<div id='notify_move' class='notifications'></div>";
+    var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search + notification_move + notification_unzoom);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_left = $(window).width() / 2 - (notify_width * 3 + notify_margin * 4) / 2;
+    var move_left = search_left + notify_width + notify_margin;
+    var unzoom_left = move_left + notify_width + notify_margin;
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var sides = ['left', 'right', 'up', 'down'];
+    var unzooms = ['horizontal', 'vertical'];
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On les positionne.
+    $('#notify_search').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + search_left
+    });
+    $('#notify_move').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + move_left,
+        'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+    });
+    $('#notify_unzoom').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + unzoom_left,
+        'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de recherche & de dézoom dans une vidéo de recherche.
+ * Est appelé dans le fichier :
 */
-mosaic.prototype.searchSearchAndUnzoom = function()
+Mosaic.prototype.searchSearchAndUnzoom = function()
 {
-	if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search + notification_unzoom);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var unzoom_left = search_left + notify_width + notify_margin;
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	// console.log(this.neighboursIds, parseInt(targetId), side);
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var unzooms = ['horizontal', 'vertical'];
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_move').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + search_left
-	});
-	
-	$('#notify_unzoom').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + unzoom_left,
-		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est effectuée, on part.
+    if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_search = "<div id='notify_search' class='notifications'></div>";
+    var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search + notification_unzoom);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var unzoom_left = search_left + notify_width + notify_margin;
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var unzooms = ['horizontal', 'vertical'];
+    
+    var notifyTop = 0, notifyLeft = 0;
+    
+    //On les positionne.
+    $('#notify_move').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + search_left
+    });
+    
+    $('#notify_unzoom').css(
+    {
+        top: -notifyTop,
+        left: -notifyLeft + unzoom_left,
+        'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat dans une vidéo de recherche.
+ * Est appelé dans les fichiers :
+ * neighbours > fonctions deselectNeighbour et moveToNeighbour.
+ * playerControl > fonction exitTimeline.
+ * zoomInteractions > fonction zoom.
+ * mosaic > fonctions onMouseUp et manageControlEvents.
+ * curvesDetector > fonction updateDists.
 */
-mosaic.prototype.searchGesture = function(gestureName, mode)
+Mosaic.prototype.searchGesture = function(gestureName, mode)
 {
-	console.log('NOTIFY GESTURE ' + this.currentMode + ' ' + this.centerId + ' ' + this.currentSearchGesture[this.centerId]);
-	if(this.currentMode != 'SEARCH' || this.currentSearchGesture[this.centerId] == '')
-	{
-		return;
-	}
-	console.log('NOTIFY GESTURE');
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search_1gesture);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	// console.log('SHOW GESTURE NOTIFICATION 1');
-	if(_.include(this.gestures, gestureName))
-	{
-		// console.log('SHOW GESTURE NOTIFICATION 2');
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
-	}
-	else if(mode == 'none')
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
-	}
-	
-	//On les positionne.
-	$('#notify_search_1gesture').css(
-	{
-		top: 0,
-		left: ($(window).width() - notify_width) / 2
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est reconnue, on part.
+    if(this.currentMode != 'SEARCH' || this.currentSearchGesture[this.centerId] == '')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search_1gesture);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
+    
+    if(_.include(this.gestures, gestureName))
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.config.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
+    }
+    else if(mode == 'none')
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
+    }
+    
+    //On les positionne.
+    $('#notify_search_1gesture').css(
+    {
+        top: 0,
+        left: ($(window).width() - notify_width) / 2
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat & de swipe dans une vidéo de recherche.
+ * Est appelé dans le fichier :
+ * mosaic > fonction manageControlEvents.
 */
-mosaic.prototype.searchGestureAndSwipe = function(gestureName, mode, direction)
+Mosaic.prototype.searchGestureAndSwipe = function(gestureName, mode, direction)
 {
-	if(this.currentMode != 'SEARCH' || !this.isCurrentlyInASearchByGesture || !this.isSwipe)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
-	var notification_swipe = "<div id='notify_swipe' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search_1gesture + notification_swipe);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var swipe_left = search_1gesture_left + notify_width + notify_margin;
-	
-	if(_.include(this.gestures, gestureName))
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
-	}
-	else if(mode == 'none')
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
-	}
-	
-	//On les positionne.
-	$('#notify_search_1gesture').css(
-	{
-		left: search_1gesture_left
-	});
-	$('#notify_swipe').css(
-	{
-		left: swipe_left,
-		'background-image': 'url(./pictos/notifications/swipe_' + direction + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est reconnue ou on ne fait pas de swipe, on part.
+    if(this.currentMode != 'SEARCH' || this.currentSearchGesture[this.centerId] == '' || !this.isSwipe)
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
+    var notification_swipe = "<div id='notify_swipe' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search_1gesture + notification_swipe);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var swipe_left = search_1gesture_left + notify_width + notify_margin;
+    
+    if(_.include(this.gestures, gestureName))
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.config.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
+    }
+    else if(mode == 'none')
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
+    }
+    
+    //On les positionne.
+    $('#notify_search_1gesture').css(
+    {
+        left: search_1gesture_left
+    });
+    $('#notify_swipe').css(
+    {
+        left: swipe_left,
+        'background-image': 'url(./pictos/notifications/swipe_' + direction + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat, de move vers un voisin.
+ * Est appelé dans le fichier :
+ * neighbours > fonction selectNeighbour.
 */
-mosaic.prototype.searchGestureAndMove = function(gestureName, mode, targetId)
+Mosaic.prototype.searchGestureAndMove = function(gestureName, mode, targetId)
 {
-	if(this.currentMode != 'SEARCH' || !this.isCurrentlyInASearchByGesture)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
-	var notification_move = "<div id='notify_move' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search_1gesture + notification_move);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var move_left = search_1gesture_left + notify_width + notify_margin;
-	
-	if(_.include(this.gestures, gestureName))
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
-	}
-	else if(mode == 'none')
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
-	}
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var sides = ['left', 'right', 'up', 'down'];
-	
-	//On les positionne.
-	$('#notify_search_1gesture').css(
-	{
-		left: search_1gesture_left
-	});
-	$('#notify_move').css(
-	{
-		left: move_left,
-		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est reconnue, on part.
+    if(this.currentMode != 'SEARCH' || this.currentSearchGesture[this.centerId] == '')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
+    var notification_move = "<div id='notify_move' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search_1gesture + notification_move);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var move_left = search_1gesture_left + notify_width + notify_margin;
+    
+    if(_.include(this.gestures, gestureName))
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.config.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
+    }
+    else if(mode == 'none')
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
+    }
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var sides = ['left', 'right', 'up', 'down'];
+    
+    //On les positionne.
+    $('#notify_search_1gesture').css(
+    {
+        left: search_1gesture_left
+    });
+    $('#notify_move').css(
+    {
+        left: move_left,
+        'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat, de move vers un voisin & de dézoom dans une vidéo de recherche.
+ * Est appelé dans le fichier :
+ * neighbours > fonction selectNeighbour.
 */
-mosaic.prototype.searchGestureAndMoveAndUnzoom = function(gestureName, mode, targetId)
+Mosaic.prototype.searchGestureAndMoveAndUnzoom = function(gestureName, mode, targetId)
 {
-	if(this.currentMode != 'SEARCH' || !this.isCurrentlyInASearchByGesture)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
-	var notification_move = "<div id='notify_move' class='notifications'></div>";
-	var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search_1gesture + notification_move + notification_unzoom);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_1gesture_left = $(window).width() / 2 - (notify_width * 3 + notify_margin * 4) / 2;
-	var move_left = search_1gesture_left + notify_width + notify_margin;
-	var unzoom_left = move_left + notify_width + notify_margin;
-	
-	if(_.include(this.gestures, gestureName))
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
-	}
-	else if(mode == 'none')
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
-	}
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var sides = ['left', 'right', 'up', 'down'];
-	var unzooms = ['horizontal', 'vertical'];
-	
-	//On les positionne.
-	$('#notify_search_1gesture').css(
-	{
-		left: search_1gesture_left
-	});
-	$('#notify_move').css(
-	{
-		left: move_left,
-		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
-	});
-	$('#notify_unzoom').css(
-	{
-		left: unzoom_left,
-		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est reconnue, on part.
+    if(this.currentMode != 'SEARCH' || this.currentSearchGesture[this.centerId] == '')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
+    var notification_move = "<div id='notify_move' class='notifications'></div>";
+    var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search_1gesture + notification_move + notification_unzoom);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_1gesture_left = $(window).width() / 2 - (notify_width * 3 + notify_margin * 4) / 2;
+    var move_left = search_1gesture_left + notify_width + notify_margin;
+    var unzoom_left = move_left + notify_width + notify_margin;
+    
+    if(_.include(this.gestures, gestureName))
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.config.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
+    }
+    else if(mode == 'none')
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
+    }
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var sides = ['left', 'right', 'up', 'down'];
+    var unzooms = ['horizontal', 'vertical'];
+    
+    //On les positionne.
+    $('#notify_search_1gesture').css(
+    {
+        left: search_1gesture_left
+    });
+    $('#notify_move').css(
+    {
+        left: move_left,
+        'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+    });
+    $('#notify_unzoom').css(
+    {
+        left: unzoom_left,
+        'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage de la notification de résultat & de dézoom dans une vidéo de recherche.
+ * Est appelé dans le fichier :
 */
-mosaic.prototype.searchGestureAndUnzoom = function(gestureName, mode, targetId)
+Mosaic.prototype.searchGestureAndUnzoom = function(gestureName, mode, targetId)
 {
-	if(this.currentMode != 'SEARCH' || !this.isCurrentlyInASearchByGesture)
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
-	var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search_1gesture + notification_unzoom);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var unzoom_left = search_1gesture_left + notify_width + notify_margin;
-	
-	if(_.include(this.gestures, gestureName))
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
-	}
-	else if(mode == 'none')
-	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
-	}
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var unzooms = ['horizontal', 'vertical'];
-	
-	//On les positionne.
-	$('#notify_search_1gesture').css(
-	{
-		left: search_1gesture_left
-	});
-	$('#notify_unzoom').css(
-	{
-		left: unzoom_left,
-		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //Si on n'est pas en mode recherche dans une video ou qu'aucune recherche n'est reconnue, on part.
+    if(this.currentMode != 'SEARCH' || this.currentSearchGesture[this.centerId] == '')
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On spécifie les notifications en div.
+    var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
+    var notification_unzoom = "<div id='notify_unzoom' class='notifications'></div>";
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notification_search_1gesture + notification_unzoom);
+    
+    //On calcule leurs coordonnées et dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+    var unzoom_left = search_1gesture_left + notify_width + notify_margin;
+    
+    if(_.include(this.gestures, gestureName))
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.config.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
+    }
+    else if(mode == 'none')
+    {
+        $('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
+    }
+    
+    var side = $.inArray(parseInt(targetId), this.neighboursIds);
+    
+    if(side == -1)
+    {
+        return;
+    }
+    
+    var unzooms = ['horizontal', 'vertical'];
+    
+    //On les positionne.
+    $('#notify_search_1gesture').css(
+    {
+        left: search_1gesture_left
+    });
+    $('#notify_unzoom').css(
+    {
+        left: unzoom_left,
+        'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
+    });
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
  * Affichage des notifications de gestures trouvées dans une recherche par courbes.
+ * Est appelé dans le fichier :
+ * curvesDetector > fonction updateDists.
 */
-mosaic.prototype.curvesGestures = function(gestures)
+Mosaic.prototype.curvesGestures = function(gestures)
 {
-	//S'il n'y a pas de gestures à afficher.
-	if(gestures.length == 0)
-	{
-		console.log('NONE');
-		//On ajoute une seule notification.
-		var notification_curves = "<div class='notifications' id='notify_curves'></div>";
-		$('body').append(notification_curves);
-		
-		//On calcule leurs dimensions et coordonnées.
-		var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-		var notify_margin = parseInt($('.notifications').css('margin'));
-		var curves_left = $(window).width() / 2 - (notify_width + notify_margin * 2) / 2;
-		
-		$('#notify_curves').css(
-		{
-			left: curves_left,
-			'background-image': 'url("./pictos/big/normal/inconnu.png")',
-			opacity: '0.9'
-		});
-		return;
-	}
-	
-	//Sinon, on les met dans un tableau.
-	var gestures_tab = gestures.split(';');
-	
-	var notifications_curves_gestures = '';
-	
-	//On crée autant de notifications qu'il y a de gestures.
-	for(var i = 0 ; i < gestures_tab.length ; i++)
-	{
-		notifications_curves_gestures += "<div class='notifications' id='notify_curves_" + gestures_tab[i] + "'></div>";
-	}
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notifications_curves_gestures);
-	
-	//On calcule leurs dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var curves_gestures_left = [];
-	
-	//On calcule leurs dimensions et leur backgrounds.
-	curves_gestures_left[0] = $(window).width() / 2 - (notify_width * (gestures_tab.length) + notify_margin * (gestures_tab.length + 2)) / 2;
-	
-	for(var i = 0 ; i < gestures_tab.length ; i++)
-	{
-		//On va chercher leurs backgrounds.
-		$('#notify_curves_' + gestures_tab[i]).css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + 'normal/' + gestures_tab[i] + '.png")');
-		// console.log('url("./pictos/big/MI/normal/' + gestures_tab[i] + '.png")');
-		
-		//On calcule leurs coordonnées.
-		if(i+1 < gestures_tab.length)
-		{
-			curves_gestures_left[i+1] = curves_gestures_left[i] + notify_width + notify_margin * 2;
-		}
-		
-		//On les place.
-		$('#notify_curves_' + gestures_tab[i]).css('left', curves_gestures_left[i]);
-	}
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
+    //S'il n'y a pas de gestures à afficher.
+    if(gestures.length == 0)
+    {
+        //On ajoute une seule notification.
+        var notification_curves = "<div class='notifications' id='notify_curves'></div>";
+        $('body').append(notification_curves);
+        
+        //On calcule leurs dimensions et coordonnées.
+        var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+        var notify_margin = parseInt($('.notifications').css('margin'));
+        var curves_left = $(window).width() / 2 - (notify_width + notify_margin * 2) / 2;
+        
+        $('#notify_curves').css(
+        {
+            left: curves_left,
+            'background-image': 'url("./pictos/big/normal/inconnu.png")',
+            opacity: '0.9'
+        });
+        return;
+    }
+    
+    //Sinon, on les met dans un tableau.
+    var gestures_tab = gestures.split(';');
+    
+    var notifications_curves_gestures = '';
+    
+    //On crée autant de notifications qu'il y a de gestures.
+    for(var i = 0 ; i < gestures_tab.length ; i++)
+    {
+        notifications_curves_gestures += "<div class='notifications' id='notify_curves_" + gestures_tab[i] + "'></div>";
+    }
+    
+    //On les ajoute à la mosaïque.
+    $('body').append(notifications_curves_gestures);
+    
+    //On calcule leurs dimensions.
+    var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+    var notify_margin = parseInt($('.notifications').css('margin'));
+    var curves_gestures_left = [];
+    
+    //On calcule leurs dimensions et leur backgrounds.
+    curves_gestures_left[0] = $(window).width() / 2 - (notify_width * (gestures_tab.length) + notify_margin * (gestures_tab.length + 2)) / 2;
+    
+    for(var i = 0 ; i < gestures_tab.length ; i++)
+    {
+        //On va chercher leurs backgrounds.
+        $('#notify_curves_' + gestures_tab[i]).css('background-image', 'url("./pictos/big/' + (this.config.mouseInteractions ? 'MI/' : '') + 'normal/' + gestures_tab[i] + '.png")');
+        
+        //On calcule leurs coordonnées.
+        if(i+1 < gestures_tab.length)
+        {
+            curves_gestures_left[i+1] = curves_gestures_left[i] + notify_width + notify_margin * 2;
+        }
+        
+        //On les place.
+        $('#notify_curves_' + gestures_tab[i]).css('left', curves_gestures_left[i]);
+    }
+    
+    //On les fait apparaître.
+    $('.notifications').css(
+    {
+        opacity: "0.9"
+    });
 }
 
 /*
- * Efface les notifications.
+ * Efface les notifications. Précède chaque notification.
+ * Est appelé dans les fichiers :
+ * neighbours > fonctions listenToNeighbours, selectNeighbour, deselectNeighbour et moveToNeighbour.
+ * notifications > fonction notifyHelp.
+ * playerControl > fonction exitTimeline.
+ * pointers > fonctions pointersTimelineSelection, launchIdlePointers et removeSearchNotificationIfOnIt.
+ * search > fonction removeFilter.
+ * zoomInteractions > fonctions preZoom, preUnzoom, zoom et unzoom.
+ * mosaic > fonctions onMouseUp, showNImages et manageControlEvents.
+ * curvesDetector > fonction updateDists.
 */
-mosaic.prototype.removeNotifications = function()
+Mosaic.prototype.removeNotifications = function()
 {
-	// console.trace();
-	$('.notifications').remove();
+    $('.notifications').remove();
 }
\ No newline at end of file
--- a/front_idill/src/mosaic/js/playerControl.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/mosaic/js/playerControl.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,134 +1,168 @@
-mosaic.prototype.playNextVideo = function()
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : playerControl.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les fonctions d'interaction avec le player dans la mosaique.
+ */
+
+/*
+ * Passe à une vidéo suivante pour la lire, peut passer d'une vidéo à une autre en cas de filtrage.
+ * Est appelé : dans le fichier mosaic > fonctions manageControlEvents et onPlayerLoad.
+*/
+Mosaic.prototype.playNextVideo = function()
 {
-	var videoId = this.centerId, nextId = (+videoId + 1);
-	
-	//Si on arrive à la fin de la mosaique on revient au début.
-	if(videoId >= this.config['imagesToShow'] - 1)
-	{
-		nextId = 0;
-	}
-	
-	//Si la mosaique est filtrée, on passe directement à la prochaine vidéo non filtrée.
-	if(this.isMosaicFiltered)
-	{
-		while(this.opacities[nextId] == 0 && nextId < this.config['imagesToShow'])
-		{
-			nextId++;
-		}
-		
-		if(nextId == this.config['imagesToShow'])
-		{
-			nextId = 0;
-			// return;
-		}
-	}
-	
-	console.log('movetonext');
-	this.autoMove = true;
-	console.log('dep : ' + this.centerId + ' next : ' + nextId);
-	this.moveToNeighbour($('#snapshotDiv-' + nextId));
+    //Définit l'id du snapshot principal et le suivant à lire.
+    var videoId = this.centerId, nextId = (+videoId + 1);
+    
+    //Si on arrive à la fin de la mosaique on revient au début.
+    if(videoId >= this.config.imagesToShow - 1)
+    {
+        nextId = 0;
+    }
+    
+    //Si la mosaique est filtrée, on passe directement à la prochaine vidéo non filtrée.
+    if(this.isMosaicFiltered)
+    {
+        //Tant que la vidéo est masquée par un filtre de recherche, on passe à la vidéo suivante.
+        while(this.opacities[nextId] == 0 && nextId < this.config.imagesToShow)
+        {
+            nextId++;
+        }
+        
+        //Si on arrive à la fin on revient au début.
+        if(nextId == this.config.imagesToShow)
+        {
+            nextId = 0;
+        }
+    }
+    
+    //On se déplace vers la prochaine vidéo à lire.
+    this.autoMove = true;
+    this.moveToNeighbour($('#snapshotDiv-' + nextId));
 }
 
-mosaic.prototype.isTLSelected = function(entering, mainPointer)
+/*
+ * Indique si la timeline est sélectionnée.
+ * Est appelé : dans le fichier pointers > fonctions mainPointerDisplay et pointersTimelineSelection.
+*/
+Mosaic.prototype.isTLSelected = function(entering, mainPointer)
 {
-	//Si les deux pointeurs ne sont pas là ou qu'on n'est pas en lecture d'une vidéo.
-	if(this.isMainPointerDisplayed && this.isSecondPointerDisplayed || this.currentMode != 'VIDEO' && this.currentMode != 'SEARCH' && this.currentMode != 'TIMELINE' || !this.playerIsReady)
-	{
-		// $('.a').remove();
-		return false;
-	}
-	
-	var pointer;
-	var Px, Py;
-	
-	if(this.mouseInteractions)
-	{
-		Px = this.mousePosX;
-		Py = this.mousePosY;
-	}
-	else
-	{
-		pointer = (mainPointer ? $('#mainPointer') : $('#secondPointer'));
-		Px = pointer.position().left + pointer.width() / 2;
-		Py = pointer.position().top + pointer.height() / 2;
-	}
-	
-	var TL = $('.Ldt-Timeline');
-	var TLwidth = TL.width(), TLheight = TL.height();
-	var TLtop = (+$('.LdtPlayer').position().top + $('.LdtPlayer').height() - TLheight), TLleft = $('.LdtPlayer').position().left;
-	
-	var correctHorizontalPosition = (entering ? (Px > TLleft && Px < (+TLleft + TLwidth)) : (true));
-	
-	//Seulement avec une main.
-	// if(this.isMainPointerDisplayed && !this.isSecondPointerDisplayed && correctHorizontalPosition && Py > (TLtop - TLheight / 2) && Py < (+TLtop + TLheight))
-	
-	if(correctHorizontalPosition && Py > (TLtop - TLheight / 2) && Py < (+TLtop + TLheight))
-	{
-		// if($('.a').length < 1)
-			// $('body').append('<div class="a" style="position: absolute; background-color: #fff; top: ' + (TLtop - TLheight / 2) + 'px; left: ' + TLleft + 'px; height: ' + (TLheight * 3 / 2) +'px; width: ' + TLwidth + 'px"></div>');
-		return true;
-	}
-	
-	// $(".a").remove();
-	return false;
+    //Si les deux pointeurs ne sont pas là ou qu'on n'est pas en lecture d'une vidéo.
+    if(this.isMainPointerDisplayed && this.isSecondPointerDisplayed || this.currentMode != 'VIDEO' && this.currentMode != 'SEARCH' && this.currentMode != 'TIMELINE' || !this.playerIsReady)
+    {
+        return false;
+    }
+    
+    var pointer;
+    var Px, Py;
+    
+    //Si on est en mode d'interaction souris.
+    if(this.config.mouseInteractions)
+    {
+        //On met à jour la position estimée de la souris.
+        Px = this.mousePosX;
+        Py = this.mousePosY;
+    }
+    else
+    {
+        //Sinon on se fie à la position des pointeurs.
+        pointer = (mainPointer ? $('#mainPointer') : $('#secondPointer'));
+        Px = pointer.position().left + pointer.width() / 2;
+        Py = pointer.position().top + pointer.height() / 2;
+    }
+    
+    //Si le pointeur se situe sur la timeline, on renvoie vrai, sinon faux.
+    var TL = $('.Ldt-Timeline');
+    var TLwidth = TL.width(), TLheight = TL.height();
+    var TLtop = (+$('.LdtPlayer').position().top + $('.LdtPlayer').height() - TLheight), TLleft = $('.LdtPlayer').position().left;
+    
+    var correctHorizontalPosition = (entering ? (Px > TLleft && Px < (+TLleft + TLwidth)) : (true));
+    
+    if(correctHorizontalPosition && Py > (TLtop - TLheight / 2) && Py < (+TLtop + TLheight))
+    {
+        return true;
+    }
+    
+    return false;
 }
 
-mosaic.prototype.exitTimeline = function(typeOfInteraction)
+/*
+ * Sert à déselectionner la timeline.
+ * Est appelé : dans les fichiers neighbours > fonction moveToNeighbour, pointers > fonctions mainPointerDisplay, secondPointerDisplay et pointersTimelineSelection et zoomInteractions > fonction unzoom.
+*/
+Mosaic.prototype.exitTimeline = function(typeOfInteraction)
 {
-	if(this.currentMode == 'TIMELINE' && this.playerIsReady)
-	{
-		console.log('(5) QUIT');
-		// console.trace();
-		this.removeNotifications();
-		
-		this.isTLRequested = false;
-		this.canSlideInTL = false;
-		this.player.widgets[0].deselectTimeline();
-		
-		if($('#spinner').length > 0)
-		{
-			$('#spinner').remove();
-		}
-		
-		if(this.isTLSelectedByMainPointer)
-		{
-			$('#mainPointer').css('background-image', 'url(./img/cursors/pointer.png)');
-		}
-		if(this.isTLSelectedBySecondPointer)
-		{
-			$('#secondPointer').css('background-image', 'url(./img/cursors/pointer2.png)');
-		}
-		
-		this.isTLSelectedByMainPointer = false;
-		this.isTLSelectedBySecondPointer = false;
-		
-		if(typeOfInteraction == 'unzoom')
-		{
-			if(this.isMosaicFiltered)
-			{
-				this.currentMode = 'FILTER';
-			}
-			else
-			{
-				this.currentMode = 'MOSAIC';
-			}
-		}
-		else if(typeOfInteraction == 'move')
-		{
-			this.currentMode = 'VIDEO';
-		}
-		else
-		{
-			if(this.isCurrentlyInASearchByGesture)
-			{
-				this.currentMode = 'SEARCH';
-				
-				this.searchGesture(this.currentSearchGesture[this.centerId], 'valid');
-			}
-			else
-			{
-				this.currentMode = 'VIDEO';
-			}
-		}
-	}
+    //Si on est en mode timeline et que le player est prêt.
+    if(this.currentMode == 'TIMELINE' && this.playerIsReady)
+    {
+        //On enlève les notifications.
+        this.removeNotifications();
+        
+        //On remet à zéro les variables concernées.
+        this.isTLRequested = false;
+        this.canSlideInTL = false;
+        //On déselectionne la timeline au niveau du player.
+        this.player.widgets[0].deselectTimeline();
+        
+        if($('#spinner').length > 0)
+        {
+            $('#spinner').remove();
+        }
+        
+        //On remet l'apparence des pointeurs.
+        if(this.isTLSelectedByMainPointer)
+        {
+            $('#mainPointer').css('background-image', 'url(./img/cursors/pointer.png)');
+        }
+        if(this.isTLSelectedBySecondPointer)
+        {
+            $('#secondPointer').css('background-image', 'url(./img/cursors/pointer2.png)');
+        }
+        
+        this.isTLSelectedByMainPointer = false;
+        this.isTLSelectedBySecondPointer = false;
+        
+        //On revient dans le mode précédent, en fonction de l'action effectuée pour quitter la timeline.
+        //Si l'action était juste de mettre le pointeur hors de la timeline, on revient en mode video/search en fonction de l'existence d'une gesture de recherche.
+        if(typeOfInteraction == 'unzoom')
+        {
+            if(this.isMosaicFiltered)
+            {
+                this.currentMode = 'FILTER';
+            }
+            else
+            {
+                this.currentMode = 'MOSAIC';
+            }
+        }
+        else if(typeOfInteraction == 'move')
+        {
+            this.currentMode = 'VIDEO';
+        }
+        else
+        {
+            if(this.isCurrentlyInASearchByGesture)
+            {
+                this.currentMode = 'SEARCH';
+                
+                this.searchGesture(this.currentSearchGesture[this.centerId], 'valid');
+            }
+            else
+            {
+                this.currentMode = 'VIDEO';
+            }
+        }
+    }
 }
\ No newline at end of file
--- a/front_idill/src/mosaic/js/pointers.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/mosaic/js/pointers.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,1059 +1,915 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : pointers.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les fonctions d'interaction avec les pointeurs.
+ */
+
 /*
  * Affiche les pointeurs.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadMosaic.
 */
-mosaic.prototype.addPointers = function()
+Mosaic.prototype.addPointers = function()
 {
-	if(this.mouseInteractions)
-	{
-		return;
-	}
-	
-	var mainPointer = '<div id="mainPointer" class="pointers"></div>';
-	var secondPointer = '<div id="secondPointer" class="pointers"></div>';
-	$('body').append(mainPointer + secondPointer);
-	
-	$('#secondPointer').css(
-	{
-		top: $(window).height() / 2 - $('#secondPointer').height() / 2,
-		left: $(window).width() / 4 - $('#secondPointer').width() / 2
-	});
-	
-	this.secondPointerLastX = $(window).width() / 4 - $('#secondPointer').width() / 2;
-	this.secondPointerLastY = $(window).height() / 2 - $('#secondPointer').height() / 2;
-	
-	$('#mainPointer').css(
-	{
-		top: $(window).height() / 2 - $('#mainPointer').height() / 2,
-		left: $(window).width() * 3 / 4 - $('#mainPointer').width() / 2
-	});
+    //On n'affiche pas les pointeurs en mode d'interaction souris.
+    if(this.config.mouseInteractions)
+    {
+        return;
+    }
+    
+    //On crée et ajoute les pointeurs.
+    var mainPointer = '<div id="mainPointer" class="pointers"></div>';
+    var secondPointer = '<div id="secondPointer" class="pointers"></div>';
+    $('body').append(mainPointer + secondPointer);
+    
+    //On les place au centre de l'écran.
+    $('#secondPointer').css(
+    {
+        top: $(window).height() / 2 - $('#secondPointer').height() / 2,
+        left: $(window).width() / 4 - $('#secondPointer').width() / 2
+    });
+    
+    this.secondPointerLastX = $(window).width() / 4 - $('#secondPointer').width() / 2;
+    this.secondPointerLastY = $(window).height() / 2 - $('#secondPointer').height() / 2;
+    
+    $('#mainPointer').css(
+    {
+        top: $(window).height() / 2 - $('#mainPointer').height() / 2,
+        left: $(window).width() * 3 / 4 - $('#mainPointer').width() / 2
+    });
 
-	this.mainPointerLastX = $(window).width() * 3 / 4 - $('#mainPointer').width() / 2;
-	this.mainPointerLastY = $(window).height() / 2 - $('#mainPointer').height() / 2;
-	
-	this.mainPointerIdleStartX = this.mainPointerLastX;
-	this.mainPointerIdleStartY = this.mainPointerLastY;
-	this.secondPointerIdleStartX = this.secondPointerLastX;
-	this.secondPointerIdleStartY = this.secondPointerLastY;
+    this.mainPointerLastX = $(window).width() * 3 / 4 - $('#mainPointer').width() / 2;
+    this.mainPointerLastY = $(window).height() / 2 - $('#mainPointer').height() / 2;
+    
+    //On met à jour les anciennes coordonnées des pointeurs.
+    this.mainPointerIdleStartX = this.mainPointerLastX;
+    this.mainPointerIdleStartY = this.mainPointerLastY;
+    this.secondPointerIdleStartX = this.secondPointerLastX;
+    this.secondPointerIdleStartY = this.secondPointerLastY;
 }
 
 /*
  * Affiche/Masque le pointeur principal.
  * Main est un booléen valant vrai s'il faut afficher le pointeur.
+ * Est appelé dans le fichier :
+ * client > fonction processMsg.
 */
-mosaic.prototype.mainPointerDisplay = function(main)
+Mosaic.prototype.mainPointerDisplay = function(main)
 {
-	var _this = this;
-	
-	//On n'affiche pas les pointeurs dans le mode sans utilisateur ni utilisateur en phase d'approche.
-	if(this.currentMode != 'NO-USER' && this.currentMode.indexOf('INCOMING-') == -1)
-	{
-		if(main)
-		{
-			clearTimeout(this.arrowSpinnerTimeout);
-			
-			$('#mainPointer').fadeTo(this.config['timeFilling'], '1');
-			
-			//Si on a un seul pointeur, on affiche la mire.
-			if(!this.areBothPointersHere)
-			{
-				// console.log('ONE');
-				/*$('#mainPointer').css(
-				{
-					'background-image': 'url(./img/cursors/selector_gray.png)',
-					width: 85,
-					height: 85
-				});*/
-			}
-		}
-	}
-	
-	//Si le booléen est à faux, on masque le pointeur.
-	if(!main)
-	{
-		$('#spinner').remove();
-		
-		$('#mainPointer').fadeTo(this.config['timeFilling'], '0');
-		if(this.mainPointerNeighbourSelectedId != null)
-		{
-			// this.deselectNeighbour(this.mainPointerNeighbourSelectedId);
-		}
-		
-		//Si on a zoomé sur une vidéo.
-		if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH')
-		{
-			//On annule aussi la TL s'il y a lieu.
-			if(this.isTLSelected())
-			{
-				this.isTLRequested = false;
-				clearTimeout(this.selectTLTimeout);
-			}
-		}
-		
-		if(this.isTLSelectedByMainPointer)
-		{
-			//On déselectionne la TL.
-			this.exitTimeline('');
-		}
-	}
+    var _this = this;
+    
+    //On n'affiche pas les pointeurs dans le mode sans utilisateur ni utilisateur en phase d'approche.
+    if(this.currentMode != 'NO-USER' && this.currentMode.indexOf('INCOMING-') == -1)
+    {
+        if(main)
+        {
+            clearTimeout(this.arrowSpinnerTimeout);
+            
+            $('#mainPointer').fadeTo(this.config.timeFilling, '1');
+        }
+    }
+    
+    //Si le booléen est à faux, on masque le pointeur.
+    if(!main)
+    {
+        $('#spinner').remove();
+        
+        $('#mainPointer').fadeTo(this.config.timeFilling, '0');
+        
+        //Si on a zoomé sur une vidéo.
+        if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH')
+        {
+            //On annule aussi la TL s'il y a lieu.
+            if(this.isTLSelected())
+            {
+                this.isTLRequested = false;
+                clearTimeout(this.selectTLTimeout);
+            }
+        }
+        
+        if(this.isTLSelectedByMainPointer)
+        {
+            //On déselectionne la TL.
+            this.exitTimeline('');
+        }
+    }
 }
 /*
  * Affiche/Masque le pointeur secondaire.
  * Main est un booléen valant vrai s'il faut afficher le pointeur.
+ * Est appelé dans le fichier :
+ * client > fonction processMsg.
 */
-mosaic.prototype.secondPointerDisplay = function(second)
+Mosaic.prototype.secondPointerDisplay = function(second)
 {
-	//On n'affiche pas les pointeurs dans le mode sans utilisateur ni utilisateur en phase d'approche.
-	if(this.currentMode != 'NO-USER' && this.currentMode.indexOf('INCOMING-') == -1)
+    //On n'affiche pas les pointeurs dans le mode sans utilisateur ni utilisateur en phase d'approche.
+    if(this.currentMode != 'NO-USER' && this.currentMode.indexOf('INCOMING-') == -1)
+    {
+        if(second)
+        {
+            clearTimeout(this.arrowSpinnerTimeout);
+            
+            $('#secondPointer').fadeTo(this.config.timeFilling, '1');
+        }
+    }
+    
+    //Si le booléen est à faux, on masque le pointeur.
+    if(!second)
+    {
+        $('#spinner').remove();
+        
+        $('#secondPointer').fadeTo(this.config.timeFilling, '0');
+        
+        if(this.isTLSelectedBySecondPointer)
+        {
+            //On déselectionne la TL.
+            this.exitTimeline('');
+        }
+    }
+}
+
+/*
+ * Assure les interactions des pointeurs avec la mosaique.
+ * Est appelé dans le fichier :
+ * pointers > fonction refreshPointers.
+*/
+Mosaic.prototype.pointersMosaicInteractions = function(pointerX, pointerY, isMainPointer)
+{
+	var snapshot = null, isOtherPointerDisplayed, pointer, pointerImg;
+	
+	if(isMainPointer)
 	{
-		if(second)
-		{
-			clearTimeout(this.arrowSpinnerTimeout);
-			
-			$('#secondPointer').fadeTo(this.config['timeFilling'], '1');
-			
-			//Si on a un seul pointeur, on affiche la mire.
-			if(!this.areBothPointersHere)
-			{
-				// console.log('ONE');
-				/*$('#secondPointer').css(
-				{
-					'background-image': 'url(./img/cursors/selector_gray.png)',
-					width: 85,
-					height: 85
-				});*/
-			}
-		}
+		isOtherPointerDisplayed = this.isSecondPointerDisplayed;
+		pointer = $('#mainPointer');
+		pointerImg = 'url(./img/cursors/pointer.png)';
+	}
+	else
+	{
+		isOtherPointerDisplayed = this.isMainPointerDisplayed;
+		pointer = $('#secondPointer');
+		pointerImg = 'url(./img/cursors/pointer2.png)';
 	}
 	
-	//Si le booléen est à faux, on masque le pointeur.
-	if(!second)
+	//On regarde si on est sur un snapshot.
+	snapshot = this.pointerPositionToSN(pointerX, pointerY, true);
+	
+	//Si c'est le cas, on récupère son id.
+	if(this.previousZoomedSN != null)
 	{
-		$('#spinner').remove();
+		var id = this.previousZoomedSN.attr('id').replace('snapshotDiv-', '');
+	}
+	
+	//Sinon, on effectue un preunzoom et on redonne son apparence au pointeur principal.
+	if(snapshot == null)
+	{
+		this.isOnASnapshot = false;
+		this.lastNonNullSN = this.previousZoomedSN;
+		this.preUnzoom();
+		
+		var image
 		
-		$('#secondPointer').fadeTo(this.config['timeFilling'], '0');
-		if(this.secondPointerNeighbourSelectedId != null)
-		{
-			// this.deselectNeighbour(this.secondPointerNeighbourSelectedId);
-		}
+		pointer.css('background-image', pointerImg);
+	}
+	
+	//Si le pointeur secondaire n'est pas affiché et qu'on est sur un snapshot ou que le dernier snapshot sur lequel on est allé n'est pas nul et que les deux pointeurs ne sont pas là en même temps.
+	if(!isOtherPointerDisplayed && snapshot != null && (this.previousZoomedSN != null && snapshot.attr('id') !== this.previousZoomedSN.attr('id') || this.lastNonNullSN != null && snapshot.attr('id') === this.lastNonNullSN.attr('id')) && !this.areBothPointersHere)
+	{
+		//On prézoom sur le snapshot sélectionné et on change l'apparence du pointeur.
+		this.isOnASnapshot = true;
+		this.previousZoomedSN = snapshot;
+		this.lastNonNullSN = null;
+		this.preZoom(snapshot);
 		
-		if(this.isTLSelectedBySecondPointer)
-		{
-			//On déselectionne la TL.
-			this.exitTimeline('');
-		}
+		pointer.css('background-image', 'url(./img/cursors/selector_gray.png)');
+	}
+	
+	//Si on se trouve actuellement dans une recherche par gestures.
+	if(this.isMosaicFiltered && !this.isMosaicFiltering)
+	{
+		//On vérifie si on se trouve sur une notification.
+		this.checkIfPointerIsOnSearchNotification(pointerX, pointerY, pointer);
 	}
 }
 
 /*
- * Raffraîchit la position des pointeurs.
+ * Assure les interactions des pointeurs avec la mosaique.
+ * Est appelé dans le fichier :
+ * pointers > fonction refreshPointers.
 */
-mosaic.prototype.refreshMainPointer = function(x, y)
+Mosaic.prototype.pointersVideoInteractions = function(pointerX, pointerY, isMainPointer)
 {
-	// console.log('                                    DEBUG MP');
-	if(this.currentMode == "NO-USER" || this.currentMode.indexOf('INCOMING-') != -1)
-	{
-		return;
-	}
+	var _this = this, pointer, thisPointerNeighbourSelectedId, pointerImg, thisPointerExitBorder, otherPointerExitBorder;
 	
-	if(!this.mouseInteractions)
-	{
-		x *= 7;
-		y *= 7;
-		x -= $(window).width() * 3 / 4;
-		y -= $(window).height() * 2 / 4;
-	}
-	
-	//Si le pointeur quitte la fenêtre en X, on ne le change pas.
-	// console.log('x : ' + x + ' mplx : ' + this.mainPointerLastX);
-	if(x < 0 || x > $(window).width())
+	if(isMainPointer)
 	{
-		x = this.mainPointerLastX;
-	}
-	//Sinon, on le met à jour.
-	else
-	{
-		this.mainPointerLastX = x;
-	}
-	
-	//Si le pointeur quitte la fenêtre en Y, on ne le change pas.
-	if(y < 0 || y > $(window).height())
-	{
-		y = this.mainPointerLastY;
-	}
-	//Sinon, on le met à jour.
-	else
-	{
-		this.mainPointerLastY = y;
-	}
-	
-	var pointerX, pointerY;
-
-	if(this.mouseInteractions)
-	{
-		pointerX = x;
-		pointerY = y;
+		pointer = $('#mainPointer');
+		thisPointerNeighbourSelectedId = this.mainPointerNeighbourSelectedId;
+		pointerImg = 'url(./img/cursors/pointer.png)';
+		thisPointerExitBorder = this.mainPointerExitBorder;
+		otherPointerExitBorder = this.secondPointerExitBorder;
 	}
 	else
 	{
-		pointerX = x - $('#mainPointer').width()/2;
-		pointerY = y - $('#mainPointer').height()/2;
+		pointer = $('#secondPointer');
+		thisPointerNeighbourSelectedId = this.secondPointerNeighbourSelectedId;
+		pointerImg = 'url(./img/cursors/pointer2.png)';
+		thisPointerExitBorder = this.secondPointerExitBorder;
+		otherPointerExitBorder = this.mainPointerExitBorder;
 	}
-	var _this = this;
 	
-	$('#mainPointer').css(
+	var zoomX = pointerX - this.notifyLeftVideo, zoomY = pointerY - this.notifyTopVideo;
+		
+	//On calcule les interactions du pointeur avec la timeline.
+	this.pointersTimelineSelection(pointerX, pointerY, isMainPointer);
+	
+	//Si on se trouve actuellement dans une recherche par gestures.
+	if(this.isCurrentlyInASearchByGesture)
 	{
-		top: pointerY,
-		left: pointerX
-	});
-	
-	if($('#spinner').length > 0)
-	{
-		$('#spinner').css(
-		{
-			top: pointerY,
-			left: pointerX
-		});
+		this.checkIfPointerIsOnSearchNotification(pointerX, pointerY, pointer);
 	}
 	
-	var snapshot = null;
-	
-	if(this.currentMode == 'MOSAIC' || this.currentMode == 'FILTER' && this.isMosaicFiltered)
+	//on vérifie si le pointeur est sur un snapshot zoomé.
+	snapshot = this.pointerPositionToSN(zoomX, zoomY, true);
+	if(snapshot == null)
 	{
-		snapshot = this.pointerPositionToSN(pointerX, pointerY, true);
-		
-		if(this.previousZoomedSN != null)
+		pointer.css('background-image', pointerImg);
+		snapshot = this.pointerPositionToAN(pointerX, pointerY);
+	}
+	
+	var intValueOfId;
+	//Si c'est le cas.
+	if(snapshot != null && snapshot.length > 0)
+	{
+		//S'il s'agit d'un voisin additionnel.
+		if(snapshot.attr('id').indexOf('borderNeighbour') != -1)
 		{
-			var id = this.previousZoomedSN.attr('id').replace('snapshotDiv-', '');
-		}
-		
-		if(snapshot == null)
-		{
-			this.isOnASnapshot = false;
-			this.lastNonNullSN = this.previousZoomedSN;
-			this.preUnzoom();
-			
-			$('#mainPointer').css('background-image', 'url(./img/cursors/pointer.png)');
+			intValueOfId = parseInt(snapshot.attr('id').replace('borderNeighbour-', ''));
 		}
-		
-		if(!this.isSecondPointerDisplayed && snapshot != null && (this.previousZoomedSN != null && snapshot.attr('id') !== this.previousZoomedSN.attr('id') || this.lastNonNullSN != null && snapshot.attr('id') === this.lastNonNullSN.attr('id')) && !this.areBothPointersHere)
+		//Sinon si c'est un voisin normal.
+		else
 		{
-			this.isOnASnapshot = true;
-			this.previousZoomedSN = snapshot;
-			this.lastNonNullSN = null;
-			this.preZoom(snapshot);
-			
-			$('#mainPointer').css('background-image', 'url(./img/cursors/selector_gray.png)');
-			// console.log(this.isMainPointerDisplayed + ' ' + this.isSecondPointerDisplayed);
-		}
-		
-		//Si on se trouve actuellement dans une recherche par gestures.
-		// /!\ // RAJOUTE EN ATTENDANT UN GESTE DE CANCEL.
-		if(this.isMosaicFiltered && !this.isMosaicFiltering)
-		{
-			//console.log('CHECK IF ON NOTIFY GESTURE');
-			this.checkIfPointerIsOnSearchNotification(pointerX, pointerY, $('#mainPointer'));
+			intValueOfId = parseInt(snapshot.attr('id').replace('snapshotDiv-', ''));
 		}
 	}
-	else if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH' || this.currentMode == 'TIMELINE')
+	else
 	{
-		//On vérifie si on veut sélectionner la TL.
-		if((this.currentMode != 'TIMELINE' || this.isTLRequested) && this.playerIsReady && !this.isTLSelectedBySecondPointer && !this.helpDisplayed)
+		intValueOfId = -2;
+	}
+	
+	//Si c'est un voisin additionnel.
+	if(snapshot != null && snapshot.attr('id').indexOf('borderNeighbour') != -1)
+	{
+		//S'il a été trouvé parmi les voisins du centre.
+		if(intValueOfId > -1 && intValueOfId < 5)
 		{
-			// console.log('(1) SP : ' + this.isTLSelectedBySecondPointer + ' MP : ' + this.isTLSelectedByMainPointer);
-			if(this.isTLSelected(true, true) && !this.isTLRequested)
+			//On le sélectionne.
+			this.selectNeighbour(snapshot, pointer);
+			if(isMainPointer)
 			{
-				// console.log('(2) TIMELINE REQUESTED ' + this.date());
-				// $('.a').css('background-color', '#f00');
-				//On a demandé à aller dans la TL.
-				this.isTLRequested = true;
-				this.isTLSelectedByMainPointer = true;
-				this.isTLSelectedBySecondPointer = false;
-				// console.log('(1) SP : ' + this.isTLSelectedBySecondPointer + ' MP : ' + this.isTLSelectedByMainPointer);
-				this.currentMode = 'TIMELINE';
-				this.player.widgets[0].selectTimeline();
-				$('#mainPointer').css('background-image', 'url(./img/cursors/selector_gray.png)');
-				
-				if(!this.mouseInteractions)
-				{
-					//On met le spinner gif sur le pointeur.
-					var spinner = "<img id='spinner'></div>";
-					$('body').append(spinner);
-					$('#spinner').css(
-					{
-						position: 'absolute',
-						top: $('#mainPointer').position().top,
-						left: $('#mainPointer').position().left,
-						width: 85,
-						height: 85,
-						'z-index': 600
-					});
-					$('#spinner').attr('src', './img/cursors/selector_anim.gif');
-				}
-				
-				this.selectTLTimeout = setTimeout(function()
-				{
-					//On permet l'interaction après un laps de temps.
-					_this.canSlideInTL = true;
-					
-					_this.removeNotifications();
-					_this.timelineTimeline();
-					
-					// console.log('(4) TIMELINE SLIDE ' + _this.date());
-				}, this.config['timeoutSlideTL']);
-			}
-			else if(!this.isTLSelected(true, true) && this.isTLRequested)
-			{
-				// console.log('(3) TIMELINE ABORTED');
-				this.isTLRequested = false;
-				clearTimeout(this.selectTLTimeout);
-				//On déselectionne la TL.
-				this.exitTimeline('');
-			}
-		}
-		
-		if(this.isTLSelectedByMainPointer && !this.isTLSelected(false, true))
-		{
-			// console.log('(4) TIMELINE EXITED');
-			// $('.a').css('background-color', '#0f0');
-			
-			//On déselectionne la TL.
-			this.exitTimeline('');
-		}
-
-		// var zoomX = pointerX, zoomY = pointerY;
-		var zoomX = pointerX - this.notifyLeftVideo, zoomY = pointerY - this.notifyTopVideo;
-		
-		//Si on a sélectionné la TL et qu'on a le pointeur droit dessus, on peut modifier la position de lecture.
-		if(this.currentMode == 'TIMELINE' && this.playerIsReady && !this.isSecondPointerDisplayed && this.canSlideInTL)
-		{
-			var time, TL = $('.Ldt-Timeline'), P = $('.LdtPlayer');
-			
-			if(pointerX < P.position().left)
-			{
-				time = 0;
-				// console.log('trop à droite');
-			}
-			else if(pointerX > (+P.position().left + TL.width()))
-			{
-				time = this.player.widgets[0].source.getDuration().getSeconds();
-				// console.log('trop à gauche');
-				// time = 0;
+				this.mainPointerExitBorder = true;
+				this.mainPointerNeighbourSelectedId = intValueOfId + this.config.imagesToShow;
 			}
 			else
 			{
-				time = this.player.widgets[0].scaleIntervals(P.position().left, (+P.position().left + TL.width()), 0, this.player.widgets[0].source.getDuration().getSeconds(), pointerX);
-				// console.log(time);
-			}
-			
-			this.player.popcorn.currentTime(time);
-		}
-		
-		
-		//Si on se trouve actuellement dans une recherche par gestures.
-		if(this.isCurrentlyInASearchByGesture)
-		{
-			this.checkIfPointerIsOnSearchNotification(pointerX, pointerY, $('#mainPointer'));
-		}
-		
-		//on vérifie si le pointeur est sur un snapshot zoomé.
-		snapshot = this.pointerPositionToSN(zoomX, zoomY, true);
-		if(snapshot == null)
-		{
-			$('#mainPointer').css('background-image', 'url(./img/cursors/pointer.png)');
-			snapshot = this.pointerPositionToAN(pointerX, pointerY);
-		}
-		
-		// console.log(snapshot);
-		
-		var intValueOfId;
-		//Si c'est le cas.
-		if(snapshot != null && snapshot.length > 0)
-		{
-			//S'il s'agit d'un voisin additionnel.
-			if(snapshot.attr('id').indexOf('borderNeighbour') != -1)
-			{
-				intValueOfId = parseInt(snapshot.attr('id').replace('borderNeighbour-', ''));
-			}
-			//Sinon si c'est un voisin normal.
-			else
-			{
-				intValueOfId = parseInt(snapshot.attr('id').replace('snapshotDiv-', ''));
+				this.secondPointerExitBorder = true;
+				this.secondPointerNeighbourSelectedId = intValueOfId + this.config.imagesToShow;
 			}
 		}
 		else
 		{
-			intValueOfId = -2;
-		}
-		
-		//Si c'est un voisin additionnel.
-		if(snapshot != null && snapshot.attr('id').indexOf('borderNeighbour') != -1)
-		{
-			//S'il a été trouvé.
-			if(intValueOfId > -1 && intValueOfId < 5)
+			//Sinon on le déselectionne.
+			if(thisPointerNeighbourSelectedId != null && thisPointerNeighbourSelectedId > -1)
 			{
-				//On le sélectionne.
-				this.selectNeighbour(snapshot, $('#mainPointer'));
-				this.mainPointerExitBorder = true;
-				this.mainPointerNeighbourSelectedId = intValueOfId + this.config['imagesToShow'];
-			}
-			else
-			{
-				if(this.mainPointerNeighbourSelectedId != null && this.mainPointerNeighbourSelectedId > -1)
-				{
-					this.deselectNeighbour(this.mainPointerNeighbourSelectedId);
-				}
+				this.deselectNeighbour(thisPointerNeighbourSelectedId);
 			}
 		}
-		else
+	}
+	else
+	{
+		//Si c'est un voisin.
+		if(_.include(this.neighboursIds, intValueOfId))
 		{
-			//Si c'est un voisin.
-			if(_.include(this.neighboursIds, intValueOfId))
+			//On le sélectionne.
+			this.selectNeighbour(snapshot, pointer);
+			clearTimeout(this.moveToNeighbourTimeout);
+			if(isMainPointer)
 			{
-				//On le sélectionne.
-				this.selectNeighbour(snapshot, $('#mainPointer'));
-				clearTimeout(this.moveToNeighbourTimeout);
 				clearTimeout(this.mainPointerExitBorderTimeout);
 				this.mainPointerExitBorder = true;
 				this.mainPointerNeighbourSelectedId = intValueOfId;
 			}
 			else
 			{
-				if(this.mainPointerNeighbourSelectedId != null && this.mainPointerNeighbourSelectedId > -1)
-				{
-					this.deselectNeighbour(this.mainPointerNeighbourSelectedId);
-					
-					if(this.mainPointerExitBorder && !this.secondPointerExitBorder)
-					{
-						this.correctMoveToNeighbour(this.mainPointerNeighbourSelectedId, zoomX, zoomY);
-					}
-					
-					this.moveToNeighbourTimeout = setTimeout(function()
-					{
-						_this.canMoveToNeighbour = false;
-					}, this.config['timeoutMoveToNeighbour']);
-					
-					this.mainPointerExitBorderTimeout = setTimeout(function()
-					{
-						if(_this.mainPointerExitBorder)
-						{
-							// console.log('Main pointer left');
-						}
-						_this.mainPointerExitBorder = false;
-					}, this.config['timeoutUnzoom']);
-					
-					this.checkForDezoom();
-				}
-			}
-		}
-	}
-}
-
-mosaic.prototype.refreshSecondPointer = function(x, y)
-{
-	if(this.currentMode == "NO-USER" || this.currentMode.indexOf('INCOMING-') != -1)
-	{
-		return;
-	}
-	
-	if(!this.mouseInteractions)
-	{
-		x *= 7;
-		y *= 7;
-		x -= $(window).width() * 3 / 4;
-		y -= $(window).height() * 2 / 4;
-	}
-	
-	//Si le pointeur quitte la fenêtre en X, on ne le change pas.
-	if(x < 0 || x > $(window).width())
-	{
-		x = this.secondPointerLastX;
-	}
-	//Sinon, on le met à jour.
-	else
-	{
-		this.secondPointerLastX = x;
-	}
-	
-	//Si le pointeur quitte la fenêtre en Y, on ne le change pas.
-	if(y < 0 || y > $(window).height())
-	{
-		y = this.secondPointerLastY;
-	}
-	//Sinon, on le met à jour.
-	else
-	{
-		this.secondPointerLastY = y;
-	}
-	
-	var pointerX = x - $('#secondPointer').width()/2, pointerY = y - $('#secondPointer').height()/2;
-	var _this = this;
-	
-	$('#secondPointer').css(
-	{
-		top: pointerY,
-		left: pointerX
-	});
-	
-	var snapshot = null;
-	
-	if(this.currentMode == 'MOSAIC' || this.currentMode == 'FILTER' && this.isMosaicFiltered)
-	{
-		snapshot = this.pointerPositionToSN(pointerX, pointerY, false);
-		
-		if(this.previousZoomedSN != null)
-		{
-			var id = this.previousZoomedSN.attr('id').replace('snapshotDiv-', '');
-		}
-		
-		if(snapshot == null)
-		{
-			this.isOnASnapshot = false;
-			this.lastNonNullSN = this.previousZoomedSN;
-			this.preUnzoom();
-			
-			$('#secondPointer').css('background-image', 'url(./img/cursors/pointer2.png)');
-		}
-		
-		if(!this.isMainPointerDisplayed && snapshot != null && (this.previousZoomedSN != null && snapshot.attr('id') !== this.previousZoomedSN.attr('id') || this.lastNonNullSN != null && snapshot.attr('id') === this.lastNonNullSN.attr('id')) && !this.areBothPointersHere)
-		{
-			this.isOnASnapshot = true;
-			this.previousZoomedSN = snapshot;
-			this.lastNonNullSN = null;
-			this.preZoom(snapshot);
-			
-			$('#secondPointer').css('background-image', 'url(./img/cursors/selector_gray.png)');
-			// console.log(this.isMainPointerDisplayed + ' ' + this.isSecondPointerDisplayed);
-		}
-		
-		//Si on se trouve actuellement dans une recherche par gestures.
-		// /!\ // RAJOUTE EN ATTENDANT UN GESTE DE CANCEL.
-		if(this.isMosaicFiltered && !this.isMosaicFiltering)
-		{
-			this.checkIfPointerIsOnSearchNotification(pointerX, pointerY, $('#secondPointer'));
-		}
-	}
-	else if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH' || this.currentMode == 'TIMELINE')
-	{
-		//On vérifie si on veut sélectionner la TL.
-		if((this.currentMode != 'TIMELINE' || this.isTLRequested) && this.playerIsReady && !this.isTLSelectedByMainPointer && !this.helpDisplayed)
-		{
-			// console.log('(1) SP : ' + this.isTLSelectedBySecondPointer + ' MP : ' + this.isTLSelectedByMainPointer);
-			if(this.isTLSelected(true, false) && !this.isTLRequested)
-			{
-				// console.log('(2) TIMELINE REQUESTED ' + this.date());
-				// $('.a').css('background-color', '#f00');
-				//On a demandé à aller dans la TL.
-				this.isTLRequested = true;
-				this.isTLSelectedBySecondPointer = true;
-				this.isTLSelectedByMainPointer = false;
-				// console.log('(1) SP : ' + this.isTLSelectedBySecondPointer + ' MP : ' + this.isTLSelectedByMainPointer);
-				this.currentMode = 'TIMELINE';
-				this.player.widgets[0].selectTimeline();
-				$('#secondPointer').css('background-image', 'url(./img/cursors/selector_gray.png)');
-				
-				if(!this.mouseInteractions)
-				{
-					//On met le spinner gif sur le pointeur.
-					var spinner = "<div id='spinner'></div>";
-					$('body').append(spinner);
-					$('#spinner').css(
-					{
-						position: 'absolute',
-						'background-repeat': 'no-repeat',
-						top: $('#mainPointer').position().top,
-						left: $('#mainPointer').position().left,
-						width: 85,
-						height: 85,
-						'z-index': 600
-					});
-					$('#spinner').attr('src', './img/cursors/selector_anim.gif');
-				}
-				
-				this.selectTLTimeout = setTimeout(function()
-				{
-					//On permet l'interaction après un laps de temps.
-					_this.canSlideInTL = true;
-					
-					_this.removeNotifications();
-					_this.timelineTimeline();
-					
-					// console.log('(4) TIMELINE SLIDE ' + _this.date());
-				}, this.config['timeoutSlideTL']);
-			}
-			else if(!this.isTLSelected(true, false) && this.isTLRequested)
-			{
-				// console.log('(3) TIMELINE ABORTED');
-				this.isTLRequested = false;
-				clearTimeout(this.selectTLTimeout);
-				//On déselectionne la TL.
-				this.exitTimeline('');
-			}
-		}
-		
-		if(this.isTLSelectedByMainPointer && !this.isTLSelected(false, false))
-		{
-			// console.log('(4) TIMELINE EXITED');
-			// $('.a').css('background-color', '#0f0');
-			
-			//On déselectionne la TL.
-			this.exitTimeline('');
-		}
-		
-		// var zoomX = pointerX, zoomY = pointerY;
-		var zoomX = pointerX - this.notifyLeftVideo, zoomY = pointerY - this.notifyTopVideo;
-		
-		//Si on a sélectionné la TL et qu'on a le pointeur droit dessus, on peut modifier la position de lecture.
-		if(this.currentMode == 'TIMELINE' && this.playerIsReady && !this.isMainPointerDisplayed && this.canSlideInTL)
-		{
-			var time, TL = $('.Ldt-Timeline'), P = $('.LdtPlayer');
-			
-			if(pointerX < P.position().left)
-			{
-				time = 0;
-				// console.log('trop à droite');
-			}
-			else if(pointerX > (+P.position().left + TL.width()))
-			{
-				time = this.player.widgets[0].source.getDuration().getSeconds();
-				// console.log('trop à gauche');
-				// time = 0;
-			}
-			else
-			{
-				time = this.player.widgets[0].scaleIntervals(P.position().left, (+P.position().left + TL.width()), 0, this.player.widgets[0].source.getDuration().getSeconds(), pointerX);
-				// console.log(time);
-			}
-			
-			this.player.popcorn.currentTime(time);
-		}
-		
-		//Si on se trouve actuellement dans une recherche par gestures.
-		if(this.isCurrentlyInASearchByGesture)
-		{
-			this.checkIfPointerIsOnSearchNotification(pointerX, pointerY, $('#secondPointer'));
-		}
-		
-		//on vérifie si le pointeur est sur un snapshot zoomé.
-		snapshot = this.pointerPositionToSN(zoomX, zoomY, false);
-		if(snapshot == null)
-		{
-			$('#secondPointer').css('background-image', 'url(./img/cursors/pointer2.png)');
-			snapshot = this.pointerPositionToAN(pointerX, pointerY);
-		}
-		
-		var intValueOfId;
-		//Si c'est le cas.
-		if(snapshot != null && snapshot.length > 0)
-		{
-			//S'il s'agit d'un voisin additionnel.
-			if(snapshot.attr('id').indexOf('borderNeighbour') != -1)
-			{
-				intValueOfId = parseInt(snapshot.attr('id').replace('borderNeighbour-', ''));
-			}
-			//Sinon si c'est un voisin normal.
-			else
-			{
-				intValueOfId = parseInt(snapshot.attr('id').replace('snapshotDiv-', ''));
+				clearTimeout(this.secondPointerExitBorderTimeout);
+				this.secondPointerExitBorder = true;
+				this.secondPointerNeighbourSelectedId = intValueOfId;
 			}
 		}
 		else
 		{
-			intValueOfId = -2;
-		}
-		
-		//Si c'est un voisin additionnel.
-		if(snapshot != null && snapshot.attr('id').indexOf('borderNeighbour') != -1)
-		{
-			//S'il a été trouvé.
-			if(intValueOfId > -1 && intValueOfId < 5)
+			//Sinon on déselectionne le snapshot.
+			if(thisPointerNeighbourSelectedId != null && thisPointerNeighbourSelectedId > -1)
 			{
-				//On le sélectionne.
-				this.selectNeighbour(snapshot, $('#secondPointer'));
-				this.secondPointerExitBorder = true;
-				this.secondPointerNeighbourSelectedId = intValueOfId + this.config['imagesToShow'];
-			}
-			else
-			{
-				if(this.secondPointerNeighbourSelectedId != null && this.secondPointerNeighbourSelectedId > -1)
+				this.deselectNeighbour(thisPointerNeighbourSelectedId);
+				
+				//Si le pointeur quitte le voisin sans que l'autre pointeur ne fasse de même ailleurs.
+				if(thisPointerExitBorder && !otherPointerExitBorder)
 				{
-					this.deselectNeighbour(this.secondPointerNeighbourSelectedId);
-					
-					/*this.secondPointerExitBorderTimeout = setTimeout(function()
-					{
-						if(_this.secondPointerExitBorder)
-						{
-							console.log('Second pointer left');
-						}
-						_this.secondPointerExitBorder = false;
-					}, this.config['timeoutUnzoom']);*/
-					
-					this.checkForDezoom();
+					//On va vers le voisin.
+					this.correctMoveToNeighbour(thisPointerNeighbourSelectedId, zoomX, zoomY);
 				}
-			}
-		}
-		else
-		{
-			//Si c'est un voisin.
-			if(_.include(this.neighboursIds, intValueOfId))
-			{
-				//On le sélectionne.
-				this.selectNeighbour(snapshot, $('#secondPointer'));
-				clearTimeout(this.moveToNeighbourTimeout);
-				clearTimeout(this.secondPointerExitBorderTimeout);
-				this.secondPointerExitBorder = true;
-				this.secondPointerNeighbourSelectedId = intValueOfId;
-			}
-			else
-			{
-				if(this.secondPointerNeighbourSelectedId != null && this.secondPointerNeighbourSelectedId > -1)
+				
+				//Il n'est possible de se déplacer vers un voisin que dans un certain laps de temps lorsqu'on quitte la sélection d'un voisin.
+				this.moveToNeighbourTimeout = setTimeout(function()
 				{
-					this.deselectNeighbour(this.secondPointerNeighbourSelectedId);
-					
-					if(!this.mainPointerExitBorder && this.secondPointerExitBorder)
+					_this.canMoveToNeighbour = false;
+				}, this.config.timeoutMoveToNeighbour);
+				
+				if(isMainPointer)
+				{
+					this.mainPointerExitBorderTimeout = setTimeout(function()
 					{
-						this.correctMoveToNeighbour(this.secondPointerNeighbourSelectedId, zoomX, zoomY);
-					}
-					
-					this.moveToNeighbourTimeout = setTimeout(function()
-					{
-						_this.canMoveToNeighbour = false;
-					}, this.config['timeoutMoveToNeighbour']);
-					
+						_this.mainPointerExitBorder = false;
+					}, this.config.timeoutUnzoom);
+				}
+				else
+				{
 					this.secondPointerExitBorderTimeout = setTimeout(function()
 					{
-						if(_this.secondPointerExitBorder)
-						{
-							// console.log('Second pointer left');
-						}
 						_this.secondPointerExitBorder = false;
-					}, this.config['timeoutUnzoom']);
-					
-					this.checkForDezoom();
+					}, this.config.timeoutUnzoom);
 				}
+				
+				//On regarde si on a voulu faire de dézoom.
+				this.checkForDezoom();
 			}
 		}
 	}
 }
 
-mosaic.prototype.detectIdlePointers = function()
+/*
+ * Assure les interactions des pointeurs avec la timeline.
+ * Est appelé dans le fichier :
+ * pointers > fonction pointersVideoInteractions.
+*/
+Mosaic.prototype.pointersTimelineSelection = function(pointerX, pointerY, isMainPointer)
 {
-	var mainPointer = $('#mainPointer');
-	var secondPointer = $('#secondPointer');
+	var _this = this, pointer, isTLSelectedByThisPointer, isTLSelectedByOtherPointer, isOtherPointerDisplayed;
 	
-	//Si la position des pointeurs au début de l'analyse d'idle change de plus ou moins leur taille par rapport à leur position actuelle.
-	if(Math.abs(this.mainPointerIdleStartX - this.mainPointerLastX) > mainPointer.width() || Math.abs(this.mainPointerIdleStartY - this.mainPointerLastY) > mainPointer.height() ||
-	Math.abs(this.secondPointerIdleStartX - this.secondPointerLastX) > secondPointer.width() || Math.abs(this.secondPointerIdleStartY - this.secondPointerLastY) > secondPointer.height())
+	if(isMainPointer)
 	{
-		//On réinitialise les dernières positions connues.
-		this.mainPointerIdleStartX = this.mainPointerLastX;
-		this.mainPointerIdleStartY = this.mainPointerLastY;
-		this.secondPointerIdleStartX = this.secondPointerLastX;
-		this.secondPointerIdleStartY = this.secondPointerLastY;
-		
-		this.removeIdlePointers();
-		this.pointersIdleNeedLaunch = true;
+		pointer = $('#mainPointer');
+		isTLSelectedByThisPointer = this.isTLSelectedByMainPointer;
+		isTLSelectedByOtherPointer = this.isTLSelectedBySecondPointer;
+		isOtherPointerDisplayed = this.isSecondPointerDisplayed;
+	}
+	else
+	{
+		pointer = $('#secondPointer');
+		isTLSelectedByThisPointer = this.isTLSelectedBySecondPointer;
+		isTLSelectedByOtherPointer = this.isTLSelectedByMainPointer;
+		isOtherPointerDisplayed = this.isMainPointerDisplayed;
 	}
 	
-	if(this.helpDisplayed)
+	//On vérifie si on veut sélectionner la TL.
+	if((this.currentMode != 'TIMELINE' || this.isTLRequested) && this.playerIsReady && !isTLSelectedByOtherPointer && !this.helpDisplayed)
 	{
-		this.removeHelp();
+		//Si la timeline est sélectionnée.
+		if(this.isTLSelected(true, true) && !this.isTLRequested)
+		{
+			//On a demandé à aller dans la TL.
+			this.isTLRequested = true;
+			if(isMainPointer)
+			{
+				this.isTLSelectedByMainPointer = true;
+				this.isTLSelectedBySecondPointer = false;
+			}
+			else
+			{
+				this.isTLSelectedBySecondPointer = true;
+				this.isTLSelectedByMainPointer = false;
+			}
+			this.currentMode = 'TIMELINE';
+			this.player.widgets[0].selectTimeline();
+			pointer.css('background-image', 'url(./img/cursors/selector_gray.png)');
+			
+			//Si on est en mode d'interaction Kinect.
+			if(!this.config.mouseInteractions)
+			{
+				//On met le spinner gif sur le pointeur.
+				var spinner = "<img id='spinner'></div>";
+				$('body').append(spinner);
+				$('#spinner').css(
+				{
+					position: 'absolute',
+					top: pointer.position().top,
+					left: pointer.position().left,
+					width: 85,
+					height: 85,
+					'z-index': 600
+				});
+				$('#spinner').attr('src', './img/cursors/selector_anim.gif');
+			}
+			
+			this.selectTLTimeout = setTimeout(function()
+			{
+				//On permet l'interaction après un laps de temps.
+				_this.canSlideInTL = true;
+				_this.removeNotifications();
+				_this.timelineTimeline();
+			}, this.config.timeoutSlideTL);
+		}
+		//Sinon si on était sur la timeline sans qu'elle soit sélectionnée encore et qu'on l'a quitté avant la sélection.
+		else if(!this.isTLSelected(true, true) && this.isTLRequested)
+		{
+			this.isTLRequested = false;
+			clearTimeout(this.selectTLTimeout);
+			//On déselectionne la TL.
+			this.exitTimeline('');
+		}
+	}
+	
+	//Si on a quitté la timeline après une sélection.
+	if(isTLSelectedByThisPointer && !this.isTLSelected(false, true))
+	{
+		//On déselectionne la TL.
+		this.exitTimeline('');
 	}
 	
-	if((this.currentMode == 'SEARCH' || this.currentMode == 'FILTER') && !this.isSearchByCurvesOn)
+	//Si on a sélectionné la TL et qu'on a le pointeur droit dessus, on peut modifier la position de lecture.
+	if(this.currentMode == 'TIMELINE' && this.playerIsReady && !isOtherPointerDisplayed && this.canSlideInTL)
 	{
-		// this.isSearchByCurvesOn = true;
-		// this.startSearch();
+		var time, TL = $('.Ldt-Timeline'), P = $('.LdtPlayer');
+		
+		//Si le pointeur est trop à gauche, on met le curseur de lecture à 0.
+		if(pointerX < P.position().left)
+		{
+			time = 0;
+		}
+		//S'il est trop à droite, on le place à la fin.
+		else if(pointerX > (+P.position().left + TL.width()))
+		{
+			time = this.player.widgets[0].source.getDuration().getSeconds();
+		}
+		//Sinon, on le met à la position du pointeur.
+		else
+		{
+			time = this.player.widgets[0].scaleIntervals(P.position().left, (+P.position().left + TL.width()), 0, this.player.widgets[0].source.getDuration().getSeconds(), pointerX);
+		}
+		
+		this.player.popcorn.currentTime(time);
 	}
-	// console.log('DETECT IDLE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
-}
-
-mosaic.prototype.removeIdlePointers = function()
-{
-	clearTimeout(this.pointersSearchIdleTimeout);
-	// console.log(this.date() + ' - ra');
 }
 
-mosaic.prototype.launchIdlePointers = function()
+/*
+ * Raffraîchit la position des pointeurs.
+ * Est appelé dans les fichiers :
+ * mosaic > fonction loadMosaic.
+ * client > fonction processMsg.
+*/
+Mosaic.prototype.refreshPointers = function(x, y, isMainPointer)
 {
-	var _this = this;
+    if(this.currentMode == "NO-USER" || this.currentMode.indexOf('INCOMING-') != -1)
+    {
+        return;
+    }
+    
+    //Si on est en mode d'interaction Kinect, on effectue un réhaussement de la position.
+    if(!this.config.mouseInteractions)
+    {
+        x *= 7;
+        y *= 7;
+        x -= $(window).width() * 3 / 4;
+        y -= $(window).height() * 2 / 4;
+    }
+    
+	var pointer;
 	
-	//Si on est en mode TL, on ne peut pas effectuer de recherche.
-	if(this.currentMode == 'TIMELINE' || (!this.playerIsReady && (this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH')))
-	{
-		return;
-	}
-	
-	if(this.currentMode == 'VIDEO')// || this.currentMode == 'SEARCH')
+	//S'il s'agit du pointeur principal.
+	if(isMainPointer)
 	{
-		//On peut le faire que sur la video au dessus de la TL.
-		var mainPointer = $('#mainPointer'), secondPointer = $('#secondPointer'), TL = $('.Ldt-Timeline');
-		var TLwidth = TL.width(), TLheight = TL.height();
-		var Ptop = $('.LdtPlayer').position().top, Pleft = $('.LdtPlayer').position().left;
-		var Pheight = $('.LdtPlayer').height();
-		var MPx = mainPointer.position().left + mainPointer.width() / 2, MPy = mainPointer.position().top + mainPointer.height() / 2;
-		var SPx = secondPointer.position().left + secondPointer.width() / 2, SPy = secondPointer.position().top + secondPointer.height() / 2;
+		//On affecte les éléments relatifs au pointeur principal.
+		pointer = $('#mainPointer');
+		
+		//Si le pointeur quitte la fenêtre en X, on ne le change pas.
+		if(x < 0 || x > $(window).width())
+		{
+			x = this.mainPointerLastX;
+		}
+		//Sinon, on le met à jour.
+		else
+		{
+			this.mainPointerLastX = x;
+		}
 		
-		if(MPx < Pleft || MPx > (+Pleft + TLwidth) || MPy < Ptop || MPy > (+Ptop + Pheight - TLheight) ||
-		SPx < Pleft || SPx > (+Pleft + TLwidth) || SPy < Ptop || SPy > (+Ptop + Pheight - TLheight))
+		//Si le pointeur quitte la fenêtre en Y, on ne le change pas.
+		if(y < 0 || y > $(window).height())
+		{
+			y = this.mainPointerLastY;
+		}
+		//Sinon, on le met à jour.
+		else
 		{
-			return;
+			this.mainPointerLastY = y;
+		}
+	}
+	//Sinon.
+	else
+	{
+		//On affecte les éléments relatifs au pointeur principal.
+		pointer = $('#secondPointer');
+		
+		//Si le pointeur quitte la fenêtre en X, on ne le change pas.
+		if(x < 0 || x > $(window).width())
+		{
+			x = this.secondPointerLastX;
+		}
+		//Sinon, on le met à jour.
+		else
+		{
+			this.secondPointerLastX = x;
+		}
+		
+		//Si le pointeur quitte la fenêtre en Y, on ne le change pas.
+		if(y < 0 || y > $(window).height())
+		{
+			y = this.secondPointerLastY;
+		}
+		//Sinon, on le met à jour.
+		else
+		{
+			this.secondPointerLastY = y;
 		}
 	}
 	
-	//A la fin du timeout, si rien n'est venu l'interrompre, on entre en recherche/filtrage en fonction du mode dans lequel on se trouve.
-	this.pointersSearchIdleTimeout = setTimeout(function()
-	{
-		if(!_this.areBothPointersHere)
-		{
-			return;
-		}
-		
-		// console.log('rdy for idle');
-		
-		if(_this.currentMode == "MOSAIC")
-		{
-			_this.currentMode = "FILTER";
-			// _this.currentMode = "FILTR";
-			_this.isMosaicFiltered = true;
-			
-			console.log(_this.date() + ' - ENTRE EN MODE FILTRAGE');
-			
-			_this.removeNotifications();
-			_this.filterSearch();
-		}
-		else if(_this.currentMode == "VIDEO" || _this.currentMode == "TIMELINE")
-		{
-			_this.currentMode = "SEARCH";
-			
-			console.log(_this.date() + ' - ENTRE EN MODE RECHERCHE');
-			// console.log('');
-			
-			_this.removeNotifications();
-			_this.searchSearch();
-		}
-		
-		if(!_this.canNotifyHelp)
-		{
-			_this.canNotifyHelpTimeout = setTimeout(function()
-			{
-				// console.log(_this.date() + ' CAN NOTIFY HELP');
-				_this.canNotifyHelp = true;
-			}, _this.config['timeoutCanNotifyHelp']);
-		}
-		
-		//Si on est déjà en recherche, et que l'aide n'est pas encore affichée, on l'affiche.
-		/*if(_this.currentMode == 'SEARCH' && _this.canNotifyHelp)
-		{
-			_this.notifyHelp(false);
-		}
-		if(_this.currentMode == 'FILTER' && _this.canNotifyHelp)
-		{
-			_this.notifyHelp(true);
-		}*/
-		
-	}, this.config['timeoutPointersIdle']);
+    var pointerX, pointerY;
+    
+    //Si on est en mode d'interaction souris, on met à jour les coordonnées utilisées dans les fonctions par celles de la souris.
+    //Sinon on se base sur les coordonnées des pointeurs.
+    if(this.config.mouseInteractions)
+    {
+        pointerX = x;
+        pointerY = y;
+    }
+    else
+    {
+        pointerX = x - pointer.width()/2;
+        pointerY = y - pointer.height()/2;
+    }
+    var _this = this;
+    
+    pointer.css(
+    {
+        top: pointerY,
+        left: pointerX
+    });
+    
+    if($('#spinner').length > 0)
+    {
+        $('#spinner').css(
+        {
+            top: pointerY,
+            left: pointerX
+        });
+    }
+    
+    var snapshot = null;
+    
+    //Si on est dans la mosaique ou en filtrage.
+    if(this.currentMode == 'MOSAIC' || this.currentMode == 'FILTER' && this.isMosaicFiltered)
+    {
+		this.pointersMosaicInteractions(pointerX, pointerY, isMainPointer);
+    }
+    //Si on est dans une vidéo ou dans une recherche ou dans la timeline.
+    else if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH' || this.currentMode == 'TIMELINE')
+    {
+		this.pointersVideoInteractions(pointerX, pointerY, isMainPointer);
+    }
+}
+
+/*
+ * Détecte si les deux pointeurs sont dans la zone de recherche et qu'ils ne bougent pas.
+ * Est appelé dans le fichier :
+ * client > fonction processMsg.
+*/
+Mosaic.prototype.detectIdlePointers = function()
+{
+    var mainPointer = $('#mainPointer');
+    var secondPointer = $('#secondPointer');
+    
+    //Si la position des pointeurs au début de l'analyse d'idle change de plus ou moins leur taille par rapport à leur position actuelle.
+    if(Math.abs(this.mainPointerIdleStartX - this.mainPointerLastX) > mainPointer.width() || Math.abs(this.mainPointerIdleStartY - this.mainPointerLastY) > mainPointer.height() ||
+    Math.abs(this.secondPointerIdleStartX - this.secondPointerLastX) > secondPointer.width() || Math.abs(this.secondPointerIdleStartY - this.secondPointerLastY) > secondPointer.height())
+    {
+        //On réinitialise les dernières positions connues.
+        this.mainPointerIdleStartX = this.mainPointerLastX;
+        this.mainPointerIdleStartY = this.mainPointerLastY;
+        this.secondPointerIdleStartX = this.secondPointerLastX;
+        this.secondPointerIdleStartY = this.secondPointerLastY;
+        
+        this.removeIdlePointers();
+        this.pointersIdleNeedLaunch = true;
+    }
+    
+    //Si l'aide est affichée, on la masque.
+    if(this.helpDisplayed)
+    {
+        this.removeHelp();
+    }
+    
+    if((this.currentMode == 'SEARCH' || this.currentMode == 'FILTER') && !this.isSearchByCurvesOn)
+    {
+        // this.isSearchByCurvesOn = true;
+        // this.startSearch();
+    }
+}
+
+/*
+ * Enlève la vérification sur les pointeurs qui ne bougent pas.
+ * Est appelé dans les fichiers :
+ * pointers > detectIdlePointers.
+ * client > fonction processMsg.
+*/
+Mosaic.prototype.removeIdlePointers = function()
+{
+    clearTimeout(this.pointersSearchIdleTimeout);
 }
 
-mosaic.prototype.checkForBothPointersHere = function()
+/*
+ * Lance une vérification sur les pointeurs qui ne bougent pas.
+ * Est appelé dans le fichier :
+ * client > fonction processMsg.
+*/
+Mosaic.prototype.launchIdlePointers = function()
 {
-	var _this = this;
-	
-	if(!this.areBothPointersTimeoutLaunched)
-	{
-		this.areBothPointersHereTimeout = setTimeout(function()
-		{
-			_this.areBothPointersHere = false;
-			/*if(_this.isSearchByCurvesOn)
-			{
-				_this.leaveSearch();
-			}*/
-		}, this.config['timeoutAreBothPointersHere']);
-		
-		this.areBothPointersHereTimeoutLaunched = true;
-	}
+    var _this = this;
+    
+    //Si on est en mode TL, on ne peut pas effectuer de recherche.
+    if(this.currentMode == 'TIMELINE' || (!this.playerIsReady && (this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH')))
+    {
+        return;
+    }
+    
+    if(this.currentMode == 'VIDEO')
+    {
+        //On peut le faire que sur la video au dessus de la TL.
+        var mainPointer = $('#mainPointer'), secondPointer = $('#secondPointer'), TL = $('.Ldt-Timeline');
+        var TLwidth = TL.width(), TLheight = TL.height();
+        var Ptop = $('.LdtPlayer').position().top, Pleft = $('.LdtPlayer').position().left;
+        var Pheight = $('.LdtPlayer').height();
+        var MPx = mainPointer.position().left + mainPointer.width() / 2, MPy = mainPointer.position().top + mainPointer.height() / 2;
+        var SPx = secondPointer.position().left + secondPointer.width() / 2, SPy = secondPointer.position().top + secondPointer.height() / 2;
+        
+        //Si les pointeurs ne sont pas sur le player, on part.
+        if(MPx < Pleft || MPx > (+Pleft + TLwidth) || MPy < Ptop || MPy > (+Ptop + Pheight - TLheight) ||
+        SPx < Pleft || SPx > (+Pleft + TLwidth) || SPy < Ptop || SPy > (+Ptop + Pheight - TLheight))
+        {
+            return;
+        }
+    }
+    
+    //A la fin du timeout, si rien n'est venu l'interrompre, on entre en recherche/filtrage en fonction du mode dans lequel on se trouve.
+    this.pointersSearchIdleTimeout = setTimeout(function()
+    {
+        //Si les deux pointeurs ne sont pas dans la zone de recherche, on part.
+        if(!_this.areBothPointersHere)
+        {
+            return;
+        }
+        
+        //Si on est dans la mosaique.
+        if(_this.currentMode == "MOSAIC")
+        {
+            //On passe en filtrage.
+            _this.currentMode = "FILTER";
+            _this.isMosaicFiltered = true;
+            //On notifie.
+            _this.removeNotifications();
+            _this.filterSearch();
+        }
+        //Si on est dans la video ou dans la timeline.
+        else if(_this.currentMode == "VIDEO" || _this.currentMode == "TIMELINE")
+        {
+            //On entre en recherche.
+            _this.currentMode = "SEARCH";
+            //On notifie.
+            _this.removeNotifications();
+            _this.searchSearch();
+        }
+        
+        //Si on ne peut pas afficher l'aide.
+        if(!_this.canNotifyHelp)
+        {
+            //On peut l'afficher après un laps de temps.
+            _this.canNotifyHelpTimeout = setTimeout(function()
+            {
+                _this.canNotifyHelp = true;
+            }, _this.config.timeoutCanNotifyHelp);
+        }
+    }, this.config.timeoutPointersIdle);
 }
 
-mosaic.prototype.removeCheckForBothPointersHere = function()
+/*
+ * Vérifie si les deux pointeurs sont dans la zone de recherche.
+ * Est appelé dans le fichier :
+ * client > fonction processMsg.
+*/
+Mosaic.prototype.checkForBothPointersHere = function()
 {
-	// console.log('TRY QUIT');
-	
-	// if(this.areBothPointersTimeoutLaunched)
-	// {
-		clearTimeout(this.areBothPointersHereTimeout);
-		// console.log('QUIT');
-	// }
-	this.areBothPointersHereTimeoutLaunched = false;
+    var _this = this;
+    
+    //Si le timeout de vérification n'a pas été lancé.
+    if(!this.areBothPointersTimeoutLaunched)
+    {
+        //On le lance.
+        this.areBothPointersHereTimeout = setTimeout(function()
+        {
+            //On considère après un laps de temps qu'au moins une des mains a quitté la zone sauf si on est notifié du contraire.
+            _this.areBothPointersHere = false;
+        }, this.config.timeoutAreBothPointersHere);
+        
+        //On spécifie qu'on l'a lancé.
+        this.areBothPointersHereTimeoutLaunched = true;
+    }
+}
+
+/*
+ * Enlève la vérification de présence des deux pointeurs dans la zone de recherche.
+ * Est appelé dans le fichier :
+ * client > fonction processMsg.
+*/
+Mosaic.prototype.removeCheckForBothPointersHere = function()
+{
+    //On désactive le timeout.
+    clearTimeout(this.areBothPointersHereTimeout);
+    //On indique que la vérification n'est pas lancée.
+    this.areBothPointersHereTimeoutLaunched = false;
 }
 
 /*
  * Vérifie si on se trouve sur la notification de recherche par gesture.
+ * Est appelé dans le fichier :
+ * pointers > fonctions pointersMosaicInteractions et pointersVideoInteractions.
 */
-mosaic.prototype.checkIfPointerIsOnSearchNotification = function(x, y, pointer)
+Mosaic.prototype.checkIfPointerIsOnSearchNotification = function(x, y, pointer)
 {
-	var _this = this;
-	var notification_search = $('#notify_search_1gesture');
-	
-	//Si la notification de recherche existe (dans le player).
-	if(notification_search.length > 0)
-	{
-		//Pictogramme actuel de la notification.
-		var currentPicto = notification_search.css('background-image');
-
-		//y -= this.MPTop_margin;
-		
-		/*console.log('===================================');
-		console.log('x : ' + x + ' > ' + notification_search.position().left);
-		console.log('x : ' + x + ' < ' + (+notification_search.position().left + notification_search.width()));
-		console.log('y : ' + y + ' > ' + notification_search.position().top);
-		console.log('y : ' + y + ' < ' + (+notification_search.position().top + notification_search.height()));
-		console.log('===================================');*/
-		
-		//Si le pointeur est sur la notification.
-		if(x > notification_search.position().left && x < (+notification_search.position().left + notification_search.width()) && y > notification_search.position().top && y < (+notification_search.position().top + notification_search.height()))
-		{
-			/*if($('#a').length == 0)
-			{
-				var a = "<div id='a'></div>";
-				$('body').append(a);
-				$('#a').css(
-				{
-					left: notification_search.position().left,
-					top: notification_search.position().top,
-					width: notification_search.width(),
-					height: notification_search.height(),
-					"background-color": "#fff",
-					position: 'absolute',
-				});
-			}*/
-			
-			if(!this.alreadyOnNotification && ($('#spinner').length == 0 && !this.mouseInteractions || this.mouseInteractions))
-			{
-				notification_search.css('background-image', currentPicto.replace('/big/' + (this.mouseInteractions ? 'MI/' : '') + 'valid/', '/big/' + (this.mouseInteractions ? 'MI/' : '') + 'hover/'));
-				
-				this.gestureDelRequested = true;
-				
-				// console.log(this.date() + ' try remove not ' + currentPicto.replace('/big/' + (this.mouseInteractions ? 'MI/' : '') + 'valid/', '/big/' + (this.mouseInteractions ? 'MI/' : '') + 'hover/'));
-				
-				if(!this.mouseInteractions)
-				{
-					//On met le spinner gif sur le pointeur.
-					var spinner = "<img id='spinner'></div>";
-					$('body').append(spinner);
-					$('#spinner').css(
-					{
-						position: 'absolute',
-						top: pointer.position().top,
-						left: pointer.position().left,
-						width: 85,
-						height: 85,
-						'z-index': 600
-					});
-					$('#spinner').attr('src', './img/cursors/selector_anim.gif');
-					
-					this.removeNotificationByGestureTimeout = setTimeout(function()
-					{
-						if(_this.currentMode == 'SEARCH')
-						{
-							_this.player.widgets[0].removeSearchByGesture();
-							_this.currentMode = 'VIDEO';
-						}
-						else if(_this.currentMode == 'TIMELINE')
-						{
-							_this.player.widgets[0].removeSearchByGesture();
-							_this.currentMode = 'TIMELINE';
-						}
-						else if(_this.currentMode == 'FILTER')
-						{
-							_this.removeFilter();
-						}
-						
-						_this.alreadyOnNotification = false;
-						_this.isCurrentlyInASearchByGesture = false;
-						
-						if(_this.currentMode != 'MOSAIC' && _this.currentMode != 'FILTER')
-						{
-							_this.currentSearchGesture[_this.centerId] = '';
-						}
-						
-						_this.canNotifyHelp = false;
-					}, this.config['timeoutRemoveNotificationByGesture']);
-				}
-				else
-				{
-				
-				}
-				
-				this.alreadyOnNotification = true;
-			}
-			
-			return true;
-		}
-		else
-		{
-			if(this.alreadyOnNotification)
-			{
-				notification_search.css('background-image', currentPicto.replace('/big/' + (this.mouseInteractions ? 'MI/' : '') + 'hover/', '/big/' + (this.mouseInteractions ? 'MI/' : '') + 'valid/'));
-				
-				this.gestureDelRequested = false;
-				
-				// console.log(currentPicto.replace('/big/' + (this.mouseInteractions ? 'MI/' : '') + 'hover/', '/big/' + (this.mouseInteractions ? 'MI/' : '') + 'valid/'));
-				
-				clearTimeout(this.removeNotificationByGestureTimeout);
-				this.alreadyOnNotification = false;
-				$('#spinner').remove();
-			}
-			
-			return false;
-		}
-	}
-	
-	return false;
+    var _this = this;
+    var notification_search = $('#notify_search_1gesture');
+    
+    //Si la notification de recherche existe (dans le player).
+    if(notification_search.length > 0)
+    {
+        //Pictogramme actuel de la notification.
+        var currentPicto = notification_search.css('background-image');
+        
+        //Si le pointeur est sur la notification.
+        if(x > notification_search.position().left && x < (+notification_search.position().left + notification_search.width()) && y > notification_search.position().top && y < (+notification_search.position().top + notification_search.height()))
+        {
+            if(!this.alreadyOnNotification && ($('#spinner').length == 0 && !this.config.mouseInteractions || this.config.mouseInteractions))
+            {
+                notification_search.css('background-image', currentPicto.replace('/big/' + (this.config.mouseInteractions ? 'MI/' : '') + 'valid/', '/big/' + (this.config.mouseInteractions ? 'MI/' : '') + 'hover/'));
+                
+                //On émet la requete de suppression de la notification.
+                this.gestureDelRequested = true;
+                
+                //Si on est en interaction Kinect.
+                if(!this.config.mouseInteractions)
+                {
+                    //On met le spinner gif sur le pointeur.
+                    var spinner = "<img id='spinner'></div>";
+                    $('body').append(spinner);
+                    $('#spinner').css(
+                    {
+                        position: 'absolute',
+                        top: pointer.position().top,
+                        left: pointer.position().left,
+                        width: 85,
+                        height: 85,
+                        'z-index': 600
+                    });
+                    $('#spinner').attr('src', './img/cursors/selector_anim.gif');
+                    
+                    //Après un laps de temps sur la notification, on supprime la recherche et on revient au mode précédent.
+                    this.removeNotificationByGestureTimeout = setTimeout(function()
+                    {
+                        //Si on est en recherche, on revient en video.
+                        if(_this.currentMode == 'SEARCH')
+                        {
+                            _this.player.widgets[0].removeSearchByGesture();
+                            _this.currentMode = 'VIDEO';
+                        }
+                        //Si on est en timeline, on revient en timeline.
+                        else if(_this.currentMode == 'TIMELINE')
+                        {
+                            _this.player.widgets[0].removeSearchByGesture();
+                            _this.currentMode = 'TIMELINE';
+                        }
+                        //Si on est en filtrage, on l'enlève.
+                        else if(_this.currentMode == 'FILTER')
+                        {
+                            _this.removeFilter();
+                        }
+                        
+                        _this.alreadyOnNotification = false;
+                        _this.isCurrentlyInASearchByGesture = false;
+                        
+                        //Si on n'est ni en recherche, ni en filtrage, on enlève la gesture de recherche.
+                        if(_this.currentMode != 'MOSAIC' && _this.currentMode != 'FILTER')
+                        {
+                            _this.currentSearchGesture[_this.centerId] = '';
+                        }
+                        
+                        _this.canNotifyHelp = false;
+                    }, this.config.timeoutRemoveNotificationByGesture);
+                }
+                
+                this.alreadyOnNotification = true;
+            }
+            //On retourne vrai si on est sur la notification, et faux sinon.
+            return true;
+        }
+        //S'il n'est pas sur la notification.
+        else
+        {
+            //Si on était sur la notification, on remet la notification dans l'état où elle était avant qu'on soit dessus.
+            if(this.alreadyOnNotification)
+            {
+                notification_search.css('background-image', currentPicto.replace('/big/' + (this.config.mouseInteractions ? 'MI/' : '') + 'hover/', '/big/' + (this.config.mouseInteractions ? 'MI/' : '') + 'valid/'));
+                
+                this.gestureDelRequested = false;
+                
+                clearTimeout(this.removeNotificationByGestureTimeout);
+                this.alreadyOnNotification = false;
+                $('#spinner').remove();
+            }
+            
+            return false;
+        }
+    }
+    
+    return false;
 }
 
 /*
  * Si on se trouve sur la notification de recherche par gesture, on la supprime.
+ * Est appelé dans les fichiers :
+ * mosaic > onMouseDown.
+ * zoomInteractions > unzoom.
 */
-mosaic.prototype.removeSearchNotificationIfOnIt = function(x, y)
+Mosaic.prototype.removeSearchNotificationIfOnIt = function(x, y)
 {
-	var _this = this;
-	
-	var notification_search = $('#notify_search_1gesture');
-	
-	//Si la notification de recherche existe (dans le player).
-	if(notification_search.length > 0)
-	{
-		if(x > notification_search.position().left && x < (+notification_search.position().left + notification_search.width()) && y > notification_search.position().top && y < (+notification_search.position().top + notification_search.height()))
-		{
-			_this.removeNotifications();
-			if(_this.currentMode == 'SEARCH')
-			{
-				_this.player.widgets[0].removeSearchByGesture();
-				_this.currentMode = 'VIDEO';
-				_this.currentSearchGesture[_this.centerId] = '';
-			}
-			else if(_this.currentMode == 'TIMELINE')
-			{
-				_this.player.widgets[0].removeSearchByGesture();
-				_this.currentMode = 'TIMELINE';
-				_this.currentSearchGesture[_this.centerId] = '';
-			}
-			else if(_this.currentMode == 'FILTER')
-			{
-				_this.removeFilter();
-			}
-			
-			_this.alreadyOnNotification = false;
-			_this.isCurrentlyInASearchByGesture = false;
-			_this.curvesGesturesFound = false;
-			_this.canDrawNextCurve = false;
-			_this.isSearchByCurvesOn = false;
-			_this.canNotifyHelp = false;
-			
-			//Si on est dans une vidéo, on laisse cette variable afin de ne pas dézoomer / bouger.
-			if(_this.currentMode != 'VIDEO' && _this.currentMode != 'TIMELINE')
-			{
-				_this.gestureDelRequested = false;
-			}
-		}
-	}
+    var _this = this;
+    
+    var notification_search = $('#notify_search_1gesture');
+    
+    //Si la notification de recherche existe (dans le player).
+    if(notification_search.length > 0)
+    {
+        if(x > notification_search.position().left && x < (+notification_search.position().left + notification_search.width()) && y > notification_search.position().top && y < (+notification_search.position().top + notification_search.height()))
+        {
+            _this.removeNotifications();
+            if(_this.currentMode == 'SEARCH')
+            {
+                _this.player.widgets[0].removeSearchByGesture();
+                _this.currentMode = 'VIDEO';
+                _this.currentSearchGesture[_this.centerId] = '';
+            }
+            else if(_this.currentMode == 'TIMELINE')
+            {
+                _this.player.widgets[0].removeSearchByGesture();
+                _this.currentMode = 'TIMELINE';
+                _this.currentSearchGesture[_this.centerId] = '';
+            }
+            else if(_this.currentMode == 'FILTER')
+            {
+                _this.removeFilter();
+            }
+            
+            _this.alreadyOnNotification = false;
+            _this.isCurrentlyInASearchByGesture = false;
+            _this.curvesGesturesFound = false;
+            _this.canDrawNextCurve = false;
+            _this.isSearchByCurvesOn = false;
+            _this.canNotifyHelp = false;
+            
+            //Si on est dans une vidéo, on laisse cette variable afin de ne pas dézoomer / bouger.
+            if(_this.currentMode != 'VIDEO' && _this.currentMode != 'TIMELINE')
+            {
+                _this.gestureDelRequested = false;
+            }
+        }
+    }
 }
\ No newline at end of file
--- a/front_idill/src/mosaic/js/search.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/mosaic/js/search.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,358 +1,347 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : search.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les fonctions de recherche par courbe de haut niveau (instantiation et manipulation de la classe de recherche par courbe mais pas les courbes en elles-mêmes ni le détecteur).
+ */
+
 /*
  * Lance une recherche par courbes.
+ * Est appelé dans le fichier :
+ * mosaic > fonction onMouseMove.
  */
-mosaic.prototype.startSearch = function()
+Mosaic.prototype.startSearch = function()
 {
-	var _this = this;
-	
-	var top, left, width, height, margin_top, inMosaic;
-	//Si on est dans le cas d'un filtrage de mosaïque.
-	if(this.currentMode == "FILTER")
-	{
-		var mainPanel = $('#mainPanel');
-		top = mainPanel.position().top;
-		left = mainPanel.position().left;
-		width = mainPanel.width();
-		height = mainPanel.height();
-		margin_top = this.MPTop_margin;
-		inMosaic = true;
-	}
-	//Sinon si c'est une recherche dans la vidéo.
-	else if(this.currentMode == "SEARCH")
-	{
-		top = this.snTop;
-		left = this.snLeft;
-		width = this.snWidth;
-		height = this.snHeight;
-		margin_top = '0px';
-		inMosaic = false;
-	}
-	
-	this.searchCanvas = new searchCanvas(top, left, width, height, margin_top, this.timeSearchFade, inMosaic, this);
-	this.searchCanvas.create(this.dictionary);
+    var _this = this;
+    
+    var top, left, width, height, margin_top, inMosaic;
+    //Si on est dans le cas d'un filtrage de mosaïque.
+    if(this.currentMode == "FILTER")
+    {
+        var mainPanel = $('#mainPanel');
+        top = mainPanel.position().top;
+        left = mainPanel.position().left;
+        width = mainPanel.width();
+        height = mainPanel.height();
+        margin_top = this.MPTop_margin;
+        inMosaic = true;
+    }
+    //Sinon si c'est une recherche dans la vidéo.
+    else if(this.currentMode == "SEARCH")
+    {
+        top = this.snTop;
+        left = this.snLeft;
+        width = this.snWidth;
+        height = this.snHeight;
+        margin_top = '0px';
+        inMosaic = false;
+    }
+    
+    //On crée le canvas et on récupère le dictionnaire des courbes.
+    this.searchCanvas = new SearchCanvas(top, left, width, height, margin_top, this.timeSearchFade, inMosaic, this);
+    this.searchCanvas.create(this.dictionary);
 }
 
 /*
  * Lit le dictionnaire pour reconnaître les courbes de recherche.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadParameters.
 */
-mosaic.prototype.getDictionary = function()
+Mosaic.prototype.getDictionary = function()
 {
-	var path = this.config['dico'];
-	var dico = [];
-	
-	var _this = this;
-	
-	$.getJSON(path, function(data)
-	{
-		for(var i = 0 ; i < data.gestures.length ; i++)
-		{
-			_this.dictionary[i] = data.gestures[i];
-		}
-	});
+    var path = this.config.curveDictionary;
+    var dico = [];
+    
+    var _this = this;
+    
+    $.getJSON(path, function(data)
+    {
+        //Chaque entrée comporte un objet de cette forme : (nom, tableau). Tableau est un array de strings, qui sont les codes décrivant la courbe. Chaque code est un alias de cette courbe.
+        for(var i = 0 ; i < data.gestures.length ; i++)
+        {
+            _this.dictionary[i] = data.gestures[i];
+        }
+    });
 }
 
 /*
  * Charge le texte affichable en fonction de la langue.
+ * Est appelé dans le fichier :
+ * mosaic > fonction loadParameters.
 */
-mosaic.prototype.getLang = function(lang)
+Mosaic.prototype.getLang = function(lang)
 {
-	var path = 'lang/' + this.config['lang'] + '.json';
-	
-	var _this = this;
-	
-	$.getJSON(path, function(data)
-	{
-		_this.gesturesText = data.gesturesText;
-	});
+    var path = 'lang/' + this.config.lang + '.json';
+    
+    var _this = this;
+    
+    $.getJSON(path, function(data)
+    {
+        _this.gesturesText = data.gesturesText;
+    });
 }
 
-mosaic.prototype.listenToPointers = function()
+/*Mosaic.prototype.listenToPointers = function()
 {
-	if(this.searchCanvas)
-	{
-		
-	}
-}
+    if(this.searchCanvas)
+    {
+        
+    }
+}*/
 
 /*
  * Quitte une recherche par courbes.
+ * Est appelé dans les fichiers :
+ * mosaic > fonction onMouseUp.
+ * curvesDetector > fonction updateDists.
  */
-mosaic.prototype.leaveSearch = function()
-{
-	if(this.searchCanvas)
-	{
-		this.searchCanvas.leaveSearch();
-	}
-	this.searchCanvas = null;
-}
-
-/*
- * Affiche les types de marqueurs correspondants à ce qu'on a commencé à tracer lors d'une recherche.
-*/
- mosaic.prototype.notifySearchMarkers = function(markersStr)
+Mosaic.prototype.leaveSearch = function()
 {
-	if($('.notifications_inSearch_container').length > 0)
-	{
-		return;
-	}
-	
-	// console.log(markersStr);
-	
-	var markersList = markersStr.split(new RegExp(';'));
-	
-	var notification_search_markers = "<div class='notifications_inSearch_container'>";
-	
-	//On spécifie les notifications en div.
-	for(var i = 0 ; i < markersList.length ; i++)
-	{
-		notification_search_markers += "<div class='notifications_inSearch' style='background-image: url(./pictos/big/normal/" + markersList[i] + ".png);'></div>";
-	}
-	
-	notification_search_markers += "</div>";
-	
-	//On les ajoute à la mosaïque.
-	$('#mainPanel').append(notification_search_markers);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications_inSearch_container').width(), notify_height = $('.notifications_inSearch_container').height();
-	var notify_margin = parseInt($('.notifications_inSearch').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	var point_top = 0;
-	
-	if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH")
-	{
-		point_top = -this.notifyTopVideo,
-		point_left = -this.notifyLeftVideo + ($(window).width() - notify_width) / 2
-	}
-	
-	//On les positionne.
-	$('.notifications_inSearch_container').css(
-	{
-		left: point_left,
-		top: point_top
-	});
-	
-	//On les fait apparaître.
-	$('.notifications_inSearch').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de maintient du pointage.
-*/
-mosaic.prototype.removeSearchMarkers = function()
-{	
-	$('.notifications_inSearch_container').remove();
+    if(this.searchCanvas)
+    {
+        this.searchCanvas.leaveSearch();
+		//Dans le cadre du mode d'interactions souris, on indique qu'on est en mouse down de facon à ne plus être en mouse move avant le prochain mouse up puis d'un mouse down.
+		this.isMouseDown = false;
+    }
+    this.searchCanvas = null;
 }
 
 /*
  * Effectuer un filtrage de la mosaïque par rapport à un type de marqueurs.
+ * Est appelé dans les fichiers :
+ * mosaic > fonctions onMouseUp et manageControlEvents.
+ * curvesDetector > fonction updateDists.
 */
-mosaic.prototype.searchFilter = function(type)
+Mosaic.prototype.searchFilter = function(type)
 {
-	// type = 'a';
-	var _this = this;
-	
-	if(this.currentMode == "FILTER")
-	{
-		for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
-		{
-			this.currentSearchGesture[i] = type;
-		}
-		
-		this.filterSearchedType = type;
-		
-		// console.log('Annotations length : ' + this.annotations.length);
-		if(this.annotations.length > 0)
-		{
-			this.isMosaicFiltering = true;
-			
-			var gestureNumberByVideo = new Object();
-			var maxAnnotationNumber = 0;
-			// for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
-			for(var i = 0 ; i < this.annotations.length ; i++)
-			{
-				var current = this.annotations[i];
-				// console.log(current.annotationType.contents.title + ' == ' + type);
-				if(current.annotationType.contents.title == type)
-				{
-					if(gestureNumberByVideo[current.source.url] == undefined || gestureNumberByVideo[current.source.url] == '')
-					{
-						gestureNumberByVideo[current.source.url] = 0;
-					}
-					
-					gestureNumberByVideo[current.source.url]++;
-				}
-			}
-			
-			for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
-			{
-				if(gestureNumberByVideo[this.urls[i]] == undefined || gestureNumberByVideo[this.urls[i]] == '')
-				{
-					gestureNumberByVideo[this.urls[i]] = 0;
-				}
-			}
-			
-			//On récupère la vidéo qui score le nombre d'occurences de la gesture le plus haut.
-			for(i in gestureNumberByVideo)
-			{	
-				// console.log(i + " " + gestureNumberByVideo[i] + ' ' + type);
-				if(maxAnnotationNumber < gestureNumberByVideo[i])
-				{
-					maxAnnotationNumber = gestureNumberByVideo[i];
-				}
-			}
-			
-			var snMargin = parseInt($('.snapshotDivs').css('margin'));
-			
-			//On affiche l'opacité résultante pour chaque vidéo.
-			for(var i = 0 ; i < this.config['imagesToShow'] ; i++)// in gestureNumberByVideo)
-			{
-				//Toutes les videos ont cette recherche.
-				this.filterSearchedType[i] = type;
-				//Opacité conventionelle.
-				var opacity;
-				if(maxAnnotationNumber > 0)
-				{
-					opacity = gestureNumberByVideo[this.urls[i]] / maxAnnotationNumber;
-				}
-				else
-				{
-					opacity = 0;
-				}
-				
-				// console.log('opacity b : ' + opacity + ' for ' + gestureNumberByVideo[i]);
-				//Ce qui est à zéro le restera (par conséquent le snapshot associé sera invisible).
-				if(opacity > 0)
-				{
-					//On réhausse l'opacité de 50%.
-					opacity = this.scaleIntervals(0., 1., 0.5, 1., opacity);	
-				}
-				this.opacities[i] = opacity;
-				
-				//var filterIndex = this.getIdxFromMetadata(i);
-				var filterIndex = i;
-				//if(filterIndex >= 0)
-				//{
-					// console.log('#snapshotDiv-' + filterIndex + " " + _this.config['timeFilterFade'] + " " + opacity);
-					$('#snapshotDiv-' + filterIndex).fadeTo(this.config['timeFilterFade'], opacity, function()
-					{
-						//Pour ne notifier qu'une fois.
-						if(_this.isMosaicFiltering)
-						{
-							_this.isMosaicFiltering = false;
-						}
-					});
-					
-					// console.log('filterIdx : ' + filterIndex);
-					
-					if(opacity == 0)
-					{
-						var filteredSnapshot = $('#snapshotDiv-' + filterIndex);
-						
-						if(filteredSnapshot.length > 0)
-						{
-							var hider = '<div id="filterHider-' + filterIndex + '" class="filterHiders"></div>';
-							$('#mainPanel').append(hider);
-							
-							$('#filterHider-' + filterIndex).css(
-							{
-								width: +filteredSnapshot.width() + 4 * snMargin,
-								height: +filteredSnapshot.height() + 4 * snMargin,
-								top: filteredSnapshot.position().top - snMargin,
-								left: filteredSnapshot.position().left - snMargin
-							});
-						}
-					}
-				//}
-			}
-			// for(var a = 0 ; a < this.config['imagesToShow'] ; a++)
-				// console.log('op : ' + ' ' + this.imgs[a] + ' \t ' + this.opacities[a]);
-			
-			this.isMosaicFiltered = true;
-		}
-	}
+    var _this = this;
+    
+    //Si on est en mode filtrage.
+    if(this.currentMode == "FILTER")
+    {
+        //On indique pour chaque snapshot la recherche de filtrage.
+        for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
+        {
+            this.currentSearchGesture[i] = type;
+        }
+        
+        this.filterSearchedType = type;
+        
+        //Si on a des annotations.
+        if(this.annotations.length > 0)
+        {
+            //On indique qu'on est en train de filtrer.
+            this.isMosaicFiltering = true;
+            
+            //Va servir à compter le nombre d'occurence des marqueurs dans chaque video.
+            var gestureNumberByVideo = new Object();
+            var maxAnnotationNumber = 0;
+            
+            //Pour chaque annotation.
+            for(var i = 0 ; i < this.annotations.length ; i++)
+            {
+                //On récupère l'annotation en cours.
+                var current = this.annotations[i];
+                
+                //Si l'annotation correspond à la gesture recherchée.
+                if(current.annotationType.contents.title == type)
+                {
+                    //Si une video n'a pas été traitée, on met son nombre d'occurences à 0.
+                    if(gestureNumberByVideo[current.source.url] == undefined || gestureNumberByVideo[current.source.url] == '')
+                    {
+                        gestureNumberByVideo[current.source.url] = 0;
+                    }
+                    
+                    //On incrémente le nombre d'occurences de la video.
+                    gestureNumberByVideo[current.source.url]++;
+                }
+            }
+            
+            //Pour chaque snapshot, s'il son nombre d'occurences n'a pas été encore calculé (cas où il n'y a pas de résultats dans ces videos là, on met leur nombre d'occurences à 0.
+            for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
+            {
+                if(gestureNumberByVideo[this.urls[i]] == undefined || gestureNumberByVideo[this.urls[i]] == '')
+                {
+                    gestureNumberByVideo[this.urls[i]] = 0;
+                }
+            }
+            
+            //On récupère la vidéo qui score le nombre d'occurences de la gesture le plus haut.
+            for(i in gestureNumberByVideo)
+            {
+                if(maxAnnotationNumber < gestureNumberByVideo[i])
+                {
+                    maxAnnotationNumber = gestureNumberByVideo[i];
+                }
+            }
+            
+            var snMargin = parseInt($('.snapshotDivs').css('margin'));
+            
+            //On affiche l'opacité résultante pour chaque vidéo.
+            for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
+            {
+                //Opacité conventionelle.
+                var opacity;
+                if(maxAnnotationNumber > 0)
+                {
+                    opacity = gestureNumberByVideo[this.urls[i]] / maxAnnotationNumber;
+                }
+                else
+                {
+                    opacity = 0;
+                }
+                
+                //Ce qui est à zéro le restera (par conséquent le snapshot associé sera invisible).
+                if(opacity > 0)
+                {
+                    //On réhausse l'opacité de 50%.
+                    opacity = this.scaleIntervals(0., 1., 0.5, 1., opacity);    
+                }
+                this.opacities[i] = opacity;
+                
+                var filterIndex = i;
+                
+                //On applique les opacités aux snapshots.
+                $('#snapshotDiv-' + filterIndex).fadeTo(this.config['timeFilterFade'], opacity, function()
+                {
+                    //On indique lorsque c'est terminé que la mosaique a terminé de filtrer.
+                    if(_this.isMosaicFiltering)
+                    {
+                        _this.isMosaicFiltering = false;
+                    }
+                });
+                
+                //Si l'opacité est nulle.
+                if(opacity == 0)
+                {
+                    //Le snapshot filtré actuel.
+                    var filteredSnapshot = $('#snapshotDiv-' + filterIndex);
+                    
+                    //S'il existe.
+                    if(filteredSnapshot.length > 0)
+                    {
+                        //On rajoute un hider de façon à ce qu'on ne puisse pas le sélectionner.
+                        var hider = '<div id="filterHider-' + filterIndex + '" class="filterHiders"></div>';
+                        $('#mainPanel').append(hider);
+                        
+                        $('#filterHider-' + filterIndex).css(
+                        {
+                            width: +filteredSnapshot.width() + 4 * snMargin,
+                            height: +filteredSnapshot.height() + 4 * snMargin,
+                            top: filteredSnapshot.position().top - snMargin,
+                            left: filteredSnapshot.position().left - snMargin
+                        });
+                    }
+                }
+            }
+            
+            //On indique que la mosaique a été filtrée.
+            this.isMosaicFiltered = true;
+        }
+    }
 }
 
 /*
  * Passe une valeur de l'intervalle [A, B] à l'intervalle [C, D].
+ * Est appelé dans les fichiers :
+ * pointers > fonction pointersTimelineSelection.
+ * search > fonction searchFilter.
 */
-mosaic.prototype.scaleIntervals = function(A, B, C, D, val)
+Mosaic.prototype.scaleIntervals = function(A, B, C, D, val)
 {
-	return (D - C + A) * val + (C - A);
+    return (D - C + A) * val + (C - A);
 }
 
 /*
  * Retourne l'index d'un snapshot en fonction de ses metadonnées.
 */
-mosaic.prototype.getIdxFromMetadata = function(metadata)
+/*Mosaic.prototype.getIdxFromMetadata = function(metadata)
 {
-	var _this = this;
-	
-	for(idx in this.urls)
-	{
-		if(this.urls[idx] == metadata)
-		{
-			for(id in this.ids)
-			{
-				if(this.ids[id] == idx)
-				{
-					return id;
-				}
-			}
-		}
-	}
-	
-	return -1;
-}
+    var _this = this;
+    
+    for(idx in this.urls)
+    {
+        if(this.urls[idx] == metadata)
+        {
+            for(id in this.ids)
+            {
+                if(this.ids[id] == idx)
+                {
+                    return id;
+                }
+            }
+        }
+    }
+    
+    return -1;
+}*/
 
 /*
  * Enlève une recherche par filtre.
+ * Est appelé : dans les fichiers :
+ * pointers > fonctions checkIfPointerIsOnSearchNotification et removeSearchNotificationIfOnIt.
+ * mosaic > fonction onMarkersReady.
 */
-mosaic.prototype.removeFilter = function()
+Mosaic.prototype.removeFilter = function()
 {
-	if(this.currentMode == "FILTER")
-	{
-		this.currentMode = "MOSAIC";
-		
-		var _this = this;
-		
-		this.isMosaicFiltered = false;
-		this.filterSearchedType = '';
-		
-		for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
+    //Si on est en filtrage, on passe en mosaic et on retire la recherche.
+    if(this.currentMode == "FILTER")
+    {
+        this.currentMode = "MOSAIC";
+        
+        var _this = this;
+        
+        this.isMosaicFiltered = false;
+		this.isMosaicFiltering = true;
+        this.filterSearchedType = '';
+        
+        for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
+        {
+            this.currentSearchGesture[i] = '';
+        }
+        
+        this.removeNotifications();
+        $('.filterHiders').remove();
+        $('.snapshotDivs').fadeTo(_this.config['timeFilterFade'], 1, function()
 		{
-			this.currentSearchGesture[i] = '';
-		}
-		
-		$('#notify_search').remove();
-		$('#notify_search_1gesture').remove();
-		$('.filterHiders').remove();
-		$('.snapshotDivs').fadeTo(_this.config['timeFilterFade'], 1);
-	}
+			_this.isMosaicFiltering = false;
+		});
+    }
 }
 
 /*
  * Parcours le dictionnaire pour trouver la première gesture à avoir un code identique à celui en entrée.
+ * Est appelé dans le fichier :
+ * mosaic > fonction onMouseUp.
 */
-mosaic.prototype.gestureWithSameCode = function(code)
+Mosaic.prototype.gestureWithSameCode = function(code)
 {
-	//Pour tout le dictionnaire.
-	for(var i = 0 ; i < this.dictionary.length ; i++)
-	{
-		//Pour touts les codes de chaque gesture du dictionnaire.
-		for(var j = 0 ; j < this.dictionary[i].codes.length ; j++)
-		{
-			//Si le code en entrée est une partie début d'un des codes.
-			if(this.dictionary[i].codes[j] === code)
-			{
-				//On retourne le nom de la gesture.
-				return this.dictionary[i].name;
-			}
-		}
-	}
-	
-	return '';
+    //Pour tout le dictionnaire.
+    for(var i = 0 ; i < this.dictionary.length ; i++)
+    {
+        //Pour touts les codes de chaque gesture du dictionnaire.
+        for(var j = 0 ; j < this.dictionary[i].codes.length ; j++)
+        {
+            //Si le code en entrée est une partie début d'un des codes.
+            if(this.dictionary[i].codes[j] === code)
+            {
+                //On retourne le nom de la gesture.
+                return this.dictionary[i].name;
+            }
+        }
+    }
+    
+    return '';
 }
\ No newline at end of file
--- a/front_idill/src/mosaic/js/zoomInteractions.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/mosaic/js/zoomInteractions.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,57 +1,63 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : zoomInteractions.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les fonctions de zoom/dezoom prezoom/preunzoom.
+ */
+
 /*
  * Zoom sur la position d'une image, 1ère partie. Durant le laps de temps de time ms, l'utilisateur a le choix de zoomer sur une autre image.
  * Après ce laps de temps, l'image zoom complétement et il n'est plus possible de sélectionner une autre image par pointage.
+ * Est appelé dans le fichier :
+ * pointers > fonction pointersMosaicInteractions.
  */
-mosaic.prototype.preZoom = function(snapshot)
+Mosaic.prototype.preZoom = function(snapshot)
 {
-	if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") > -1 || snapshot == null || this.helpDisplayed || this.isMosaicFiltering || this.isSearchByCurvesOn || this.gestureDelRequested)
-	{
-		return;
-	}
-	
+    if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") > -1 || snapshot == null || this.helpDisplayed || this.isMosaicFiltering || this.isSearchByCurvesOn || this.gestureDelRequested)
+    {
+        return;
+    }
+    
     if(this.fullscreen)
-	{
+    {
         return;
-	}
-	this.preUnzoom();
-	//On enlève les notifications initiales si elles existent.
-	// this.removeSelectionSearchMosaicFull();
-	this.removeNotifications();
-	
+    }
+	this.isPrezooming = true;
+    this.preUnzoom();
+    //On enlève les notifications initiales si elles existent.
+    this.removeNotifications();
+    
     //Mosaïque.
     var _this = this;
     //Dimensions de la mosaïque.
     var h = this.height, w = this.width;
     //Longueur en images, nombre d'images et taille de bordure de la mosaïque.
-    var len = this.config['length'], imgs = this.config['imagesToShow'], margin = this.marginWidth;
+    var len = this.config.length, imgs = this.config.imagesToShow, margin = this.marginWidth;
     //Dimensions et position d'un snapshot dans la mosaïque.
     var snHeight = this.snapshotHeight, snWidth = this.snapshotWidth;
     var sTop = snapshot.position().top, sLeft = snapshot.position().left;
-    var prezoomPercentage = this.config['prezoomPercentage'];
+    var prezoomPercentage = this.config.prezoomPercentage;
     
     //ID de l'image actuelle.
     var currentId = $('img', snapshot).attr('id');
     
     //Si un zoom est déjà en cours, on ne zoom sur rien d'autre en attendant que ce snapshot ai dézoomé en cas de mouseleave.
     if(this.zoomed)
-	{
-		/*var currentSN = this.pointerPositionToSN(pointerX, pointerY);
-		if(currentSN != null && currentSN.attr('id') != snapshot.attr('id'))
-		{
-			this.preUnzoom();
-		}*/
-        // if($('#preZoomContainer-' + currentId) != $(this) && this.previousZoomedSN != '' && this.previousId != '')
-        /*if(this.previousZoomedSN.attr('id') !== snapshot.attr('id'))
-		{
-            this.preUnzoom();
-		}
-        else
-		{
-            return;
-		}*/
-		this.preUnzoom();
-		// return;
-	}
+    {
+        this.preUnzoom();
+    }
     
     //On indique qu'on a zoomé et on spécifie le snapshot sur lequel on a zoomé.
     this.zoomed = true;
@@ -68,13 +74,13 @@
     //On l'ajoute à la mosaïque.
     $('#mainPanel').append(fakeSnapshot);
     //On modifie ses attributs.
-	// console.log('cid : ' + currentId, $('#fake-' + currentId).length);
+    // console.log('cid : ' + currentId, $('#fake-' + currentId).length);
     $('#fake-' + currentId).load(function()
     {
-	// snapshot.fadeTo(400, '0.5').delay(200).fadeTo(400, '1');
+    // snapshot.fadeTo(400, '0.5').delay(200).fadeTo(400, '1');
         $('#prezoomContainer-' + currentId).css('top', sTop).css('left', sLeft).css('width', (snWidth + margin)).css('height', (snHeight + margin));
         $('#prezoomSnapshot-' + currentId).css('width', (snWidth)).css('height', (snHeight));
-		$('#prezoomContainer-' + currentId).css('display', 'block');
+        $('#prezoomContainer-' + currentId).css('display', 'block');
         
         //Dimensions et coordonnées initiales du div sur lequel on zoom.
         var initialDivWidth = $('#prezoomContainer-' + currentId).width(), initialDivHeight = $('#prezoomContainer-' + currentId).height();
@@ -85,31 +91,21 @@
         
         //CAS PARTICULIER pour la position du snapshot zoomé : les bordures.
         if(finalDivTop < 0)
-		{
+        {
             finalDivTop = -margin;
-		}
+        }
         if(finalDivTop + finalDivHeight > h)
-		{
+        {
             finalDivTop = h - finalDivHeight;
-		}
+        }
         if(finalDivLeft < 0)
-		{
+        {
             finalDivLeft = 0;
-		}
+        }
         if(finalDivLeft + finalDivWidth + margin*2 > w)
-		{
+        {
             finalDivLeft = w - finalDivWidth - margin*2;
-		}
-        
-        ////Code de debug.
-        ////CAUTION////
-        /*var red = '<div id="red"></div>';
-        if($('#red') != null || $('#red') != undefined)
-            $('body').append(red);
-        $('#red').css('background-color', '#FF0000').css('position', 'absolute').css('top', '0px').css('left', '0px').css('width', '100px').css('height', '100px');
-        $('#red').css('top', finalDivTop).css('left', finalDivLeft).css('width', finalDivWidth).css('height', finalDivHeight);*/
-        //alert("initial : " + initialDivWidth + " " + initialDivHeight + " ; final : " + finalDivWidth + " " + finalDivHeight);
-        ////CAUTION////
+        }
         
         //On prézoom le div en le centrant sur le milieu du snapshot pointé.
         $('#prezoomSnapshot-' + currentId).animate(
@@ -118,179 +114,170 @@
             height: finalDivHeight - margin*2,
             top: finalDivTop + margin,
             left: finalDivLeft + margin
-        }, _this.config['timePrezoom']);
+        }, _this.config.timePrezoom);
         $('#prezoomContainer-' + currentId).animate(
         {
             width: finalDivWidth + margin*2,
             height: finalDivHeight - margin,
             top: finalDivTop + margin,
             left: finalDivLeft
-        }, _this.config['timePrezoom'], function()
-		{
-			if(!_this.mouseInteractions)
-			{
-				//On met le spinner gif sur le pointeur, s'il n'existe pas déjà.
-				if($('#spinner').length == 0)
-				{
-					//On repère le pointeur ayant provoqué le prezoom.
-					var prezoomPointer;
-					if(!_this.isMainPointerDisplayed)
-					{
-						prezoomPointer = $('#secondPointer');
-					}
-					if(!_this.isSecondPointerDisplayed)
-					{
-						prezoomPointer = $('#mainPointer');
-					}
-					
-					var spinner = "<img id='spinner'></div>";
-					$('body').append(spinner);
-					$('#spinner').css(
-					{
-						position: 'absolute',
-						top: prezoomPointer.position().top,
-						left: prezoomPointer.position().left,
-						width: 85,
-						height: 85,
-						'z-index': 600
-					});
-					$('#spinner').attr('src', './img/cursors/selector_anim_2.gif');
-				}
-			}
-			else
-			{
-				_this.isOnAPrezoomSN = true;
-			}
-			
-			if(_this.currentMode == 'MOSAIC')
-			{
-				_this.removeNotifications();
-				_this.mosaicSelection();
-			}
-			else if(_this.currentMode == 'FILTER' && !_this.filterSearchedType && _this.curvesGesturesFound)
-			{
-				_this.removeNotifications();
-				_this.filterSearchAndSelection();
-			}
-			else if(_this.currentMode == 'FILTER' && _this.filterSearchedType)
-			{
-				_this.removeNotifications();
-				_this.filterGestureAndSelection(_this.filterSearchedType, 'valid');
-			}
-		});
+        }, _this.config.timePrezoom, function()
+        {
+			//On a fini de prézoomer.
+			_this.isPrezooming = false;
+            //Si on est en mode Kinect.
+            if(!_this.config.mouseInteractions)
+            {
+                //On met le spinner gif sur le pointeur, s'il n'existe pas déjà.
+                if($('#spinner').length == 0)
+                {
+                    //On repère le pointeur ayant provoqué le prezoom.
+                    var prezoomPointer;
+                    if(!_this.isMainPointerDisplayed)
+                    {
+                        prezoomPointer = $('#secondPointer');
+                    }
+                    if(!_this.isSecondPointerDisplayed)
+                    {
+                        prezoomPointer = $('#mainPointer');
+                    }
+                    
+                    //On crée le spinner qui indique le temps restant avant le zoom.
+                    var spinner = "<img id='spinner'></div>";
+                    $('body').append(spinner);
+                    $('#spinner').css(
+                    {
+                        position: 'absolute',
+                        top: prezoomPointer.position().top,
+                        left: prezoomPointer.position().left,
+                        width: 85,
+                        height: 85,
+                        'z-index': 600
+                    });
+                    $('#spinner').attr('src', './img/cursors/selector_anim_2.gif');
+                }
+            }
+            //Si on est en mode d'interaction souris, on indique juste qu'on est en prezoom.
+            else
+            {
+                _this.isOnAPrezoomSN = true;
+            }
+            
+            //Si on est en mode mosaic, on indique juste qu'on effectue une selection.
+            if(_this.currentMode == 'MOSAIC')
+            {
+                _this.removeNotifications();
+                _this.mosaicSelection();
+            }
+            //Si on est en filtrage, mais qu'on n'a pas encore de gesture de filtrage, on indique qu'on est en filtrage et en selection.
+            else if(_this.currentMode == 'FILTER' && !_this.filterSearchedType && _this.curvesGesturesFound)
+            {
+                _this.removeNotifications();
+                _this.filterSearchAndSelection();
+            }
+            //Si on est en filtrage avec une gesture de recherche, on indique la gesture et la selection.
+            else if(_this.currentMode == 'FILTER' && _this.filterSearchedType)
+            {
+                _this.removeNotifications();
+                _this.filterGestureAndSelection(_this.filterSearchedType, 'valid');
+            }
+        });
     });
     
-	if(!this.mouseInteractions)
-	{
-		this.zoomTimeout = setTimeout(function()
-		{
-			_this.zoom();
-		}, this.config['timeoutZoom']);
-	}
+    //Si on est en mode Kinect, on zoom après un certain temps.
+    if(!this.config.mouseInteractions)
+    {
+        this.zoomTimeout = setTimeout(function()
+        {
+            _this.zoom();
+        }, this.config.timeoutZoom);
+    }
 }
 
 /*
  * 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é.
+ * Est appelé dans les fichiers :
+ * pointers > fonction pointersMosaicInteractions.
+ * zoomInteractions > fonctions preZoom et zoom.
+ * mosaic > fonction onMouseMove.
+ * client > fonction processMsg.
  */
-mosaic.prototype.preUnzoom = function()
+Mosaic.prototype.preUnzoom = function()
 {
-    //Si on n'a pas zoomé, on quitte la fonction.
-    /*if(!this.zoomed)
-	{
-        return;
-	}*/
-	
-	/*if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") > -1)
-	{
-		return;
-	}*/
-	
-	$('#spinner').remove();
-	
-	var _this = this;
-	
-	this.isOnAPrezoomSN = false;
-	clearTimeout(this.zoomTimeout);
-	
-	if(this.currentMode == 'MOSAIC')
-	{
-		this.removeNotifications();
-		this.mosaicSelectionAndSearch();
-	}
-	else if(_this.currentMode == 'FILTER' && !this.filterSearchedType && !this.curvesGesturesFound)
-	{
-		this.removeNotifications();
-		this.filterSearch();
-	}
-	else if(_this.currentMode == 'FILTER' && this.filterSearchedType && !this.curvesGesturesFound)
-	{
-		this.removeNotifications();
-		this.filterGesture(this.filterSearchedType, 'valid');
-	}
-	/*this.removePointMosaicPrezoom();
-	this.notifySelectionSearchMosaicFull();*/
+    $('#spinner').remove();
+    
+    var _this = this;
+    
+    //On indique qu'on n'est plus en prezoom.
+    this.isOnAPrezoomSN = false;
+    clearTimeout(this.zoomTimeout);
+    
+    //Si on est en mode mosaic, on indique qu'on peut pointer ou bien rechercher.
+    if(this.currentMode == 'MOSAIC')
+    {
+        this.removeNotifications();
+        this.mosaicSelectionAndSearch();
+    }
+    //Si on est en filtrage sans gesture, on indique qu'on est juste en filtrage.
+    else if(_this.currentMode == 'FILTER' && !this.filterSearchedType && !this.curvesGesturesFound)
+    {
+        this.removeNotifications();
+        this.filterSearch();
+    }
+    //Si on est en filtrage avec gesture, on indique la gesture de filtrage.
+    else if(_this.currentMode == 'FILTER' && this.filterSearchedType && !this.curvesGesturesFound)
+    {
+        this.removeNotifications();
+        this.filterGesture(this.filterSearchedType, 'valid');
+    }
     
     //On spécifie la marge afin de centrer le prédézoom.
     var margin = this.marginWidth;
     //ID du snapshot précédemment pointé.
     var id = this.previousId;
-    //On ne zoom plus.
-    //this.zoomed = false;
     //On rétrécit le snapshot de prézoom, puis on le supprime en donnant l'illusion qu'il s'agissait du véritable snapshot, alors qu'en fait c'était un clone.
-	for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
-	{
-		if($('#prezoomContainer-snapshot-' + i).length > 0)
-		{
-			$('#prezoomContainer-snapshot-' + i).animate(
-			{
-				width: this.snapshotWidth + margin,
-				height: this.snapshotHeight + margin,
-				top: $('#snapshotDiv-' + i).position().top,//this.previousZoomedSN.position().top,
-				left: $('#snapshotDiv-' + i).position().left//this.previousZoomedSN.position().left
-			}, this.config['preUnzoomTime'], function(){ $(this).remove(); _this.zoomed = false; });
-			$('#prezoomSnapshot-snapshot-' + i).animate(
-			{
-				width: this.snapshotWidth,
-				height: this.snapshotHeight,
-				top: $('#snapshotDiv-' + i).position().top,//this.previousZoomedSN.position().top,
-				left: $('#snapshotDiv-' + i).position().left//this.previousZoomedSN.position().left
-			}, this.config['preUnzoomTime']);
-		}
-	}
-	
-    /*$('#prezoomSnapshot-' + id).animate(
+    for(var i = 0 ; i < this.config.imagesToShow ; i++)
     {
-        width: this.snapshotWidth,
-        height: this.snapshotHeight,
-        top: this.previousZoomedSN.position().top,
-        left: this.previousZoomedSN.position().left
-    }, this.config['preUnzoomTime']);
-    $('#prezoomContainer-' + id).animate(
-    {
-        width: this.snapshotWidth + margin,
-        height: this.snapshotHeight + margin,
-        top: this.previousZoomedSN.position().top,
-        left: this.previousZoomedSN.position().left
-    }, this.config['preUnzoomTime'], function(){ $(this).remove(); _this.zoomed = false; });*/
+        if($('#prezoomContainer-snapshot-' + i).length > 0)
+        {
+            $('#prezoomContainer-snapshot-' + i).animate(
+            {
+                width: this.snapshotWidth + margin,
+                height: this.snapshotHeight + margin,
+                top: $('#snapshotDiv-' + i).position().top,
+                left: $('#snapshotDiv-' + i).position().left
+            }, this.config.preUnzoomTime, function(){ $(this).remove(); _this.zoomed = false; });
+            $('#prezoomSnapshot-snapshot-' + i).animate(
+            {
+                width: this.snapshotWidth,
+                height: this.snapshotHeight,
+                top: $('#snapshotDiv-' + i).position().top,
+                left: $('#snapshotDiv-' + i).position().left
+            }, this.config.preUnzoomTime);
+        }
+    }
 }
 
 
 /*
  * Zoom d'un snapshot en plein écran.
+ * Est appelé dans les fichiers :
+ * zoomInteractions > fonction preZoom.
+ * mosaic > fonctions onMouseUp et init.
  */
-mosaic.prototype.zoom = function()
+Mosaic.prototype.zoom = function()
 {
     var _this = this;
     
     //Si la mosaïque est en pleine écran, pas la peine de zoomer.
     if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH" || this.currentMode.indexOf("INCOMING") > -1 || this.helpDisplayed)
-	{
+    {
         return;
-	}
+    }
     
     //On prend les attributs nécessaires au calculs.
-    var margin = this.marginWidth, len = this.config['length'], imgs = this.config['imagesToShow'], zoomedMargin = this.config['zoomedMargin'];
-	var zoomPercentage = this.config['zoomPercentage'];
+    var margin = this.marginWidth, len = this.config.length, imgs = this.config.imagesToShow, zoomedMargin = this.config.zoomedMargin;
+    var zoomPercentage = this.config.zoomPercentage;
     var initMPWidth = this.previousZoomedSN.width() * len + margin*len, initMPHeight = this.previousZoomedSN.height() * (imgs / len) + margin*(imgs / len);
     var newMPWidth = initMPWidth * len + zoomedMargin * (len), newMPHeight = initMPHeight * (imgs / len) + zoomedMargin * ((imgs / len));
     var newPreMPWidth = initMPWidth * len * zoomPercentage + zoomedMargin * (len), newPreMPHeight = initMPHeight * (imgs / len) * zoomPercentage + zoomedMargin * ((imgs / len));
@@ -303,7 +290,7 @@
     var newZoomTop = -this.previousZoomedSN.position().top*(newPreMPHeight/initMPHeight) - zoomedMargin/2 + (initMPHeight - initMPHeight * zoomPercentage)/2, newZoomLeft = -this.previousZoomedSN.position().left*(newPreMPWidth/initMPWidth) - zoomedMargin/2 + (initMPWidth - initMPWidth * zoomPercentage)/2;
     var newSnWidth = initMPWidth * zoomPercentage, newSnHeight = initMPHeight * zoomPercentage;
     
-    this.preUnzoom(this);
+    this.preUnzoom();
     /*SINGULARITE*/
     this.fullscreen = true;
     
@@ -316,29 +303,28 @@
     var tab, zoomedImgId;
     tab = _this.previousId.split('-');
     zoomedImgId = tab[1];
-	
-	//On donne les dimensions des snapshots.
-	$('.snapshotDivs').animate(
-	{
-		width: newSnWidth,
-		height: newSnHeight,
-		margin: zoomedMargin/2 + 'px',
-	}, this.config['zoomTime']);
-	
-	if(this.currentMode != 'NO-USER')
-	{
-		//Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
-		$('.snapshotDivs').animate(
-		{
-			opacity: '0.4'
-		}, this.config['zoomTime']);
-		//Le snapshot du milieu revient à une opacité optimale, ce qui attire l'attention de l'utilisateur.
-		$(this.previousZoomedSN).animate(
-		{
-			opacity: '1'
-		}, this.config['zoomTime']);
-	}
-	// console.log('BBB1 : ' + this.currentMode);
+    
+    //On donne les dimensions des snapshots.
+    $('.snapshotDivs').animate(
+    {
+        width: newSnWidth,
+        height: newSnHeight,
+        margin: zoomedMargin/2 + 'px',
+    }, this.config.zoomTime);
+    
+    if(this.currentMode != 'NO-USER')
+    {
+        //Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
+        $('.snapshotDivs').animate(
+        {
+            opacity: '0.4'
+        }, this.config.zoomTime);
+        //Le snapshot du milieu revient à une opacité optimale, ce qui attire l'attention de l'utilisateur.
+        $(this.previousZoomedSN).animate(
+        {
+            opacity: '1'
+        }, this.config.zoomTime);
+    }
     //On zoome sur la mosaïque.
     $('#mainPanel').animate(
     {
@@ -346,134 +332,81 @@
         height: newPreMPHeight,
         top: newZoomTop,
         left: newZoomLeft
-    }, this.config['zoomTime'], function()
+    }, this.config.zoomTime, function()
     {
         _this.snTop = (zoomedImg.position().top + newZoomTop + _this.MPTop_margin), _this.snLeft = (zoomedImg.position().left + newZoomLeft);
-		_this.snWidth = newSnWidth + 1, _this.snHeight = newSnHeight + 1;
-		
-		_this.notifyTopVideo = newZoomTop;
-		_this.notifyLeftVideo = newZoomLeft;
-		
-		//On charge les interactions avec les voisins.
+        _this.snWidth = newSnWidth + 1, _this.snHeight = newSnHeight + 1;
+        
+        _this.notifyTopVideo = newZoomTop;
+        _this.notifyLeftVideo = newZoomLeft;
+        
+        //On charge les interactions avec les voisins.
         _this.centerId = zoomedImgId;
-		// console.log('BBB2 : ' + _this.currentMode);
-		if(_this.currentMode != "NO-USER")
-		{
-			// console.log('PROBLEM');
-			_this.currentMode = 'VIDEO';
-			_this.listenToNeighbours();
-		}
-		
-		console.log('gesture shown : ' + _this.currentSearchGesture[_this.centerId]);
-		
-		if(_this.currentSearchGesture[_this.centerId] != '')
-		{
-			_this.currentMode = 'SEARCH';
-			_this.isCurrentlyInASearchByGesture = true;
-			_this.removeNotifications();
-			_this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid');
-		}
-		
-		$('#spinner').remove();
-		$('#mainPointer').css('background-image', 'url(./img/cursors/pointer.png)');
-		$('#secondPointer').css('background-image', 'url(./img/cursors/pointer2.png)');
-		
-		// console.log('BBB3 : ' + _this.currentMode);
-		_this.loadPlayer(_this.snTop, _this.snLeft, _this.snWidth, _this.snHeight, newZoomTop, newZoomLeft, _this.timeToGoAt[_this.centerId]);
-		
-		$('body').click(function()
-		{
-			//Si on clique en dehors de la video centrale, alors on dézoome.
-			var TL = $('.Ldt-Timeline');
-			var TLwidth = TL.width(), TLheight = TL.height();
-			var Ptop = $('.LdtPlayer').position().top, Pleft = $('.LdtPlayer').position().left;
-			var Pheight = $('.LdtPlayer').height();
-			var MPx = _this.mousePosX, MPy = _this.mousePosY;
-			
-			//On regarde si on a cliqué sur un snapshot.
-			var SN = _this.pointerPositionToSN(MPx - _this.notifyLeftVideo, MPy - _this.notifyTopVideo, true);
-			var SNId;
-			if(SN)
-			{
-				SNId = parseInt(SN.attr('id').replace('snapshotDiv-', ''));
-			}
-			
-			if(!_this.gestureDelRequested)
-			{
-				//Si non, ou s'il ne fait pas partie des voisins.
-				if(!SNId || !_.include(_this.neighboursIds, SNId))
-				{
-					if(MPx < Pleft || MPx > (+Pleft + TLwidth) || MPy < Ptop || MPy > (+Ptop + Pheight - TLheight))
-					{
-						_this.unzoom();
-					}
-				}
-				//Si on se trouve sur un voisin, on bouge.
-				else if(SNId && _.include(_this.neighboursIds, SNId) && _this.canMoveToNeighbour)
-				{
-					_this.moveToNeighbour($('#snapshotDiv-' + SNId));
-				}
-			}
-			else
-			{
-				_this.gestureDelRequested = false;
-			}
-		});
-		
-		$('body').on('mousewheel', function(event, delta, deltaX, deltaY)
-		{
-			//Action quand on "tire" la molette vers soi.
-			if (delta < 0)
-			{
-				_this.unzoom();
-			}
-		});
+        
+        //Si on n'est pas en mode sans utilisateur, on passe en mode video et on regarde les voisins.
+        if(_this.currentMode != "NO-USER")
+        {
+            _this.currentMode = 'VIDEO';
+            _this.listenToNeighbours();
+        }
+        
+        //Si on a une recherche dans cette video.
+        if(_this.currentSearchGesture[_this.centerId] != '')
+        {
+            //On passe en recherche en indiquant la gesture de recherche.
+            _this.currentMode = 'SEARCH';
+            _this.isCurrentlyInASearchByGesture = true;
+            _this.removeNotifications();
+            _this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid');
+        }
+        
+        //On enlève le spinner et on redonne les apparences par défaut aux pointeurs.
+        $('#spinner').remove();
+        $('#mainPointer').css('background-image', 'url(./img/cursors/pointer.png)');
+        $('#secondPointer').css('background-image', 'url(./img/cursors/pointer2.png)');
+        
+        //On charge le player.
+        _this.loadPlayer(_this.snTop, _this.snLeft, _this.snWidth, _this.snHeight, newZoomTop, newZoomLeft, _this.timeToGoAt[_this.centerId]);
     });
 }
 
 /*
  * Retour à la taille normale de la mosaïque.
+ * Est appelé dans les fichiers :
+ * neighbours > fonction checkForDezoom.
+ * zoomInteractions > fonction zoom.
+ * mosaic > fonctions showNImages et onPlayerLoad.
  */
-mosaic.prototype.unzoom = function()
+Mosaic.prototype.unzoom = function()
 {
     //Si on n'est pas en plein écran, on quitte.
-	// console.log("'" + this.currentMode + "'");
     if(this.currentMode != "SEARCH" && this.currentMode != "VIDEO" && this.currentMode != "NO-USER" && this.currentMode.indexOf("INCOMING") == -1)
-	{
+    {
         return;
-	}
-	
-	var _this = this;
-	
-	if(this.mouseInteractions)
-	{
-		$(window).unbind('click');
-		$(window).unbind('mousewheel');
-	
-		//On rebind le clic pour supprimer une recherche.
-		$(window).click(function(e)
-		{
-			_this.removeSearchNotificationIfOnIt(e.pageX, e.pageY);
-		});
-	}
-	
-	this.canSwipe = false;
-	
-	//Si la TL avait été sélectionnée, on la déselectionne.
-	if(this.currentMode == 'TIMELINE')
-	{
-		this.exitTimeline('unzoom');
-	}
-	
-	this.currentlyUnzooming = true;
-	
-	this.removeAdditionalNeighbours();
-	this.deselectAllNeighbours();
-	
-	this.snTop = 0;
-	this.snLeft = 0;
-	this.Width = 0;
-	this.snHeight = 0;
+    }
+    
+    var _this = this;
+    
+    //Il n'est plus possible de swiper.
+    this.canSwipe = false;
+    
+    //Si la TL avait été sélectionnée, on la déselectionne.
+    if(this.currentMode == 'TIMELINE')
+    {
+        this.exitTimeline('unzoom');
+    }
+    
+    //On indique qu'on est en train de dezoomer.
+    this.currentlyUnzooming = true;
+    
+    //On supprime les voisins additionnels et on déselectionne les voisins.
+    this.removeAdditionalNeighbours();
+    this.deselectAllNeighbours();
+    
+    this.snTop = 0;
+    this.snLeft = 0;
+    this.Width = 0;
+    this.snHeight = 0;
     
     //On charge les attributs nécessaires aux calculs.
     var sWidth = this.snapshotWidth, sHeight = this.snapshotHeight;
@@ -484,18 +417,18 @@
     var zoomedImg = $('img', this.previousZoomedSN);
     var src = zoomedImg.attr('src');
     zoomedImg.attr('src', src.replace('snapshots/', 'snapshots-little/'));
-	
-	if(_this.player.widgets && _this.player.widgets[0])
-	{
-		// console.log(Math.floor(_this.player.popcorn.currentTime()));
-		_this.timeToGoAt[_this.centerId] = Math.floor(_this.player.popcorn.currentTime());
-		_this.player.widgets[0].freePlayer();
-	}
-	
-	_this.playerIsReady = false;
-	$('.LdtPlayer').remove();
-	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
-	_this.reaffectKeyPress();
+    
+    //On libère le player.
+    if(_this.player.widgets && _this.player.widgets[0])
+    {
+        _this.timeToGoAt[_this.centerId] = Math.floor(_this.player.popcorn.currentTime());
+        _this.player.widgets[0].freePlayer();
+    }
+    
+    //On indique que le player n'est pas prêt et on le supprime.
+    _this.playerIsReady = false;
+    $('.LdtPlayer').remove();
+    $('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
     
     //On rend leur opacité aux snapshots. Qui ne sont alors plus grisés.
     $('.snapshotDivs').animate(
@@ -503,41 +436,46 @@
         width: sWidth,
         height: sHeight,
         margin: this.marginWidth/2 + 'px'
-    }, this.config['unzoomTime'], function()
-	{
-		_this.neighboursIds.length = 0;
-		_this.currentlyUnzooming = false;
-	});
-	
-	if(this.currentMode != 'NO-USER')
-	{
-		if(this.currentMode.indexOf("INCOMING") == -1 && !this.isMosaicFiltered)
-		{
-			$('.snapshotDivs').animate(
-			{
-				opacity: '1'
-			}, this.config['unzoomTime']);
-		}
-		else if(this.currentMode.indexOf("INCOMING") == -1 && this.isMosaicFiltered)
-		{
-			for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
-			{
-				$('#snapshotDiv-' + i).animate(
-				{
-					opacity: this.opacities[i]
-				}, this.config['unzoomTime']);
-			}
-		}
-	}
-	else
-	{
-		// console.log('init');
-		this.previousZoomedSN.fadeTo(this.config['unzoomTime'], 0, function()
-		{
-			_this.init();
-		});
-	}
-	
+    }, this.config.unzoomTime, function()
+    {
+        //Après le dezoom, on indique qu'on a finit de dezoomer.
+        _this.neighboursIds.length = 0;
+        _this.currentlyUnzooming = false;
+    });
+    
+    //Si l'utilisateur est là.
+    if(this.currentMode != 'NO-USER')
+    {
+        //Si l'utilisateur est déjà au moins d'interaction maximal et que la mosaique n'est pas filtrée, on rend visibles tous les snapshots.
+        if(this.currentMode.indexOf("INCOMING") == -1 && !this.isMosaicFiltered)
+        {
+            $('.snapshotDivs').animate(
+            {
+                opacity: '1'
+            }, this.config.unzoomTime);
+        }
+        //Si l'utilisateur est déjà au moins d'interaction maximal et que la mosaique est filtrée, on réapplique le filtre sur la mosaique.
+        else if(this.currentMode.indexOf("INCOMING") == -1 && this.isMosaicFiltered)
+        {
+            for(var i = 0 ; i < this.config.imagesToShow ; i++)
+            {
+                $('#snapshotDiv-' + i).animate(
+                {
+                    opacity: this.opacities[i]
+                }, this.config.unzoomTime);
+            }
+        }
+    }
+    //Si on est en mode sans utilisateur.
+    else
+    {
+        //On sélectionne un autre snapshot pour le jouer dans le player.
+        this.previousZoomedSN.fadeTo(this.config.unzoomTime, 0, function()
+        {
+            _this.init();
+        });
+    }
+    
     //On dézoom sur la mosaïque.
     $('#mainPanel').animate(
     {
@@ -545,40 +483,34 @@
         height: mpHeight,
         top: '0px',
         left: '0px'
-    }, this.config['unzoomTime'], function()
+    }, this.config.unzoomTime, function()
     {
         //On n'est plus en plein écran, et on ne peut plus se déplacer vers le prochain voisin.
         _this.fullscreen = false;
         _this.canMoveToNeighbour = false;
-		
-		if(_this.currentMode != 'NO-USER' && _this.currentMode.indexOf('INCOMING-') == -1)
-		{
-			if(_this.isMosaicFiltered)
-			{
-				//On revient en mode FILTER.
-				_this.currentMode = 'FILTER';
-			}
-			else
-			{
-				//On revient en mode MOSAIC.
-				_this.currentMode = 'MOSAIC';
-			}
-			
-			//On ne permet plus le déplacement vers les voisins.
-			/*$('.snapshotDivs').unbind('mouseover', function()
-			{
-				_this.selectNeighbour();
-			});*/
-			
-			//On remet les notifications initiales si on n'est pas dans une recherche par filtrage.
-			if(_this.currentMode == 'MOSAIC' && !_this.filterSearchedType)
-			{
-				_this.removeNotifications();
-				// _this.notifySelectionSearchMosaicFull();
-				_this.mosaicSelectionAndSearch();
-			}
-		}
-		
-		this.currentlyUnzooming = false;
+        
+        //Si on est au point d'interaction maximal.
+        if(_this.currentMode != 'NO-USER' && _this.currentMode.indexOf('INCOMING-') == -1)
+        {
+            //Si la mosaique est filtrée, on revient en mode de filtrage, sinon en mode mosaic.
+            if(_this.isMosaicFiltered)
+            {
+                _this.currentMode = 'FILTER';
+            }
+            else
+            {
+                _this.currentMode = 'MOSAIC';
+            }
+            
+            //On remet les notifications initiales si on n'est pas dans une recherche par filtrage.
+            if(_this.currentMode == 'MOSAIC' && !_this.filterSearchedType)
+            {
+                _this.removeNotifications();
+                _this.mosaicSelectionAndSearch();
+            }
+        }
+        
+        //On indique qu'on est plus en dezoom.
+        this.currentlyUnzooming = false;
     });
 }
\ No newline at end of file
--- a/front_idill/src/player/metadataplayer/Timeline.css	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/player/metadataplayer/Timeline.css	Mon Jul 23 16:59:35 2012 +0200
@@ -1,13 +1,41 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : Timeline.css
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Style associé au Widget Timeline chargé dans le metadataplayer.
+ */
+
 /* Timeline Widget */
 
+/*
+ * Charset utilisé dans la Timeline.
+*/
 @charset "UTF-8";
 
+/*
+ * Police utilisée dans la Timeline.
+*/
 @font-face {
     font-family: "DINMedium";
     src: url("../../fonts/DINMedium.ttf") format("truetype");
     font-weight:10;
 }
 
+/*
+ * Style de la Timeline.
+*/
 .Ldt-Timeline {
 	border: none;
 	border-radius: 0;
@@ -19,6 +47,9 @@
 	background-repeat: repeat;
 }
 
+/*
+ * Style de la barre centrale de la Timeline.
+*/
 .Ldt-TimelineMiddle {
 	border: none;
 	border-radius: 0;
@@ -31,10 +62,16 @@
 	z-index:100;
 }
 
+/*
+ * Style du slider de la Timeline.
+*/
 .Ldt-Timeline .ui-slider-handle {
 	display: none;
 }
 
+/*
+ * Style du slider lu de la Timeline.
+*/
 .Ldt-Timeline .ui-slider-range {
 	border: none;
 	border-radius: 0;
@@ -47,6 +84,9 @@
 	z-index: 50;
 }
 
+/*
+ * Style des marqueurs et des marqueurs recherchés.
+*/
 .Ldt-Marker, .search_Marker {
 	position: absolute;
 	width: 10px;
@@ -58,6 +98,9 @@
 	z-index: 200;
 }
 
+/*
+ * Style des bordures d'une Timeline sélectionnée.
+*/
 .TL_Borders {
 	position: absolute;
 	background-image: url("../../img/selected_timeline.png");
@@ -66,6 +109,9 @@
 	z-index: 150;
 }
 
+/*
+ * Style des flèches d'une Timeline sélectionnée.
+*/
 .TL_Arrows {
 	position: absolute;
 	display: none;
@@ -76,12 +122,18 @@
 	z-index: 150;
 }
 
+/*
+ * Style des détails des marqueurs lorsque le curseur passe dessus.
+*/
 .TL_MarkersBig {
 	position: absolute;
 	display: none;
 	z-index: 200;
 }
 
+/*
+ * Style des textes des détails des marqueurs.
+*/
 #MB_Text {
 	background-color: rgba(34, 34, 34, 1);
 	padding: 8px 18px 8px 18px;
@@ -90,6 +142,9 @@
 	font-size: 22px;
 }
 
+/*
+ * Style des pics associés aux textes des détails des marqueurs.
+*/
 #MB_Spike {
 	width: 10px;
 	height: 5px;
@@ -98,6 +153,9 @@
 	background-repeat: no-repeat;
 }
 
+/*
+ * Style des images associées aux détails des marqueurs.
+*/
 #MB_Pic, .search_MBPic {
 	width: 38px;
 	height: 45px;
--- a/front_idill/src/player/metadataplayer/Timeline.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/player/metadataplayer/Timeline.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,159 +1,166 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : Timeline.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Widget de la timeline du player incorporé dans le Front.
+ */
+
 /*
  The Timeline Widget fits right under the video
+ * Est appelé dans les fichiers créant les widgets du metadataplayer.
  */
 
 IriSP.Widgets.Timeline = function(player, config) {
-	
+    
     IriSP.Widgets.Widget.call(this, player, config);
-	this.bindPopcorn("timeupdate","onTimeupdate");
-	this.bindPopcorn("loadedmetadata","ready");
-	this.bindPopcorn("markersready","onMarkersReady");
-    //this.bindPopcorn("IriSP.PlayerWidget.MouseOver","onMouseover");
-    //this.bindPopcorn("IriSP.PlayerWidget.MouseOut","onMouseout");
-	this.timelineSelected = false;
-	this.markerShowTime = 200;
-	this.markerLastTime = 5000;
-	this.markerBigShown = false;
-	this.currentMarkerIdx = -1;
-	this.previousMarkerIdx = -1;
-	this.hideTimeout;
-	this.currentMode = "VIDEO";
-	this.paused = false
-	this.top_epsilon = 0;
-	this.imgDir = "player/img/";
-	this.markersDir = "pictos/small/";
-	this.player = player;
-	this.isCurrentlyInASearchByGesture = false;
-	this.mouseInteractions = false;
-	
-	//Id du marqueur enregistré.
-	this.currentMarkerId;
-	
-	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "knee-up", "right-angle", "wave", "no-motion", "contact"];
-	this.gesturesText = ["chute", "saut", "rotation", "rotation de groupe", "inclinaison", "port de bras", "levé de genou", "angle droit", "ondulation", "immobilité", "contact"];
-	
-	this.annotations = this.annotationsFilter(this.source.getAnnotations(), this.gestures, this.isGesture);
-	
-	// for(var a = 0 ; a < this.annotations.length ; a++)
-		// console.log("A : " + this.annotations[a].annotationType.contents.title);
+    this.bindPopcorn("timeupdate","onTimeupdate");
+    this.bindPopcorn("loadedmetadata","ready");
+    this.bindPopcorn("markersready","onMarkersReady");
+    this.timelineSelected = false;
+    this.markerShowTime = 200;
+    this.markerLastTime = 5000;
+    this.markerBigShown = false;
+    this.currentMarkerIdx = -1;
+    this.previousMarkerIdx = -1;
+    this.hideTimeout;
+    this.currentMode = "VIDEO";
+    this.paused = false
+    this.top_epsilon = 0;
+    this.imgDir = "player/img/";
+    this.markersDir = "pictos/small/";
+    this.player = player;
+    this.isCurrentlyInASearchByGesture = false;
+    this.mouseInteractions = false;
+    
+    //Id du marqueur enregistré.
+    this.currentMarkerId;
+    
+    //Gestures et noms par défaut.
+    this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "knee-up", "right-angle", "wave", "no-motion", "contact"];
+    this.gesturesText = ["chute", "saut", "rotation", "rotation de groupe", "inclinaison", "port de bras", "levé de genou", "angle droit", "ondulation", "immobilité", "contact"];
+    
+	var _this = this;
+    this.annotations = this.source.getAnnotations().filter(function(annotation)
+	{
+		return _this.isGesture(annotation, null, _this.gestures);
+	});
 };
 
+/*
+ * Constructeur du Widget.
+*/
 IriSP.Widgets.Timeline.prototype = new IriSP.Widgets.Widget();
 
+/*
+ * Indique si l'annotation passée en paramètre référence une gesture utilisée dans ce Front.
+*/
 IriSP.Widgets.Timeline.prototype.isGesture = function(element, index, array)
 {
-	return ($.inArray(element.annotationType.contents.title, array) > -1);
+    return ($.inArray(element.annotationType.contents.title, array) > -1);
 }
 
 /*
  * Spécifie si on est en événements souris ou non.
+ * Est appelé dans le fichier :
+ * mosaic > fonction onMarkersReady.
 */
 IriSP.Widgets.Timeline.prototype.setMouseInteractions = function(mouseInteractions)
 {
-	this.mouseInteractions = mouseInteractions;
-	
-	if(mouseInteractions)
-	{
-		this.markersDir += 'MI/';
-	}
+    this.mouseInteractions = mouseInteractions;
+    
+    if(mouseInteractions)
+    {
+        this.markersDir += 'MI/';
+    }
 }
 
 /*
  * Spécifie la langue pour l'affichage des marqueurs.
+ * Est appelé dans le fichier :
+ * mosaic > fonction onMarkersReady.
 */
 IriSP.Widgets.Timeline.prototype.setLang = function(gesturesText)
 {
-	this.gesturesText = gesturesText;
+    this.gesturesText = gesturesText;
 }
 
-//Fonction associée à l'événement : les marqueurs sont prêts.
+/*
+ * Fonction associée à l'événement : les marqueurs sont prêts.
+ * Est appelé dans le fichier :
+ * mosaic > fonction onPlayerLoad.
+*/
 IriSP.Widgets.Timeline.prototype.onMarkersReady = function() {}
 
-//Fonction de filtrage de tableaux
-IriSP.Widgets.Timeline.prototype.annotationsFilter = function(annotations, gestures, fun /*, thisp*/)
-{
-	var len = annotations.length;
-	if (typeof fun != "function")
-		throw new TypeError();
-
-	var res = new Array();
-	var thisp = arguments[1];
-	for (var i = 0; i < len; i++)
-	{
-		if (i in annotations)
-		{
-			var val = annotations[i]; // in case fun mutates this
-			if (fun.call(thisp, val, i, gestures))
-			{
-				res.push(val);
-			}
-		}
-	}
-	return res;
-};
-
+/*
+ * Paramètres par défaut de la timeline.
+*/
 IriSP.Widgets.Timeline.prototype.defaults = {
     minimized_height : 114,//44,
     maximized_height : 114,
-	middle_height: 10,//4,
-	timelineBorderLength : 6,
+    middle_height: 10,//4,
+    timelineBorderLength : 6,
     minimize_timeout : 1500 // time before minimizing timeline after mouseout
 };
 
+/*
+ * Fonction appelée pour dessiner la timeline.
+*/
 IriSP.Widgets.Timeline.prototype.draw = function() {
     this.$timeline = IriSP.jQuery('<div>')
         .addClass("Ldt-Timeline")
         .css(this.calculateTimelineCss(this.minimized_height));
-	this.$timelineMiddle = IriSP.jQuery('<div>')
-		.addClass("Ldt-TimelineMiddle")
+    this.$timelineMiddle = IriSP.jQuery('<div>')
+        .addClass("Ldt-TimelineMiddle")
         .css(this.calculateTimelineMiddleCss(this.minimized_height, this.middle_height));
-	
-	/*this.$timelineContainer = IriSP.jQuery('<div>')
-        .addClass("Ldt-TimelineContainer");
-	this.$timelineContainer.append(this.$timeline);
-	this.$timelineContainer.append(this.$timelineMiddle);*/
-	
-	
+    
+    //On l'ajoute au widget.
     this.$.append(this.$timeline);
     this.$.append(this.$timelineMiddle);
-	
+    
     var _this = this;
     
+    //On définit le slider.
     this.$timeline.slider({
         range: "min",
         value: 0,
         min: 0,
         max: this.source.getDuration().milliseconds,
         slide: function(event, ui) {
-			if(_this.player.popcorn)
-			{
-				_this.player.popcorn.currentTime(Math.floor(ui.value/1000));
-				_this.player.popcorn.trigger("IriSP.Mediafragment.setHashToTime");
-			}
-			
-			// console.log("manual " + _this.previousMarkerIdx);
-			//On supprime le marqueur précédemment affiché si c'est le cas.
-			if(_this.previousMarkerIdx > -1)
-			{
-				// /!\ var annotations = _this.source.getAnnotations();
-				
-				// console.log("EXT hide idx " + _this.previousMarkerIdx);
-				// /!\ var previousMarker = IriSP.jQuery("#" + annotations[_this.previousMarkerIdx].id.replace(":", "_"));
-				var previousMarker = IriSP.jQuery("#" + _this.annotations[_this.previousMarkerIdx].id.replace(":", "_"));
-				_this.hideMarkerBig(previousMarker);
-				// console.log("EXT hide " + _this.previousMarkerIdx);
-			}
+            if(_this.player.popcorn)
+            {
+                _this.player.popcorn.currentTime(Math.floor(ui.value/1000));
+                _this.player.popcorn.trigger("IriSP.Mediafragment.setHashToTime");
+            }
+            
+            //On supprime le marqueur précédemment affiché.
+            if(_this.previousMarkerIdx > -1)
+            {
+                var previousMarker = IriSP.jQuery("#" + _this.annotations[_this.previousMarkerIdx].id.replace(":", "_"));
+                _this.hideMarkerBig(previousMarker);
+            }
         }
     });
-	
+    
     this.$handle = this.$timeline.find('.ui-slider-handle');
     
     this.$handle.css(this.calculateHandleCss(this.minimized_height));
-	
-    this.$
-        .mouseover(this.functionWrapper("onMouseover"))
-        .mouseout(this.functionWrapper("onMouseout"));
-		IriSP.jQuery('body').keypress(function(evt) {_this.keyPress(evt)});
+    
+    //On wrapp mouseover et mouse out.
+    this.$.mouseover(this.functionWrapper("onMouseover")).mouseout(this.functionWrapper("onMouseout"));
+    //On bind keypress.
+    IriSP.jQuery('body').keypress(function(evt) {_this.keyPress(evt)});
     
     this.maximized = false;
     this.timeoutId = false;
@@ -163,856 +170,818 @@
  * Starts playing the video when it's ready.
 */
 IriSP.Widgets.Timeline.prototype.ready = function() {
-	this.player.popcorn.play();
-	this.player.popcorn.mute();
-	this.processMarkers();
+    this.player.popcorn.play();
+    this.player.popcorn.mute();
+    this.processMarkers();
 }
 
 /*
- * Scale a value from [A, B] to [C, D].
+ * Met à l'échelle une valeur de [A, B] vers [C, D].
+ * Est appelé dans les fichiers :
+ * pointers > fonction pointersTimelineSelection.
+ * search > fonction searchFilter.
+ * Timeline > fonctions processMarkers, onTimeupdate et timeDisplayUpdater.
 */
 IriSP.Widgets.Timeline.prototype.scaleIntervals = function(A, B, C, D, val) {
-	if(C == D)
-	{
-		return C;
-	}	
-	if(B != A)
-	{
-		return D / (B - A) * (val - A);
-	}
-	else
-	{
-		//If A and B have the same sign.
-		if(A * B > 0)
-		{
-			//If they are positive.
-			if(A > 0)
-			{
-				return (D - C)/2;
-			}
-			else
-			{
-				return (C - D)/2;
-			}
-		}
-		else
-		{
-			return (C + D)/2;
-		}
-	}
+    if(C == D)
+    {
+        return C;
+    }    
+    if(B != A)
+    {
+        return D / (B - A) * (val - A);
+    }
+    else
+    {
+        //Si A et B ont le même signe.
+        if(A * B > 0)
+        {
+            //S'ils sont positifs.
+            if(A > 0)
+            {
+                return (D - C)/2;
+            }
+            else
+            {
+                return (C - D)/2;
+            }
+        }
+        else
+        {
+            return (C + D)/2;
+        }
+    }
 }
 
 /*
- * Process the markers.
+ * On calcule les marqueurs.
+ * Est appelé dans le fichier :
+ * Timeline > fonction ready.
 */
 IriSP.Widgets.Timeline.prototype.processMarkers = function() {
-	var _this = this;
-	var markers = "";
-	var timelineMiddleTop = this.$timelineMiddle.position().top;
-	
-	for(var i = 0 ; i < this.annotations.length ; i++)
-	{
-		markers += "<div class='Ldt-Marker' id='" + this.annotations[i].id.replace(":", "_") + "'></div>";
-	}
-	
-	this.$.append(markers);
-	var markerHeight = IriSP.jQuery(".Ldt-Marker").height();
-	IriSP.jQuery(".Ldt-Marker").css("z-align", "150");
-	
-	for(var i = 0 ; i < this.annotations.length ; i++)
-	{
-		IriSP.jQuery("#" + this.annotations[i].id.replace(":", "_")).css(
-		{
-			top: timelineMiddleTop + "px",
-			left: Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), this.annotations[i].begin/1000) + this.$timeline.position().left) + "px",
-			"margin-top": (-_this.$timeline.height()/2 - markerHeight/2) - this.top_epsilon + "px"
-		});
-	}
-	
-	//On lance l'événement pour dire à popcorn que les marqueurs sont utilisables.
-	// this.player.popcorn.trigger(IriSP.Widgets.Timeline.onMarkersReady);
-	this.player.popcorn.trigger("markersready");
-	//console.log('markers processed');
+    var _this = this;
+    var markers = "";
+    //On calcule la position en Y de la timeline.
+    var timelineMiddleTop = this.$timelineMiddle.position().top;
+    
+    //Pour toutes les annotations, on crée les marqueurs.
+    for(var i = 0 ; i < this.annotations.length ; i++)
+    {
+        markers += "<div class='Ldt-Marker' id='" + this.annotations[i].id.replace(":", "_") + "'></div>";
+    }
+    
+    //On les ajoute.
+    this.$.append(markers);
+    var markerHeight = IriSP.jQuery(".Ldt-Marker").height();
+    IriSP.jQuery(".Ldt-Marker").css("z-align", "150");
+    
+    //Pour toutes les annotations.
+    for(var i = 0 ; i < this.annotations.length ; i++)
+    {
+        //On les place sur la timeline.
+        IriSP.jQuery("#" + this.annotations[i].id.replace(":", "_")).css(
+        {
+            top: timelineMiddleTop + "px",
+            left: Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), this.annotations[i].begin/1000) + this.$timeline.position().left) + "px",
+            "margin-top": (-_this.$timeline.height()/2 - markerHeight/2) - this.top_epsilon + "px"
+        });
+    }
+    
+    //On lance l'événement pour dire à popcorn que les marqueurs sont utilisables.
+    this.player.popcorn.trigger("markersready");
 }
 
 /*
- * Fonction de recherche par gesures.
+ * Fonction de recherche par gestures.
+ * Est appelé dans les fichiers :
+ * mosaic > fonctions onMouseUp, manageControlEvents et onMarkersReady.
+ * curvesDetector > fonction updateDists.
 */
 IriSP.Widgets.Timeline.prototype.searchByGesture = function(typeName)
 {
-	if(typeName != '' || typeName != undefined)
-	{
-		if(_.include(this.gestures, typeName))
-		{
-			this.currentMode = "SEARCH";
-			this.hideMarkersSearch(typeName);
-			this.isCurrentlyInASearchByGesture = true;
-		}
-	}
+    //Si le type existe.
+    if(typeName != '' || typeName != undefined)
+    {
+        if(_.include(this.gestures, typeName))
+        {
+            //On entre en mode recherche et on affiche les marqueurs sélectionnés.
+            this.currentMode = "SEARCH";
+            this.hideMarkersSearch(typeName);
+            this.isCurrentlyInASearchByGesture = true;
+        }
+    }
 }
 
 /*
  * Fonction de suppression de recherche par gesures.
+ * Est appelé dans le fichier :
+ * pointers > checkIfPointerIsOnSearchNotification et removeSearchNotificationIfOnIt.
 */
 IriSP.Widgets.Timeline.prototype.removeSearchByGesture = function()
 {
-	this.hideMarkersSearch();
-	this.isCurrentlyInASearchByGesture = false;
+    this.hideMarkersSearch();
+    this.isCurrentlyInASearchByGesture = false;
+}
+
+/*
+ * Place le curseur sur la timeline en fonction de la touche pressée.
+ * Est appelé dans le fichier :
+*/
+IriSP.Widgets.Timeline.prototype.keyPress = function(e) {
+    var key = this.whichKey(e.which);
+    var time = 0;
+    
+    //Entre 0 et 10, on met à jour la position du curseur dans la video.
+    if(key > -1 && key < 11)
+    {
+        time = this.source.getDuration().getSeconds()/10*key;
+        this.$timeline.slider("value",time);
+        this.player.popcorn.currentTime(time);
+        
+        //On supprime le marqueur précédemment affiché.
+        if(this.previousMarkerIdx > -1)
+        {
+            var previousMarker = IriSP.jQuery("#" + this.annotations[this.previousMarkerIdx].id.replace(":", "_"));
+            this.hideMarkerBig(previousMarker);
+        }
+    }
+    
+    //p ou P pour mettre en pause.
+    if(key == 21)
+    {
+        if(!this.paused)
+        {
+            this.paused = true;
+            this.player.popcorn.pause();
+        }
+        else
+        {
+            this.paused = false;
+            this.player.popcorn.play();
+        }
+    }
 }
 
 /*
- * Place the cursor on the timeline depending on the keytyped.
+ * Donne une clé correspondante à une touche donnée.
+ * Est appelé dans le fichier :
+ * Timeline > fonction keyPress.
+*/
+IriSP.Widgets.Timeline.prototype.whichKey = function(code) {
+    var key;
+    
+    if(code > 47 && code < 58)
+    {
+        return (code - 48);
+    }
+    
+    if(code == 115 || code == 83)
+    {
+        return 11;
+    }
+    
+    //p ou P pour mettre la vidéo en pause.
+    if(code == 112 || code == 80)
+    {
+        return 21;
+    }
+    
+    switch(code)
+    {
+        case 224:
+            key = 0;
+        break;
+        case 38:
+            key = 1;
+        break;
+        case 233:
+            key = 2;
+        break;
+        case 34:
+            key = 3;
+        break;
+        case 39:
+            key = 4;
+        break;
+        case 40:
+            key = 5;
+        break;
+        case 45:
+            key = 6;
+        break;
+        case 232:
+            key = 7;
+        break;
+        case 95:
+            key = 8;
+        break;
+        case 231:
+            key = 9;
+        break;
+        default:
+            key = -1;
+    }
+    
+    return key;
+}
+
+/*
+ * Fonction de sélection de la timeline.
+ * Est appelé dans le fichier :
+ * pointers > fonction pointersTimelineSelection.
 */
-IriSP.Widgets.Timeline.prototype.keyPress = function(e) {
-	var key = this.whichKey(e.which);
-	var time = 0;
-	
-	// console.log($(this));
-	
-	if(key > -1 && key < 11)
-	{
-		time = this.source.getDuration().getSeconds()/10*key;
-		this.$timeline.slider("value",time);
-		this.player.popcorn.currentTime(time);
-		
-		//On supprime le marqueur précédemment affiché si c'est le cas.
-		if(this.previousMarkerIdx > -1)
-		{
-			// console.log("EXT hide idx " + this.previousMarkerIdx);
-			var previousMarker = IriSP.jQuery("#" + this.annotations[this.previousMarkerIdx].id.replace(":", "_"));
-			this.hideMarkerBig(previousMarker);
-			// console.log("EXT hide " + this.previousMarkerIdx);
-		}
-	}
-	
-	if(key == 11)
-	{
-		if(!this.timelineSelected)
-		{
-			this.currentMode = "TIMELINE";
-			this.selectTimeline();
-		}
-		else
-		{
-			this.currentMode = "VIDEO";
-			this.deselectTimeline();
-		}
-	}
-	
-	if(key == 12)
-	{
-		this.hideMarkersSearch();
-	}
-	
-	if(key == 13)
-	{
-		var gesturesStr = '';
-		for(var i = 0 ; i < this.gestures.length ; i++)
-		{
-			gesturesStr += this.gestures[i] + ", ";
-		}
-		gesturesStr = gesturesStr.substr(0, gesturesStr.length - 2);
-		
-		var typeName = prompt("Please enter a type name among (" + gesturesStr + ").", "");
-		
-		if(typeName != '' || typeName != undefined)
-		{
-			if(_.include(this.gestures, typeName))
-			{
-				this.currentMode = "SEARCH";
-				this.hideMarkersSearch(typeName);
-			}
-		}
-	}
-	
-	if(key == 21)
-	{
-		// console.log(this);
-		if(!this.paused)
-		{
-			this.paused = true;
-			this.player.popcorn.pause();
-		}
-		else
-		{
-			this.paused = false;
-			this.player.popcorn.play();
-		}
-	}
+IriSP.Widgets.Timeline.prototype.selectTimeline = function() {
+    //On crée les bordures.
+    this.timelineSelected = true;
+    this.$timelineBorderUp = "<div class='TL_Borders' id='TL_BorderUp'></div>";
+    this.$timelineBorderDown = "<div class='TL_Borders' id='TL_BorderDown'></div>";
+    this.$timelineBorderLeft = "<div class='TL_Borders' id='TL_BorderLeft'></div>";
+    this.$timelineBorderRight = "<div class='TL_Borders' id='TL_BorderRight'></div>";
+    //Les flèches verticales aussi.
+    this.$arrowUp = "<div class='TL_Arrows' id='TL_ArrowUp'></div>";
+    this.$arrowDown = "<div class='TL_Arrows' id='TL_ArrowDown'></div>";
+    //On les ajoute.
+    this.$.append(this.$timelineBorderUp + this.$timelineBorderDown + this.$timelineBorderLeft + this.$timelineBorderRight + this.$arrowUp + this.$arrowDown);
+    //On calcule la position en Y de la timeline.
+    var timelineTop = IriSP.jQuery("#LdtPlayer").position().top + IriSP.jQuery("#LdtPlayer").height();
+    //On met les styles à jour.
+    IriSP.jQuery("#TL_BorderUp").css(
+    {
+        "margin-top": -this.$timeline.height() - this.top_epsilon,
+        left: this.$timeline.position().left,
+        width: this.$timeline.width(),
+        height: this.timelineBorderLength
+    });
+    IriSP.jQuery("#TL_BorderDown").css(
+    {
+        "margin-top": -this.timelineBorderLength - 2 - this.top_epsilon,
+        left: this.$timeline.position().left,
+        width: this.$timeline.width(),
+        height: this.timelineBorderLength
+    });
+    IriSP.jQuery("#TL_BorderLeft").css(
+    {
+        "margin-top": -this.$timeline.height() - this.top_epsilon,
+        left: this.$timeline.position().left,
+        width: this.timelineBorderLength,
+        height: this.$timeline.height()
+    });
+    IriSP.jQuery("#TL_BorderRight").css(
+    {
+        "margin-top": -this.$timeline.height() - this.top_epsilon,
+        left: +this.$timeline.position().left + this.$timeline.width() - this.timelineBorderLength - 2,
+        width: this.timelineBorderLength,
+        height: this.$timeline.height()
+    });
+    
+    IriSP.jQuery("#TL_ArrowUp").css(
+    {
+        "background-image": "url(" + this.imgDir + "arrow_up.png)",
+        "margin-top": -this.$timeline.height() - IriSP.jQuery("#TL_ArrowUp").height() - this.top_epsilon,
+        left: this.$timeline.position().left - IriSP.jQuery("#TL_ArrowUp").width()/2,
+    });
+    IriSP.jQuery("#TL_ArrowDown").css(
+    {
+        "background-image": "url(" + this.imgDir + "arrow_down.png)",
+        "margin-top": -this.timelineBorderLength + this.timelineBorderLength - this.top_epsilon,
+        left: this.$timeline.position().left - IriSP.jQuery("#TL_ArrowUp").width()/2,
+    });
+    
+    IriSP.jQuery(".Ldt-Timeline .ui-slider-range").css("background-image", "url(" + this.imgDir + "past_timeline.png)");
+}
+
+/*
+ * Déselectionne la timeline.
+ * Est appelé dans le fichier :
+ * playerControl > fonction exitTimeline.
+*/
+IriSP.Widgets.Timeline.prototype.deselectTimeline = function() {
+    //On supprime les éléments qui faisaient que la timeline était sélectionnée.
+    this.timelineSelected = false;
+    IriSP.jQuery(".TL_Borders").remove();
+    IriSP.jQuery(".TL_Arrows").remove();
+    IriSP.jQuery(".Ldt-Timeline .ui-slider-range").css("background-image", "url(" + this.imgDir + "selected_timeline.png)");
 }
 
 /*
- * Find the key corresponding to a given code.
+ * Se met à jour durant la lecture d'une video.
+ * Est appelé dans le fichier :
+ * Timeline
 */
-IriSP.Widgets.Timeline.prototype.whichKey = function(code) {
-	var key;
-	
-	console.log(code);
-	
-	if(code > 47 && code < 58)
-	{
-		return (code - 48);
-	}
-	
-	if(code == 115 || code == 83)
-	{
-		return 11;
-	}
-	
-	//m ou M pour quitter une recherche.
-	if(code == 109 || code == 77)
-	{
-		return 12;
-	}
-	
-	//p ou P pour mettre la vidéo en pause.
-	if(code == 112 || code == 80)
-	{
-		return 21;
-	}
-	
-	//n ou N pour une recherche par type.
-	if(code == 110 || code == 78)
-	{
-		return 13;
-	}
-	
-	switch(code)
-	{
-		case 224:
-			key = 0;
-		break;
-		case 38:
-			key = 1;
-		break;
-		case 233:
-			key = 2;
-		break;
-		case 34:
-			key = 3;
-		break;
-		case 39:
-			key = 4;
-		break;
-		case 40:
-			key = 5;
-		break;
-		case 45:
-			key = 6;
-		break;
-		case 232:
-			key = 7;
-		break;
-		case 95:
-			key = 8;
-		break;
-		case 231:
-			key = 9;
-		break;
-		default:
-			key = -1;
-	}
-	
-	return key;
+IriSP.Widgets.Timeline.prototype.onTimeupdate = function() {
+    //On récupère la position du curseur en secondes.
+    var _time = this.player.popcorn.currentTime();
+    //Position des flèches au cas où la timeline serait sélectionnée.
+    var arrowLeft = Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), _time) + this.$timeline.position().left) - IriSP.jQuery("#TL_ArrowUp").width()/2 + "px";
+    //On met à jour la position du slider en ms.
+    this.$timeline.slider("value",_time*1000);
+    //On affiche les flèches si la timeline est sélectionnée.
+    IriSP.jQuery(".TL_Arrows").css("display", "block");
+    IriSP.jQuery("#TL_ArrowUp").css("left", arrowLeft);
+    IriSP.jQuery("#TL_ArrowDown").css("left", arrowLeft);
+    
+    //Si on a une distance de 500 ms à un marqueur, on l'affiche.
+    var nearestMarkerIdx = 0;
+    for(var i = 0 ; i < this.annotations.length ; i++)
+    {
+        //S'il existe des marqueurs dans l'intervalle de temps actuel (ici 500ms).
+        if(Math.abs(_time*1000 - this.annotations[i].begin.milliseconds) <= 250)
+        {
+            //On sélectionne le plus proche marqueur (dans les cas où il en existe plusieurs dans l'intervalle des 1s) ou bien le premier marqueur.
+            if(Math.abs(_time*1000 - this.annotations[i].begin.milliseconds) < Math.abs(_time*1000 - this.annotations[nearestMarkerIdx].begin.milliseconds) || i == nearestMarkerIdx)
+            {
+                //Si le prochain marqueur se situe après le curseur de lecture, on passe donc au marqueur le plus proche.
+                if(_time*1000 < this.annotations[i].begin.milliseconds)
+                {
+                    nearestMarkerIdx = i;
+                    //S'il y a un changement de marqueur (marqueur actuel différent du précédent).
+                    if(nearestMarkerIdx != this.previousMarkerIdx)
+                    {
+                        var currentMarker = IriSP.jQuery("#" + this.annotations[nearestMarkerIdx].id.replace(":", "_"));
+                        //S'il existe un marqueur précédent, on le cache.
+                        if(this.previousMarkerIdx > -1)
+                        {
+                            var previousMarker = IriSP.jQuery("#" + this.annotations[this.previousMarkerIdx].id.replace(":", "_"));
+                            this.hideMarkerBig(previousMarker);
+                        }
+                        
+                        this.showMarkerBig(currentMarker, this.annotations[nearestMarkerIdx].annotationType.contents.title);
+                        //Mise à jour du marqueur précédent s'il y a un changement.
+                        this.previousMarkerIdx = nearestMarkerIdx;
+                    }
+                }
+            }
+            this.currentMarkerIdx = nearestMarkerIdx;
+        }
+    }
 }
 
-IriSP.Widgets.Timeline.prototype.selectTimeline = function() {
-	this.timelineSelected = true;
-	this.$timelineBorderUp = "<div class='TL_Borders' id='TL_BorderUp'></div>";
-	this.$timelineBorderDown = "<div class='TL_Borders' id='TL_BorderDown'></div>";
-	this.$timelineBorderLeft = "<div class='TL_Borders' id='TL_BorderLeft'></div>";
-	this.$timelineBorderRight = "<div class='TL_Borders' id='TL_BorderRight'></div>";
-	
-	this.$arrowUp = "<div class='TL_Arrows' id='TL_ArrowUp'></div>";
-	this.$arrowDown = "<div class='TL_Arrows' id='TL_ArrowDown'></div>";
-	
-	this.$.append(this.$timelineBorderUp + this.$timelineBorderDown + this.$timelineBorderLeft + this.$timelineBorderRight + this.$arrowUp + this.$arrowDown);
-	
-	var timelineTop = IriSP.jQuery("#LdtPlayer").position().top + IriSP.jQuery("#LdtPlayer").height();
-	
-	IriSP.jQuery("#TL_BorderUp").css(
-	{
-		"margin-top": -this.$timeline.height() - this.top_epsilon,
-		left: this.$timeline.position().left,
-		width: this.$timeline.width(),
-		height: this.timelineBorderLength
-	});
-	IriSP.jQuery("#TL_BorderDown").css(
-	{
-		"margin-top": -this.timelineBorderLength - 2 - this.top_epsilon,
-		left: this.$timeline.position().left,
-		width: this.$timeline.width(),
-		height: this.timelineBorderLength
-	});
-	IriSP.jQuery("#TL_BorderLeft").css(
-	{
-		"margin-top": -this.$timeline.height() - this.top_epsilon,
-		left: this.$timeline.position().left,
-		width: this.timelineBorderLength,
-		height: this.$timeline.height()
-	});
-	IriSP.jQuery("#TL_BorderRight").css(
-	{
-		"margin-top": -this.$timeline.height() - this.top_epsilon,
-		left: +this.$timeline.position().left + this.$timeline.width() - this.timelineBorderLength - 2,
-		width: this.timelineBorderLength,
-		height: this.$timeline.height()
-	});
-	
-	IriSP.jQuery("#TL_ArrowUp").css(
-	{
-		"background-image": "url(" + this.imgDir + "arrow_up.png)",
-		"margin-top": -this.$timeline.height() - IriSP.jQuery("#TL_ArrowUp").height() - this.top_epsilon,
-		left: this.$timeline.position().left - IriSP.jQuery("#TL_ArrowUp").width()/2,
-	});
-	IriSP.jQuery("#TL_ArrowDown").css(
-	{
-		"background-image": "url(" + this.imgDir + "arrow_down.png)",
-		"margin-top": -this.timelineBorderLength + this.timelineBorderLength - this.top_epsilon,
-		left: this.$timeline.position().left - IriSP.jQuery("#TL_ArrowUp").width()/2,
-	});
-	
-	IriSP.jQuery(".Ldt-Timeline .ui-slider-range").css("background-image", "url(" + this.imgDir + "past_timeline.png)");
-}
-
-IriSP.Widgets.Timeline.prototype.deselectTimeline = function() {
-	this.timelineSelected = false;
-	IriSP.jQuery(".TL_Borders").remove();
-	IriSP.jQuery(".TL_Arrows").remove();
-	IriSP.jQuery(".Ldt-Timeline .ui-slider-range").css("background-image", "url(" + this.imgDir + "selected_timeline.png)");
+/*
+ * Met à jour l'affichage régulièrement.
+ * Est appelé dans le fichier :
+ * Timeline
+*/
+IriSP.Widgets.Timeline.prototype.timeDisplayUpdater = function() {
+    //On récupère la position du curseur en secondes.
+    var _time = this.player.popcorn.currentTime();
+    //Position des flèches au cas où la timeline serait sélectionnée.
+    var arrowLeft = Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), _time) + this.$timeline.position().left) -
+    this.$timeline.slider("value",_time*1000);
+    //On affiche les flèches si la timeline est sélectionnée.
+    IriSP.jQuery(".TL_Arrows").css("display", "block");
+    IriSP.jQuery("#TL_ArrowUp").css("left", arrowLeft);
+    IriSP.jQuery("#TL_ArrowDown").css("left", arrowLeft);
 }
 
-IriSP.Widgets.Timeline.prototype.onTimeupdate = function() {
-    var _time = this.player.popcorn.currentTime();
-	var arrowLeft = Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), _time) + this.$timeline.position().left) - IriSP.jQuery("#TL_ArrowUp").width()/2 + "px";
-	
-    this.$timeline.slider("value",_time*1000);
-	IriSP.jQuery(".TL_Arrows").css("display", "block");
-	IriSP.jQuery("#TL_ArrowUp").css("left", arrowLeft);
-	IriSP.jQuery("#TL_ArrowDown").css("left", arrowLeft);
-	// this.player.popcorn.trigger("IriSP.Arrow.updatePosition",{widget: this.type, time: 1000 * _time});
-	//Si on a une distance de 500 ms à un marqueur, on l'affiche.
-	var nearestMarkerIdx = 0;
-	for(var i = 0 ; i < this.annotations.length ; i++)
-	{
-		//S'il existe des marqueurs dans l'intervalle de temps actuel (ici 500ms).
-		if(Math.abs(_time*1000 - this.annotations[i].begin.milliseconds) <= 250)
-		{
-			// console.log("1) i = " + i + " " + Math.abs(_time*1000 - annotations[i].begin.milliseconds));
-			
-			//On sélectionne le plus proche marqueur (dans les cas où il en existe plusieurs dans l'intervalle des 1s) ou bien le premier marqueur.
-			if(Math.abs(_time*1000 - this.annotations[i].begin.milliseconds) < Math.abs(_time*1000 - this.annotations[nearestMarkerIdx].begin.milliseconds) || i == nearestMarkerIdx)
-			{
-				// console.log("2) " + Math.abs(_time*1000 - annotations[i].begin.milliseconds) + " < " + Math.abs(_time*1000 - annotations[nearestMarkerIdx].begin.milliseconds));
-				//Si le prochain marqueur se situe après le curseur de lecture, on passe donc au marqueur le plus proche.
-				if(_time*1000 < this.annotations[i].begin.milliseconds)
-				{
-					// console.log("3) " + _time*1000 + " < " + annotations[i].begin.milliseconds);
-					// console.log("4) " + "nearest = " + i);
-					nearestMarkerIdx = i;
-					// console.log("5a0) before");
-					//S'il y a un changement de marqueur (marqueur actuel différent du précédent).
-					if(nearestMarkerIdx != this.previousMarkerIdx)
-					{
-						var currentMarker = IriSP.jQuery("#" + this.annotations[nearestMarkerIdx].id.replace(":", "_"));
-						//S'il existe un marqueur précédent, on le cache.
-						if(this.previousMarkerIdx > -1)
-						{
-							// console.log("hide idx " + this.previousMarkerIdx);
-							var previousMarker = IriSP.jQuery("#" + this.annotations[this.previousMarkerIdx].id.replace(":", "_"));
-							this.hideMarkerBig(previousMarker);
-							// console.log("5a) hide " + this.previousMarkerIdx);
-						}
-						
-						// console.log("5b) show " + nearestMarkerIdx);
-						this.showMarkerBig(currentMarker, this.annotations[nearestMarkerIdx].annotationType.contents.title);
-						//Mise à jour du marqueur précédent s'il y a un changement.
-						this.previousMarkerIdx = nearestMarkerIdx;
-						// console.log("MAJ : " + this.previousMarkerIdx);
-					}
-				}
-			}
-			// nearestMarker = (Math.abs(_time*1000 - annotations[i].begin.milliseconds) < Math.abs(_time*1000 - annotations[nearestMarker].begin.milliseconds) && annotations[i].begin.milliseconds >= annotations[nearestMarker].begin.milliseconds && annotations[i].begin.milliseconds >= _time*1000) ? i : nearestMarker;
-			this.currentMarkerIdx = nearestMarkerIdx;
-			// this.showMarkerBig(IriSP.jQuery("#" + annotations[i].id.replace(":", "_")), annotations[i].annotationType.contents.title);
-		}
-	}
-}
-
-IriSP.Widgets.Timeline.prototype.timeDisplayUpdater = function() {
-    var _time = this.player.popcorn.currentTime();
-	var arrowLeft = Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), _time) + this.$timeline.position().left) -
-    this.$timeline.slider("value",_time*1000);
-	
-	IriSP.jQuery(".TL_Arrows").css("display", "block");
-	IriSP.jQuery("#TL_ArrowUp").css("left", arrowLeft);
-	IriSP.jQuery("#TL_ArrowDown").css("left", arrowLeft);
-    // this.player.popcorn.trigger("IriSP.Arrow.updatePosition",{widget: this.type, time: 1000 * _time});
-}
-
+/*
+ * Fonction appelée quand la souris est au dessus de la timeline.
+*/
 IriSP.Widgets.Timeline.prototype.onMouseover = function() {}
 
+/*
+ * Fonction appelée quand la souris est hors de la timeline.
+*/
 IriSP.Widgets.Timeline.prototype.onMouseout = function() {}
 
+/*
+ * Fonction appelée pour modifier la hauteur de la timeline.
+*/
 IriSP.Widgets.Timeline.prototype.animateToHeight = function(_height) {}
 
+/*
+ * Calcule le css de la timeline.
+ * Est appelé dans le fichier :
+ * Timeline > fonction draw.
+*/
 IriSP.Widgets.Timeline.prototype.calculateTimelineCss = function(_size) {
-	var middleWidth = this.player.config.gui.width;
+    //Longueur du player.
+    var middleWidth = this.player.config.gui.width;
+    //On met à jour la marge, les coordonnées et positions de la timeline.
     return {
-		position: "absolute",
-		top: "0px",
-		left: "0px",
-		width: middleWidth + "px",
+        position: "absolute",
+        top: "0px",
+        left: "0px",
+        width: middleWidth + "px",
         height: _size + "px",
         "margin-top": (-this.minimized_height - this.top_epsilon) + "px",
-		"z-align": "50"
+        "z-align": "50"
     };
 }
 
+/*
+ * Calcule le css de la barre grise de milieu de la timeline.
+ * Est appelé dans le fichier :
+ * Timeline > fonction draw.
+*/
 IriSP.Widgets.Timeline.prototype.calculateTimelineMiddleCss = function(_size, _middleSize) {
-	var middleWidth = this.player.config.gui.width;
+    //Longueur du player.
+    var middleWidth = this.player.config.gui.width;
+    //On met à jour la marge, les coordonnées et positions de la barre grise de milieu de la timeline.
     return {
-		position: "absolute",
-		top: "0px",
-		left: "0px",
-		width: middleWidth + "px",
+        position: "absolute",
+        top: "0px",
+        left: "0px",
+        width: middleWidth + "px",
         height: _middleSize + "px",
         "margin-top": (-this.minimized_height/2 - _middleSize/2 - this.top_epsilon) + "px",
-		"z-align": "100"
+        "z-align": "100"
     };
 }
 
+/*
+ * Calcule le css de la portion de la timeline qui a déjà été lue.
+ * Est appelé dans le fichier :
+ * Timeline > fonction draw.
+*/
 IriSP.Widgets.Timeline.prototype.calculateHandleCss = function(_size) {
     return {
-		position: "absolute",
-		top: "0px",
-		left: "0px",
+        position: "absolute",
+        top: "0px",
+        left: "0px",
         height: (2 + _size) + "px",
         width: (2 + _size) + "px",
         "margin-left": -Math.ceil(2 + _size / 2) + "px",
-		"z-align": "60"
+        "z-align": "60"
     }
 }
 
+/*
+ * Affiche les marqueurs lorsqu'ils sont affichés au passage du curseur.
+ * Est appelé dans le fichier :
+ * Timeline > fonction onTimeupdate.
+*/
 IriSP.Widgets.Timeline.prototype.showMarkerBig = function(marker, type) {
-	// console.log("avant");
-	if(this.markerBigShown)
-	{
-		return;
-	}
-	// console.log("apres");
-	
-	clearTimeout(this.hideTimeout);
-	
-	var _this = this;
-	
-	var markerTop, markerLeft;
-	
-	if(marker.position() == null)
-	{
-		markerTop = 0;
-		markerLeft = 0;
-	}
-	else
-	{
-		markerTop = marker.position().top;
-		markerLeft = marker.position().left;
-	}
-	
-	var markerWidth = marker.width(), markerHeight = marker.height();
-	
-	this.markerBigShown = true;
-	var markerBig = "<div class='TL_MarkersBig' id='MB_Text'>" + this.gesturesText[IriSP.jQuery.inArray(type, this.gestures)] + "<div class='TL_MarkersBig' id='MB_Spike'></div></div><div class='TL_MarkersBig' id='MB_Pic'></div>";
-	this.$.append(markerBig);
-	
-	var markerBigText = IriSP.jQuery("#MB_Text");
-	var markerBigSpike = IriSP.jQuery("#MB_Spike");
-	var markerBigPic = IriSP.jQuery("#MB_Pic");
-	
-	var markerBigTextWidth = markerBigText.outerWidth(), markerBigTextHeight = markerBigText.outerHeight();
-	var markerBigSpikeWidth = markerBigSpike.width(), markerBigSpikeHeight = markerBigSpike.height();
-	var markerBigPicWidth = markerBigPic.width(), markerBigPicHeight = markerBigPic.height();
-	var markerBigPicTop = +parseFloat(marker.css("margin-top")) + markerHeight, markerBigPicLeft = (markerLeft - markerBigPicWidth/2 + markerWidth/2);
-	var markerBigTextTop = (parseFloat(marker.css("margin-top")) - markerBigTextHeight - markerBigSpikeHeight), markerBigTextLeft = (markerLeft - (markerBigTextWidth - markerBigSpikeWidth)/2);
-	var markerBigSpikeLeft = ((markerBigTextWidth - markerBigSpikeWidth)/2);
-	
-	marker.css("background-image", "url(" + this.imgDir + "selected_marker.png)");
-	IriSP.jQuery("#MB_Text").css(
-	{
-		top: markerBigTextTop,
-		left: markerBigTextLeft
-	});
-	IriSP.jQuery("#MB_Spike").css(
-	{
-		left: markerBigSpikeLeft
-	});
-	IriSP.jQuery("#MB_Pic").css(
-	{
-		"background-image": "url(" + this.markersDir + type + ".png)",
-		top: markerBigPicTop,
-		left: markerBigPicLeft,
-		"z-index": "400"
-	});
-	
-	IriSP.jQuery(".TL_MarkersBig").fadeTo(this.markerShowTime, "1");
-	
-	//On rajoute un timeout pour supprimer le marqueur après un certain temps.
-	this.hideTimeout = setTimeout(function()
-	{
-		_this.hideMarkerBig(marker);
-	}, this.markerLastTime);
+    //Si le marqueur est déjà affiché, on part.
+    if(this.markerBigShown)
+    {
+        return;
+    }
+    
+    //On annule le masquage du pointeur.
+    clearTimeout(this.hideTimeout);
+    
+    var _this = this;
+    //On met à jour la position du marqueur.
+    var markerTop, markerLeft;
+    
+    if(marker.position() == null)
+    {
+        markerTop = 0;
+        markerLeft = 0;
+    }
+    else
+    {
+        markerTop = marker.position().top;
+        markerLeft = marker.position().left;
+    }
+    //Ses dimensions aussi.
+    var markerWidth = marker.width(), markerHeight = marker.height();
+    //On spécifie qu'il est affiché.
+    this.markerBigShown = true;
+    //On le crée.
+    var markerBig = "<div class='TL_MarkersBig' id='MB_Text'>" + this.gesturesText[IriSP.jQuery.inArray(type, this.gestures)] + "<div class='TL_MarkersBig' id='MB_Spike'></div></div><div class='TL_MarkersBig' id='MB_Pic'></div>";
+    //On l'ajoute.
+    this.$.append(markerBig);
+    //On forme ses éléments.
+    var markerBigText = IriSP.jQuery("#MB_Text");
+    var markerBigSpike = IriSP.jQuery("#MB_Spike");
+    var markerBigPic = IriSP.jQuery("#MB_Pic");
+    //On spécifie leurs coordonnées et dimensions.
+    var markerBigTextWidth = markerBigText.outerWidth(), markerBigTextHeight = markerBigText.outerHeight();
+    var markerBigSpikeWidth = markerBigSpike.width(), markerBigSpikeHeight = markerBigSpike.height();
+    var markerBigPicWidth = markerBigPic.width(), markerBigPicHeight = markerBigPic.height();
+    var markerBigPicTop = +parseFloat(marker.css("margin-top")) + markerHeight, markerBigPicLeft = (markerLeft - markerBigPicWidth/2 + markerWidth/2);
+    var markerBigTextTop = (parseFloat(marker.css("margin-top")) - markerBigTextHeight - markerBigSpikeHeight), markerBigTextLeft = (markerLeft - (markerBigTextWidth - markerBigSpikeWidth)/2);
+    var markerBigSpikeLeft = ((markerBigTextWidth - markerBigSpikeWidth)/2);
+    //On va chercher les images correspondantes.
+    marker.css("background-image", "url(" + this.imgDir + "selected_marker.png)");
+    //On met à jour leur apparence.
+    IriSP.jQuery("#MB_Text").css(
+    {
+        top: markerBigTextTop,
+        left: markerBigTextLeft
+    });
+    IriSP.jQuery("#MB_Spike").css(
+    {
+        left: markerBigSpikeLeft
+    });
+    IriSP.jQuery("#MB_Pic").css(
+    {
+        "background-image": "url(" + this.markersDir + type + ".png)",
+        top: markerBigPicTop,
+        left: markerBigPicLeft,
+        "z-index": "400"
+    });
+    //On l'affiche.
+    IriSP.jQuery(".TL_MarkersBig").fadeTo(this.markerShowTime, "1");
+    
+    //On rajoute un timeout pour supprimer le marqueur après un certain temps.
+    this.hideTimeout = setTimeout(function()
+    {
+        _this.hideMarkerBig(marker);
+    }, this.markerLastTime);
 }
 
+/*
+ * Cache un marqueur.
+ * Est appelé dans le fichier :
+ * Timeline > fonctions draw, keyPress, onTimeupdate et showMarkerBig.
+*/
 IriSP.Widgets.Timeline.prototype.hideMarkerBig = function(marker) {
-	if(!this.markerBigShown)
-	{
-		return;
-	}
-	
-	this.currentMarker = -1;
-	this.markerBigShown = false;
-	marker.css("background-image", "url(" + this.imgDir + "marker.png)");
-	
-	IriSP.jQuery(".TL_MarkersBig").fadeOut(this.markerShowTime).remove();
+    //S'il n'est pas affiché, on part.
+    if(!this.markerBigShown)
+    {
+        return;
+    }
+    
+    //On lui remet son apparence initiale.
+    this.currentMarker = -1;
+    this.markerBigShown = false;
+    marker.css("background-image", "url(" + this.imgDir + "marker.png)");
+    //On efface ce qui était affiché du marqueur.
+    IriSP.jQuery(".TL_MarkersBig").fadeOut(this.markerShowTime).remove();
 }
 
 /*
  * Affiche le bas des marqueurs correspondants à la recherche.
+ * Est appelé dans le fichier :
+ * Timeline > fonction hideMarkersSearch.
 */
 IriSP.Widgets.Timeline.prototype.showMarkersSearchByType = function(type) {
-	//Si on est en mode SEARCH.
-	if(this.currentMode != "SEARCH")
-	{
-		return;
-	}
-	
-	var _this = this;
-	
-	//On récupère les annotations.
-	var markersSearch = "", markersPicSearch = "";
-	//Pour chaque annotation, on ajoute un double.
-	for(var i = 0 ; i < this.annotations.length ; i++)
-	{
-		//Si elle correspond à la recherche.
-		if(this.annotations[i].annotationType.contents.title == type)
-		{
-			//On récupère le marqueur associé à l'annotation.
-			var markerId = this.annotations[i].id.replace(":", "_");
-			
-			markersSearch += "<div class='search_Marker' id='search_Marker_" + markerId + "'></div>";
-			markersPicSearch += "<div class='search_MBPic' id='search_Pic_" + markerId + "'></div>";
-		}
-	}
-	
-	this.$.append(markersSearch + markersPicSearch);
-	
-	//On place chaque double.
-	for(var i = 0 ; i < this.annotations.length ; i++)
-	{
-		//Si elle correspond à la recherche.
-		if(this.annotations[i].annotationType.contents.title == type)
-		{
-			var markerId = this.annotations[i].id.replace(":", "_"), marker = IriSP.jQuery("#" + markerId);
-			var markerTop = marker.position().top, markerLeft = marker.position().left, markerWidth = marker.width(), markerHeight = marker.height();
-			var markerBigPicWidth = parseFloat(IriSP.jQuery(".search_MBPic").css("width")), markerBigPicHeight = parseFloat(IriSP.jQuery(".search_MBPic").css("height")), markerBigPicTop = +parseFloat(marker.css("margin-top")) + markerHeight, markerBigPicLeft = (markerLeft - markerBigPicWidth/2 + markerWidth/2);
-
-			// console.log(markerLeft + " - " + IriSP.jQuery(".search_MBPic").css("width") + " " + markerBigPicWidth + "/2 " + markerWidth + "/2");
-			
-			IriSP.jQuery("#search_Pic_" + markerId).css(
-			{
-				position: "absolute",
-				"background-image": "url(" + this.markersDir + type + ".png)",
-				top: markerBigPicTop,
-				left: markerBigPicLeft,
-				"z-index": "300"
-			}).fadeTo(this.markerShowTime, "1");
-			
-			IriSP.jQuery("#search_Marker_" + markerId).css(
-			{
-				position: "absolute",
-				top: _this.$timelineMiddle.position().top - _this.top_epsilon,
-				"margin-top": (-_this.$timeline.height()/2 - markerHeight/2),
-				"background-image": "url(" + this.imgDir + "selected_marker.png)",
-				//top: markerTop,
-				left: markerLeft,
-				"z-index": "300"
-			}).fadeTo(this.markerShowTime, "1");
-		}
-	}
+    //Si on est en mode SEARCH.
+    if(this.currentMode != "SEARCH")
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On récupère les annotations.
+    var markersSearch = "", markersPicSearch = "";
+    //Pour chaque annotation, on ajoute un double.
+    for(var i = 0 ; i < this.annotations.length ; i++)
+    {
+        //Si elle correspond à la recherche.
+        if(this.annotations[i].annotationType.contents.title == type)
+        {
+            //On récupère le marqueur associé à l'annotation.
+            var markerId = this.annotations[i].id.replace(":", "_");
+            
+            markersSearch += "<div class='search_Marker' id='search_Marker_" + markerId + "'></div>";
+            markersPicSearch += "<div class='search_MBPic' id='search_Pic_" + markerId + "'></div>";
+        }
+    }
+    
+    this.$.append(markersSearch + markersPicSearch);
+    
+    //On place chaque double.
+    for(var i = 0 ; i < this.annotations.length ; i++)
+    {
+        //Si elle correspond à la recherche.
+        if(this.annotations[i].annotationType.contents.title == type)
+        {
+            //On calcule les coordonnées et dimensions du marqueur.
+            var markerId = this.annotations[i].id.replace(":", "_"), marker = IriSP.jQuery("#" + markerId);
+            var markerTop = marker.position().top, markerLeft = marker.position().left, markerWidth = marker.width(), markerHeight = marker.height();
+            var markerBigPicWidth = parseFloat(IriSP.jQuery(".search_MBPic").css("width")), markerBigPicHeight = parseFloat(IriSP.jQuery(".search_MBPic").css("height")), markerBigPicTop = +parseFloat(marker.css("margin-top")) + markerHeight, markerBigPicLeft = (markerLeft - markerBigPicWidth/2 + markerWidth/2);
+            //On calcule son apparence et on le fait apparaître.
+            IriSP.jQuery("#search_Pic_" + markerId).css(
+            {
+                position: "absolute",
+                "background-image": "url(" + this.markersDir + type + ".png)",
+                top: markerBigPicTop,
+                left: markerBigPicLeft,
+                "z-index": "300"
+            }).fadeTo(this.markerShowTime, "1");
+            
+            IriSP.jQuery("#search_Marker_" + markerId).css(
+            {
+                position: "absolute",
+                top: _this.$timelineMiddle.position().top - _this.top_epsilon,
+                "margin-top": (-_this.$timeline.height()/2 - markerHeight/2),
+                "background-image": "url(" + this.imgDir + "selected_marker.png)",
+                left: markerLeft,
+                "z-index": "300"
+            }).fadeTo(this.markerShowTime, "1");
+        }
+    }
 }
 
 /*
  * Enlever une recherche faite précédemment.
+ * Est appelé dans le fichier :
+ * Timeline > fonctions searchByGesture et removeSearchByGesture.
 */
 IriSP.Widgets.Timeline.prototype.hideMarkersSearch = function(type) {
-	//Si on est en mode SEARCH.
-	if(this.currentMode != "SEARCH")
-	{
-		return;
-	}
-	
-	// console.log('(0)');
-	
-	var _this = this;
-	
-	IriSP.jQuery(".search_MBPic").fadeOut(this.markerShowTime, function()
-	{
-		IriSP.jQuery("div").remove(".search_MBPic");
-	});
-	IriSP.jQuery(".search_Marker").fadeOut(this.markerShowTime, function()
-	{
-		IriSP.jQuery("div").remove(".search_Marker");
-		
-		if(type == undefined)
-		{
-			_this.currentMode = "VIDEO";
-		}
-		else
-		{
-			// console.log('(1)');
-			// console.log(_this.currentMode);
-			_this.showMarkersSearchByType(type);
-			return;
-		}
-	});
-	
-	if(IriSP.jQuery(".search_Marker").length == 0 && type != undefined)
-	{
-		// console.log('(2)');
-		this.showMarkersSearchByType(type);
-		
-		if(!_.include(this.gestures, type))
-		{
-			// this.notifySearch1Gesture(type, "none");
-		}
-		else
-		{
-			// _this.notifySearch1Gesture(type, "valid");
-		}
-		// console.log(this.currentMode);
-	}
+    //Si on est en mode SEARCH.
+    if(this.currentMode != "SEARCH")
+    {
+        return;
+    }
+    
+    var _this = this;
+    
+    //On efface tous les marqueurs affichés.
+    IriSP.jQuery(".search_MBPic").fadeOut(this.markerShowTime, function()
+    {
+        IriSP.jQuery("div").remove(".search_MBPic");
+    });
+    IriSP.jQuery(".search_Marker").fadeOut(this.markerShowTime, function()
+    {
+        IriSP.jQuery("div").remove(".search_Marker");
+        
+        //Si le type est définit, c'est qu'on souhaite remplacer cette recherche par une autre.
+        if(type == undefined)
+        {
+            _this.currentMode = "VIDEO";
+        }
+        else
+        {
+            _this.showMarkersSearchByType(type);
+            return;
+        }
+    });
+    
+    //Si à la base il n'y avait pas de marqueurs affichés, on crée une nouvelle recherche si le type est définit.
+    if(IriSP.jQuery(".search_Marker").length == 0 && type != undefined)
+    {
+        this.showMarkersSearchByType(type);
+    }
 }
 
+/*
+ * Libère le player.
+ * Est appelé dans les fichiers :
+ * neighbours > fonction moveToNeighbour.
+ * zoomInteractions > fonction unzoom.
+*/
 IriSP.Widgets.Timeline.prototype.freePlayer = function()
 {
-	IriSP.jQuery('body').unbind('keypress');
-	IriSP.jQuery('.notifications').remove();
+    IriSP.jQuery('body').unbind('keypress');
+    IriSP.jQuery('.notifications').remove();
 }
 
 /*
  * Va au marqueur suivant/précédant lors d'un swipe right/left dans une lecture simple.
  * Prend comme argument le fait qu'il s'agisse d'un swipe left ou non (en prenant en condition toujours vraie 
  * que la fonction est appelée si et seulement si il y a swipe et que l'utilisateur ne tente pas d'aller vers un voisin.
+ * Est appelé dans le fichier :
+ * mosaic > fonction manageControlEvents.
 */
 IriSP.Widgets.Timeline.prototype.switchToMarker = function(isSwipeLeft, searchedGesture)
 {
-	console.log((isSwipeLeft == true) ? 'SWIPE LEFT' : 'SWIPE RIGHT');
-	
-	//On prend le temps actuel du curseur en ms.
-	var currentCursorPosition = this.player.popcorn.currentTime() * 1000;
-	//Position visée.
-	var targetCursorPosition = currentCursorPosition;
-	//Distance minimum de l'annotation par rapport au curseur et son index, ainsi que l'index - 1 pour le cas du swipe right.
-	var minDistance = this.source.getDuration().milliseconds, minIdx = 0, mindIdx_1 = 0;
+    console.log((isSwipeLeft == true) ? 'SWIPE LEFT' : 'SWIPE RIGHT');
+    
+    //On prend le temps actuel du curseur en ms.
+    var currentCursorPosition = this.player.popcorn.currentTime() * 1000;
+    //Position visée.
+    var targetCursorPosition = currentCursorPosition;
+    //Distance minimum de l'annotation par rapport au curseur et son index, ainsi que l'index - 1 pour le cas du swipe right.
+    var minDistance = this.source.getDuration().milliseconds, minIdx = 0, mindIdx_1 = 0;
 	
-	//Si il y a au moins 1 annotation.
-	if(this.annotations && this.annotations.length > 0)
-	{
-		if(isSwipeLeft)
-		{
-			//Pour toutes les annotations, on prend celle qui est la plus proche et supérieure à la position.
-			for(var i = 0 ; i < this.annotations.length ; i++)
-			{
-				// console.log('curr : ' + currentCursorPosition + ' ann : ' + this.annotations[i].begin);
-				if(currentCursorPosition < this.annotations[i].begin && minDistance > Math.abs(currentCursorPosition - this.annotations[i].begin))
-				{
-					if(searchedGesture != '')
-					{
-						if(this.annotations[i].annotationType.contents.title != searchedGesture)
-						{
-							continue;
-						}
-					}
-					
-					minDistance = (currentCursorPosition - this.annotations[i].begin);
-					minIdx = i;
-				}
-			}
-		}
-		else
-		{
-			//Pour toutes les annotations, on prend celle qui est la plus proche et inférieure à la position.
-			for(var i = 0 ; i < this.annotations.length ; i++)
-			{
-				if(currentCursorPosition > this.annotations[i].begin && minDistance > Math.abs(currentCursorPosition - this.annotations[i].begin))
-				{
-					if(searchedGesture != '')
-					{
-						if(this.annotations[i].annotationType.contents.title != searchedGesture)
-						{
-							continue;
-						}
-					}
-					
-					minDistance = (currentCursorPosition - this.annotations[i].begin);
-					minIdx = i;
-				}
-			}
-		}
-		
-		targetCursorPosition = this.annotations[minIdx].begin;
-		
-		if(this.annotations[minIdx].begin > 1000)
-		{
-			targetCursorPosition -= 1000;
-		}
-	}
+	//Condition de sélection du marqueur selon le type de swipe.
+	var swipeCondition = (isSwipeLeft ? (currentCursorPosition < this.annotations[i].begin && minDistance > Math.abs(currentCursorPosition - this.annotations[i].begin)) : (currentCursorPosition > this.annotations[i].begin && minDistance > Math.abs(currentCursorPosition - this.annotations[i].begin)));
 	
-	this.player.popcorn.currentTime(targetCursorPosition / 1000);
-}
-
-/*
- * Indique s'il y a des marqueurs devant le curseur (pour une recherche)
-*/
-IriSP.Widgets.Timeline.prototype.isAMarkerAhead = function(searchedGesture)
-{
-	if(searchedGesture == '')
-	{
-		return true;
-	}
-	
-	//On prend le temps actuel du curseur en ms.
-	var currentCursorPosition = this.player.popcorn.currentTime() * 1000;
-	//Position visée.
-	var targetCursorPosition = currentCursorPosition;
-	//Distance minimum de l'annotation par rapport au curseur et son index, ainsi que l'index - 1 pour le cas du swipe right.
-	var minDistance = this.source.getDuration().milliseconds, minIdx = 0, mindIdx_1 = 0;
-	
-	//Si il y a au moins 1 annotation.
-	if(this.annotations && this.annotations.length > 0)
-	{
+    //Si il y a au moins 1 annotation.
+    if(this.annotations && this.annotations.length > 0)
+    {
 		//Pour toutes les annotations, on prend celle qui est la plus proche et supérieure à la position.
 		for(var i = 0 ; i < this.annotations.length ; i++)
 		{
-			// console.log('curr : ' + currentCursorPosition + ' ann : ' + this.annotations[i].begin);
-			if(this.annotations[i].annotationType.contents.title == searchedGesture && currentCursorPosition < this.annotations[i].begin)
+			if(swipeCondition)
 			{
-				return true;
-			}
-		}
-	}
-		
-		return false;
-}
-
-/*
- * Indique, après un swipe, si on est au dernier marqueur d'un type recherché dans la vidéo.
-*/
-IriSP.Widgets.Timeline.prototype.switchToMarker2 = function(isSwipeLeft, searchedGesture)
-{
-	/*if(isSwipeLeft)
-	{
-		//Pour toutes les annotations, on prend celle qui est la plus proche et supérieure à la position.
-		for(var i = 0 ; i < this.annotations.length ; i++)
-		{
-			// console.log('curr : ' + currentCursorPosition + ' ann : ' + this.annotations[i].begin);
-			if(currentCursorPosition < this.annotations[i].begin && minDistance > Math.abs(currentCursorPosition - this.annotations[i].begin))
-			{
+				//Si on recherche une gesture.
 				if(searchedGesture != '')
 				{
+					//Si l'annotation actuelle ne correspond pas à la gesture recherchée, on passe.
 					if(this.annotations[i].annotationType.contents.title != searchedGesture)
 					{
 						continue;
 					}
 				}
 				
+				//On calcule la plus petite distance entre le marqueur marqueur actuel et les autres.
 				minDistance = (currentCursorPosition - this.annotations[i].begin);
 				minIdx = i;
 			}
 		}
-	}
-	else
-	{
-		//Pour toutes les annotations, on prend celle qui est la plus proche et inférieure à la position.
-		for(var i = 0 ; i < this.annotations.length ; i++)
-		{
-			if(currentCursorPosition > this.annotations[i].begin && minDistance > Math.abs(currentCursorPosition - this.annotations[i].begin))
-			{
-				if(searchedGesture != '')
-				{
-					if(this.annotations[i].annotationType.contents.title != searchedGesture)
-					{
-						continue;
-					}
-				}
-				
-				minDistance = (currentCursorPosition - this.annotations[i].begin);
-				minIdx = i;
-			}
-		}
-	}*/
+        
+        //On obtient la position du plus proche marqueur.
+        targetCursorPosition = this.annotations[minIdx].begin;
+        
+        //Si le marqueur est situé minimum à 1s du début de la video, on place la position cible à 1s avant celle du marqueur recherché.
+        if(this.annotations[minIdx].begin > 1000)
+        {
+            targetCursorPosition -= 1000;
+        }
+    }
+    
+    //On place le marqueur au niveau de la position cible.
+    this.player.popcorn.currentTime(targetCursorPosition / 1000);
+}
+
+/*
+ * Indique s'il y a des marqueurs devant le curseur (pour une recherche).
+ * Est appelé dans le fichier :
+ * mosaic > fonction manageControlEvents.
+*/
+IriSP.Widgets.Timeline.prototype.isAMarkerAhead = function(searchedGesture)
+{
+    if(searchedGesture == '')
+    {
+        return true;
+    }
+    
+    //On prend le temps actuel du curseur en ms.
+    var currentCursorPosition = this.player.popcorn.currentTime() * 1000;
+    //Position visée.
+    var targetCursorPosition = currentCursorPosition;
+    //Distance minimum de l'annotation par rapport au curseur et son index, ainsi que l'index - 1 pour le cas du swipe right.
+    var minDistance = this.source.getDuration().milliseconds, minIdx = 0, mindIdx_1 = 0;
+    
+    //Si il y a au moins 1 annotation.
+    if(this.annotations && this.annotations.length > 0)
+    {
+        //Pour toutes les annotations, on prend celle qui est la plus proche et supérieure à la position.
+        for(var i = 0 ; i < this.annotations.length ; i++)
+        {
+            if(this.annotations[i].annotationType.contents.title == searchedGesture && currentCursorPosition < this.annotations[i].begin)
+            {
+                return true;
+            }
+        }
+    }
+    
+    //Si elle n'a pas été trouvée on renvoie faux.
+    return false;
 }
 
 /*
  * Quand on entre dans la vidéo après un filtrage, on va au premier marqueur correspondant à la recherche (à l'exception d'une recherche infructueuse).
+ * Est appelé dans les fichiers :
+ * mosaic > fonctions onMouseUp et onMarkersReady.
+ * curvesDetector > fonction updateDists.
 */
 IriSP.Widgets.Timeline.prototype.goToFirstSearchedMarker = function(gesture)
 {
-	if(_.include(this.gestures, gesture))
-	{
-		if(this.annotations && this.annotations.length > 0)
-		{
-			var minIdx = 0, minPosition = this.source.getDuration().milliseconds, targetCursorPosition = 0;
-			
-			//On parcourt les annotations, pour chaque correspondant à la gesture recherchée, on trouve celle qui se trouve à la position minimum.
-			for(var i = 0 ; i < this.annotations.length ; i++)
-			{
-				//Si le marker n'est pas du type recherché, on passe.
-				if(this.annotations[i].annotationType.contents.title != gesture)
-				{
-					continue;
-				}
-				else if(minPosition > this.annotations[i].begin)
-				{
-					minPosition = this.annotations[i].begin;
-					minIdx = i;
-				}
-			}
-			
-			targetCursorPosition = this.annotations[minIdx].begin;
-			
-			console.log('pos : ' + targetCursorPosition);
-			
-			if(this.annotations[minIdx].begin > 1000)
-			{
-				targetCursorPosition -= 1000;
-			}
-			
-			this.player.popcorn.currentTime(targetCursorPosition / 1000);
-		}
-	}
+    if(_.include(this.gestures, gesture))
+    {
+        if(this.annotations && this.annotations.length > 0)
+        {
+            var minIdx = 0, minPosition = this.source.getDuration().milliseconds, targetCursorPosition = 0;
+            
+            //On parcourt les annotations, pour chaque correspondant à la gesture recherchée, on trouve celle qui se trouve à la position minimum.
+            for(var i = 0 ; i < this.annotations.length ; i++)
+            {
+                //Si le marker n'est pas du type recherché, on passe.
+                if(this.annotations[i].annotationType.contents.title != gesture)
+                {
+                    continue;
+                }
+                else if(minPosition > this.annotations[i].begin)
+                {
+                    minPosition = this.annotations[i].begin;
+                    minIdx = i;
+                }
+            }
+            
+            targetCursorPosition = this.annotations[minIdx].begin;
+            
+            //Si le marqueur est situé minimum à 1s du début de la video, on place la position cible à 1s avant celle du marqueur recherché.
+            if(this.annotations[minIdx].begin > 1000)
+            {
+                targetCursorPosition -= 1000;
+            }
+            
+            //On place le marqueur au niveau de la position cible.
+            this.player.popcorn.currentTime(targetCursorPosition / 1000);
+        }
+    }
 }
 
 /*
  * Renvoie vrai si il y a au moins une gesture de notre recherche dans les marqueurs de la video.
+ * Est appelé dans les fichiers :
+ * mosaic > fonctions onMouseUp et onMarkersReady.
+ * curvesDetector > fonction updateDists.
 */
 IriSP.Widgets.Timeline.prototype.atLeastOneSearchMarker = function(gesture)
 {
-	if(_.include(this.gestures, gesture))
-	{
-		if(this.annotations && this.annotations.length > 0)
-		{
-			//On parcourt les annotations, pour chaque correspondant à la gesture recherchée, on trouve celle qui se trouve à la position minimum.
-			for(var i = 0 ; i < this.annotations.length ; i++)
-			{
-				//Si le marker est reconnu, c'est bon.
-				if(this.annotations[i].annotationType.contents.title == gesture)
-				{
-					return true;
-				}
-			}
-			
-			return false;
-		}
-	}
+    if(_.include(this.gestures, gesture))
+    {
+        if(this.annotations && this.annotations.length > 0)
+        {
+            //On parcourt les annotations, pour chaque correspondant à la gesture recherchée, on trouve celle qui se trouve à la position minimum.
+            for(var i = 0 ; i < this.annotations.length ; i++)
+            {
+                //Si le marker est reconnu, c'est bon.
+                if(this.annotations[i].annotationType.contents.title == gesture)
+                {
+                    return true;
+                }
+            }
+            
+            return false;
+        }
+    }
 }
\ No newline at end of file
--- a/front_idill/src/search/css/searchCanvas.css	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/search/css/searchCanvas.css	Mon Jul 23 16:59:35 2012 +0200
@@ -1,3 +1,25 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : searchCanvas.css
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Style du canvas pour les courbes de recherche.
+ */
+ 
+/*
+ * Canvas sur lequel se dessinent les courbes de recherche.
+*/
 .canvas
 {
 	position: absolute;
--- a/front_idill/src/search/js/curvesDetector.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/search/js/curvesDetector.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,368 +1,403 @@
-/*
-* This file is part of the TraKERS\Front IDILL package.
-*
-* (c) IRI <http://www.iri.centrepompidou.fr/>
-*
-* For the full copyright and license information, please view the LICENSE
-* file that was distributed with this source code.
-*/
-
-/*
- * Projet : TraKERS
- * Module : Front IDILL
- * Fichier : curvesDetector.js
- * 
- * Auteur : alexandre.bastien@iri.centrepompidou.fr
- * 
- * Fonctionnalités : Détecteur de courbes de recherche, appelé par la classe de création du canvas de recherche.
- */
-
-/*
- * Détecteur de courbes (lignes droites, arcs de cercles et cercles).
-*/
-function curvesDetector(divisions, sizeTreshold, dictionary, mosaic)
-{
-	//Précision de la détection de direction en divisions (par défaut 12, selon une modélisation horaire et non mathématique).
-	this.divisions = divisions;
-	//Taille limite pour un segment/courbe pour être considéré comme tel en px.
-	this.sizeTreshold = sizeTreshold;
-	
-	this.dictionary = dictionary;
-	
-	this.mosaic = mosaic;
-	
-	//Code actuel généré. Il représente la structure de la courbe de recherche.
-	this.actualCode = '';
-	
-	this.joints = [];
-	this.jInc = 0;
-	
-	//Longueur totale de la courbe.
-	this.MPTotalDist = 0;
-	this.SPTotalDist = 0;
-	//Longueur de la partie actuelle (après début ou changement de direction).
-	this.MPActualDist = 0;
-	this.SPActualDist = 0;
-	//Angles actuels.
-	this.MPActualAngle = -1;
-	this.SPActualAngle = -1;
-	
-	//Centre du repère du pointeur principal.
-	this.MPrepX;
-	this.MPrepY;
-	//Centre du repère du pointeur secondaire.
-	this.SPrepX;
-	this.SPrepY;
-	
-	//Coordonnées actuelles du/des pointeur/s.
-	this.MPx = 0;
-	this.MPy = 0;
-	this.SPx = 0;
-	this.SPy = 0;
-	//Coordonnées précédentes du/des pointeur/s.
-	this.MPpx = 0;
-	this.MPpy = 0;
-	this.SPpx = 0;
-	this.SPpy = 0;
-	
-	//Si les paramètres sont incorrects, on leur donne une valeur par défaut.
-	if(isNaN(divisions) || divisions < 1 || divisions > 360)
-	{
-		this.divisions = 12;
-	}
-	if(sizeTreshold < 1)
-	{
-		sizeTreshold = 30;
-	}
-}
-
-/*
- * Reinit les paramètres du détecteur.
-*/
-curvesDetector.prototype.reinit = function()
-{
-	this.MPrepX = 0;
-	this.MPrepY = 0;
-	this.MPpx = 0;
-	this.MPpy = 0;
-	this.MPActualAngle = -1;
-	this.SPActualAngle = -1;
-	this.actualCode = '';
-	
-	/*for(var i = 0 ; i < this.joints.length ; i++)
-	{
-		if(this.joints[i])
-		{
-			this.joints[i].remove();
-		}
-	}
-	
-	this.jInc = 0;*/
-	this.MPActualDist = 0;
-	this.MPTotalDist = 0;
-}
-
-/*
- * Met à jour les positions des pointeurs
-*/
-curvesDetector.prototype.updatePos = function(mpx, mpy, spx, spy)
-{
-	//On met à jour les coordonnées récentes.
-	this.MPx = mpx;
-	this.MPy = mpy;
-	
-	//Si les coordonnées précédentes n'existent pas, alors on les met à jour.
-	if(!this.MPpx)
-	{
-		this.MPpx = mpx;
-	}
-	if(!this.MPpy)
-	{
-		this.MPpy = mpy;
-	}
-	if(!this.MPrepX)
-	{
-		this.MPrepX = mpx;
-	}
-	if(!this.MPrepY)
-	{
-		this.MPrepY = mpy;
-	}
-	
-	//Si on a un second pointeur.
-	if(spx && spy)
-	{
-		//On met les coordonnées à jour.
-		this.SPx = spx;
-		this.SPy = spy;
-		
-		//Si les coordonnées précédentes n'existent pas, alors on les met à jour.
-		if(!this.SPpx)
-		{
-			this.SPpx = spx;
-		}
-		if(!this.SPpy)
-		{
-			this.SPpy = spy;
-		}
-	}
-	
-	this.updateDists();
-}
-
-/*
- * Met à jour les distances parcourues.
-*/
-curvesDetector.prototype.updateDists = function()
-{
-	var foundGestures;
-	
-	//Si on a de quoi calculer les distances.
-	if(this.MPx && this.MPy && this.MPpx && this.MPpy && this.MPrepX && this.MPrepY)
-	{
-		var MPDist = Math.floor(Math.sqrt((this.MPx - this.MPpx) * (this.MPx - this.MPpx) + (this.MPy - this.MPpy) * (this.MPy - this.MPpy)));
-		this.MPTotalDist += MPDist;
-		this.MPActualDist += MPDist;
-		
-		var MPCurrentA = -1;
-		
-		if(MPDist > 0)
-		{
-			MPCurrentA = this.currentAngle(this.MPrepX, this.MPrepY, this.MPx, this.MPy, this.divisions);
-			// console.log(MPCurrentA);//, this.MPActualDist);
-		}
-		
-		if(this.MPActualDist > this.sizeTreshold && MPCurrentA != -1)
-		{
-			console.log(this.MPActualAngle, MPCurrentA, this.MPActualAngle != -1, this.MPActualAngle != MPCurrentA);
-			
-			if(this.MPActualAngle == -1 || this.MPActualAngle != MPCurrentA)
-			{
-				this.MPActualAngle = MPCurrentA;
-				this.actualCode += 'D' + MPCurrentA;
-				this.mosaic.actualCode = this.actualCode;
-				
-				foundGestures = this.codeToGestures(this.actualCode);
-				
-				console.log(+this.jInc+1, this.MPActualDist);
-				console.log(this.actualCode);
-				console.log(foundGestures);
-				
-				if(foundGestures.length == 0 || foundGestures.split(';').length != 1)
-				{
-					console.log('many curves');
-					this.mosaic.curvesGesturesFound = true;
-					this.mosaic.removeNotifications();
-					this.mosaic.curvesGestures(foundGestures);
-					
-					if(foundGestures.length == 0 && !this.mosaic.helpDisplayed)
-					{
-						this.mosaic.notifyHelp();
-						foundGestures = '';
-						this.mosaic.curvesGesturesFound = false;
-						this.mosaic.isSearchByCurvesOn = false;
-						this.mosaic.leaveSearch();
-					}
-					else if(foundGestures.split(';').length != 1 && this.mosaic.helpDisplayed)
-					{
-						if(this.mosaic.helpDisplayed)
-						{
-							this.mosaic.removeHelp();
-						}
-					}
-				}
-				else
-				{
-					// console.log(this.mosaic.currentMode);
-					this.mosaic.currentSearchGesture[this.mosaic.centerId] = foundGestures;
-					this.mosaic.isUserInSearchZone = false;
-					
-					if(this.mosaic.currentMode == "SEARCH" && this.mosaic.playerIsReady)
-					{
-						this.mosaic.player.widgets[0].searchByGesture(foundGestures);
-						this.mosaic.isCurrentlyInASearchByGesture = this.mosaic.player.widgets[0].isCurrentlyInASearchByGesture;
-						
-						this.mosaic.removeNotifications();
-						this.mosaic.searchGesture(foundGestures, 'valid');
-						
-						if(this.mosaic.player && this.mosaic.player.widgets[0] && this.mosaic.timeToGoAt[this.mosaic.centerId] === 0 && this.mosaic.player.widgets[0].atLeastOneSearchMarker(this.mosaic.currentSearchGesture[this.mosaic.centerId]))
-						{
-							this.mosaic.player.widgets[0].goToFirstSearchedMarker(this.mosaic.currentSearchGesture[this.mosaic.centerId]);
-						}
-						
-						this.mosaic.currentSearchGesture[this.mosaic.centerId] = foundGestures;
-						
-						foundGestures = '';
-						this.mosaic.curvesGesturesFound = false;
-						
-						this.mosaic.isSearchByCurvesOn = false;
-						this.mosaic.leaveSearch();
-					}
-					else if(this.mosaic.currentMode == "FILTER")
-					{
-						if(this.mosaic.isMosaicFiltered)
-						{
-							console.log('1 curve : ' + foundGestures);
-							this.mosaic.filterSearchedType = foundGestures;
-							this.mosaic.searchFilter(foundGestures);
-							this.mosaic.curvesGesturesFound = false;
-							
-							this.mosaic.removeNotifications();
-							this.mosaic.filterGesture(foundGestures, 'valid');
-							
-							foundGestures = '';
-							
-							this.mosaic.isSearchByCurvesOn = false;
-							this.mosaic.leaveSearch();
-						}
-					}
-				}
-				
-				this.MPActualDist = 0;
-				//this.jInc++
-			}
-			else
-			{
-				this.MPrepX = this.MPpx;
-				this.MPrepY = this.MPpy;
-				
-				/*if(this.joints[this.jInc])
-				{
-					this.joints[this.jInc].remove();
-				}
-				this.joints[this.jInc] = new paper.Path.Circle(new paper.Point(this.MPrepX, this.MPrepY), 10);
-				this.joints[this.jInc].strokeColor = 'black';
-				this.joints[this.jInc].fillColor = 'green';*/
-			}
-			
-			if(this.MPActualAngle == -1)
-			{
-				this.MPActualAngle = MPCurrentA;
-			}
-		}
-		
-		//On met à jour les coordonnées précédentes.
-		if(this.MPpx != this.MPx)
-		{
-			this.MPpx = this.MPx;
-		}
-		if(this.MPpy != this.MPy)
-		{
-			this.MPpy = this.MPy;
-		}
-	}
-	//Idem au cas où on aurait un deuxième pointeur.
-	if(this.SPx && this.SPy && this.SPpx && this.SPpy)
-	{
-		var SPDist = Math.floor(Math.sqrt((this.SPx - this.SPpx) * (this.SPx - this.SPpx) + (this.SPy - this.SPpy) * (this.SPy - this.SPpy)));
-		this.SPTotalDist += SPDist;
-		this.SPActualDist += SPDist;
-		
-		if(SPDist > 0)
-		{
-			this.currentAngle(this.SPpx, this.SPpy, this.SPx, this.SPy);
-		}
-		
-		//On met à jour les coordonnées précédentes.
-		if(this.SPpx != this.SPx)
-		{
-			this.SPpx = this.SPx;
-		}
-		if(this.SPpy != this.SPy)
-		{
-			this.SPpy = this.SPy;
-		}
-	}
-}
-
-/*
- * Renvoie les noms de gestures du dictionnaire qui ont un code qui commence par le code en entrée.
-*/
-curvesDetector.prototype.codeToGestures = function(code)
-{
-	//Variable qui va stocker tous les noms trouvés.
-	var retNames = '';
-	
-	//Pour tout le dictionnaire.
-	for(var i = 0 ; i < this.dictionary.length ; i++)
-	{
-		//Pour touts les codes de chaque gesture du dictionnaire.
-		for(var j = 0 ; j < this.dictionary[i].codes.length ; j++)
-		{
-			//Si le code en entrée est une partie début d'un des codes.
-			if(this.dictionary[i].codes[j].indexOf(code) == 0)
-			{
-				//On ajoute le nom de la gesture et on passe à la gesture suivante.
-				retNames += this.dictionary[i].name + ';';
-				break;
-			}
-		}
-	}
-	//Comme on sépare chaque nom par un ;, il faut supprimer le dernier si au moins un nom a été trouvé.
-	if(retNames.length > 0)
-	{
-		retNames = retNames.substring(0, retNames.length-1);
-	}
-	
-	//On renvoit les noms.
-	return retNames;
-}
-
-/*
- * Calcule l'angle emprunté par le morceau de segment actuel. On prend A va vers B.
-*/
-curvesDetector.prototype.currentAngle = function(xa, ya, xb, yb, divisions)
-{
-	//On calcule l'angle de la droite AB et des abscisses, et on effectue une rotation de 90° vers la gauche.
-	var angleRad = Math.atan2((ya - yb), (xa - xb)) - Math.PI / 2;
-	//On traduit les radians en divisions en passant de [-PI/2 ; PI/2] à [0 ; divisions - 1].
-	var angleDiv = Math.floor((angleRad > 0 ? angleRad : (2*Math.PI + angleRad)) * divisions / (2*Math.PI));
-	
-	//L'angle initial est 0.
-	if(angleDiv == divisions)
-	{
-		angleDiv = 0;
-	}
-	
-	return angleDiv;
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : curvesDetector.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Détecteur de courbes de recherche, appelé par la classe de création du canvas de recherche.
+ */
+
+/*
+ * Détecteur de courbes (lignes droites, arcs de cercles et cercles).
+ * Est appelé dans le fichier :
+ * searchCanvas > fonction create.
+*/
+function CurvesDetector(divisions, sizeTreshold, dictionary, mosaic)
+{
+    //Précision de la détection de direction en divisions (par défaut 12, selon une modélisation horaire et non mathématique).
+    this.divisions = divisions;
+    //Taille limite pour un segment/courbe pour être considéré comme tel en px.
+    this.sizeTreshold = sizeTreshold;
+    
+    this.dictionary = dictionary;
+    
+    this.mosaic = mosaic;
+    
+    //Code actuel généré. Il représente la structure de la courbe de recherche.
+    this.actualCode = '';
+    
+    this.joints = [];
+    this.jInc = 0;
+    
+    //Longueur totale de la courbe.
+    this.MPTotalDist = 0;
+    this.SPTotalDist = 0;
+    //Longueur de la partie actuelle (après début ou changement de direction).
+    this.MPActualDist = 0;
+    this.SPActualDist = 0;
+    //Angles actuels.
+    this.MPActualAngle = -1;
+    this.SPActualAngle = -1;
+    
+    //Centre du repère du pointeur principal.
+    this.MPrepX = null;
+    this.MPrepY = null;
+    //Centre du repère du pointeur secondaire.
+    this.SPrepX = null;
+    this.SPrepY = null;
+    
+    //Coordonnées actuelles du/des pointeur/s.
+    this.MPx = 0;
+    this.MPy = 0;
+    this.SPx = 0;
+    this.SPy = 0;
+    //Coordonnées précédentes du/des pointeur/s.
+    this.MPpx = 0;
+    this.MPpy = 0;
+    this.SPpx = 0;
+    this.SPpy = 0;
+    
+    //Si les paramètres sont incorrects, on leur donne une valeur par défaut.
+    if(isNaN(divisions) || divisions < 1 || divisions > 360)
+    {
+        this.divisions = 12;
+    }
+    if(sizeTreshold < 1)
+    {
+        sizeTreshold = 30;
+    }
+}
+
+/*
+ * Reinitialise les paramètres du détecteur.
+ * Est appelé dans le fichier :
+ * searchCanvas > fonction onPointerOut.
+*/
+CurvesDetector.prototype.reinit = function()
+{
+    this.MPrepX = 0;
+    this.MPrepY = 0;
+    this.MPpx = 0;
+    this.MPpy = 0;
+    this.MPActualAngle = -1;
+    this.SPActualAngle = -1;
+    this.actualCode = '';
+    this.MPActualDist = 0;
+    this.MPTotalDist = 0;
+}
+
+/*
+ * Met à jour les positions des pointeurs.
+ * Est appelé dans le fichier :
+ * searchCanvas > fonction onPointerMove.
+*/
+CurvesDetector.prototype.updatePos = function(mpx, mpy, spx, spy)
+{
+    //On met à jour les coordonnées récentes.
+    this.MPx = mpx;
+    this.MPy = mpy;
+    
+    //Si les coordonnées précédentes n'existent pas, alors on les met à jour.
+    if(!this.MPpx)
+    {
+        this.MPpx = mpx;
+    }
+    if(!this.MPpy)
+    {
+        this.MPpy = mpy;
+    }
+    if(!this.MPrepX)
+    {
+        this.MPrepX = mpx;
+    }
+    if(!this.MPrepY)
+    {
+        this.MPrepY = mpy;
+    }
+    
+    //Si on a un second pointeur.
+    if(spx && spy)
+    {
+        //On met les coordonnées à jour.
+        this.SPx = spx;
+        this.SPy = spy;
+        
+        //Si les coordonnées précédentes n'existent pas, alors on les met à jour.
+        if(!this.SPpx)
+        {
+            this.SPpx = spx;
+        }
+        if(!this.SPpy)
+        {
+            this.SPpy = spy;
+        }
+    }
+    
+    //On met à jour la distance des segments courants et on regarde les correspondances dans le dictionnaire.
+    this.updateDists();
+}
+
+/*
+ * Met à jour les distances parcourues.
+ * Est appelé dans le fichier :
+ * curvesDetector > fonction updatePos.
+*/
+CurvesDetector.prototype.updateDists = function()
+{
+	//Si on n'est pas en recherche pas courbes, on part.
+	if(!this.mosaic.isSearchByCurvesOn)
+	{
+		return;
+	}
+	
+    var foundGestures;
+    
+    //Si on a de quoi calculer les distances.
+    if(this.MPx && this.MPy && this.MPpx && this.MPpy && this.MPrepX && this.MPrepY)
+    {
+        //Distance entre les deux derniers points.
+        var MPDist = Math.floor(Math.sqrt((this.MPx - this.MPpx) * (this.MPx - this.MPpx) + (this.MPy - this.MPpy) * (this.MPy - this.MPpy)));
+        //On met à jour la distance totale de la courbe.
+        this.MPTotalDist += MPDist;
+        //Et aussi la distance du segment en cours.
+        this.MPActualDist += MPDist;
+        
+        //Angle courant initialisé à -1.
+        var MPCurrentA = -1;
+        
+        //Si la distance actuelle du segment existe.
+        if(MPDist > 0)
+        {
+            //On calcule l'angle courant entre ce segment et 
+            MPCurrentA = this.currentAngle(this.MPrepX, this.MPrepY, this.MPx, this.MPy, this.divisions);
+        }
+        
+        //Si la distance du segment actuel excède le seuil de la config et qu'il y a un angle.
+        if(this.MPActualDist > this.sizeTreshold && MPCurrentA != -1)
+        {
+            //Si l'angle affecté n'a pas encore de valeur ou si l'angle affecté est différent de l'angle calculé.
+            if(this.MPActualAngle == -1 || this.MPActualAngle != MPCurrentA)
+            {
+                //On affecte le nouvel angle.
+                this.MPActualAngle = MPCurrentA;
+                //On construit le code correspondant à ce segment.
+                this.actualCode += 'D' + MPCurrentA;
+                //On affecte le code dans la mosaique.
+                this.mosaic.actualCode = this.actualCode;
+                //On recherche les gestures commencant par ce code.
+                foundGestures = this.codeToGestures(this.actualCode);
+                
+                //S'il n'y a pas de gestures trouvées ou s'il y en a plus d'une.
+                if(foundGestures.length == 0 || foundGestures.split(';').length != 1)
+                {
+                    //On a trouvé quelque chose, même si ce qu'on a trouvé est vide ('').
+                    this.mosaic.curvesGesturesFound = true;
+                    //On notifie ce qu'on a trouvé. Dans le cas où c'est '', on affiche geste inconnu.
+                    this.mosaic.removeNotifications();
+                    this.mosaic.curvesGestures(foundGestures);
+                    
+                    //Si ce qu'on a trouvé est vide et si l'aide n'est pas affichée.
+                    if(foundGestures.length == 0 && !this.mosaic.helpDisplayed)
+                    {
+                        //On l'affiche.
+                        this.mosaic.notifyHelp();
+                        foundGestures = '';
+                        
+                        //On enlève la recherche.
+                        this.mosaic.curvesGesturesFound = false;
+                        this.mosaic.isSearchByCurvesOn = false;
+                        this.mosaic.leaveSearch();
+						
+						//Si on était en mode filtrage de la mosaïque et qu'aucune gesture de filtrage n'avait été détectée avant ca, on revient en mode mosaïque.
+						if(this.mosaic.currentMode == "FILTER" && this.mosaic.filterSearchedType == "")
+						{
+							this.mosaic.currentMode = "MOSAIC";
+							this.mosaic.isMosaicFiltered = false;
+						}
+						//Sinon si on était en mode recherche dans une video et qu'aucune gesture n'avait été détectée avant ca, on revient en mode video.
+						if(this.mosaic.currentMode == "SEARCH" && this.mosaic.currentSearchGesture[this.centerId] == "")
+						{
+							this.mosaic.currentMode = "VIDEO";
+						}
+                    }
+                    //Si l'aide est déjà affichée, on l'enlève.
+                    else if(foundGestures.split(';').length != 1 && this.mosaic.helpDisplayed)
+                    {
+                        this.mosaic.removeHelp();
+                    }
+                }
+                //Si on a un seul résultat.
+                else
+                {
+                    //On affecte la recherche.
+                    this.mosaic.currentSearchGesture[this.mosaic.centerId] = foundGestures;
+                    this.mosaic.isUserInSearchZone = false;
+                    
+                    //Si on est en mode recherche et que le player est prêt.
+                    if(this.mosaic.currentMode == "SEARCH" && this.mosaic.playerIsReady)
+                    {
+                        //On effectue la recherche.
+                        this.mosaic.player.widgets[0].searchByGesture(foundGestures);
+                        this.mosaic.isCurrentlyInASearchByGesture = this.mosaic.player.widgets[0].isCurrentlyInASearchByGesture;
+                        
+                        //On notifie.
+                        this.mosaic.removeNotifications();
+                        this.mosaic.searchGesture(foundGestures, 'valid');
+                        
+                        //S'il y a un marqueur trouvé au moins, on place le curseur sur le premier résultat.
+                        if(this.mosaic.player && this.mosaic.player.widgets[0] && this.mosaic.timeToGoAt[this.mosaic.centerId] === 0 && this.mosaic.player.widgets[0].atLeastOneSearchMarker(this.mosaic.currentSearchGesture[this.mosaic.centerId]))
+                        {
+                            this.mosaic.player.widgets[0].goToFirstSearchedMarker(this.mosaic.currentSearchGesture[this.mosaic.centerId]);
+                        }
+                        
+                        //On enlève a recherche par courbes.
+                        foundGestures = '';
+                        this.mosaic.curvesGesturesFound = false;
+                        
+                        this.mosaic.isSearchByCurvesOn = false;
+                        this.mosaic.leaveSearch();
+                    }
+                    //Si on est en filtrage.
+                    else if(this.mosaic.currentMode == "FILTER")
+                    {
+                        if(this.mosaic.isMosaicFiltered)
+                        {
+                            //On met à jour la gesture de filtrage.
+                            this.mosaic.filterSearchedType = foundGestures;
+                            //On filtre la mosaique.
+                            this.mosaic.searchFilter(foundGestures);
+                            this.mosaic.curvesGesturesFound = false;
+                            //On notifie.
+                            this.mosaic.removeNotifications();
+                            this.mosaic.filterGesture(foundGestures, 'valid');
+                            
+                            foundGestures = '';
+                            //On enlève la recherche par courbes.
+                            this.mosaic.isSearchByCurvesOn = false;
+                            this.mosaic.leaveSearch();
+                        }
+                    }
+                }
+                //On réinitialise la distance entre les deux derniers points.
+                this.MPActualDist = 0;
+            }
+            //Sinon si l'angle n'a pas changé dans le segment en cours.
+            else
+            {
+                //On met à jour les dernières coordonnées du pointeur principal.
+                this.MPrepX = this.MPpx;
+                this.MPrepY = this.MPpy;
+            }
+            
+            //Si l'angle affecté n'a pas encore de valeur.
+            if(this.MPActualAngle == -1)
+            {
+                //On le met à jour.
+                this.MPActualAngle = MPCurrentA;
+            }
+        }
+        
+        //On met à jour les coordonnées précédentes.
+        if(this.MPpx != this.MPx)
+        {
+            this.MPpx = this.MPx;
+        }
+        if(this.MPpy != this.MPy)
+        {
+            this.MPpy = this.MPy;
+        }
+    }
+    //Idem au cas où on aurait un deuxième pointeur.
+    if(this.SPx && this.SPy && this.SPpx && this.SPpy)
+    {
+        //Distance entre les deux derniers points.
+        var SPDist = Math.floor(Math.sqrt((this.SPx - this.SPpx) * (this.SPx - this.SPpx) + (this.SPy - this.SPpy) * (this.SPy - this.SPpy)));
+        //On met à jour la distance totale de la courbe.
+        this.SPTotalDist += SPDist;
+        //Et aussi la distance du segment en cours.
+        this.SPActualDist += SPDist;
+        
+        //Si la distance actuelle du segment existe.
+        if(SPDist > 0)
+        {
+            /*En développement*/
+            this.currentAngle(this.SPpx, this.SPpy, this.SPx, this.SPy);
+        }
+        
+        //On met à jour les coordonnées précédentes.
+        if(this.SPpx != this.SPx)
+        {
+            this.SPpx = this.SPx;
+        }
+        if(this.SPpy != this.SPy)
+        {
+            this.SPpy = this.SPy;
+        }
+    }
+}
+
+/*
+ * Renvoie les noms de gestures du dictionnaire qui ont un code qui commence par le code en entrée.
+ * Est appelé dans le fichier :
+ * curvesDetector > fonction updateDists.
+*/
+CurvesDetector.prototype.codeToGestures = function(code)
+{
+    //Variable qui va stocker tous les noms trouvés.
+    var retNames = '';
+    
+    //Pour tout le dictionnaire.
+    for(var i = 0 ; i < this.dictionary.length ; i++)
+    {
+        //Pour touts les codes de chaque gesture du dictionnaire.
+        for(var j = 0 ; j < this.dictionary[i].codes.length ; j++)
+        {
+            //Si le code en entrée est une partie début d'un des codes.
+            if(this.dictionary[i].codes[j].indexOf(code) == 0)
+            {
+                //On ajoute le nom de la gesture et on passe à la gesture suivante.
+                retNames += this.dictionary[i].name + ';';
+                break;
+            }
+        }
+    }
+    //Comme on sépare chaque nom par un ;, il faut supprimer le dernier si au moins un nom a été trouvé.
+    if(retNames.length > 0)
+    {
+        retNames = retNames.substring(0, retNames.length-1);
+    }
+    
+    //On renvoit les noms.
+    return retNames;
+}
+
+/*
+ * Calcule l'angle emprunté par le morceau de segment actuel. On prend A va vers B.
+ * Est appelé dans le fichier :
+ * curvesDetector > fonction updateDists.
+*/
+CurvesDetector.prototype.currentAngle = function(xa, ya, xb, yb, divisions)
+{
+    //On calcule l'angle de la droite AB et des abscisses, et on effectue une rotation de 90° vers la gauche.
+    var angleRad = Math.atan2((ya - yb), (xa - xb)) - Math.PI / 2;
+    //On traduit les radians en divisions en passant de [-PI/2 ; PI/2] à [0 ; divisions - 1].
+    var angleDiv = Math.floor((angleRad > 0 ? angleRad : (2*Math.PI + angleRad)) * divisions / (2*Math.PI));
+    
+    //L'angle initial est 0.
+    if(angleDiv == divisions)
+    {
+        angleDiv = 0;
+    }
+    
+    return angleDiv;
 }
\ No newline at end of file
--- a/front_idill/src/search/js/searchCanvas.js	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_idill/src/search/js/searchCanvas.js	Mon Jul 23 16:59:35 2012 +0200
@@ -1,285 +1,295 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : searchCanvas.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les fonctions de recherche par courbe de haut niveau (instantiation et manipulation de la classe de recherche par courbe mais pas les courbes en elles-mêmes ni le détecteur).
+ */
 
 /*
  * Déclaration du canvas de recherche par courbes.
+ * Est appelé dans le fichier :
+ * search > fonction startSearch.
 */
-function searchCanvas(_canvasTop, _canvasLeft, _canvasWidth, _canvasHeight, _margin_top, _fadeTime, _inMosaic, _mosaic)
+function SearchCanvas(_canvasTop, _canvasLeft, _canvasWidth, _canvasHeight, _margin_top, _fadeTime, _inMosaic, _mosaic)
 {
-	//Coordonnées, dimensions et autres paramètres du canvas.
-	this.canvasTop = _canvasTop;
-	this.canvasLeft = _canvasLeft;
-	this.canvasWidth = _canvasWidth;
-	this.canvasHeight = _canvasHeight;
-	this.fadeTime = _fadeTime;
-	this.margin_top = _margin_top;
-	
-	this.mosaic = _mosaic;
-	
-	//Courbe du pointeur principal.
-	this.mainPath;
-	this.mainPathStroke;
-	
-	//Courbe du pointeur secondaire.
-	this.secondPath;
-	this.secondPathStroke;
-	
-	//Courbe indicatrice de la direction actuelle.
-	this.direction;
-	
-	//Point précédent des pointeurs.
-	this.mainLastPoint;
-	this.secondLastPoint;
-	
-	//Coordonnées précédentes des pointeurs.
-	this.mainPointerLastX;
-	this.mainPointerLastY;
-	this.secondPointerLastX;
-	this.secondPointerLastY;
-	
-	this.inMosaic = _inMosaic;
-	
-	this.detector;
+    //Coordonnées, dimensions et autres paramètres du canvas.
+    this.canvasTop = _canvasTop;
+    this.canvasLeft = _canvasLeft;
+    this.canvasWidth = _canvasWidth;
+    this.canvasHeight = _canvasHeight;
+    this.fadeTime = _fadeTime;
+    this.margin_top = _margin_top;
+    
+    this.mosaic = _mosaic;
+    
+    //Courbe du pointeur principal.
+    this.mainPath;
+    this.mainPathStroke;
+    
+    //Courbe du pointeur secondaire.
+    this.secondPath;
+    this.secondPathStroke;
+    
+    //Courbe indicatrice de la direction actuelle.
+    this.direction;
+    
+    //Point précédent des pointeurs.
+    this.mainLastPoint;
+    this.secondLastPoint;
+    
+    //Coordonnées précédentes des pointeurs.
+    this.mainPointerLastX;
+    this.mainPointerLastY;
+    this.secondPointerLastX;
+    this.secondPointerLastY;
+    
+    this.inMosaic = _inMosaic;
+    
+    this.detector;
 }
 
 /*
  * Fonction d'initialisation du canvas de recherche par courbes.
+ * Est appelé dans le fichier :
+ * search > fonction startSearch.
 */
-searchCanvas.prototype.create = function(dictionary)
+SearchCanvas.prototype.create = function(dictionary)
 {
-	var _this = this;
-	
-	//On crée le canvas.
-	var canvas = '<canvas id="paperCanvas" width="' + this.canvasWidth + 'px" height="' + this.canvasHeight + 'px" class="canvas"></canvas>';
-	//On l'ajoute à la page.
-	$('body').append(canvas);
-	
-	$('.canvas').css(
-	{
-		top: this.canvasTop,
-		left: this.canvasLeft
-	});
-	
-	//S'il est dans la mosaique, on le réhausse en fonction de la taille de la marge verticale.
-	if(this.inMosaic)
-	{
-		console.log(this.margin_top);
-		$('.canvas').css(
-		{
-			"margin-top": this.margin_top
-		});
-	}
-	
-	//On instancie le détecteur de courbes de recherche.
-	this.detector = new curvesDetector(6, 100, dictionary, this.mosaic);
-	
-	//On active le canvas.
-	paper.setup('paperCanvas');
+    var _this = this;
+    
+    //On crée le canvas.
+    var canvas = '<canvas id="paperCanvas" width="' + this.canvasWidth + 'px" height="' + this.canvasHeight + 'px" class="canvas"></canvas>';
+    //On l'ajoute à la page.
+    $('body').append(canvas);
+    
+    $('.canvas').css(
+    {
+        top: this.canvasTop,
+        left: this.canvasLeft
+    });
+    
+    //S'il est dans la mosaique, on le réhausse en fonction de la taille de la marge verticale.
+    if(this.inMosaic)
+    {
+        $('.canvas').css(
+        {
+            "margin-top": this.margin_top
+        });
+    }
+    
+    //On instancie le détecteur de courbes de recherche.
+    this.detector = new CurvesDetector(6, 100, dictionary, this.mosaic);
+    
+    //On active le canvas.
+    paper.setup('paperCanvas');
 };
 
 /*
  * Fonction appelée pour quitter le mode de recherche par courbes.
+ * Est appelé dans le fichier :
+ * search > fonction leaveSearch.
 */
-searchCanvas.prototype.leaveSearch = function()
+SearchCanvas.prototype.leaveSearch = function()
 {
-	$('.canvas').fadeTo(this.fadeTime, 0, function()
-	{
-		$('.canvas').remove();
-	});
+    $('.canvas').fadeTo(this.fadeTime, 0, function()
+    {
+        $('.canvas').remove();
+    });
 };
 
 /*
  * Fonction de déclaration des courbes.
+ * Est appelé dans les fichiers :
+ * mosaic > fonctions onMouseDown et onMouseMove.
+ * client > fonction processMsg.
 */
-searchCanvas.prototype.onPointerIn = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
+SearchCanvas.prototype.onPointerIn = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
 {
-	if(this.mosaic.currentMode != 'MOSAIC' && this.mosaic.currentMode != 'FILTER')
-	{
-		mainPointerX -= 130;
-		mainPointerY -= 60;
-	}
-	
-	//On obtient les coordonnées du pointeur principal en px.
-	mainPointerX = Math.floor(mainPointerX);
-	mainPointerY = Math.floor(mainPointerY);
-	
-	//On forme le contour la courbe principale.
-	this.mainPathStroke = new paper.Path();
-	this.mainPathStroke.strokeColor = '#366F7A';
-	this.mainPathStroke.strokeWidth = 18;
-	this.mainPathStroke.strokeCap = 'round';
-	this.mainPathStroke.strokeJoin = 'round';
-	
-	//On forme la courbe principale.
-	this.mainPath = new paper.Path();
-	this.mainPath.strokeColor = '#02FEFF';
-	this.mainPath.strokeWidth = 10;
-	this.mainPath.strokeCap = 'round';
-	this.mainPath.strokeJoin = 'round';
-	
-	/*this.direction = new paper.Path();
-	this.direction.strokeColor = '#FF0000';
-	this.direction.strokeWidth = 5;
-	this.direction.strokeCap = 'round';
-	this.direction.strokeJoin = 'round';*/
-	
-	//Si on a un pointeur secondaire
-	if(secondPointerX && secondPointerY)
-	{
-		//On obtient les coordonnées du pointeur secondaire en px.
-		secondPointerX = Math.floor(secondPointerX);
-		secondPointerY = Math.floor(secondPointerY);
-		
-		//On forme le contour de la courbe secondaire.
-		this.secondPathStroke = new paper.Path();
-		this.secondPathStroke.fillColor = '#366F7A';
-		this.secondPathStroke.strokeWidth = 12;
-		this.secondPathStroke.strokeCap = 'round';
-		this.secondPathStroke.strokeJoin = 'round';
-		
-		//On forme la courbe secondaire.
-		this.secondPath = new paper.Path();
-		this.secondPath.fillColor = '#02FEFF';
-		this.secondPath.strokeWidth = 10;
-		this.secondPath.strokeCap = 'round';
-		this.secondPath.strokeJoin = 'round';
-	}
-	
-	// console.log('IN');
-	
-	//On raffraichit l'affichage.
-	paper.view.draw();
+    if(this.mosaic.currentMode != 'MOSAIC' && this.mosaic.currentMode != 'FILTER')
+    {
+        mainPointerX -= 130;
+        mainPointerY -= 60;
+    }
+    
+    //On obtient les coordonnées du pointeur principal en px.
+    mainPointerX = Math.floor(mainPointerX);
+    mainPointerY = Math.floor(mainPointerY);
+    
+    //On forme le contour la courbe principale.
+    this.mainPathStroke = new paper.Path();
+    this.mainPathStroke.strokeColor = '#366F7A';
+    this.mainPathStroke.strokeWidth = 18;
+    this.mainPathStroke.strokeCap = 'round';
+    this.mainPathStroke.strokeJoin = 'round';
+    
+    //On forme la courbe principale.
+    this.mainPath = new paper.Path();
+    this.mainPath.strokeColor = '#02FEFF';
+    this.mainPath.strokeWidth = 10;
+    this.mainPath.strokeCap = 'round';
+    this.mainPath.strokeJoin = 'round';
+    
+    //Si on a un pointeur secondaire
+    if(secondPointerX && secondPointerY)
+    {
+        //On obtient les coordonnées du pointeur secondaire en px.
+        secondPointerX = Math.floor(secondPointerX);
+        secondPointerY = Math.floor(secondPointerY);
+        
+        //On forme le contour de la courbe secondaire.
+        this.secondPathStroke = new paper.Path();
+        this.secondPathStroke.fillColor = '#366F7A';
+        this.secondPathStroke.strokeWidth = 12;
+        this.secondPathStroke.strokeCap = 'round';
+        this.secondPathStroke.strokeJoin = 'round';
+        
+        //On forme la courbe secondaire.
+        this.secondPath = new paper.Path();
+        this.secondPath.fillColor = '#02FEFF';
+        this.secondPath.strokeWidth = 10;
+        this.secondPath.strokeCap = 'round';
+        this.secondPath.strokeJoin = 'round';
+    }
+    
+    //On raffraichit l'affichage.
+    paper.view.draw();
 };
 
 /*
  * Fonction appelée lorsque les pointeurs bougent pour construire la courbe.
+ * Est appelé dans les fichiers :
+ * mosaic > fonction onMouseMove.
+ * client > fonction processMsg.
 */
-searchCanvas.prototype.onPointerMove = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
+SearchCanvas.prototype.onPointerMove = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
 {
-	// console.log('MOVE');
-	
-	if(this.mosaic.currentMode != 'MOSAIC' && this.mosaic.currentMode != 'FILTER')
-	{
-		mainPointerX -= 130;
-		mainPointerY -= 60;
-	}
-	
-	if(!this.mainPointerLastX || !this.mainPointerLastY)
-	{
-		this.mainPointerLastX = mainPointerX;
-		this.mainPointerLastY = mainPointerY;
-	}
-	
-	//On obtient les coordonnées du pointeur principal en px.
-	mainPointerX = Math.floor(mainPointerX);
-	mainPointerY = Math.floor(mainPointerY);
-	
-	//On crée les points de la courbe principale.
-	var mainPoint = new paper.Point(mainPointerX, mainPointerY);
-	var mainPointStroke = new paper.Point(mainPointerX, mainPointerY);
-	
-	//On les ajoute à la courbe.
-	this.mainPathStroke.add(mainPointStroke);
-	this.mainPathStroke.smooth();
-	
-	this.mainPath.add(mainPoint);
-	this.mainPath.smooth();
-	
-	//this.direction.remove();
-	// console.log(this.mainPointerLastX, this.mainPointerLastY);
-	/*var directionPoint = new paper.Point(this.mainPointerLastX, this.mainPointerLastY);
-	var directionPointEnd = new paper.Point((mainPointerX - this.mainPointerLastX) * 2 + mainPointerX, (mainPointerY - this.mainPointerLastY) * 2 + mainPointerY);
-	this.direction.add(directionPoint);
-	this.direction.add(directionPointEnd);
-	this.direction.smooth();*/
-	
-	//Variables de construction de la courbe secondaire.
-	var secondPoint, secondDelta, secondStep, secondStepStroke, secondTop, secondBottom, secondTopStroke, secondBottomStroke;
-	
-	//Si on a un pointeur secondaire.
-	if(secondPointerX && secondPointerY)
-	{
-		//On obtient les coordonnées du pointeur secondaire en px.
-		secondPointerX = Math.floor(secondPointerX);
-		secondPointerY = Math.floor(secondPointerY);
-		
-		//On crée les points de la courbe secondaire.
-		secondPoint = new paper.Point(mainPointerX, mainPointerY);
-		secondPointStroke = new paper.Point(mainPointerX, mainPointerY);
-		
-		//On les ajoute à la courbe.
-		this.secondPathStroke.add(secondPointStroke);
-		this.secondPathStroke.smooth();
-		
-		this.secondPath.add(secondPoint);
-		this.secondPath.smooth();
-	}
-	
-	if(this.mainPointerLastX != mainPointerX)
-	{
-		this.mainPointerLastX = mainPointerX;
-	}
-	if(this.mainPointerLastY != mainPointerY)
-	{
-		this.mainPointerLastY = mainPointerY;
-	}
-	
-	//On met à jour les points dans le détecteur de courbes.
-	this.detector.updatePos(mainPointerX, mainPointerY);
-	
-	//On met à jour l'affichage.
-	paper.view.draw();
+    //Si on est dans une video, on réhausse
+    if(this.mosaic.currentMode != 'MOSAIC' && this.mosaic.currentMode != 'FILTER')
+    {
+        mainPointerX -= 130;
+        mainPointerY -= 60;
+    }
+    
+    //On obtient les coordonnées du pointeur principal en px.
+    mainPointerX = Math.floor(mainPointerX);
+    mainPointerY = Math.floor(mainPointerY);
+    
+    //Si les coordonnées du pointeur principal n'ont pas été affectées, on les affecte.
+    if(!this.mainPointerLastX || !this.mainPointerLastY)
+    {
+        this.mainPointerLastX = mainPointerX;
+        this.mainPointerLastY = mainPointerY;
+    }
+    
+    //On crée les points de la courbe principale.
+    var mainPoint = new paper.Point(mainPointerX, mainPointerY);
+    var mainPointStroke = new paper.Point(mainPointerX, mainPointerY);
+    
+    //On les ajoute à la courbe.
+    this.mainPathStroke.add(mainPointStroke);
+    this.mainPathStroke.smooth();
+    
+    //On place le premier point de la courbe, qu'on lisse.
+    this.mainPath.add(mainPoint);
+    this.mainPath.smooth();
+    
+    //Variables de construction de la courbe secondaire.
+    var secondPoint, secondDelta, secondStep, secondStepStroke, secondTop, secondBottom, secondTopStroke, secondBottomStroke;
+    
+    //Si on a un pointeur secondaire.
+    if(secondPointerX && secondPointerY)
+    {
+        //On obtient les coordonnées du pointeur secondaire en px.
+        secondPointerX = Math.floor(secondPointerX);
+        secondPointerY = Math.floor(secondPointerY);
+        
+        //Si les coordonnées du pointeur principal n'ont pas été affectées, on les affecte.
+        if(!this.secondPointerLastX || !this.secondPointerLastY)
+        {
+            this.secondPointerLastX = secondPointerX;
+            this.secondPointerLastY = secondPointerY;
+        }
+        
+        //On crée les points de la courbe secondaire.
+        secondPoint = new paper.Point(mainPointerX, mainPointerY);
+        secondPointStroke = new paper.Point(mainPointerX, mainPointerY);
+        
+        //On les ajoute à la courbe.
+        this.secondPathStroke.add(secondPointStroke);
+        this.secondPathStroke.smooth();
+        
+        //On place le premier point de la seconde courbe, qu'on lisse.
+        this.secondPath.add(secondPoint);
+        this.secondPath.smooth();
+        
+        //On met l'avant dernière position du pointeur secondaire à jour.
+        if(this.secondPointerLastX != secondPointerX)
+        {
+            this.secondPointerLastX = secondPointerX;
+        }
+        if(this.secondPointerLastY != secondPointerY)
+        {
+            this.secondPointerLastY = secondPointerY;
+        }
+    }
+    
+    //On met l'avant dernière position du pointeur principal à jour.
+    if(this.mainPointerLastX != mainPointerX)
+    {
+        this.mainPointerLastX = mainPointerX;
+    }
+    if(this.mainPointerLastY != mainPointerY)
+    {
+        this.mainPointerLastY = mainPointerY;
+    }
+    
+    //On met à jour les points dans le détecteur de courbes.
+    this.detector.updatePos(mainPointerX, mainPointerY);
+    
+    //On met à jour l'affichage.
+    paper.view.draw();
 };
 
 /*
  * Fonction appelée lorsqu'on cesse de dessiner une courbe.
+ * Est appelé dans les fichiers :
+ * mosaic > fonction onMouseUp.
+ * client > fonction processMsg.
 */
-searchCanvas.prototype.onPointerOut = function()
+SearchCanvas.prototype.onPointerOut = function()
 {
-	// console.log('OUT');
-	
-	//On réinitialise la courbe principale.
-	this.mainPathStroke.remove();
-	this.mainPath.remove();
-	
-	this.mainPointerLastX = 0;
-	this.mainPointerLastY = 0;
-	
-	// this.direction.remove();
-	
-	this.detector.reinit();
-	
-	//Si on a un second pointeur, on réinitialise la courbe secondaire.
-	if(this.secondPathStroke)
-	{
-		this.secondPathStroke.remove();
-	}
-	if(this.secondPath)
-	{
-		this.secondPath.remove();
-	}
-	
-	//On met à jour l'affichage.
-	paper.view.draw();
-};
-
-searchCanvas.prototype.onKeyDown = function(event)
-{
-	//S'il n'y a rien a colorier, on quitte.
-	if(typeof this.pathStroke === 'undefined' || typeof this.path === 'undefined')
-		return;
-	
-	if(event.key == 'r' || event.key == 'R')
-	{
-		this.pathStroke.fillColor = '#49564F';
-		this.path.fillColor = '#00FE00'
-	}
-	else if(event.key == 'x' || event.key == 'X')
-	{
-		this.pathStroke.fillColor = '#535F6D';
-		this.path.fillColor = '#CCCCCC'
-	}
-	else if(event.key == 'w' || event.key == 'W')
-	{
-		this.pathStroke.fillColor = '#366F7A';
-		this.path.fillColor = '#02FEFF'
-	}
+    //On réinitialise la courbe principale.
+    this.mainPathStroke.remove();
+    this.mainPath.remove();
+    
+    this.mainPointerLastX = 0;
+    this.mainPointerLastY = 0;
+    
+    //On réinitialise le détecteur.
+    this.detector.reinit();
+    
+    //Si on a un second pointeur, on réinitialise la courbe secondaire.
+    if(this.secondPathStroke)
+    {
+        this.secondPathStroke.remove();
+    }
+    if(this.secondPath)
+    {
+        this.secondPath.remove();
+    }
+    
+    //On met à jour l'affichage.
+    paper.view.draw();
 };
\ No newline at end of file
--- a/front_processing/doc/tutorial front processing.html	Mon Jul 23 10:52:41 2012 +0200
+++ b/front_processing/doc/tutorial front processing.html	Mon Jul 23 16:59:35 2012 +0200
@@ -12,6 +12,8 @@
         Le deuxième module de ce projet est un Front en Processing doté d'un client TUIO et récupérant les messages OSC (sous forme d'objets tels que des Curseurs ou des Strings).</p>
         
         <p>Ce tutoriel concerne ce second module et a pour but d'expliquer le fonctionnement général d'un sketch Processing et la récupération des notifications du Middleware. Il sera agrémenté d'exemples fonctionnels créés pour les besoins de ce tutoriel ou inspirés d'exemples réels disponibles sur le site processing.org.</p>
+		
+		<h2>Sommaire</h2>
         
         <ol type="I">
             <a href="#I"><li>Installation de Processing</li></a>
@@ -26,7 +28,7 @@
         <hr />
         
         <ol type="I" start="1">
-            <a name="I"><li>Installation de Processing</li></a>
+            <h3><a name="I"><li>Installation de Processing</li></a></h3>
         </ol>
         
         <p>Avant de pouvoir modifier les sketches Processing fournis dans l'installateur, il est nécessaire d'installer Processing.<br />
@@ -42,7 +44,7 @@
         <hr />
         
         <ol type="I" start="2">
-            <a name="#II"><li>Structure d'un sketch</li></a>
+            <h3><a name="#II"><li>Structure d'un sketch</li></a></h3>
         </ol>
         
         <p>Un sketch est représenté par un dossier, contenant plusieurs choses :
@@ -68,7 +70,7 @@
         <hr />
         
         <ol type="I" start="3">
-            <a name="#III"><li>Fonctions principales de Processing</li></a>
+            <h3><a name="#III"><li>Fonctions principales de Processing</li></a></h3>
         </ol>
         
         <p>En Processing, les variables déclarées absolues (en dehors d'une fonction ou d'une classe) sont visibles dans tous les autres fichiers .pde du sketch. Il en va de même pour les classes et fonctions (et non méthodes de classe, qui est une fonction appartenant à la classe et donc ne pouvant être appelée qu'en créant un objet de cette classe).</p>
@@ -101,7 +103,7 @@
         <hr />
         
         <ol type="I" start="4">
-            <a name="#IV"><li>Récupérer les objets envoyés par le Middleware TraKERS via un Client TUIO</li></a>
+            <h3><a name="#IV"><li>Récupérer les objets envoyés par le Middleware TraKERS via un Client TUIO</li></a></h3>
         </ol>
         
         <p>Les objets TUIO exploités dans le cadre de TraKERS sont de deux types :
@@ -190,7 +192,7 @@
         <hr />
         
         <ol type="I" start="5">
-            <a name="#V"><li>Interactions entre les objets TUIO récupérés et des fonctions de dessin basiques</li></a>
+            <h3><a name="#V"><li>Interactions entre les objets TUIO récupérés et des fonctions de dessin basiques</li></a></h3>
         </ol>
         
         <p>Dans les exemples de code vu précédemment, nous aurions pu remplacer la fonction text() par une fonction de votre cru, comme celle-ci :<br /><br />
@@ -229,7 +231,7 @@
         <hr />
         
         <ol type="I" start="6">
-            <a name="#VI"><li>Quelques exemples d'implémentation</li></a>
+            <h3><a name="#VI"><li>Quelques exemples d'implémentation</li></a></h3>
         </ol>
         
         <p>Les exemples fournis dans l'installeur sont répartis dans 4 dossiers principaux :
@@ -245,7 +247,7 @@
         <hr />
         
         <ol type="I" start="7">
-            <a name="#VII"><li>Références</li></a>
+            <h3><a name="#VII"><li>Références</li></a></h3>
         </ol>
         
         <p>Voici quelques liens utiles où se trouvent les dépendances trop lourdes pour être incluses dans cet installeur. Ils vont permettront également d'approfondissant vos connaissances sur Processing ou TUIO.