So I am embedding a video into a custom iframe, and I'm not using youtube, vimeo or any of those so I can't use their APIs. I am making an idle-timer for it, so when the user hasnt acted in X amount of time, it will bring up a confirm window asking if they want to keep watching or restart. However, while this window is up, I want the video to pause, which is proving surprisingly difficult. It also pretty much needs to be cross-domain as I will be serving the videos with an s3 bucket.
I have seen many threads saying this is basically not possible, but I find that hard to believe. Is it true?
Here's my code (the main part I need help with is pauseVideo() near the bottom):
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>HRMSC</title>
</head>
<body>
<iframe class="iframe" id="primaryVideo" src="amazon-s3-video-link.mp4"
width="1000"
height="562.5">
<p> Your browser does not support iframes. </p>
</iframe>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<script type="text/javascript" src="./IdleScript.js">
</script>
</body>
</html>
IdleScript.js :
var idleTime = 0;
var clickIframe = window.setInterval(checkFocus, 100);
var idleInterval = setInterval(timerIncrement, 600); // 1 second
var i = 0;
function checkFocus() {
if(document.activeElement == document.getElementById("primaryVideo")) {
idleTime = 0;
console.log("clicked "+(i++));
$('#primaryVideo').blur();
}
}
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 5) { // seconds
console.log("restart?");
if (this.resetInterstitial()){
idleTime = 0;
window.location.reload();
}
else{
idleTime = 0;
console.log("keep watching");
}
}
}
var pauseVideo = function ( element ) {
// WHAT CAN I DO HERE?
console.log("pause!");
// WHAT CAN I DO HERE?
};
function resetInterstitial(){
pauseVideo(primaryVideo);
return confirm("You haven't tapped anything in a while. Do you want to keep watching or start from the beginning?");
}
Use a <video>-tag: https://www.w3schools.com/tags/tag_video.asp
and use the build-in javascript functions https://www.w3schools.com/tags/av_met_pause.asp
Related
I have researched and experimented my brains out on this one. I have built a working application that uses the HTML5 canvas to play videos and interact with users through a web page (a game, sort of). Works like a charm, but I want to add captions to the video to make it more accessible. I don't even seem to be able to get the WebVTT file to load and I've reached the stage of voodoo programming by trying examples from the web and am making no progress. I have tried to distill the application down to its bare minimum here in hopes someone can provide some insight into what I'm doing wrong.
The video plays when I click on the canvas, the "...waiting for cuechange event..." message stays up while it plays, and then it goes to the "video complete ... reload to try again" message when done (kept it simple by requiring a page reload to try the test again), so the basic mechanics seem to be working. It never gets into the "load" function for the text track (never displays "... loaded text track ..."), and the updateSubtitle() function is never invoked. If I insert a trackElement.readyStatus() call, it always returns 0 (unsurprisingly). As a further note, if I add a testStatus.innerHTML = "...loaded metadata..."; statement in the "loadedmetadata" listener, it does get there.
var canvasContext, videoElement, intervalHandle, testStatus, trackElement;
function processFrame() {
canvasContext.drawImage(videoElement, 193, 50, 256, 194);
}
function videoEnded() {
clearInterval(intervalHandle);
testStatus.innerHTML = "video complete ... reload to try again";
}
var count = 0;
function updateSubtitle(event) {
count = count + 1;
testStatus.innerHTML = "count" + count;
}
function clickHandler(event) {
testStatus.innerHTML = "...waiting for cuechange event...";
videoElement.setAttribute("src", "start.ogg");
videoElement.load();
intervalHandle = setInterval(processFrame, 25);
videoElement.play();
}
function init() {
var canvasElement, textTrack;
canvasElement = document.createElement("canvas");
videoElement = document.createElement("video");
videoElement.addEventListener("loadedmetadata", function() {
trackElement = document.createElement("track");
trackElement.kind = "captions";
trackElement.label = "English";
trackElement.srclang = "en";
trackElement.src = "start_en.vtt";
trackElement.addEventListener("load", function() {
testStatus.innerHTML = "... loaded text track ...";
trackElement.mode = "showing";
});
videoElement.appendChild(trackElement);
trackElement.addEventListener("cuechange", updateSubtitle, false);
});
var mainDiv = document.getElementById("arghMainDiv");
canvasElement.setAttribute("id", "mediaScreen");
canvasElement.width = 640;
canvasElement.height = 480;
var firstChild;
if(mainDiv.hasChildNodes()) {
firstChild = mainDiv.firstChild;
mainDiv.insertBefore(canvasElement, firstChild);
} else {
firstChild = mainDiv.appendChild(canvasElement);
}
testStatus = document.createElement("p");
testStatus.setAttribute("id", "testStatus");
mainDiv.insertBefore(testStatus, firstChild);
testStatus.innerHTML = "click on canvas to test";
canvasContext = canvasElement.getContext('2d');
canvasElement.addEventListener("click", clickHandler);
videoElement.addEventListener("ended", videoEnded);
}
#fatalError {
color: red;
}
#arghMainDiv {
text-align: center;
}
#mediaScreen {
border: 5px solid #303030;
margin-left: auto;
margin-right: auto;
display: block;
cursor: default;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Problems With TextTrack Object</title>
<link rel="stylesheet" type="text/css" href="subargh.css">
<script src="subargh.js"></script>
</head>
<body onload="init()">
<div id="arghMainDiv">
</div>
</body>
</html>
If you want the video and WebVTT files I'm using (just a few seconds long), they are here and here (respectively). I should also mention that if I play the video using VLC, that it recognizes and plays the .vtt file as subtitles properly on the video (so it appears to be well-formed). I am running my tests on Firefox 57.0.4 (64-bit) on a Windows 7 system if that makes any difference (but I am under the impression that Firefox is mostly fixed where Timed Text Tracks are concerned now).
So I have made a code for some coursework, the code is suppose to start a function on page load which will then run the function of changing the traffic light image on screen. It is suppose to keep on changing forever however the program crashes or fails to load when I try to run. Before you suggest the problem is that the variable used in the condition isnt changed, I have tried to change it in the following code. when I ran it in the chrome debugger this is the thing that came up; 'Uncaught SyntaxError: Unexpected token <'.
<DOCTYPE html>
<html>
<body onload="infinity()">
<p></p>
<h1>Traffic Light Sequence</h1>
<img id ="trafficlight" src="r.jpg">
<script>
var images = [
"r.jpg",
"randy.jpg",
"g.jpg",
"y.jpg"
];
var counter = 0;
function start() {
counter = counter + 1;
if(counter == images.length) counter=0;
var image = document.getElementById("trafficlight");
image.src=images[counter];
}
var a = 100;
function infinity() {
while (200>a) {
setTimeout(start(), 3000);
}
a = a - 25;
}
</script>
</body>
</html>
Instead of setting while loop and setTimeout, use setInterval. The below code will work I think. It will change the image 100 times
var url="http://www.hdwallpapers.in/thumbs/2017/";
var a=0,Handler;
var images = ["yosemite_national_park_winter_4k-t1.jpg","namib_coastal_desert_4k-t1.jpg","beach_dock-t1.jpg"];
var counter = 0;
function start() {
counter = counter + 1;
a++;
if(a>=100 && Handler)
clearInterval(Handler);
if(counter == images.length) counter=0;
var image = document.getElementById("trafficlight");
image.src=url+images[counter];
return;
}
function infinity() {
Handler=setInterval(start, 3000);
}
<DOCTYPE html>
<html>
<body onload="infinity()">
<p></p>
<h1>Traffic Light Sequence</h1>
<img id ="trafficlight" src="http://www.hdwallpapers.in/thumbs/2017/yosemite_national_park_winter_4k-t1.jpg">
<script>
</script>
</body>
</html>
I know that this question already has an answer, but i just figured that the following code might be a better and a relatively simpler way of doing it.
<DOCTYPE html>
<html>
<body onload="infinity()">
<p></p>
<h1>Traffic Light Sequence</h1>
<img id ="trafficlight" src="r.jpg">
<script>
var images = [
"red.JPG",
"green.jpg",
"randy.jpg",
"yellow.JPG"
];
function infinity() {
var counter = 0,
image = document.getElementById("trafficlight"),
a = 5,
timeoutInterval = 3000;
setInterval(function() {
counter++;
if(counter == images.length) counter=0;
if (a>=0) {
image.src=images[counter];
a--;
}else{
// this else case is in the event that the timeout
// variable is 1, which is essentially 1ms, which
// is bad as it would make your cpu usage go to a
// 100%
if (timeoutInterval <= Number.MAX_SAFE_INTEGER - 2) {
// the above if condition is to stop timeoutInterval
// from ever reaching 2^53 which would cause an
// overflow
timeoutInterval *= 2;
Math.pow(timeoutInterval, 20);
}
}
}, timeoutInterval);
}
</script>
</body>
</html>
Thanks!
P.S. my laptop is still hot from running your infinite loop code of an example
I've created HTML and JavaScript files to display bulletgraphs, using the 'canvas' HTML5 tag. I've tried it in Chrome and it works nicely and changes width along with the size of the browser. I have to have this working in IE8, too, so I've used Excanvas, which is working in all except one way: when I resize the browser I get remnants of the valueIndicator. This only happens on IE8.
I've tried looking round for information on redrawing the canvas but I don't think this is the issue. Can anyone see where I'm going wrong, please?
EDIT
I'm keeping the complete code at the bottom, however, following advice I've cut my code down somewhat.
In IE8 it looks like this:
In Chrome it looks like this:
When I refresh the IE8 page it looks OK again.
Cut-down Bulletgraph.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bulletgraph</title>
<!--[if IE]><script src="excanvas.js"></script><![endif]-->
</head>
<body>
<canvas id="graph1"></canvas>
<script src="Scripts.js"></script>
<script>
drawGraphs();
window.onresize=function() { drawGraphs() };
function drawGraphs() {
drawBulletGraph(getScreenWidth(),300,1000,350,"graph1");
}
</script>
</body>
</html>
Complete code:
Cut-down Scripts.js:
function drawBulletGraph (cwidth, left, right, loValue, id) {
var canvas=document.getElementById(id);
var cheight=30;
var multiplier=cwidth/(right-left);
canvas.width=cwidth;
canvas.height=cheight;
var valueIndicator=canvas.getContext("2d");
valueIndicator.lineWidth="1";
valueIndicator.moveTo((loValue-left)*multiplier,0);
valueIndicator.lineTo((loValue-left)*multiplier,cheight);
valueIndicator.fill();
valueIndicator.stroke();
}
function getScreenWidth () {
return (window.innerWidth || document.documentElement.clientWidth)/7;
}
Bulletgraph.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bulletgraph</title>
<!--[if IE]><script src="excanvas.js"></script><![endif]-->
</head>
<body>
<canvas id="graph1"></canvas><br>
<canvas id="graph2"></canvas>
<script src="Scripts.js"></script>
<script>
drawGraphs();
window.onresize=function() { drawGraphs() };
function drawGraphs() {
drawBulletGraph(bgWidth(getScreenWidth()),300,400,450,600,700,1000,800,350,850,"graph1");
drawBulletGraph(bgWidth(getScreenWidth()),250,450,500,650,700,1200,600,350,850,"graph2");
}
</script>
</body>
</html>
Scripts.js:
function drawBulletGraph (cwidth, left, loRed, loAmber, hiAmber, hiRed, right, value, loValue, hiValue, id) {
var canvas=document.getElementById(id);
var cheight=16;
var colour="#008000";
if (value <= loRed || value >= hiRed)
{
colour="#FF0000";
}
else if (value <= loAmber || value >= hiAmber)
{
colour="#FFA500";
}
var multiplier=cwidth/(right-left);
canvas.width=cwidth;
canvas.height=cheight;
var red=canvas.getContext("2d");
red.fillStyle="#F4C3C6";
red.fillRect(0,0,cwidth,cheight);
var amber=canvas.getContext("2d");
amber.fillStyle="#F4F6C6";
amber.fillRect((loRed-left)*multiplier,0,(hiRed-loRed)*multiplier,cheight);
var green=canvas.getContext("2d");
green.fillStyle="#CCE5CC";
green.fillRect((loAmber-left)*multiplier,0,(hiAmber-loAmber)*multiplier,cheight);
var valueIndicator=canvas.getContext("2d");
valueIndicator.fillStyle=colour;
valueIndicator.strokeStyle=colour;
valueIndicator.lineWidth="2";
valueIndicator.moveTo((loValue-left)*multiplier,0);
valueIndicator.lineTo((loValue-left)*multiplier,cheight);
valueIndicator.moveTo((loValue-left)*multiplier,cheight/2);
valueIndicator.lineTo((hiValue-left)*multiplier,cheight/2);
valueIndicator.moveTo((hiValue-left)*multiplier,0);
valueIndicator.lineTo((hiValue-left)*multiplier,cheight);
valueIndicator.moveTo(((value-left)*multiplier)-(cheight/2),cheight/2);
valueIndicator.stroke();
valueIndicator.lineWidth="1";
valueIndicator.lineTo((value-left)*multiplier,cheight);
valueIndicator.lineTo(((value-left)*multiplier)+(cheight/2),cheight/2);
valueIndicator.lineTo((value-left)*multiplier,0);
valueIndicator.lineTo(((value-left)*multiplier)-(cheight/2),cheight/2);
valueIndicator.fill();
valueIndicator.stroke();
}
function getScreenWidth () {
return window.innerWidth || document.documentElement.clientWidth;
}
function bgWidth (screenWidth) {
var graphWidth=screenWidth/7;
if (graphWidth<70) {graphWidth=70;}
if (graphWidth>260) {graphWidth=260;}
return graphWidth;
}
I've managed to get a solution. It feels like a bit of a hack but it does the trick. Basically it involves drawing a white line round the canvas and filling it each time it's drawn again. The following code goes between the var valueIndicator=canvas.getContext("2d"); and the valueIndicator.lineWidth="1"; lines:
valueIndicator.fillStyle="#FFFFFF";
valueIndicator.strokeStyle="#FFFFFF";
valueIndicator.moveTo(0,0);
valueIndicator.beginPath();
valueIndicator.lineTo(0,cheight);
valueIndicator.lineTo(cwidth,cheight);
valueIndicator.lineTo(cwidth,0);
valueIndicator.closePath();
valueIndicator.fill();
valueIndicator.stroke();
valueIndicator.strokeStyle="#000000";
I've tried it in the full code and it works. If anyone has a more elegant solution, and I'm sure there must be many, I would still love to see them.
Single request and response model at one time do not utilizes full network/internet bandwidth, thus resulting in low performance. (benchmark is of half speed utilization)
how to make this code use 2 or 3 or more async requests instead of one.(ajax)
or do i need multi threading? and is it possible in javascript?
(this is for making a video out of an ip )
every time the image changes on request. and yes i need to be async with multiple fetch requests (not single as i explained above) or you recomend threads?
<html>
<head> <script language="JavaScript">
// Global vars
img = 'http://pastebin.com/i/t.gif';
timeout = 1000;
next = 0;
function onLoad( ) {
setTimeout( 'reloadImage( )', timeout );
}
// Reloader
function reloadImage( ) {
next = ( new Date( ) ).getTime( ) + timeout;
document.images.dv.src = img + "?" + next;
}
</script>
</head>
<body>
<img src="img" name="dv" onLoad="onLoad( )">
</body>
</html>
and
<html>
<head>
</head>
<body>
<div id="container"></div>
<script language="JavaScript">
var canLoad = true;
var container = document.getElementById("container");
var image = document.createElement("img");
image.onload = function() {
canLoad = true;
console.log("Image reloaded.");
}
var imageUrl = "http://url/snapshot.jpg";
var fps = 2;
container.appendChild(image);
function loadImage() {
if (canLoad) {
canLoad = false;
var str = new Date().getTime();
image.setAttribute("src", imageUrl + "?" + str);
console.log("Reloaded now.");
} else {
console.log("Can't reload now.");
}
}
setInterval(loadImage, fps); // 30 fps
</script>
</body>
</html>
Not actually tested, and I think it'll very likely to cause a "stack overflow" eventually (if you directly implement it), but you may still give it a look:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(){
var img="/*url*/";
var interval=50;
var pointer=0;
function showImg(image,idx)
{
if(idx<=pointer) return;
document.body.replaceChild(image,document.getElementsByTagName("img")[0]);
pointer=idx;
preload();
}
function preload()
{
var cache=null,idx=0;;
for(var i=0;i<5;i++)
{
idx=Date.now()+interval*(i+1);
cache=new Image();
cache.onload=(function(ele,idx){return function(){showImg(ele,idx);};})(cache,idx);
cache.src=img+"?"+idx;
}
}
window.onload=function(){
document.getElementsByTagName("img")[0].onload=preload;
document.getElementsByTagName("img")[0].src="/*initial url*/";
};
})();
</script>
</head>
<body>
<img />
</body>
</html>
What it does:
When the initial image loads, preload() is called;
When preload() is called, it creates 5 image cache, and each attach its onload event to showImg();
When showImg() is called, it checks whether the current index is behind current pointer, and if it does, replace the current image with this new one, and call preload();
Back to 2.
If you really going to implement this, increase interval and decrease i<5. Also, a caching/queuing mechanic to check how many images in cache/queue before loading the next queue would be nice.
Also, notice that I didn't use getElementById to get the image, because there will be no stable ID.
In mobile safari on iPhone or iPod Touch if a user clicks on a mailto link and then returns to the page (either send or cancel), timers no longer function inside of javascript. I've posted a bug to apple, and on openradar.
However, I was wondering if anyone out there has come across this before and come up with some sort of workaround.
update: Here is some sample code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Testing</title>
</head>
<body>
<h1 id="normal">Normal: 0</h1>
<h1 id="timed">Timed: 0</h1>
<h1 id="interval">Interval: 0</h1>
<a id="clicker">Click Me</a><br />
Mail To
<script type="text/javascript">
window.addEventListener('load', function ()
{
var count = 0;
var interval = 0;
var id;
document.getElementById('clicker').addEventListener('click', function () {
interval = 0;
count++;
document.getElementById('normal').innerHTML = 'Normal: ' + count;
setTimeout(function () {document.getElementById('timed').innerHTML = 'Timed: ' + count; }, 100);
id = setInterval(function ()
{
interval++;
if(interval > 5)
{
clearInterval(id);
return;
}
document.getElementById('interval').innerHTML = 'Interval: ' + interval;
}, 200);
}, false);
}, false);
</script>
</body>
</html>
To clear up some apparent confusion about what I'm saying is a bug, its not that when you leave the page and return any timers that had been running have stopped, this is to be expected. The problem is that once a user returns to the page if you start new timers, they will never fire.
That' not a bug because the browser windows is actually closed when the Mail application launches. When the user returns, it's restored but any scripts that were running will have halted.
Though this is not very nice, it's expected.