I am trying to prevent the default scrolling within a web app which contains an HTML5 video element on Mobile Safari. Handling document.ontouchmove and calling e.preventDefault() has been the standard way that I've found to achieve this.
This seems to work everywhere except when you touch on top of the video element, where you can start pulling the page all around as if it is going to scroll. This only seems to happen when the native video controls are forced on. If you don't include the controls attribute and load the video in a way that it can be played in-line (such as on the iPad or in a UIWebView with allowsInlineMediaPlayback set), scrolling is prevented properly. So it seems like it has something to do with the native video controls (the big play button) capturing the event.
Here is a contrived example of what I am doing:
<!DOCTYPE HTML>
<html>
<head>
<title>HTML5 Video Example</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
</head>
<body style="background: blue;">
<video src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/bbb_trailer_iphone.m4v" controls></video>
<script>
window.onload = function() {
document.ontouchmove = function(e) {
e.preventDefault();
}
}
</script>
</body>
</html>
Any ideas of workarounds to completely prohibit scrolling behavior, even on the video? I've already tried handling ontouchmove directly on the video element and it doesn't work.
Thanks!
In my test, when ommiting the "controls" attribute of the video you can get the events to work. Use a custom div in top to provide custom controls
By example....
<video src="http://192.168.1.53/videoTester/Cuatro.mp4" id="player" width="100%" height="100%" x-webkit-airplay="allow" ></video>
Like you, I couldn't prevent scrolling, so as a workaround added a JS function to fire window.scrollTo(0, 1); every second which then means the user can only scroll for a certain time before the page is jumped back.
Try:
element.addEventListener('touchmove', function(event) {
// Prevent scrolling on this element
event.preventDefault();
}, false);
for just the element in question or:
window.addEventListener('touchmove', function(event) {
// Prevent scrolling on this element
event.preventDefault();
}, false);
for the whole window.
I came up with a good solution for this after running into the same issue. I got it to work by doing the following:
//Function to trigger when every half second to check if user scrolled
$(function () {
//select video player and the current time
var myPlayer = document.getElementById('VideoID');
var whereYouAt = myPlayer.currentTime;
var current;
setInterval(function () {
current = myPlayer.currentTime;
if (current > (whereYouAt + 1)) {
myPlayer.currentTime = whereYouAt; //If current 1 whole second
//Set time to before scroll.
}
else {
whereYouAt = current; //otherwise set where to current.
}
}, 500); //500 = half a second.
});
This will only work for HTML5 video and not if it triggers the mobile video player. I hope this helps and let me know if you have any questions.
Related
I am working on a One-page WordPress site and using Muffin Builder for layout. I am using its feature where i can set a self-hosted video as BG. However, there is no option to control the play/pause of the video. I need help in adding some custom JS to make the video play/pause on a click. Possible?
Link : http://flipped.in/AXSuede/
The video BG is the first section of the page.
When handling your click event, get your video using :
var myVideo = document.querySelector('#myVideo'); //must be a MediaElement like <video> or <audio>
Then, pause or play it :
myVideo.play();
myVideo.pause();
To stop it, you have to manually set the cursor to the beginning :
myVideo.pause();
myVideo.currentTime = 0; //Set the cursor to 0 seconds
just add this jquery code
<script src="jquery-1.11.3.min.js"></script>
<script>
(function($) {
$('video').addClass('is_playing');
$(document).on('click', '.section_video', function(){
var $video = $(this).find('video');
if($video.hasClass('is_playing')){
$video.get(0).pause();
$video.removeClass('is_playing').addClass('is_paused');
} else {
$video.removeClass('is_paused').addClass('is_playing')
$video.get(0).play();
}
});
})(jQuery);
<script>
didn't try it but should work.
greetings timotheus
Since you have element with an higher z-index over your video element, the click events will be blocked.
One solution to check if the click event happened on the video element is to get its getBoundingClientRect() values and compare them with the event's clientX and clientY properties.
document.addEventListener('click', function(e){
var vid = document.querySelector('video');
// get the video position in viewport
var rect = vid.getBoundingClientRect();
// Did we clicked over the video ?
if(e.clientY > rect.top && e.clientY < rect.top + rect.height)
// is our video already paused?
vid.paused? vid.play(): vid.pause();
}, false);
In Firefox when a video tag is wrapped in an a tag, using the standard video controls when clicking on the video to pause it also re-directs. How can I make it behave like the other browsers where for example clicking on pause only pauses the video and does NOT re-direct as well. This is what I need.
Here is a simple demo: http://jsfiddle.net/me2loveit2/cSTGM/
<a href="http://www.google.com" target="_blank">
<video controls="" muted="" preload="auto" id="testid" width="500">
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"/>
<source src="http://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg"/>
<source src="http://www.w3schools.com/html/mov_bbb.webm" type="video/webm"/>
<img src="http://dummyimage.com/1044x585/000/fff"/>
</video>
</a>
What you've got there is invalid markup, the HTML5 spec clearly states that
The a element may be wrapped around entire paragraphs, lists, tables, and so forth, even entire sections, so long as there is no interactive content within (e.g. buttons or other links).
and the video navigation is in fact interactive content containing buttons.
For some reason clicking the controls in Chrome does not trigger the anchor, while in Firefox it does.
This is dependant on how the browser constructs the controls with the Shadow DOM, and as the markup is invalid and there is no real standard for this, it's anyone's guess.
What you should have done is to remove the anchor and use javascript to redirect when the video is clicked, something like this
$('#testid').on('click', function() {
var win = window.open('http://www.google.com', '_blank');
win.focus();
});
That would have given you valid markup as you could just remove the wrapping anchor, but it doesn't solve the problem with not redirecting when clicking the controls either, it's exactly the same, as the controls are still inside the video and triggers the click handler in Firefox, but not in Chrome.
In webkit the controls could potentially have been targeted somehow with the -webkit-media-controls pseudo class, however Firefox doesn't seem to have any such pseudo class, so that won't work either.
What you're left with is relying on the fact that the controls seem to always be at the bottom, and they are around 30 pixels high, so you can just overlay the anchor on top of the video and leave out a little part of the bottom.
This will work in all browsers, and you'll have valid markup.
<video controls="" muted="" autoplay preload="auto" id="testid" width="500">
<!-- stuff -->
</video>
To make sure the anchor is placed correctly and has the correct size, a little javascript can be used
$('.overlay').each(function() {
var vid = $(this).prev('video');
$(this).css({
position : 'fixed',
top : vid.offset().top + 'px',
left : vid.offset().left + 'px',
width : vid.width() + 'px',
height : (vid.height() - 30) + 'px',
});
});
FIDDLE
Other than using custom controls, I am not sure it's possible to get around the control behavior in a truly elegant way, given that the video events (play, pause, etc) trigger after the click events. This is a solution that hardcodes the approximate height of the default controls. I don't like the hardcoding, but in other respects I think it is OK. It applies to all a and video elements and doesn't do any excessive iterating through elements. The setTimeout bit is a workaround for event.preventDefault() killing both the link behavior and the play/pause behavior.
$(document).on('click', 'a', function(event) {
var video = $('video:hover').first();
if (video.length && video.offset().top + video.height() - event.pageY < 35) {
var anchor = $(this);
var href = anchor.attr('href');
var target = anchor.attr('target');
anchor.attr('href', 'javascript:;');
anchor.attr('target', null);
setTimeout(function() {
anchor.attr('href', href);
anchor.attr('target', target);
}, 1);
}
});
You can accomplish this by creating custom controls for your video and wrap only the video tag with the a tag and not the controls. This gives you the option of having consistent looking controls for your video across browsers, but you have to have a good understanding of CSS to make it look good and consistent across browsers. I have included a CodePen project of what you wanted, with some custom controls. The controls don't look very good across browsers, but I think you can get the idea.
http://codepen.io/anon/pen/dtHsb
Very ugly, but the usual solutions don't works because event.stropPropagation() only work for event handlers and event.preventDefault() breaks the controls.
http://jsfiddle.net/cSTGM/28/
$('#testid').click(function() {
link = $(this).parent();
originalHref = link.attr('href');
originalTarget = link.attr('target');
link.attr('href', 'javascript:void(0)');
link.attr('target', '_self');
setTimeout(function() {
link.attr('href', originalHref);
link.attr('target', originalTarget);
}, 0);
});
We just need to prevent redirecting if it is VIDEO tag
$('#testid').click(function() {
if (event.target.tagName !=== 'VIDEO') {
//redirect
}
});
Nothing specific, E.g:
I have a video [with controls(Pause, play, forward... ) in a tag] How would you do to: when the video is in the second 30, make a div appear, then, in the second 32, make it disappear.
Thanks :)
If you're using the HTML5 <video> element you can use the ontimeupdate event to track where the playback has got to, as in this example:
// display the current and remaining times
video.addEventListener("timeupdate", function () {
// Current time
var vTime = video.currentTime;
document.getElementById("curTime").textContent = vTime.toFixed(1);
document.getElementById("vRemaining").textContent = (vLength - vTime).toFixed(1);
}, false);
Thanks to Microsoft for their reference
Here's a working example:
<!DOCTYPE html>
<html>
<head>
<title>Video demo</title>
<script>
// ontimeupdate event handler
function update(e) {
// get the video element id so that we can retrieve the current time.
el = document.getElementById('myVideo');
// set the current time in the page
document.getElementById('timer').innerHTML = el.currentTime;
// If the current time is between 10 and 15 seconds pop-up the
// second div
if (el.currentTime > 20 && el.currentTime <=25) {
document.getElementById('popup').style.display='block';
} else {
document.getElementById('popup').style.display='none';
}
}
</script>
<style>
video {width:300px;}
</style>
</head>
<body>
<video id=myVideo ontimeupdate="update()" src="http://archive.org/download/HardDriveSpinning/HardDriveWebm.webm" autoplay>Sorry - format unsupported</video>
<div id="timer"></div>
<div id="popup" style="display:none">Boo!</div>
</body>
</html>
See it at this fiddle (Works for Firefox and Chrome. IE doesn't like the WebM video format)
You could use window.setTimeout to run a function after a specified amount of time. This won't be enough by itself if the user is able to pause the video. You'd have to tell us more about how you're displaying the video in order to get a more in-depth solution.
But perhaps more importantly, you might want to go back to square one and think again about what you're really trying to accomplish. Because it seems to me that if it seems like you need to trigger DOM manipulations based on the time index of a video, there's probably a better way to do what you really want that doesn't involve that.
I have a button, when you click on that button, I'm doing a fadeToggle() to show or hide a popup.
That popup is appearing on top of a flash video that autoplays.
So, what I want to do, is when the popup is visible, I want to pause the video. When it's hidden, play the video.
My video player already support those function. So this is working fine:
videoPlayer.pause();
videoPlayer.play()
So what my FadeToggle() would looks like ? Right now I have this code:
$("#categorySlider").fadeToggle('fast', function() {
var videoPlayer = document.getElementById("videoContainer");
videoPlayer.pause();
});
I'm missing the play() part here, but I cant figure out the syntax to add it?! If fadeToggle is not the right thing to use, any jquery or javascript is fine!
Any helps please?
You could use the jquery :visible selector to find out if #categorySlider is visible or not and depending on that pause or play the video.
$("#categorySlider").fadeToggle('fast', function() {
var videoPlayer = document.getElementById("videoContainer");
if ($("#categorySlider").is(":visible"))
videoPlayer.pause();
else
videoPlayer.play();
});
I want to pause the video being played at a particular instant till a question that pops up has been answered. The user should not be able to go ahead and forward the video till a particular question that has just poppped up has been answered.
So I can pause the video using JS at that particular instant. How can I ensure the video's controls are unlocked or the video plays again only after answering the question that pops up?
look at this demo http://jsfiddle.net/dgLds/58/
var video = document.getElementById("myvideo");
function toggleControls() {
document.getElementById('myvideo').pause();
if (video.hasAttribute("controls")) {
video.removeAttribute("controls")
} else {
video.setAttribute("controls","controls")
}
}
<video id="myvideo">
<source src="http://www.w3schools.com/html5/movie.mp4" />
</video>
<p onclick="toggleControls();">Toggle</p>
instead of on click you can call the function when ever you want
Here is a opera article on everything you wish to know about html5 video http://dev.opera.com/articles/view/everything-you-need-to-know-about-html5-video-and-audio/
Specifically look at How to keep things synchronized section
EDIT: I you want to disable right-click options. Just go ahead and disable right click on that tag/id
Here is a jquery code
$('video').bind('contextmenu', function()
{
alert('no right click.');
return false;
});
I ran into the need to be able to disable the context menu myself today because we have our own custom controls. You can do this fairly easily:
video.addEventListener('contextmenu', function(e) {
e.preventDefault();
return false;
});
He is an example built upon Web Developer's demo: http://jsfiddle.net/dgLds/308/
There is a pause() method available for the video element:
document.getElementById('myVideo').pause();
Similarly, there is play().