Added video player
authorveltr
Thu, 21 Mar 2013 18:48:12 +0100
changeset 11 9833f3e24105
parent 10 ab587bf164f9
child 12 81a8bb1d872a
Added video player
css/ipadsim.css
css/playscreen.css
css/socialmedia.css
css/startscreen.css
js/playscreen.js
js/remote-player.js
js/startscreen.js
js/video-window.js
lib/hammer.min.js
lib/jquery.ui.touch-punch.min.js
playscreen-frame.html
playscreen.html
startscreen-frame.html
startscreen.html
tv.html
--- a/css/ipadsim.css	Tue Mar 19 12:27:34 2013 +0100
+++ b/css/ipadsim.css	Thu Mar 21 18:48:12 2013 +0100
@@ -1,13 +1,21 @@
 .iPad-simulator {
     position: absolute; /* top: 50%; margin-top: -444px; */
-    left: 50%; margin-left: -572px; 
+    left: 50%; margin-left: -552px; 
     width: 1024px; height: 768px; border-radius: 30px;
-    padding: 0; border: 60px solid #f8f6f4;
+    padding: 0; border: 40px solid #f8f6f4;
     box-shadow: 5px 5px 20px #000000;
 }
 
 .iPad-simulator:after {
-    content: ""; position: absolute; top: 364px; height: 40px;
-    width: 40px; left: 1034px; background: #f2f0ed; border-radius: 20px;
+    content: ""; position: absolute; top: 364px; height: 20px;
+    width: 20px; left: 1034px; background: #f2f0ed; border-radius: 20px;
     box-shadow: inset 5px 5px 10px #a0a0a0;
 }
+
+.tv {
+	position: absolute; top: -35px; left: 0px;
+	background: #8080CC; color: #ffffff;
+	font-size: 18px; font-weight: bold; line-height: 30px;
+	padding: 0 5px; border-radius: 5px;
+	text-decoration: none;
+}
--- a/css/playscreen.css	Tue Mar 19 12:27:34 2013 +0100
+++ b/css/playscreen.css	Thu Mar 21 18:48:12 2013 +0100
@@ -16,20 +16,31 @@
 }
 
 .play-block {
-    width: 248px; height: 30px;
+    width: 402px; height: 30px;
+}
+
+.play-button, .next-button {
+    float: left; width: 30px; margin: 5px; font-size: 18px;
+    line-height: 20px; height: 20px; cursor: pointer;
 }
 
-.play-button {
-    float: left; margin: 5px; font-size: 18px;
-    line-height: 20px;
+.duration, .time-separator, .current-time {
+    float: left; height: 30px;
+    font-size: 20px; line-height: 30px;
 }
 
-.duration {
-    float: right; font-size: 20px; margin: 0 8px; line-height: 30px;
+.time-separator {
+	width: 10px; text-align: center;
+}
+.duration, .current-time {
+	width: 140px; margin: 0 8px;
+}
+.current-time {
+	text-align: right; color: #CCCCCC;
 }
 
 .explain-block {
-    width: 494px; height: 30px; padding: 0 5px;
+    width: 340px; height: 30px; padding: 0 5px;
 }
 
 .keyword-search {
@@ -50,11 +61,7 @@
 }
 
 .play-bottom {
-    position: absolute; top: 86px; bottom: 8px; overflow: hidden; width: 100%;
-}
-
-.play-dataviz {
-    float: left; height: 672px; width: 100%; position: relative; margin-left: 8px; overflow: hidden;
+    position: absolute; left: 8px; top: 86px; bottom: 8px; right: 8px; overflow: hidden;
 }
 
 .play-svg {
@@ -129,3 +136,15 @@
 	margin-top: 10px;
 }
 
+.local-position, .global-position {
+	position: absolute; height: 1px;
+	background: #FF00FC;
+}
+
+.global-position {
+	left: 0; width: 125px;
+}
+
+.local-position {
+	left: 155px; width: 215px;
+}
--- a/css/socialmedia.css	Tue Mar 19 12:27:34 2013 +0100
+++ b/css/socialmedia.css	Thu Mar 21 18:48:12 2013 +0100
@@ -8,5 +8,5 @@
 }
 
 .contents {
-    position: absolute; width: 100%; height: 100%; background: #000; color: #fff; overflow: hidden;
+    position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: #000; color: #fff; overflow: hidden;
 }
--- a/css/startscreen.css	Tue Mar 19 12:27:34 2013 +0100
+++ b/css/startscreen.css	Thu Mar 21 18:48:12 2013 +0100
@@ -116,6 +116,10 @@
     width: 236px; padding: 6px; cursor: pointer; background: #333333;
 }
 
+.topic:hover li {
+	color: #000000;
+}
+
 .highlight {
     color: #333333; background: #ffff00;
 }
--- a/js/playscreen.js	Tue Mar 19 12:27:34 2013 +0100
+++ b/js/playscreen.js	Thu Mar 21 18:48:12 2013 +0100
@@ -14,6 +14,17 @@
     
     var pageParams = {};
     
+    var syncVideo = true,
+    	syncTimer;
+    
+    function deSync() {
+    	syncVideo = false;
+    	clearTimeout(syncTimer);
+    	syncTimer = setTimeout(function() {
+    		syncVideo = true;
+    	},5000);
+    }
+    
     topicHash
     	.replace(/^#/,'')
     	.split('&')
@@ -61,22 +72,47 @@
         return pageParams.visibletopics.indexOf(t.index.toString()) !==-1 && t.index !== topicPoubelle;
     });
     
+    function hasTopics(mmso, topics) {
+    	for (var j = 0; j < mmso.topics.length; j++) {
+			if (topics.indexOf(mmso.topics[j].topic) !== -1) {
+				return true;
+			}
+		}
+		return false;
+    }
+    
+    function checkOrGoNext() {
+    	var topics = Array.prototype.slice.call(
+    		$(".topic.selected").map(function() {
+    			return parseInt($(this).attr("data-topic-id"))
+			})
+		);
+		var currentMmso = _(data.segments).find(function(s) {
+			return s.start <= player.currentTime && s.end > player.currentTime;
+		});
+		
+		if (hasTopics(currentMmso, topics)) {
+			throttledShowLocal();
+		} else {
+			goToNext();
+		}
+		
+    }
     
     function goToNext() {
-    	var topics = Array.prototype.slice.call($(".topic.selected").map(function(){return $(this).attr("data-topic-id")}));
+    	var topics = Array.prototype.slice.call(
+    		$(".topic.selected").map(function() {
+    			return parseInt($(this).attr("data-topic-id"));
+			})
+		);
     	for (var i = 0; i < data.segments.length; i++) {
     		var mmso = data.segments[i];
-    		if (mmso.start >= localpos) {
-    			for (var j = 0; j < mmso.topics.length; j++) {
-    				if (topics.indexOf(mmso.topics[j].topic.toString()) !== -1) {
-    					localpos = mmso.start;
-    					showLocal();
-    					return;
-    				}
-    			}
+    		if (mmso.start >= player.currentTime && hasTopics(mmso, topics)) {
+    			player.setCurrentTime(mmso.start);
+				throttledShowLocal();
+				return;
     		}
     	}
-    	console.log("We haven't found a segment");
     }
     
     function showTopics(topiclist) {
@@ -175,7 +211,7 @@
         tweetLines.forEach(function(tl) { tl.remove(); });
         tweetLines = [];
         
-        var deltaY = $(".play-dataviz").offset().top;
+        var deltaY = $(".play-bottom").offset().top;
         
         $(".play-localtweets .tweet:visible").each(function() {
         	var el = $(this),
@@ -207,7 +243,6 @@
         yscale = ph / data.duration,
         mx = Math.max.apply(Math, data.minutes.map(function(s) { return s.count})),
         xscale = globW/mx;
-    
     var segmentrects = data.segments.map(function(mmso) {
         var rect = paper.rect(globL, yscale * mmso.start, globW, yscale * mmso.duration);
         rect.attr({stroke: "none"});
@@ -274,6 +309,10 @@
     
     var cloudTemplate = _.template('<li style="font-size: <%- size %>px;"<% if (selected) {%> class="selected"<% } %>><%- word %></li>');
     
+    var globalIndic = $(".global-position"),
+    	localIndic = $(".local-position"),
+    	playTime = $(".current-time");
+    
     function showLocal() {
 		localyscale = ph / localduration;
     	var localstart = localpos - localduration/2;
@@ -293,6 +332,7 @@
 			localkeywords = {};
 			
 		entonnoir.attr("path",entonnoird);
+    	localIndic.css("top",(player.currentTime - localstart) * localyscale);
 		localTimes.forEach(function(t) {
 			t.text.remove();
 			t.line.remove();
@@ -447,7 +487,7 @@
     	callnum = 0,
     	tweetstructure = {},
     	requestedtweets = {},
-    	_NTWEETS = 20,
+    	_NTWEETS = 50,
     	selectedWord = false;
     
     function showTweets() {
@@ -676,8 +716,39 @@
     
     var localpos = 300,
     	localduration = 600;
-    	
-    goToNext();
+   	
+   	var player = new Player();
+   	
+   	player.duration = data.duration;
+   	
+   	player.on("play", function() {
+   		$(".play-button").html("▐&nbsp;▌");
+   	});
+   	player.on("pause", function() {
+   		$(".play-button").text("▶");
+   	});
+   	player.on("timeupdate", function(t) {
+   		playTime.text(secsToString(t));
+   		globalIndic.css("top", yscale * t);
+   		if (localyscale) {
+   			var localy = (+t - localpos + localduration / 2) * localyscale;
+   			localIndic.css("top", localy);
+   		}
+    	if (syncVideo) {
+    		localpos = Math.max(localduration / 2, Math.min(data.duration - localduration / 2, t));
+    		throttledShowLocal();
+    	}
+   	});
+   	
+   	$(".play-button").click(function() {
+   		if (player.paused) {
+   			player.play();
+   		} else {
+   			player.pause();
+   		}
+   	});
+    
+    $(".next-button").click(goToNext);
     
     $(".topics-block").on("mouseenter", ".topic", function() {
         var el = $(this);
@@ -692,48 +763,58 @@
         el.attr("data-timestamp", el.hasClass("selected") ? ++ordertag : 999999);
         showTopicViz();
     });
-    
-    var mouseIsDown, isDragging, startY, startT, startPos, scrollGlobal, speedscale, slowiterations;
-    
-    $(document).mouseup(function() { mouseIsDown = false; isDragging = false; });
-    
-    $(".play-dataviz").mousedown(function(e) {
-    	var l = $(this).offset().left,
-    		scrollLimit = l + 380;
-		if (e.pageX < scrollLimit) {
-			mouseIsDown = true;
-	    	startY = e.pageY;
-	    	startT = new Date();
-	    	startPos = localpos;
-	    	scrollGlobal = e.pageX < (l + 140);
-	    	e.preventDefault();
+
+	var h = Hammer($(".play-bottom")[0]);
+	
+	var scrollGlobal, isDragging, startPos, startLevel, scaleStep = 1/Math.log(Math.sqrt(2));
+	
+	h.on("tap", function(e) {
+		var _o = $(this).offset(),
+			posX = e.gesture.center.pageX - _o.left,
+			posY = e.gesture.center.pageY - _o.top;
+		if (posX < 140) {
+			deSync();
+			localpos = Math.max(localduration / 2, Math.min(data.duration - localduration / 2, Math.floor(posY / yscale)));
+			throttledShowLocal();
 		}
-    }).mousemove(function(e) {
-    	if (mouseIsDown) {
-    		if (isDragging) {
-    			var deltaY = e.pageY - startY,
-    				delta = Math.floor(deltaY / (scrollGlobal ? yscale : - localyscale));
-				localpos = Math.max(localduration / 2, Math.min(data.duration - localduration / 2, startPos + delta));
-				throttledShowLocal();
-    		} else {
-    			isDragging = true;
-    		}
-    	}
-    }).mouseup(function(e) {
-    	if (scrollGlobal && !isDragging) {
-    		var _o = $(this).offset(),
-    			posX = e.pageX - _o.left,
-    			posY = e.pageY - _o.top;
-			if (posX < 140) {
-				localpos = Math.max(localduration / 2, Math.min(data.duration - localduration / 2, Math.floor(posY / yscale)));
-				throttledShowLocal();
-			}
-    	}
-    });
-    
+	})
+	.on("dragstart", function(e) {
+		startPos = localpos;
+		var x = e.gesture.center.pageX - $(this).offset().left;
+		isDragging = (x < 380);
+		scrollGlobal = (x < 140);
+	})
+	.on("drag", function(e) {
+		if (isDragging && e.gesture) {
+			var delta = Math.floor(e.gesture.deltaY / (scrollGlobal ? yscale : - localyscale));
+			deSync();
+			localpos = Math.max(localduration / 2, Math.min(data.duration - localduration / 2, startPos + delta));
+			throttledShowLocal();
+		}
+	})
+	.on("touch", function(e) {
+		startLevel = currentlevel;
+	})
+	.on("pinchin", function(e) {
+		var newlevel = Math.max(0, Math.min(zoomlevels.length - 1, startLevel + Math.round(Math.log(e.gesture.scale)*scaleStep)));
+		if (newlevel !== currentlevel) {
+			currentlevel = newlevel;
+			localduration = zoomlevels[currentlevel];
+			localpos = Math.max(localduration / 2, Math.min(data.duration - localduration / 2, localpos));
+			throttledShowLocal();
+		}
+	});
+   
     var totalScroll = 0, zoomlevels = [ 1800, 900, 600, 300, 120, 60 ], currentlevel = 2;
     
-    $(".play-dataviz").mousewheel(function(_event, _scrolldelta) {
+    $(".play-bottom")
+    .mousedown(function(_e) {
+    	_e.preventDefault();
+    })
+    .on("touchstart", function(_e) {
+    	_e.preventDefault();
+    })
+    .mousewheel(function(_event, _scrolldelta) {
     	totalScroll += _scrolldelta;
 	    if (Math.abs(totalScroll) >= 1) {
 	    	var d = (totalScroll > 0 ? 1 : -1),
@@ -746,12 +827,14 @@
     		}
 	        totalScroll = 0;
 	    }
+	    _event.preventDefault();
     });
     
     if (pageParams.keywords && pageParams.keywords.length) {
     	$(".keyword-search a").removeClass("placeholder").text(pageParams.keywords.join(", "));
     }
     
+    checkOrGoNext();
 }
 
 var data = { duration: 10200, topics: [] },
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/js/remote-player.js	Thu Mar 21 18:48:12 2013 +0100
@@ -0,0 +1,119 @@
+function Player() {
+	
+	var events = {},
+        self = this,
+        loaded = false,
+//        tvWindow,
+        destination = document.location.href.replace(/^(https?:\/\/[^\/]+).*$/,'$1'),
+        timeAtLoad,
+        timeDelta = 0,
+        timeOut,
+        playAtLoad = false;
+    
+    this.currentTime = 0;
+    this.duration = 0;
+    this.paused = true;
+    
+	function receiveMessage(evt) {
+		var dataparts = evt.data.split(":");
+		loaded = true;
+		switch(dataparts[0]) {
+			case "loadedmetadata":
+				self.duration = parseFloat(dataparts[1]);
+				self.setCurrentTime(self.currentTime);
+				if (!self.paused) {
+					self.play();
+				}
+			break;
+			case "play":
+				self.paused = false;
+				self.trigger("play");
+			break;
+			case "pause":
+				self.paused = true;
+				self.trigger("pause");
+			break;
+			case "timeupdate":
+				self.currentTime = parseFloat(dataparts[1])
+				self.trigger("timeupdate", self.currentTime);
+			break;
+			case "unload":
+				loaded = false;
+				self.pause();
+			break;
+		}
+	}
+	
+    function updateTime() {
+    	clearTimeout(timeOut);
+        if (!loaded && !self.paused) {
+            self.currentTime = (new Date().valueOf() / 1000 - timeDelta);
+            if (self.currentTime <= self.duration) {
+                self.trigger("timeupdate", self.currentTime);
+                timeOut = setTimeout(updateTime, 100);
+            } else {
+                self.currentTime = self.duration;
+                self.pause();
+            }
+        }
+    }
+	
+	function sendMessage(msg) {
+		if (tvWindow) {
+			tvWindow.postMessage(msg, destination);
+		}
+	}
+	
+	$(".tv").click(function() {
+		tvWindow = window.open("tv.html","TV","width=640,height=360,toolbar=0,location=0,status=0,titlebar=0");
+		window.addEventListener("message",receiveMessage,false);
+	});
+	
+	this.setCurrentTime = function(t) {
+		if (loaded) {
+			sendMessage("timeupdate:" + t);
+		} else {
+        	timeDelta = (new Date().valueOf() / 1000 - t);
+			self.currentTime = t;
+			self.trigger("timeupdate",t);
+		}
+	}
+	this.play = function() {
+		if (loaded) {
+			sendMessage("play")
+		} else {
+	        self.paused = false;
+	        timeDelta = (new Date().valueOf() / 1000 - self.currentTime)
+	        self.trigger("play");
+	        updateTime();
+		}
+	}
+	this.pause = function() {
+		if (loaded) {
+			sendMessage("pause");
+		} else {
+			self.paused = true;
+			self.trigger("pause");
+		}
+	}
+	
+	this.on = function(_event, _callback) {
+	    if (typeof events[_event] === "undefined") {
+	        events[_event] = [];
+	    }
+	    events[_event].push(_callback);
+	}
+	this.off = function(_event, _callback) {
+	    if (typeof events[_event] !== "undefined") {
+	        events[_event] = _(events[_event]).reject(function(_fn) {
+	            return _fn === _callback;
+	        });
+	    }
+	}
+	this.trigger = function(_event, _data) {
+	    var _list = this;
+	    _(events[_event]).each(function(_callback) {
+	        _callback.call(_list, _data);
+	    });
+	}
+}
--- a/js/startscreen.js	Tue Mar 19 12:27:34 2013 +0100
+++ b/js/startscreen.js	Thu Mar 21 18:48:12 2013 +0100
@@ -1,4 +1,4 @@
-var topicPoubelle = 13;
+var topicPoubelle = -13;
 
 function showData() {
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/js/video-window.js	Thu Mar 21 18:48:12 2013 +0100
@@ -0,0 +1,46 @@
+window.addEventListener("DOMContentLoaded", function() {
+	
+	var video = document.querySelector("video"),
+		destination = document.location.href.replace(/^(https?:\/\/[^\/]+).*$/,'$1');
+	
+	function receiveMessage(evt) {
+		var dataparts = evt.data.split(":");
+		switch(dataparts[0]) {
+			case "play":
+				video.play();
+			break;
+			case "pause":
+				video.pause();
+			break;
+			case "timeupdate":
+				video.currentTime = parseFloat(dataparts[1]);
+			break;
+		}
+	}
+	
+	function sendMessage(msg) {
+		if (window.opener) {
+			window.opener.postMessage(msg, destination);
+		}
+	}
+	
+	window.addEventListener("message", receiveMessage, false);
+	
+	window.addEventListener("unload", function() {
+		sendMessage("unload");
+	}, false);
+	
+	video.addEventListener("loadedmetadata", function() {
+		sendMessage("loadedmetadata:"+video.duration);
+	}, false);
+	video.addEventListener("timeupdate", function() {
+		sendMessage("timeupdate:"+video.currentTime);
+	}, false);
+	video.addEventListener("play", function() {
+		sendMessage("play");
+	}, false);
+	video.addEventListener("pause", function() {
+		sendMessage("pause");
+	}, false);
+	
+}, false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/hammer.min.js	Thu Mar 21 18:48:12 2013 +0100
@@ -0,0 +1,7 @@
+/*! Hammer.JS - v1.0.3 - 2013-03-02
+ * http://eightmedia.github.com/hammer.js
+ *
+ * Copyright (c) 2013 Jorik Tangelder <j.tangelder@gmail.com>;
+ * Licensed under the MIT license */
+
+(function(t){"use strict";function e(){if(!n.READY){n.event.determineEventTypes();for(var t in n.gestures)n.gestures.hasOwnProperty(t)&&n.detection.register(n.gestures[t]);n.event.onTouch(document,n.EVENT_MOVE,n.detection.detect),n.event.onTouch(document,n.EVENT_END,n.detection.endDetect),n.READY=!0}}var n=function(t,e){return new n.Instance(t,e||{})};n.defaults={stop_browser_behavior:{userSelect:"none",touchCallout:"none",touchAction:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},n.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,n.HAS_TOUCHEVENTS="ontouchstart"in t,n.EVENT_TYPES={},n.DIRECTION_DOWN="down",n.DIRECTION_LEFT="left",n.DIRECTION_UP="up",n.DIRECTION_RIGHT="right",n.POINTER_MOUSE="mouse",n.POINTER_TOUCH="touch",n.POINTER_PEN="pen",n.EVENT_START="start",n.EVENT_MOVE="move",n.EVENT_END="end",n.plugins={},n.READY=!1,n.Instance=function(t,i){var r=this;return e(),this.element=t,this.enabled=!0,this.options=n.utils.extend(n.utils.extend({},n.defaults),i||{}),this.options.stop_browser_behavior&&n.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),n.event.onTouch(t,n.EVENT_START,function(t){r.enabled&&n.detection.startDetect(r,t)}),this},n.Instance.prototype={on:function(t,e){for(var n=t.split(" "),i=0;n.length>i;i++)this.element.addEventListener(n[i],e,!1);return this},off:function(t,e){for(var n=t.split(" "),i=0;n.length>i;i++)this.element.removeEventListener(n[i],e,!1);return this},trigger:function(t,e){var n=document.createEvent("Event");return n.initEvent(t,!0,!0),n.gesture=e,this.element.dispatchEvent(n),this},enable:function(t){return this.enabled=t,this}};var i=null,r=!1,o=!1;n.event={bindDom:function(t,e,n){for(var i=e.split(" "),r=0;i.length>r;r++)t.addEventListener(i[r],n,!1)},onTouch:function(t,e,s){var a=this;this.bindDom(t,n.EVENT_TYPES[e],function(c){var u=c.type.toLowerCase();return u.match(/mouseup/)&&o?(o=!1,void 0):((u.match(/touch/)||u.match(/mouse/)&&1===c.which||n.HAS_POINTEREVENTS&&u.match(/down/))&&(r=!0),u.match(/touch|pointer/)&&(o=!0),!r||o&&u.match(/mouse/)||(n.HAS_POINTEREVENTS&&e!=n.EVENT_END&&n.PointerEvent.updatePointer(e,c),e===n.EVENT_END&&null!==i?c=i:i=c,s.call(n.detection,a.collectEventData(t,e,c)),n.HAS_POINTEREVENTS&&e==n.EVENT_END&&n.PointerEvent.updatePointer(e,c)),u.match(/up|cancel|end/)&&(r=!1,i=null,n.PointerEvent.reset()),void 0)})},determineEventTypes:function(){var t;t=n.HAS_POINTEREVENTS?n.PointerEvent.getEvents():["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],n.EVENT_TYPES[n.EVENT_START]=t[0],n.EVENT_TYPES[n.EVENT_MOVE]=t[1],n.EVENT_TYPES[n.EVENT_END]=t[2]},getTouchList:function(t){return n.HAS_POINTEREVENTS?n.PointerEvent.getTouchList():t.touches?t.touches:[{identifier:1,pageX:t.pageX,pageY:t.pageY,target:t.target}]},collectEventData:function(t,e,i){var r=this.getTouchList(i,e),o=n.POINTER_TOUCH;return(i.type.match(/mouse/)||n.PointerEvent.matchType(n.POINTER_MOUSE,i))&&(o=n.POINTER_MOUSE),{center:n.utils.getCenter(r),timestamp:i.timestamp||(new Date).getTime(),target:i.target,touches:r,eventType:e,pointerType:o,srcEvent:i,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault&&this.srcEvent.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return n.detection.stopDetect()}}}},n.PointerEvent={pointers:{},getTouchList:function(){var t=this.pointers,e=[];return Object.keys(t).sort().forEach(function(n){e.push(t[n])}),e},updatePointer:function(t,e){t==n.EVENT_END?delete this.pointers[e.pointerId]:(e.identifier=e.pointerId,this.pointers[e.pointerId]=e)},matchType:function(t,e){if(!e.pointerType)return!1;var i={};return i[n.POINTER_MOUSE]=e.pointerType==e.MSPOINTER_TYPE_MOUSE||e.pointerType==n.POINTER_MOUSE,i[n.POINTER_TOUCH]=e.pointerType==e.MSPOINTER_TYPE_TOUCH||e.pointerType==n.POINTER_TOUCH,i[n.POINTER_PEN]=e.pointerType==e.MSPOINTER_TYPE_PEN||e.pointerType==n.POINTER_PEN,i[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},n.utils={extend:function(t,e){for(var n in e)t[n]=e[n];return t},getCenter:function(t){for(var e=[],n=[],i=0,r=t.length;r>i;i++)e.push(t[i].pageX),n.push(t[i].pageY);return{pageX:(Math.min.apply(Math,e)+Math.max.apply(Math,e))/2,pageY:(Math.min.apply(Math,n)+Math.max.apply(Math,n))/2}},getVelocity:function(t,e,n){return{x:Math.abs(e/t)||0,y:Math.abs(n/t)||0}},getAngle:function(t,e){var n=e.pageY-t.pageY,i=e.pageX-t.pageX;return 180*Math.atan2(n,i)/Math.PI},getDirection:function(t,e){var i=Math.abs(t.pageX-e.pageX),r=Math.abs(t.pageY-e.pageY);return i>=r?t.pageX-e.pageX>0?n.DIRECTION_LEFT:n.DIRECTION_RIGHT:t.pageY-e.pageY>0?n.DIRECTION_UP:n.DIRECTION_DOWN},getDistance:function(t,e){var n=e.pageX-t.pageX,i=e.pageY-t.pageY;return Math.sqrt(n*n+i*i)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==n.DIRECTION_UP||t==n.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(t,e){var n,i=["webkit","khtml","moz","ms","o",""];if(e&&t.style){for(var r=0;i.length>r;r++)for(var o in e)e.hasOwnProperty(o)&&(n=o,i[r]&&(n=i[r]+n.substring(0,1).toUpperCase()+n.substring(1)),t.style[n]=e[o]);"none"==e.userSelect&&(t.onselectstart=function(){return!1})}}},n.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:n.utils.extend({},e),lastEvent:!1,name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);for(var e=this.current.inst.options,n=0,i=this.gestures.length;i>n;n++){var r=this.gestures[n];if(!this.stopped&&e[r.name]!==!1&&r.handler.call(r,t,this.current.inst)===!1){this.stopDetect();break}}this.current&&(this.current.lastEvent=t)}},endDetect:function(t){this.detect(t),this.stopDetect()},stopDetect:function(){this.previous=n.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var e=this.current.startEvent;if(e&&(t.touches.length!=e.touches.length||t.touches===e.touches)){e.touches=[];for(var i=0,r=t.touches.length;r>i;i++)e.touches.push(n.utils.extend({},t.touches[i]))}var o=t.timestamp-e.timestamp,s=t.center.pageX-e.center.pageX,a=t.center.pageY-e.center.pageY,c=n.utils.getVelocity(o,s,a);return n.utils.extend(t,{deltaTime:o,deltaX:s,deltaY:a,velocityX:c.x,velocityY:c.y,distance:n.utils.getDistance(e.center,t.center),angle:n.utils.getAngle(e.center,t.center),direction:n.utils.getDirection(e.center,t.center),scale:n.utils.getScale(e.touches,t.touches),rotation:n.utils.getRotation(e.touches,t.touches),startEvent:e}),t},register:function(t){var e=t.defaults||{};return e[t.name]===void 0&&(e[t.name]=!0),n.utils.extend(n.defaults,e),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.index<e.index?-1:t.index>e.index?1:0}),this.gestures}},n.gestures=n.gestures||{},n.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(t,e){switch(t.eventType){case n.EVENT_START:clearTimeout(this.timer),n.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==n.detection.current.name&&e.trigger("hold",t)},e.options.hold_timeout);break;case n.EVENT_MOVE:t.distance>e.options.hold_threshold&&clearTimeout(this.timer);break;case n.EVENT_END:clearTimeout(this.timer)}}},n.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,doubletap_distance:20,doubletap_interval:300},handler:function(t,e){if(t.eventType==n.EVENT_END){var i=n.detection.previous;if(t.deltaTime>e.options.tap_max_touchtime||t.distance>e.options.tap_max_distance)return;n.detection.current.name=i&&"tap"==i.name&&t.timestamp-i.lastEvent.timestamp<e.options.doubletap_interval&&t.distance<e.options.doubletap_distance?"doubletap":"tap",e.trigger(n.detection.current.name,t)}}},n.gestures.Swipe={name:"swipe",index:40,defaults:{swipe_max_touches:1,swipe_velocity:.7},handler:function(t,e){if(t.eventType==n.EVENT_END){if(e.options.swipe_max_touches>0&&t.touches.length>e.options.swipe_max_touches)return;(t.velocityX>e.options.swipe_velocity||t.velocityY>e.options.swipe_velocity)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},n.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,drag_max_touches:1,drag_block_horizontal:!1,drag_block_vertical:!1,drag_lock_to_axis:!1},triggered:!1,handler:function(t,e){if(n.detection.current.name!=this.name&&this.triggered)return e.trigger(this.name+"end",t),this.triggered=!1,void 0;if(!(e.options.drag_max_touches>0&&t.touches.length>e.options.drag_max_touches))switch(t.eventType){case n.EVENT_START:this.triggered=!1;break;case n.EVENT_MOVE:if(t.distance<e.options.drag_min_distance&&n.detection.current.name!=this.name)return;n.detection.current.name=this.name;var i=n.detection.current.lastEvent.direction;e.options.drag_lock_to_axis&&i!==t.direction&&(t.direction=n.utils.isVertical(i)?0>t.deltaY?n.DIRECTION_UP:n.DIRECTION_DOWN:0>t.deltaX?n.DIRECTION_LEFT:n.DIRECTION_RIGHT),this.triggered||(e.trigger(this.name+"start",t),this.triggered=!0),e.trigger(this.name,t),e.trigger(this.name+t.direction,t),(e.options.drag_block_vertical&&n.utils.isVertical(t.direction)||e.options.drag_block_horizontal&&!n.utils.isVertical(t.direction))&&t.preventDefault();break;case n.EVENT_END:this.triggered&&e.trigger(this.name+"end",t),this.triggered=!1}}},n.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,e){if(n.detection.current.name!=this.name&&this.triggered)return e.trigger(this.name+"end",t),this.triggered=!1,void 0;if(!(2>t.touches.length))switch(e.options.transform_always_block&&t.preventDefault(),t.eventType){case n.EVENT_START:this.triggered=!1;break;case n.EVENT_MOVE:var i=Math.abs(1-t.scale),r=Math.abs(t.rotation);if(e.options.transform_min_scale>i&&e.options.transform_min_rotation>r)return;n.detection.current.name=this.name,this.triggered||(e.trigger(this.name+"start",t),this.triggered=!0),e.trigger(this.name,t),r>e.options.transform_min_rotation&&e.trigger("rotate",t),i>e.options.transform_min_scale&&(e.trigger("pinch",t),e.trigger("pinch"+(1>t.scale?"in":"out"),t));break;case n.EVENT_END:this.triggered&&e.trigger(this.name+"end",t),this.triggered=!1}}},n.gestures.Touch={name:"touch",index:-1/0,defaults:{prevent_default:!1},handler:function(t,e){e.options.prevent_default&&t.preventDefault(),t.eventType==n.EVENT_START&&e.trigger(this.name,t)}},n.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==n.EVENT_END&&e.trigger(this.name,t)}},"object"==typeof module&&"object"==typeof module.exports?module.exports=n:(t.Hammer=n,"function"==typeof t.define&&t.define.amd&&t.define("hammer",[],function(){return n}))})(this);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/jquery.ui.touch-punch.min.js	Thu Mar 21 18:48:12 2013 +0100
@@ -0,0 +1,11 @@
+/*
+ * jQuery UI Touch Punch 0.2.2
+ *
+ * Copyright 2011, Dave Furfero
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * Depends:
+ *  jquery.ui.widget.js
+ *  jquery.ui.mouse.js
+ */
+(function(b){b.support.touch="ontouchend" in document;if(!b.support.touch){return;}var c=b.ui.mouse.prototype,e=c._mouseInit,a;function d(g,h){if(g.originalEvent.touches.length>1){return;}g.preventDefault();var i=g.originalEvent.changedTouches[0],f=document.createEvent("MouseEvents");f.initMouseEvent(h,true,true,window,1,i.screenX,i.screenY,i.clientX,i.clientY,false,false,false,false,0,null);g.target.dispatchEvent(f);}c._touchStart=function(g){var f=this;if(a||!f._mouseCapture(g.originalEvent.changedTouches[0])){return;}a=true;f._touchMoved=false;d(g,"mouseover");d(g,"mousemove");d(g,"mousedown");};c._touchMove=function(f){if(!a){return;}this._touchMoved=true;d(f,"mousemove");};c._touchEnd=function(f){if(!a){return;}d(f,"mouseup");d(f,"mouseout");if(!this._touchMoved){d(f,"click");}a=false;};c._mouseInit=function(){var f=this;f.element.bind("touchstart",b.proxy(f,"_touchStart")).bind("touchmove",b.proxy(f,"_touchMove")).bind("touchend",b.proxy(f,"_touchEnd"));e.call(f);};})(jQuery);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/playscreen-frame.html	Thu Mar 21 18:48:12 2013 +0100
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html lang="fr">
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+        <title>IRI/ALBLF Social Media</title>
+        <link rel="stylesheet" type="text/css" href="lib/jquery-ui.min.css" />
+        <link rel="stylesheet" type="text/css" href="css/reset.css" />
+        <link rel="stylesheet" type="text/css" href="css/ipadsim.css" />
+        <link rel="stylesheet" type="text/css" href="css/socialmedia.css" />
+        <link rel="stylesheet" type="text/css" href="css/playscreen.css" />
+        <script>
+            var pathToDwrServlet = "http://159.217.144.101:8050/sia-solr/dwr";
+        </script>
+        <script src="lib/underscore-min.js"></script>
+        <script src="lib/jquery.min.js"></script>
+        <script src="lib/jquery-ui.min.js"></script>
+        <script src="lib/jquery.mousewheel.min.js"></script>
+        <script src="lib/hammer.min.js"></script>
+        <script src="lib/raphael-min.js"></script>
+        <script src="js/playscreen.js"></script>
+        <script src="js/remote-player.js"></script>
+        <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/engine.js"></script>
+        <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/util.js"></script>
+        <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/interface/TopicsBean.js"></script>
+    </head>
+    <body>
+        <div class="iPad-simulator">
+            <div class="contents">
+                <div class="play-head">
+                    <div class="title-block">
+                        <h1>Le débat</h1>
+                    </div>
+                    <div class="play-block shadow-block">
+                        <div class="play-button">▶</div>
+                        <div class="current-time">0:00:00</div>
+                        <div class="time-separator">/</div>
+                        <div class="duration">0:00:00</div>
+                        <div class="next-button">▶▎</div>
+                    </div>
+                    <div class="explain-block shadow-block">
+                        <div class="keyword-search"><a href="startscreen.html" class="placeholder">Rechercher</a></div>
+                    </div>
+                </div>
+                
+                <div class="play-second-line">
+                	<div class="topics-block"></div>
+            	</div>
+                
+                <div class="play-bottom">
+                    <div class="play-dataviz">
+                        <div class="play-svg"></div>
+                        <div class="play-images"></div>
+	                	<div class="global-position"></div>
+	                	<div class="local-position"></div>
+                    	<ul class="play-localtweets"></ul>
+                    	<ul class="play-tagcloud"></ul>
+                    </div>
+                </div>
+            </div>
+            <a class="tv" href="#">Ouvrir la fenêtre TV</a>
+        </div>
+    </body>
+</html>
\ No newline at end of file
--- a/playscreen.html	Tue Mar 19 12:27:34 2013 +0100
+++ b/playscreen.html	Thu Mar 21 18:48:12 2013 +0100
@@ -4,9 +4,9 @@
         <meta charset="utf-8" />
         <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
         <title>IRI/ALBLF Social Media</title>
+                <meta name="viewport" content="initial-scale=1,user-scalable=no,maximum-scale=1,width=device-width" />
         <link rel="stylesheet" type="text/css" href="lib/jquery-ui.min.css" />
         <link rel="stylesheet" type="text/css" href="css/reset.css" />
-        <link rel="stylesheet" type="text/css" href="css/ipadsim.css" />
         <link rel="stylesheet" type="text/css" href="css/socialmedia.css" />
         <link rel="stylesheet" type="text/css" href="css/playscreen.css" />
         <script>
@@ -15,26 +15,31 @@
         <script src="lib/underscore-min.js"></script>
         <script src="lib/jquery.min.js"></script>
         <script src="lib/jquery-ui.min.js"></script>
+        <script src="lib/jquery.ui.touch-punch.min.js"></script>
         <script src="lib/jquery.mousewheel.min.js"></script>
+        <script src="lib/hammer.min.js"></script>
         <script src="lib/raphael-min.js"></script>
+        <script src="js/remote-player.js"></script>
         <script src="js/playscreen.js"></script>
         <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/engine.js"></script>
         <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/util.js"></script>
         <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/interface/TopicsBean.js"></script>
     </head>
     <body>
-        <div class="iPad-simulator">
             <div class="contents">
                 <div class="play-head">
                     <div class="title-block">
                         <h1>Le débat</h1>
                     </div>
                     <div class="play-block shadow-block">
-                        <div class="play-button">&#9654;</div>
+                        <div class="play-button">▶</div>
+                        <div class="current-time">0:00:00</div>
+                        <div class="time-separator">/</div>
                         <div class="duration">0:00:00</div>
+                        <div class="next-button">▶▎</div>
                     </div>
                     <div class="explain-block shadow-block">
-                        <div class="keyword-search"><a href="startscreen.html" class="placeholder">Rechercher</a></p>
+                        <div class="keyword-search"><a href="startscreen.html" class="placeholder">Rechercher</a></div>
                     </div>
                 </div>
                 
@@ -43,14 +48,13 @@
             	</div>
                 
                 <div class="play-bottom">
-                    <div class="play-dataviz">
-                        <div class="play-svg"></div>
-                        <div class="play-images"></div>
-                    	<ul class="play-localtweets"></ul>
-                    	<ul class="play-tagcloud"></ul>
-                    </div>
+                    <div class="play-svg"></div>
+                    <div class="play-images"></div>
+                	<div class="global-position"></div>
+                	<div class="local-position"></div>
+                	<ul class="play-localtweets"></ul>
+                	<ul class="play-tagcloud"></ul>
                 </div>
             </div>
-        </div>
     </body>
 </html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/startscreen-frame.html	Thu Mar 21 18:48:12 2013 +0100
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="fr">
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+        <title>IRI/ALBLF Social Media</title>
+        <link rel="stylesheet" type="text/css" href="lib/jquery-ui.min.css" />
+        <link rel="stylesheet" type="text/css" href="css/reset.css" />
+        <link rel="stylesheet" type="text/css" href="css/ipadsim.css" />
+        <link rel="stylesheet" type="text/css" href="css/socialmedia.css" />
+        <link rel="stylesheet" type="text/css" href="css/startscreen.css" />
+        <script>
+            var pathToDwrServlet = "http://159.217.144.101:8050/sia-solr/dwr";
+        </script>
+        <script src="lib/underscore-min.js"></script>
+        <script src="lib/jquery.min.js"></script>
+        <script src="lib/jquery-ui.min.js"></script>
+        <script src="lib/raphael-min.js"></script>
+        <script src="js/startscreen.js"></script>
+        <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/engine.js"></script>
+        <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/util.js"></script>
+        <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/interface/TopicsBean.js"></script>
+    </head>
+    <body>
+        <div class="iPad-simulator">
+            <div class="contents">
+                <div class="start-head">
+                    <div class="title-block">
+                        <h1>Le débat</h1>
+                    </div>
+                    <div class="play-block shadow-block">
+                        <a class="play-button" href="#">&#9654;</a>
+                        <div class="duration">0:00:00</div>
+                    </div>
+                    <div class="explain-block shadow-block">
+                        <h3>Recherchez les sujets de l'émission par mots-clés</h3>
+                        <p><input class="keyword-search" type="search" placeholder="Rechercher" /></p>
+                    </div>
+                </div>
+                
+                <div class="start-second-line">
+                    <div class="shadow-block description-block">
+                        <p>Description de la vidéo du débat ici</p>
+                    </div>
+                    <div class="topwords-block shadow-block">
+                        <ul class="topwords-list"></ul>
+                    </div>
+                </div>
+                
+                <div class="start-bottom">
+                    <div class="start-dataviz">
+                        <div class="start-svg"></div>
+                    </div>
+                    <ul class="topics-block"></div>
+                </div>
+            </div>
+        </div>
+    </body>
+</html>
\ No newline at end of file
--- a/startscreen.html	Tue Mar 19 12:27:34 2013 +0100
+++ b/startscreen.html	Thu Mar 21 18:48:12 2013 +0100
@@ -4,9 +4,9 @@
         <meta charset="utf-8" />
         <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
         <title>IRI/ALBLF Social Media</title>
+                <meta name="viewport" content="initial-scale=1,user-scalable=no,maximum-scale=1,width=device-width" />
         <link rel="stylesheet" type="text/css" href="lib/jquery-ui.min.css" />
         <link rel="stylesheet" type="text/css" href="css/reset.css" />
-        <link rel="stylesheet" type="text/css" href="css/ipadsim.css" />
         <link rel="stylesheet" type="text/css" href="css/socialmedia.css" />
         <link rel="stylesheet" type="text/css" href="css/startscreen.css" />
         <script>
@@ -15,6 +15,7 @@
         <script src="lib/underscore-min.js"></script>
         <script src="lib/jquery.min.js"></script>
         <script src="lib/jquery-ui.min.js"></script>
+        <script src="lib/jquery.ui.touch-punch.min.js"></script>
         <script src="lib/raphael-min.js"></script>
         <script src="js/startscreen.js"></script>
         <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/engine.js"></script>
@@ -22,7 +23,6 @@
         <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/interface/TopicsBean.js"></script>
     </head>
     <body>
-        <div class="iPad-simulator">
             <div class="contents">
                 <div class="start-head">
                     <div class="title-block">
@@ -54,6 +54,5 @@
                     <ul class="topics-block"></div>
                 </div>
             </div>
-        </div>
     </body>
 </html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tv.html	Thu Mar 21 18:48:12 2013 +0100
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="fr">
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+        <title>IRI/ALBLF Social Media</title>
+        <link rel="stylesheet" type="text/css" href="css/reset.css" />
+        <script src="js/video-window.js"></script>
+        <style type="text/css">
+        	body {
+        		background: #000000;
+        	}
+        	video {
+        		width: 100%;
+        	}
+        </style>
+    </head>
+    <body>
+        <video controls="true" src="http://159.217.144.101:8050/sia-solr/video/debat.webm"></video>
+    </body>
+</html>
\ No newline at end of file