front_idill/src/player/metadataplayer/Timeline.js
author bastiena
Mon, 09 Jul 2012 14:24:42 +0200
changeset 47 4e1ee94d70b1
parent 46 9d7a2aa112fb
child 52 277c94533395
permissions -rw-r--r--
Front IDILL: Help adapted to screen size & mouse interactions

/*
 The Timeline Widget fits right under the video
 */

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);
};

IriSP.Widgets.Timeline.prototype = new IriSP.Widgets.Widget();

IriSP.Widgets.Timeline.prototype.isGesture = function(element, index, array)
{
	return ($.inArray(element.annotationType.contents.title, array) > -1);
}

/*
 * Spécifie si on est en événements souris ou non.
*/
IriSP.Widgets.Timeline.prototype.setMouseInteractions = function(mouseInteractions)
{
	this.mouseInteractions = mouseInteractions;
	
	if(mouseInteractions)
	{
		this.markersDir += 'MI/';
	}
}

/*
 * Spécifie la langue pour l'affichage des marqueurs.
*/
IriSP.Widgets.Timeline.prototype.setLang = function(gesturesText)
{
	this.gesturesText = gesturesText;
}

//Fonction associée à l'événement : les marqueurs sont prêts.
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;
};

IriSP.Widgets.Timeline.prototype.defaults = {
    minimized_height : 114,//44,
    maximized_height : 114,
	middle_height: 10,//4,
	timelineBorderLength : 6,
    minimize_timeout : 1500 // time before minimizing timeline after mouseout
};

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")
        .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);*/
	
	
    this.$.append(this.$timeline);
    this.$.append(this.$timelineMiddle);
	
    var _this = this;
    
    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);
			}
        }
    });
	
    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)});
    
    this.maximized = false;
    this.timeoutId = false;
};

/*
 * Starts playing the video when it's ready.
*/
IriSP.Widgets.Timeline.prototype.ready = function() {
	this.player.popcorn.play();
	this.player.popcorn.mute();
	this.processMarkers();
}

/*
 * Scale a value from [A, B] to [C, D].
*/
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;
		}
	}
}

/*
 * Process the markers.
*/
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');
}

/*
 * Fonction de recherche par gesures.
*/
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;
		}
	}
}

/*
 * Fonction de suppression de recherche par gesures.
*/
IriSP.Widgets.Timeline.prototype.removeSearchByGesture = function()
{
	this.hideMarkersSearch();
	this.isCurrentlyInASearchByGesture = false;
}

/*
 * Place the cursor on the timeline depending on the keytyped.
*/
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();
		}
	}
}

/*
 * Find the key corresponding to a given code.
*/
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.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)");
}

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});
}

IriSP.Widgets.Timeline.prototype.onMouseover = function() {}

IriSP.Widgets.Timeline.prototype.onMouseout = function() {}

IriSP.Widgets.Timeline.prototype.animateToHeight = function(_height) {}

IriSP.Widgets.Timeline.prototype.calculateTimelineCss = function(_size) {
	var middleWidth = this.player.config.gui.width;
    return {
		position: "absolute",
		top: "0px",
		left: "0px",
		width: middleWidth + "px",
        height: _size + "px",
        "margin-top": (-this.minimized_height - this.top_epsilon) + "px",
		"z-align": "50"
    };
}

IriSP.Widgets.Timeline.prototype.calculateTimelineMiddleCss = function(_size, _middleSize) {
	var middleWidth = this.player.config.gui.width;
    return {
		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"
    };
}

IriSP.Widgets.Timeline.prototype.calculateHandleCss = function(_size) {
    return {
		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"
    }
}

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);
}

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();
}

/*
 * Affiche le bas des marqueurs correspondants à la recherche.
*/
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");
		}
	}
}

/*
 * Enlever une recherche faite précédemment.
*/
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);
	}
}

IriSP.Widgets.Timeline.prototype.freePlayer = function()
{
	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.
*/
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;
	
	//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;
		}
	}
	
	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)
	{
		//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)
			{
				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))
			{
				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;
			}
		}
	}*/
}

/*
 * 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).
*/
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);
		}
	}
}

/*
 * Renvoie vrai si il y a au moins une gesture de notre recherche dans les marqueurs de la video.
*/
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;
		}
	}
}