From af610a0df93ec6fa03417bbeeb44d064a26472f3 Mon Sep 17 00:00:00 2001 From: j Date: Tue, 17 May 2016 17:40:31 +0200 Subject: [PATCH] work around mobile interaction restrictions --- source/UI/js/Video/VideoElement.js | 51 ++++++++++++++++++++++++++---- source/UI/js/Video/VideoPlayer.js | 30 +++++++++++++++++- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/source/UI/js/Video/VideoElement.js b/source/UI/js/Video/VideoElement.js index e63b17b7..2184d9ed 100644 --- a/source/UI/js/Video/VideoElement.js +++ b/source/UI/js/Video/VideoElement.js @@ -112,12 +112,17 @@ Ox.VideoElement = function(options, self) { } }, 30); - loadItems(function() { - setCurrentItem(0); - self.options.autoplay && setTimeout(function() { - that.play(); - }); - }); + // mobile browsers only allow playing media elements after user interaction + if (mediaPlaybackRequiresUserGesture()) { + window.addEventListener('keydown', removeBehaviorsRestrictions); + window.addEventListener('mousedown', removeBehaviorsRestrictions); + window.addEventListener('touchstart', removeBehaviorsRestrictions); + setTimeout(function() { + that.triggerEvent('requiresusergesture'); + }) + } else { + setSource(); + } function getCurrentTime() { var item = self.items[self.currentItem]; @@ -327,6 +332,7 @@ Ox.VideoElement = function(options, self) { self.video.currentTime, self.video.seeking); isReady(self.$video, function(video) { self.$video.one('seeked', function() { + Ox.Log('Video', 'sCV', 'seeked callback'); self.loading = false; !self.paused && self.video.play(); self.$video.show(); @@ -336,6 +342,10 @@ Ox.VideoElement = function(options, self) { if (!self.seeking) { Ox.Log('Video', 'sCV set in', video.src, item['in'] || 0, video.currentTime, video.seeking); video.currentTime = item['in'] || 0; + if (self.paused) { + self.video.play(); + self.video.pause(); + } } }); } @@ -386,6 +396,35 @@ Ox.VideoElement = function(options, self) { } } + function setSource() { + Ox.Log('Video', 'self.loadedMetadata', self.loadedMetadata); + self.loadedMetadata = false; + loadItems(function() { + setCurrentItem(0); + self.options.autoplay && setTimeout(function() { + that.play(); + }); + }); + } + + function mediaPlaybackRequiresUserGesture() { + // test if play() is ignored when not called from an input event handler + var video = document.createElement('video'); + video.play(); + return video.paused; + } + + function removeBehaviorsRestrictions() { + Ox.Log('Video', 'remove restrictions on video', self.$video); + self.$videos.forEach(function(video) { + video.load(); + }); + window.removeEventListener('keydown', removeBehaviorsRestrictions); + window.removeEventListener('mousedown', removeBehaviorsRestrictions); + window.removeEventListener('touchstart', removeBehaviorsRestrictions); + setTimeout(setSource, 1000); + } + /*@ animate animate @*/ diff --git a/source/UI/js/Video/VideoPlayer.js b/source/UI/js/Video/VideoPlayer.js index 32852609..4e4a1989 100644 --- a/source/UI/js/Video/VideoPlayer.js +++ b/source/UI/js/Video/VideoPlayer.js @@ -443,8 +443,9 @@ Ox.VideoPlayer = function(options, self) { .bindEvent(Ox.extend({ durationchange: durationchange, ended: ended, - loadedmetadata: loadedmetadata, itemchange: itemchange, + loadedmetadata: loadedmetadata, + requiresusergesture: requiresusergesture, seeked: seeked, seeking: seeking, sizechange: sizechange @@ -1889,6 +1890,33 @@ Ox.VideoPlayer = function(options, self) { Ox.Log('Video', 'ITEMCHANGE', item); } + function requiresusergesture() { + Ox.Log('Video', 'requires user gesture'); + var $playIcon; + function removeBehaviorsRestrictions() { + window.removeEventListener('keydown', removeBehaviorsRestrictions); + window.removeEventListener('mousedown', removeBehaviorsRestrictions); + window.removeEventListener('touchstart', removeBehaviorsRestrictions); + $playIcon.remove(); + showLoadingIcon(); + } + window.addEventListener('keydown', removeBehaviorsRestrictions); + window.addEventListener('mousedown', removeBehaviorsRestrictions); + window.addEventListener('touchstart', removeBehaviorsRestrictions); + hideLoadingIcon(); + //FIXME: also load frame at current position? + $playIcon = $('') + .addClass('OxPlayIcon OxVideo OxInterface') + .attr({ + src: Ox.UI.getImageURL('symbolPlay', 'videoIcon') + }) + .css(getCSS('playIcon')) + .css({ + opacity: 1 + }) + .appendTo(self.$videoContainer); + } + function loadImage() { self.$image .one({