front_idill/src/mosaic/js/zoomInteractions.js
author bastiena
Thu, 05 Jul 2012 16:04:33 +0200
changeset 45 0e29ae4568a0
parent 44 8393d3473b98
child 47 4e1ee94d70b1
permissions -rw-r--r--
Front IDILL: Segment detector created for mouse interactions curves detection

/*
 * Zoom sur la position d'une image, 1ère partie. Durant le laps de temps de time ms, l'utilisateur a le choix de zoomer sur une autre image.
 * Après ce laps de temps, l'image zoom complétement et il n'est plus possible de sélectionner une autre image par pointage.
 */
mosaic.prototype.preZoom = function(snapshot)
{
	if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") > -1 || snapshot == null || this.helpDisplayed || this.isMosaicFiltering || this.isSearchByCurvesOn)
	{
		return;
	}
	
    if(this.fullscreen)
	{
        return;
	}
	this.preUnzoom();
	//On enlève les notifications initiales si elles existent.
	// this.removeSelectionSearchMosaicFull();
	$('.notifications').remove();
	
    //Mosaïque.
    var _this = this;
    //Dimensions de la mosaïque.
    var h = this.height, w = this.width;
    //Longueur en images, nombre d'images et taille de bordure de la mosaïque.
    var len = this.config['length'], imgs = this.config['imagesToShow'], margin = this.marginWidth;
    //Dimensions et position d'un snapshot dans la mosaïque.
    var snHeight = this.snapshotHeight, snWidth = this.snapshotWidth;
    var sTop = snapshot.position().top, sLeft = snapshot.position().left;
    var prezoomPercentage = this.config['prezoomPercentage'];
    
    //ID de l'image actuelle.
    var currentId = $('img', snapshot).attr('id');
    
    //Si un zoom est déjà en cours, on ne zoom sur rien d'autre en attendant que ce snapshot ai dézoomé en cas de mouseleave.
    if(this.zoomed)
	{
		/*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;
	}
    
    //On indique qu'on a zoomé et on spécifie le snapshot sur lequel on a zoomé.
    this.zoomed = true;
    this.previousZoomedSN = snapshot;
    this.previousId = currentId;
    
    //On récupère les attributs de l'image.
    var fakeImg = $('img', snapshot);
    //On forme la balise de la fausse image et on passe son url pour les grands snapshots.
    fakeImg = '<img id="fake-' + currentId + '" class="snapshots" src="' + fakeImg.attr('src').replace('-little/', '/') + '" />';
    //On génère un faux snapshot identique au précédent et qu'on va coller dessus.
    var fakeSnapshot = '<div id="prezoomContainer-' + currentId + '" class="prezoomContainers"><div id="prezoomSnapshot-' + currentId + '" class="snapshotDivs">' + fakeImg + '</div></div>';
    
    //On l'ajoute à la mosaïque.
    $('#mainPanel').append(fakeSnapshot);
    //On modifie ses attributs.
	// console.log('cid : ' + currentId, $('#fake-' + currentId).length);
    $('#fake-' + currentId).load(function()
    {
	// 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');
        
        //Dimensions et coordonnées initiales du div sur lequel on zoom.
        var initialDivWidth = $('#prezoomContainer-' + currentId).width(), initialDivHeight = $('#prezoomContainer-' + currentId).height();
        var initialDivTop = $('#prezoomContainer-' + currentId).position().top, initialDivLeft = $('#prezoomContainer-' + currentId).position().left;
        //Dimensions et coordonnées finales du div.
        var finalDivWidth = initialDivWidth * (prezoomPercentage+1), diffWidth = finalDivWidth - initialDivWidth, finalDivHeight = initialDivHeight + diffWidth;
        var finalDivTop = (initialDivTop - (finalDivHeight - snHeight)/2), finalDivLeft = (initialDivLeft - (finalDivWidth - snWidth)/2);
        
        //CAS PARTICULIER pour la position du snapshot zoomé : les bordures.
        if(finalDivTop < 0)
		{
            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(
        {
            width: finalDivWidth + margin,
            height: finalDivHeight - margin*2,
            top: finalDivTop + margin,
            left: finalDivLeft + margin
        }, _this.config['timePrezoom']);
        $('#prezoomContainer-' + currentId).animate(
        {
            width: finalDivWidth + margin*2,
            height: finalDivHeight - margin,
            top: finalDivTop + margin,
            left: finalDivLeft
        }, _this.config['timePrezoom'], function()
		{
			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')
			{
				$('.notifications').remove();
				_this.mosaicSelection();
			}
			else if(_this.currentMode == 'FILTER' && !_this.filterSearchedType && _this.curvesGesturesFound)
			{
				$('.notifications').remove();
				_this.filterSearchAndSelection();
			}
			else if(_this.currentMode == 'FILTER' && _this.filterSearchedType)
			{
				$('.notifications').remove();
				_this.filterGestureAndSelection(_this.filterSearchedType, 'valid');
			}
		});
    });
    
	if(!this.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é.
 */
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')
	{
		$('.notifications').remove();
		this.mosaicSelectionAndSearch();
	}
	else if(_this.currentMode == 'FILTER' && !this.filterSearchedType && !this.curvesGesturesFound)
	{
		$('.notifications').remove();
		this.filterSearch();
	}
	else if(_this.currentMode == 'FILTER' && this.filterSearchedType && !this.curvesGesturesFound)
	{
		$('.notifications').remove();
		this.filterGesture(this.filterSearchedType, 'valid');
	}
	/*this.removePointMosaicPrezoom();
	this.notifySelectionSearchMosaicFull();*/
    
    //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(
    {
        width: this.snapshotWidth,
        height: this.snapshotHeight,
        top: this.previousZoomedSN.position().top,
        left: this.previousZoomedSN.position().left
    }, this.config['preUnzoomTime']);
    $('#prezoomContainer-' + id).animate(
    {
        width: this.snapshotWidth + margin,
        height: this.snapshotHeight + margin,
        top: this.previousZoomedSN.position().top,
        left: this.previousZoomedSN.position().left
    }, this.config['preUnzoomTime'], function(){ $(this).remove(); _this.zoomed = false; });*/
}


/*
 * Zoom d'un snapshot en plein écran.
 */
mosaic.prototype.zoom = function()
{
    var _this = this;
    
    //Si la mosaïque est en pleine écran, pas la peine de zoomer.
    if(this.currentMode == "VIDEO" || this.currentMode == "SEARCH" || 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 initMPWidth = this.previousZoomedSN.width() * len + margin*len, initMPHeight = this.previousZoomedSN.height() * (imgs / len) + margin*(imgs / len);
    var newMPWidth = initMPWidth * len + zoomedMargin * (len), newMPHeight = initMPHeight * (imgs / len) + zoomedMargin * ((imgs / len));
    var newPreMPWidth = initMPWidth * len * zoomPercentage + zoomedMargin * (len), newPreMPHeight = initMPHeight * (imgs / len) * zoomPercentage + zoomedMargin * ((imgs / len));
    
    //Dimensions et coordonnées initiales du div sur lequel on zoom.
    var initialDivWidth = this.previousZoomedSN.width(), initialDivHeight = this.previousZoomedSN.height();
    var initialDivTop = this.previousZoomedSN.position().top, initialDivLeft = this.previousZoomedSN.position().left;
    //Dimensions et coordonnées finales du div.
    var finalDivWidth = initialDivWidth * (zoomPercentage+1), finalDivHeight = initialDivHeight * (zoomPercentage+1);
    var newZoomTop = -this.previousZoomedSN.position().top*(newPreMPHeight/initMPHeight) - zoomedMargin/2 + (initMPHeight - initMPHeight * zoomPercentage)/2, newZoomLeft = -this.previousZoomedSN.position().left*(newPreMPWidth/initMPWidth) - zoomedMargin/2 + (initMPWidth - initMPWidth * zoomPercentage)/2;
    var newSnWidth = initMPWidth * zoomPercentage, newSnHeight = initMPHeight * zoomPercentage;
    
    this.preUnzoom(this);
    /*SINGULARITE*/
    this.fullscreen = true;
    
    //On passe l'image du snapshot pointé en HD.
    var zoomedImg = $('img', this.previousZoomedSN);
    var src = zoomedImg.attr('src');
    zoomedImg.attr('src', src.replace('-little/', '/'));
    
    //On récupère son ID.
    var tab, zoomedImgId;
    tab = _this.previousId.split('-');
    zoomedImgId = tab[1];
	
	//On donne les dimensions des snapshots.
	$('.snapshotDivs').animate(
	{
		width: newSnWidth,
		height: newSnHeight,
		margin: zoomedMargin/2 + 'px',
	}, this.config['zoomTime']);
	
	if(this.currentMode != 'NO-USER')
	{
		//Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
		$('.snapshotDivs').animate(
		{
			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 zoome sur la mosaïque.
    $('#mainPanel').animate(
    {
        width: newPreMPWidth,
        height: newPreMPHeight,
        top: newZoomTop,
        left: newZoomLeft
    }, 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.centerId = zoomedImgId;
		// console.log('BBB2 : ' + _this.currentMode);
		if(_this.currentMode != "NO-USER")
		{
			// console.log('PROBLEM');
			_this.currentMode = 'VIDEO';
			_this.listenToNeighbours();
		}
		
		$('#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();
			}
		});
    });
}

/*
 * Retour à la taille normale de la mosaïque.
 */
mosaic.prototype.unzoom = function()
{
    //Si on n'est pas en plein écran, on quitte.
	// console.log("'" + this.currentMode + "'");
    if(this.currentMode != "SEARCH" && this.currentMode != "VIDEO" && this.currentMode != "NO-USER" && this.currentMode.indexOf("INCOMING") == -1)
	{
        return;
	}
	
	var _this = this;
	
	if(this.mouseInteractions)
	{
		$('body').unbind('click');
		$('body').unbind('mousewheel');
	
		//On rebind le clic pour supprimer une recherche.
		$('body').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;
    
    //On charge les attributs nécessaires aux calculs.
    var sWidth = this.snapshotWidth, sHeight = this.snapshotHeight;
    var mpWidth = this.width, mpHeight = this.height;
    var _this = this;
    
    //On passe le snapshot sur lequel on a zoomé en SD.
    var zoomedImg = $('img', this.previousZoomedSN);
    var src = zoomedImg.attr('src');
    zoomedImg.attr('src', src.replace('snapshots/', 'snapshots-little/'));
	
	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 rend leur opacité aux snapshots. Qui ne sont alors plus grisés.
    $('.snapshotDivs').animate(
    {
        width: sWidth,
        height: sHeight,
        margin: this.marginWidth/2 + 'px'
    }, this.config['unzoomTime'], 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();
		});
	}
	
    //On dézoom sur la mosaïque.
    $('#mainPanel').animate(
    {
        width: mpWidth,
        height: mpHeight,
        top: '0px',
        left: '0px'
    }, this.config['unzoomTime'], function()
    {
        //On n'est plus en plein écran, et on ne peut plus se déplacer vers le prochain voisin.
        _this.fullscreen = false;
        _this.canMoveToNeighbour = false;
		
		if(_this.currentMode != 'NO-USER' && _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)
			{
				$('.notifications').remove();
				// _this.notifySelectionSearchMosaicFull();
				_this.mosaicSelectionAndSearch();
			}
		}
		
		this.currentlyUnzooming = false;
    });
}