Pause HTML5 video to lighten resource load? - javascript

I have a website that has one of those annoying autoplay looping background videos that just play over and over forever instead of using just a picture. I was wondering if it would lighten the resource load on our users machines if I paused the video when they are not looking at my page through the new page visibility API?
To all the geniuses on this site, I would love to see an answer that shows how you determined your answer. I am sort of new to the front-end world and I'm not sure how I would figure this question out.

#stupidkid
Though it has been asked long before, the best solution for you is here : https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
function handleVisibilityChange() {
if (document[hidden]) {
//pause video
} else {
//play video
}
}
document.addEventListener(visibilityChange, handleVisibilityChange, false);
Please try this.

Related

Video paused on inactive tab

I have implemented hacktimer HackTimer project and i got nice game working even in inactive tab (background). I have part with video and video also works fine - after activate tab in chrome they speed up for secound to get perfect currentDuration. Now same code not working any more. Video go to pause regime in the moment of inactivity. When i go back to tab video start to play.
I have no idea what can be.
My OS: windows Chrome version: Version 80.0.3987.149 (Official
Build) (64-bit)
My html tag looks like:
<video id="videoID" muted playsinline
oncanplaythrough="console.log('video ready');">
<source src="1.ogv" type="video/ogg">
<source src="1.mp4" type="video/mp4">
no support
</video>
I just wanna permament playing like youtube did.
Only solution for last version was : Visibility api .
hackTimer works fine all the time but inactivating tab makes pause() call.
I just put on visibilityChange event code line video.play() .
Code:
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
var videoElement = document.getElementById("videoElement");
function handleVisibilityChange() {
if (document[hidden] && videoElement.style.display != 'none') {
videoElement.play();
}
}
if (typeof document.addEventListener === "undefined" || hidden === undefined) {
console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
// Handle page visibility change
document.addEventListener(visibilityChange, handleVisibilityChange, false);
}
For my app if video is visible then play but other people can add also this line :
if (video.paused) {
video.play()
}

browser close not triggering the visibilityChange on safari

I am trying to save some statistics when the user closes the browser, below is the code
if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
hidden = 'hidden';
visibilityChange = 'visibilitychange';
} else if (typeof document.mozHidden !== 'undefined') {
hidden = 'mozHidden';
visibilityChange = 'mozvisibilitychange';
} else if (typeof document.msHidden !== "undefined") {
hidden = 'msHidden';
visibilityChange = 'msvisibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
hidden = 'webkitHidden';
visibilityChange = 'webkitvisibilitychange';
} else {
console.log('in else condition');
}
if (typeof document.addEventListener === 'undefined' || hidden === undefined) {
console.log("App requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
document.addEventListener(visibilityChange, handleVisibilityChange, false);
}
function handleVisibilityChange() {
// Send a ajax call with **async: false**
}
The above code works well in mozilla firefox, google chrome but does not in safari. I am testing this on Mac Os and safari version is Version 12.1.1 (14607.2.6.1.1)
Can any please suggest if this is an expected behaviour in safari and what could be done as a workaround.
Thanks.
According to the MDN docs, the "pagehide" event should work for this:
If you're specifically trying to detect page unload events, the pagehide event is the best option.
https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event

How to check whether a video is audible?

A video has audio track and its volume is not zero or muted, but this video is not audible due to its audio track is in total quietness. I want to know how to check whether a video is audible, so I can toggle functions upon.
I found how to check whether a video has audio track from here. #upuoth's method works most browsers except IE10+. #brefd.it works for IE10+ but I didn't know how to use his code (please explain to me)
#upuoth's code
document.getElementById("video").addEventListener("loadeddata", function() {
if (typeof this.webkitAudioDecodedByteCount !== "undefined") {
// non-zero if video has audio track
if (this.webkitAudioDecodedByteCount > 0)
console.log("video has audio");
else
console.log("video doesn't have audio");
}
else if (typeof this.mozHasAudio !== "undefined") {
// true if video has audio track
if (this.mozHasAudio)
console.log("video has audio");
else
console.log("video doesn't have audio");
}
else
console.log("can't tell if video has audio");
});
#brefd's code
function hasAudio (video) {
return video.mozHasAudio ||
Boolean(video.webkitAudioDecodedByteCount) ||
Boolean(video.audioTracks && video.audioTracks.length);
}
var video = document.querySelector('video');
if(hasAudio(video)) {
console.log("video has audio");
} else{
console.log("video doesn't have audio");
}
I prepared three video clips, one with an audio track, one without audio track and one with an audio track but isn't audible. The code I found above only works for the fisrt two clips but for the third one. Please let the alert be "not audible" when playing the third clip by using the code from JSfiddle link.
Below is the merged code of above that you can replace with in your JSFiddle:
document.getElementById("myVideo").addEventListener("loadeddata", function() {
if (typeof this.webkitAudioDecodedByteCount !== "undefined") {
if (this.webkitAudioDecodedByteCount > 0)
alert("This video has a track");
else
alert("no track");
} else if (typeof this.mozHasAudio !== "undefined") {
if (this.mozHasAudio)
alert("This video has a track");
else
alert("no track");
} else if (typeof this.audioTracks !== "undefined") {
if (this.audioTracks && this.audioTracks.length)
alert("audible");
else
alert("not audible");
} else
alert("Not sure");
});
Unfortunately, I doubt if there would be a way to detect "not audible" audio tracks.
There are different ways to check whether a video file has audio or not, one of which is to use mozHasAudio, video.webkitAudioDecodedByteCount and video.audioTracks?.length properties of video, clean and simple...
const video = component.node.querySelector("video");
video.onloadeddata = function() {
if ((typeof video.mozHasAudio !== "undefined" && video.mozHasAudio) ||
(typeof video.webkitAudioDecodedByteCount !== "undefined" && video.webkitAudioDecodedByteCount > 0) ||
Boolean(video.audioTracks?.length)) {
console.log("This video has audio tracks.");
} else {
console.log("This video has no audio tracks.");
}
};

Javascript to detect if user changes tab

I am writing a webpage for online quiz. The basic requirement I have is that it must fire an event(stopping the quiz) if the user changes tabs or opens a news window even without minimizing their browser, i.e if the person is attempting to see the answer from some other window/tab. How can I do that?
Note : Try to avoid including a bleeding edge HTML5 feature in your answer because I want the feature to be supported by all major browsers currently.
You can determine if a tab or window is active by attaching a blur / focus event listener to window.
in jQuery it would be
$(window).focus(function() {
//do something
});
$(window).blur(function() {
//do something
});
quoted from this SO answer: https://stackoverflow.com/a/1760268/680578
In 2022 you can use an event listener with the visibilitychange event:
document.addEventListener("visibilitychange", (event) => {
if (document.visibilityState == "visible") {
console.log("tab is active")
} else {
console.log("tab is inactive")
}
});
If you are targeting browsers that support it, you can use the Page Visibility API available in HTML5. It doesn't directly detect tab changes, per-say, but visibility changes. Which would include (but not limited to) tab changes.
See https://developer.mozilla.org/en/DOM/Using_the_Page_Visibility_API
Best native function hands down, no jQuery.
document.hasFocus
Check the pen, check what happens when you go to the link and back to the codepen tab.
https://codepen.io/damianocel/pen/Yxxzdj
With jQuery:
$(window).on('focus', function () {
});
$(window).on('blur', function () {
});
$().focus & $().blur are deprecated.
window onfocus and onblur work just fine:
window.onfocus = function (ev) {
console.log("gained focus");
};
window.onblur = function (ev) {
console.log("lost focus");
};
Working on a similar project. This worked the best. On the highest level component which wouldn't normally rerender, add:
setInterval( checkFocus, 200 );
function checkFocus(){
if(document.hasFocus()==false){
//Do some checking and raise a red flag if this runs during an exam.
}
}
I needed something like this and it seems this behavior is slightly different on each browser.
if (document.hidden !== undefined) { // Opera 12.10 and Firefox 18 and later support
visibilityChange = "visibilitychange";
} else if (document.mozHidden !== undefined) {
visibilityChange = "mozvisibilitychange";
} else if (document.msHidden !== undefined) {
visibilityChange = "msvisibilitychange";
} else if (document.webkitHidden !== undefined) {
visibilityChange = "webkitvisibilitychange";
} else if (document.oHidden !== undefined) {
visibilityChange = "ovisibilitychange";
}
document.addEventListener(visibilityChange, function(event) {
handleVisibilityChange();
}, false);
I have an example you can check:
https://jsfiddle.net/jenol/4g1k80jq/33/

Problem with Google Chrome and Javascript. Guru needed!

i have a strange problem only in Chrome using an iframe but working in all others common browser.
the problem: If i type in the IFRAME and then press the button to send, it work fine, the focus back to the IFRAME and the cursor BLINK.
But if i type and then press ENTER to invoke the event handler function, the focus back but the cursor disappear. And then if you go in another window and then back the cursor appear. This happen only in Chrome. I did the example page to show the problem in action. Click the link below to see.
UPDATE: I added the code also here below
var editorFrame = 'myEditor'
function addFrame() {
var newFrame = new Element('iframe', {
width: '520',
height: '100',
id: editorFrame,
name: editorFrame,
src: 'blank.asp',
class: 'myClass'
});
$('myArea').appendChild(newFrame);
window.iframeLoaded = function() {
// this is call-back from the iframe to be sure that is loaded, so can safety attach the event handler
var iframeDoc, UNDEF = "undefined";
if (typeof newFrame.contentDocument != UNDEF) {
iframeDoc = newFrame.contentDocument;
} else if (typeof newFrame.contentWindow != UNDEF) {
iframeDoc = newFrame.contentWindow.document;
}
if (typeof iframeDoc.addEventListener != UNDEF) {
iframeDoc.addEventListener('keydown', keyHandler, false);
} else if (typeof iframeDoc.attachEvent != UNDEF) {
iframeDoc.attachEvent('onkeydown', keyHandler);
}
};
}
function resetContent()
{
var myIFrame = $(editorFrame);
if (myIFrame) myIFrame.contentWindow.document.body.innerHTML='';
}
function setEditFocus()
{
var iFrame = document.frames ? document.frames[editorFrame] : $(editorFrame);
var ifWin = iFrame .contentWindow || iFrame;
ifWin.focus();
}
function send()
{
resetContent();
setEditFocus();
}
function keyHandler (evt) {
var myKey=(evt.which || evt.charCode || evt.keyCode)
if (myKey==13) {
if (!evt) var evt = window.event;
evt.returnValue = false;
if (Prototype.Browser.IE) evt.keyCode = 0;
evt.cancelBubble = true;
if (evt.stopPropagation) evt.stopPropagation();
if (evt.preventDefault) evt.preventDefault();
send();
}
}
In the HTML page
<body onload="addFrame()">
<div id="myArea"></div>
<input id="myButton" type="button" value="click me to send [case 1]" onclick="send()">
To make more easy to understand the problem i've create a specific page to reproduce the problem with full example and source included.
You can view here by using Google Chrome:
example of the problem
I really need your help because i tried to solve this problem for many days with no luck. And all the suggestions, tips and workaround are well accepted.
Thanks in advance.
I'm not really sure what the cause of the issue is, as there are times where Chrome will give focus to the element correctly, though most of the time it does not. You shouldn't need to request focus at all, since the focus is not lost when you press the key. If you omit the setEditFocus() call, you should notice that it still works correctly in everything but Chrome, which apparently gets offended that you've removed all of the content in the body.
When you set contenteditable, every browser sets the innerHTML of the iframe document's body element to be something different:
Browser | innerHTML
-----------------------------
Internet Explorer | ''
Opera | '<br>\n'
Firefox | '<br>'
Chrome/Safari | '\n'
If you're not expecting to see that extra stuff when you parse the content later, you might want to remove it upfront in addFrame().
I was able to "fix" the problem by doing the following:
First, update the event handler so we can return false in it and prevent Opera from generating HTML for fun when we call getSelection() later...
function addFrame() {
...
window.iframeloaded = function() {
...
if (typeof iframeDoc.addEventListener != UNDEF) {
iframeDoc.addEventListener('keypress', keyHandler, false);
} else if (typeof iframeDoc.attachEvent != UNDEF) {
iframeDoc.attachEvent('onkeypress', keyHandler);
}
}
}
Edit: Removed original function in favour of the new one included below
Finally, return false from the key press handler to fix the Opera issue mentioned above.
function keyHandler (evt) {
var myKey=(evt.which || evt.charCode || evt.keyCode)
if (myKey==13) {
...
return false;
}
}
I had originally done what syockit suggested, but I found it was doing weird things with the caret size in Chrome, which this method seems to avoid (although Firefox is still a bit off...). If you don't care about that, setting the innerHTML to be non-blank is likely an easier solution.
Also note that you should be using className instead of class in the object you pass to new Element(), since IE seems to consider it a reserved word and says that it's a syntax error.
Edit: After playing around with it, the following function seems to work reliably in IE8/Firefox/Chrome/Safari/Opera for your more advanced test case. Unfortunately, I did have to include Prototype's browser detection to account for Opera, since while everything looks the same as far as the JavaScript is concerned, the actual behaviour requires different code that conflicts with the other browsers, and I wasn't able to find a better way to differentiate between them.
Here's the new function, which focuses on the editable content of the iframe, and makes sure that if there is already content in there, that the caret is moved to the end of that content:
function focusEditableFrame(frame) {
if (!frame)
return;
if (frame.contentWindow)
frame = frame.contentWindow;
if (!Prototype.Browser.Opera) {
frame.focus();
if (frame.getSelection) {
if (frame.document.body.innerHTML == '')
frame.getSelection().extend(frame.document.body, 0);
else
frame.getSelection().collapseToEnd();
} else if (frame.document.body.createTextRange) {
var range = frame.document.body.createTextRange();
range.moveEnd('character', frame.document.body.innerHTML.length);
range.collapse(false);
range.select();
}
} else {
frame.document.body.blur();
frame.document.body.focus();
}
}
Updated setEditFocus() (Not really necessary now, but since you already have it):
function setEditFocus()
{
focusEditableFrame($(editorFrame));
}
You know how I solved this one? In resetContent(), replace '' with ' ':
if (myIFrame) myIFrame.contentWindow.document.body.innerHTML=' ';
If it works, good. Don't ask why though, it might be one of those Webkit glitches with Range object, file a bug if you will.
Just quickly, can you try adding semicolons to the end of the lines inside your send() function? And see if that works.
function send() {
resetContent();
setEditFocus();
}

Categories

Resources