front_idill/src/mosaic/js/touchInteractions.js
author bastiena
Sun, 09 Sep 2012 15:11:32 +0200
changeset 89 b6a115568b52
parent 79 9eff85166868
permissions -rw-r--r--
Front IDILL: credits for mouse interactions

/*
* 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 : touchInteractions.js
 * 
 * Auteur : alexandre.bastien@iri.centrepompidou.fr
 * 
 * Fonctionnalités : Définit les fonctions d'intéraction pour tablettes.
 */

/*
 * Fonction appelée lors d'un touch start en mode d'interaction touch.
 * Est appelé dans le fichier :
 * mosaic > fonction loadMosaic, attachée à l'événement ontouchstart.
*/
Mosaic.prototype.onTouchStart = function(e)
{
	this.isTouchStart = true;
	this.isTouchMove = false;
	
	//Si on est sur l'icone de sortie.
	if(this.isOnExitIcon(e.pageX, e.pageY) && this.helpDisplayed)
	{
		//On ferme l'aide.
		this.removeExitIcon();
		this.removeHelp();
	}
	
	//Si on est sur l'icone de retour à la mosaïque.
	if(this.isOnHomeIcon(e.pageX, e.pageY) && !this.helpDisplayed)
	{
		//On dézoom.
		this.unzoom();
	}
	
	//Si on se trouve sur l'icone d'aide et qu'elle est zoomée.
	if(this.isOnHelpIcon(e.pageX, e.pageY) && !this.helpDisplayed)
	{
		//On affiche différentes aides en fonction de si on se trouve dans une vidéo ou non.
		if(this.currentMode == 'SEARCH' || this.currentMode == 'VIDEO' || this.currentMode == 'TIMELINE')
		{
			this.notifyHelp(false);
		}
		else if(this.currentMode == 'FILTER' || this.currentMode == 'MOSAIC')
		{
			this.notifyHelp(true);
		}
	}
	
	//Si on est sur le bouton de lecture de vidéo.
	if(this.isOnPlayButton(e.pageX, e.pageY) && this.player && this.player.widgets && this.player.widgets[1])
	{
		this.player.widgets[1].onPlayButtonTouchStart();
	}
	
	//On met à jour les coordonnées de la souris au dernier mouse down.
	this.mouseDownPosX = e.pageX;
	this.mouseDownPosY = e.pageY;
	this.mousePosX = e.pageX;
	this.mousePosY = 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)
	{
		this.searchCanvas.onPointerIn(this.mousePosX, this.mousePosY, null, null);
	}
}

/*
 * Fonction appelée lors d'un touch move en mode d'interaction touch.
 * Est appelé dans le fichier :
 * mosaic > fonction loadMosaic, attachée à l'événement jQuery ontouchmove.
*/
Mosaic.prototype.onTouchMove = function(e)
{
	//Si on n'a pas appuyé sur la souris avant, on part.
	if(!this.isTouchStart)
	{
		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);
		this.searchCanvas.onPointerMove(this.mousePosX, this.mousePosY, null, null);
	}
	
	//On met à jour l'ancienne position du doigt 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 le doigt bouge.
	this.touchUpDownDelta += 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 du doigt.
	if(this.mousePosLastX != this.mousePosX)
	{
		this.mousePosLastX = this.mousePosX;
	}
	if(this.mousePosLastY != this.mousePosY)
	{
		this.mousePosLastY = this.mousePosY;
	}
	
	//Si le doigt a parcouru une trop grande distance, on entre en recherche.
	if(this.touchUpDownDelta > this.config.touchUpDownDeltaTreshold && !this.isTLSelected(true, null))
	{
		this.isTouchMove = true;
		//Si on est en mosaique, on entre en filtrage.
		if(this.currentMode == "MOSAIC")
		{
			this.currentMode = "FILTER";
			this.isMosaicFiltered = true;
		}
		//Si on est dans une vidéo, on entre en recherche.
		else if(this.currentMode == "VIDEO" || this.currentMode == "TIMELINE")
		{
			this.currentMode = "SEARCH";
		}
		
		if(!this.isSearchByCurvesOn)
		{
			this.isSearchByCurvesOn = true;
			this.startSearch();
			// this.searchCanvas.onPointerIn(this.mousePosX, this.mousePosY - this.MPTop_margin, null, null);
			this.searchCanvas.onPointerIn(this.mousePosX, this.mousePosY, null, null);
		}
		
		//Si on est dans une vidéo et qu'on glisse le doigt sur la timeline, ça place le curseur à cet endroit.
		if(this.playerIsReady && (this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH' || this.currentMode == 'TIMELINE') && this.isTLSelected(true, null))
		{
			this.goToTimeline();
		}
	}
}

/*
 * Fonction appelée lors d'un touch end en mode d'interaction touch.
 * Est appelé dans le fichier :
 * mosaic > fonction loadMosaic, attachée à l'événement jQuery ontouchend.
*/
Mosaic.prototype.onTouchEnd = function(e)
{
	//Coordonnées du doigt.
	var posX = this.mousePosX, posY = this.mousePosY;
	
	// alert(this.mousePosX + ' ' + this.mousePosY);
	//Si on est dans la mosaïque.
	if(this.currentMode == 'MOSAIC' || this.currentMode == 'FILTER')
	{
		//On regarde si on a touché un snapshot.
		var snapshot = this.positionToSN(posX, posY);
		// alert(snapshot);
		// alert(this.isTouchMove);
		if(snapshot && !this.isTouchMove)
		{
			this.previousZoomedSN = snapshot;
			this.previousId = snapshot.attr('id');
			this.zoom();
		}
	}
	//Sinon si on est dans une vidéo.
	else if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH' || this.currentMode == 'TIMELINE')
	{
		//Si on relache le doigt sur la timeline, ça place le curseur à cet endroit.
		if(this.playerIsReady && this.isTLSelected(true, null))
		{
			this.goToTimeline();
		}
		this.exitTimeline('');
		
		posX = this.mousePosX - this.notifyLeftVideo;
		posY = this.mousePosY - this.notifyTopVideo;
		
		//On regarde si on a touché un snapshot.
		var snapshot = this.positionToSN(posX, posY);
		
		if(snapshot && !this.isOnSearchNotification(this.mousePosX, this.mousePosY) && !this.isOnSearchExitIcon(this.mousePosX, this.mousePosY))
		{
			this.canMoveToNeighbour = true;
			var id = snapshot.attr('id').replace('snapshotDiv-', '');
			this.correctMoveToNeighbour(id, posX, posY);
			this.canMoveToNeighbour = false;
		}
	}
	
	//Si on est sur l'icone de sortie de recherche.
	if(this.isOnSearchExitIcon(this.mousePosX, this.mousePosY) && !this.helpDisplayed)
	{
		//On ferme l'aide.
		this.removeSearchExitIcon();
		
		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;
	}
	
	this.isTouchStart = false;
	
	//Si on était en train de tracer une courbe.
	if(this.isSearchByCurvesOn)
	{
		//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.touchUpDownDelta <= this.config.touchUpDownDeltaTreshold)
	{
		//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.touchUpDownDelta = 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');
	}
	this.isTouchMove = false;
}

/*
 * Donne éventuellement un snapshot d'après les coordonnées passées en paramètres.
 * Renvoie null sinon.
*/
Mosaic.prototype.positionToSN = function(x, y)
{
    if(this.helpDisplayed)
    {
        return;
    }
    
    //Taille de la marge des snapshots.
    var m = parseInt($('.snapshotDivs').css('margin-left'));
    
    //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.imagesByLine, 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;
}

/*
 * Se déplace dans la timeline lorsque le doigt est dessus.
*/
Mosaic.prototype.goToTimeline = function()
{
	var time, TL = $('.Ldt-Timeline'), P = $('.LdtPlayer');
		
	//Si le pointeur est trop à gauche, on met le curseur de lecture à 0.
	if(this.mousePosX < P.position().left)
	{
		time = 0;
	}
	//S'il est trop à droite, on le place à la fin.
	else if(this.mousePosX > (+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(), this.mousePosX);
	}
	
	this.player.popcorn.currentTime(time);
	this.player.popcorn.play();
}