1

I have a simple app which I have three different videos, I want each video to play at certain time. As example:

  1. First video to play.

    between 5:00 AM and 10:00 AM.

  2. Second video to play.

    between 10:00 AM and 22:00 PM.

  3. Third video to play.

    between 22:00 PM and 5:00 AM.

So assume if a user visited my app around 9:00 AM. It should automatically play the first video. If the user visit around 11: 00 AM, the second video plays, and etc.

I want a function to run function at set interval only at certain time of the day using javascript and the postMessage function,

Here is my solution: app.js

var welcomeMovie1 = "http://mirrors.standaloneinstaller.com/video-sample/jellyfish-25-mbps-hd-hevc.mp4";
var welcomeMovie2 = "http://mirrors.standaloneinstaller.com/video-sample/TRA3106.mp4"
var welcomeMovie3 = "http://mirrors.standaloneinstaller.com/video-sample/Panasonic_HDC_TM_700_P_50i.mp4";
var messageTime;

//function to play a video1 to iframe using post messages
function welcomeMessage1() {
  document.getElementById('videoframe').contentWindow.postMessage(
    JSON.stringify({
      event: 'playVideo(welcomeMovie1)'
    }),
    '*'
  )
}
//function to play a video2 to iframe using post messages
function welcomeMessage2() {
  document.getElementById('videoframe').contentWindow.postMessage(
    JSON.stringify({
      event: 'playVideo(welcomeMovie2)'
    }),
    '*'
  )
}
//function to play a video3 to iframe using post messages
function welcomeMessage3() {
  document.getElementById('videoframe').contentWindow.postMessage(
    JSON.stringify({
      event: 'playVideo(welcomeMovie2)'
    }),
    '*'
  )
}
//function to play a video1 to iframe using post messages at Specific time
setInterval(function() {
  var messageTime = new Date().getHours();
  if (messageTime >= 5 && messageTime < 10) {
    welcomeMessage1();
    console.log(welcomeMessage2());
  }
}, 1000 * 60);

//function to play a video2 to iframe using post messages at Specific time
setInterval(function() {
  var messageTime = new Date().getHours();
  console.log(date.toLocaleString('en-GB'));
  if (messageTime >= 10 && messageTime < 22) {
    welcomeMessage2();
    console.log(welcomeMessage2());
  }
}, 1000 * 60);

//function to play a video3 to iframe using post messages at Specific time
setInterval(function() {
  var messageTime = new Date().getHours();
  if (messageTime >= 22 && messageTime < 5) {
    welcomeMessage3();
  }
}, 1000 * 60);

// promise function to create custom video controls and play functions
function playVideo(src) {
  $("#playervideo").attr("src", src);
  $("#playervideo")[0].muted = false;

  if (autoplay == true) {

    var playPromise = $("#playervideo")[0].play();

    if (playPromise !== undefined) {

      playPromise.then(function() {}).catch(function() {

        if (autoplay == true) {
          $("#video-unmute-button").addClass("show");
          $("#playervideo")[0].muted = true;
          var playPromise2 = $("#playervideo")[0].play();

          playPromise2.then(function() {

          }).catch(function() {
            $("#video-start-button").addClass("show");


            $("#video-start-button").on("click", function() {
              $("#playervideo")[0].muted = false;
              $("#playervideo")[0].play();
              $("#video-start-button").removeClass("show");

            });
          });

          console.log("pause force");
        } else {

        }
      });
    } else {}
  } else {

  }

}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Video Frame</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
  <link rel="stylesheet" href="css/style.css">
</head>

<body>
  <iframe id="videoframe" src="videoframe.html"></iframe>
  <br/>
  <!-- <input id="name" type="text"/> -->

</body>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
<script src="js/app.js" type="text/javascript"></script>
<script src="js/form.js" type="text/javascript"></script>

</html>

Here is plunker for full demo: demo

Unfortunately it's not working,

What do I need to change in my code to get what I want?

Rachel Gallen
  • 27,943
  • 21
  • 72
  • 81
The Dead Man
  • 6,258
  • 28
  • 111
  • 193
  • I couldn't figure what do u want actually! Is user gonna stay in your web-app for more than 30 mins? what's the need of **setInterval** at all? other question, are these videos all available through your website for user? our user is seeing only one of them at a time? – mrReiha Dec 19 '18 at 01:20

2 Answers2

1

There is no need to use setInterval; you only need to use an if statement or a switch case.

I removed the setInterval code and made one if statement. In the last condition, you need to change the double ampersand (&&/AND) to || (OR) - the (>22 OR <5)- otherwise it doesn't make sense. I tested the following by adjusting my system clock, it seems to work.

Here's a fiddle

Happy holidays!

var welcomeMovie1 = "http://mirrors.standaloneinstaller.com/video-sample/jellyfish-25-mbps-hd-hevc.mp4";
var welcomeMovie2 = "http://mirrors.standaloneinstaller.com/video-sample/TRA3106.mp4"
var welcomeMovie3 = "http://mirrors.standaloneinstaller.com/video-sample/Panasonic_HDC_TM_700_P_50i.mp4";

var messageTime = new Date().getHours();
var welcomeMsg = "";
var vid = " ";

//console.log(messageTime);
if (messageTime >= 5 && messageTime <= 10) {
  welcomeMsg = "early bird";
  vid = welcomeMovie1;
  //console.log(welcomeMessage2);
}
else
if (messageTime >= 10 && messageTime < 22) {
  welcomeMsg = "middle of day";
  vid = welcomeMovie2;
  //console.log(welcomeMessage2());
}
else
if (messageTime >= 22 || messageTime < 5) {
  welcomeMsg = "night owl";
  vid = welcomeMovie3;
}
////}, 1000 * 60);
playVideo(vid);

console.log("Hello! Your welcome message is " + welcomeMsg + " " + vid)
// promise functionb to create custom video controls and play functions
function playVideo(src) {
  console.log("Hello! Your welcome message is " + welcomeMsg + " " + vid)
  $("#playervideo").attr("src", src);
  $("#playervideo")[0].muted = false;

  if (autoplay == true) {

    var playPromise = $("#playervideo")[0].play();

    if (playPromise !== undefined) {

      playPromise.then(function() {}).catch(function() {

        if (autoplay == true) {
          $("#video-unmute-button").addClass("show");
          $("#playervideo")[0].muted = true;
          var playPromise2 = $("#playervideo")[0].play();

          playPromise2.then(function() {

          }).catch(function() {
            $("#video-start-button").addClass("show");


            $("#video-start-button").on("click", function() {
              $("#playervideo")[0].muted = false;
              $("#playervideo")[0].play();
              $("#video-start-button").removeClass("show");

            });
          });

          console.log("pause force");
        } else {

        }
      });
    } else {}
  } else {

  }

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<iframe id="playervideo" controls src=" ">
  
</iframe>
Rachel Gallen
  • 27,943
  • 21
  • 72
  • 81
  • Hii Rachel , Works perfectly as I want but this will be used in cross domain , that is why I wanted to use post message api, how can I apply the same mechanism with post message ? thanks for wishes and happy holidays too – The Dead Man Dec 19 '18 at 08:57
  • You didn't have a function in there to show a message. I've only just got in. If you add an alert to the welcomeMsg, that'd work. Or just write it to a field. I'll get back to it in a while – Rachel Gallen Dec 19 '18 at 09:05
  • I have test after 10:17 to see if it will play the second video, unfortunatelly it plays ony the first video there is error : `Uncaught ReferenceError: autoplay is not defined at playVideo ((index):66) at window.onload ((index):57)` check it out on fiddle u provided thanks – The Dead Man Dec 19 '18 at 09:18
  • I solved the error but still plays only first video :( – The Dead Man Dec 19 '18 at 09:58
  • @user9964622 typically to get rid of the of an uncaught reference error like this in jquery, you add $(document).ready (function(){ }) around the jquery code. I'm afraid I do have other things to do today. It plays all 3 videos . I tested it. Adjust your system clock. – Rachel Gallen Dec 19 '18 at 09:59
1

<iframe> & <video>

Autoplay

Autoplay ain't what it used to be. There's too many restrictions and various criteria involved in getting a <video> tag to autoplay. Here's what was needed:

<video> tag needs [muted] and [autoplay] attributes

<video ... muted autoplay></video>

<iframe> tag needs [allow="autoplay"] attribute. Full screen is optional

<iframe ... allowfullscreen allow="autoplay; fullscreen"></iframe>

In the demo below loadVideo() is the function that loads a MP4 file to the <video> tag's [src] according to the current time. Autoloading media from an <iframe> is tricky because they are one of the last of the DOM content to load. It's best to run the function from the child page (videoframe.html) in an IIFE (Immediately-invoked Function Expression).

(function() {
  loadVideo();
})();

Promises

In order to invoke play() method, you'll need to use the Promise API. This is another instance when something works and engineers want to overcomplicate it.

async function promisePlay() {
  try {
    await document.querySelector('video').play();
  } catch (err) {
    ...
  }
}

postMessage

For cross-domain communication using the postMessage API via <iframe>, the developer must have ownership of both domains. Ownership doesn't necessarily mean full administrative privileges, just enough so that both pages can actually be edited. There are some APIs that'll meet you halfway like YouTube and Vimeo as well.

Basically the parent page (index.html) will send a message:

window.frames[0].postMessage(data, origin);
  1. window.frames[0] will get the first <iframe> and access it's window content, an equivalent to: document.querySelector('iframe').contentWindow;.
  2. data is just a string.
  3. origin is usually the location.protocol and location.hostname or location.origin of the parent page (index.html): https://www.example.com.

The child page (videoframe.html) receives the data (just a typical string) by listening for the message event on it's Window Object:

window.addEventListener("message", callback);

Most examples show how a message is sent and received, and the result of the message being displayed on the child page -- lame . Here's what a callback would look like if it were actually useful:

function callback(event) {
  var string = event.data;
  // Optional-------------------------
  var from = event.origin;
  if (from !== 'https://www.example.com') {
    document.querySelector('#displayMsg').textContent = `MESSAGE REJECTED`;
    return;
  }
  //----------------------------------
  if (string === "play") {
    promisePlay();
  } else if (string === "pause") {
    document.querySelector('video').pause();
  } else if (string === "stop") {
    document.querySelector('video').pause();
    document.querySelector('video').currentTime = 0;
  } else {
    document.querySelector('#displayMsg').textContent = `ERROR: ${string} is not a command.`;
  }
}

Plunker

Demo

index.html

Note: The following Stack Snippet does not function properly due to SO restriction on <iframe> use. For a fully functional demo go to this Plunker.

html,
body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  font: 400 16px/1.5 Consolas;
  overflow: hidden;
}

main {
  width: 100%;
  height: auto;
  padding: 10px;
}

section {
  height: 0;
  width: 100%;
  position: relative;
  padding-bottom: 56.25%;
  margin: 15px auto 5px;
}

fieldset {
  width: fit-content;
  padding: 5px;
}

iframe {
  height: 100%;
  width: 100%;
  overflow: hidden;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

select,
button {
  font: inherit;
  padding: 0 3px;
  line-height: 1.2;
}

#msg {
  position: absolute;
  z-index: 1;
  background: rgba(0, 0, 0, 0.5);
}

#time,
#rX {
  display: block;
  float: left;
  color: gold;
  padding: 0 5px;
  width: 70px;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Video Frame</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>

  <main>
    <section>
      <iframe src="https://run.plnkr.co/preview/cjpwrvczh00073a5v3m08unmw/videoframe.html" width='100%' height='100%' scrolling='no' frameborder='0' allowfullscreen allow="autoplay; fullscreen"></iframe>
    </section>

    <form id='control'>
      <fieldset>
        <select id='tX'>
          <option value='Timeslot'>Select</option>
          <optgroup label='Command'>
            <option>Play</option>
            <option>Pause</option>
            <option>Stop</option>
          </optgroup>
          <optgroup label='Load Media'>
            <option>Video 1</option>
            <option>Video 2</option>
            <option>Video 3</option>
          </optgroup>
          <optgroup label="Test">
            <option>Messages</option>
            <option>Controls</option>
          </optgroup>
        </select>
        <button>Send</button>
      </fieldset>
    </form>
  </main>

  <script>
    window.onload = function(e) {
      var ctrl = document.forms.control;
      var cX = ctrl.elements;
      var tX = cX.tX;
      ctrl.addEventListener('submit', function(e) {
        e.preventDefault();
        window.frames[0].postMessage(tX.value, "https://" + location.hostname);
        console.log(tX.value);
      });
    };
  </script>

</body>

</html>


videoframe.html

html,
body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  font: 400 16px/1.5 Consolas;
  overflow: hidden;
}

main {
  width: 100%;
  height: auto;
  padding: 10px;
}

section {
  height: 0;
  width: 100%;
  position: relative;
  padding-bottom: 56.25%;
  margin: 15px auto 5px;
}

fieldset {
  width: fit-content;
  padding: 5px;
}

iframe {
  height: 100%;
  width: 100%;
  overflow: hidden;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

select,
button {
  font: inherit;
  padding: 0 3px;
  line-height: 1.2;
}

#msg {
  position: absolute;
  z-index: 1;
  background: rgba(0, 0, 0, 0.5);
}

#time,
#rX {
  display: block;
  float: left;
  color: gold;
  padding: 0 5px;
  width: 70px;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Video iframe</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>

  <aside id='msg'>
    <output id='rX'></output>
    <time id='time'></time>
  </aside>
  <video id='vX' src='about:blank' width='96%' muted autoplay></video>

  <script>
    var v = document.getElementById('vX');
    var vid =
      'https://storage04.dropshots.com/photos6000/photos/1381926/20170326/';
    var r = document.getElementById('rX');
    var t = document.getElementById('time');

    (function() {
      loadVideo();
    })();

    window.addEventListener("message", rXMsg);

    function rXMsg(e) {
      var msg = e.data;
      switch (msg) {
        case 'Play':
          playMedia();
          break;
        case 'Pause':
          v.pause();
          break;
        case 'Stop':
          v.pause();
          v.currentTime = 0;
          break;
        case 'Video 1':
          v.src = vid + '005609.mp4';
          v.load();
          break;
        case 'Video 2':
          v.src = vid + '005610.mp4';
          v.load();
          break;
        case 'Video 3':
          v.src = vid + '005612.mp4';
          v.load();
          break;
        case 'Messages':
          toggleAttr('#msg', 'hidden');
          break;
        case 'Controls':
          toggleAttr('#vX', 'controls');
          break;
        default:
          loadVideo();
          break;
      }
      stamp(msg);
    }

    function loadVideo() {
      var hrs = stamp();
      // 05:00 - 09:59
      if (hrs >= 5 && hrs < 10) {
        v.src = vid + '005609.mp4';
        v.load();
      }
      // 10:00 - 21:59
      else if (hrs >= 10 && hrs < 22) {
        v.src = vid + '005610.mp4';
        v.load();
      }
      // 22:00 - 04:59
      else {
        v.src = vid + '005612.mp4';
        v.load();
      }
      stamp('Autoload');
    }

    async function playMedia() {
      try {
        await v.play();
      } catch (err) {
        stamp('Promise Rejected');
      }
    }

    function toggleAttr(selector, attr) {
      var node = document.querySelector(selector);
      var prop = node.getAttribute(attr);
      if (!prop) {
        node.setAttribute(attr, true);
      } else {
        node.removeAttribute(attr);
      }
    }

    function stamp(str) {
      var now = new Date();
      var hrs = now.getHours();
      var min = now.getMinutes();
      var sec = now.getSeconds();
      var h = hrs > 9 ? "" + hrs : "0" + hrs;
      var m = min > 9 ? "" + min : "0" + min;
      var s = sec > 9 ? "" + sec : "0" + sec;
      var time = h + ":" + m + ":" + s;
      r.textContent = str;
      t.textContent = time;
      return hrs;
    }
  </script>
</body>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
  • hii . I want to use post message because It will be used to another domain, so I must test if everything works in local before sending to another doamin that is why I was using post message, ur methods works but how to aplly it with post message? thanks a lot for your answer and explanation, happy holidays – The Dead Man Dec 19 '18 at 08:54
  • also your solution does not play automatically even i tried adding autoplay still not playing auto matically when visisting the app here is demo `https://next.plnkr.co/edit/LEKcnlWKPAMC83GA?preview` – The Dead Man Dec 19 '18 at 09:47
  • @user9964622 updated to cover autoplay and I have expanded on the `postMessage` aspect as well. – zer00ne Dec 20 '18 at 16:02
  • Thank you a lot brother, very elegant answer at last with a good explanation, happy holidays though – The Dead Man Dec 20 '18 at 20:20
  • You're welcome @user9964622, and thank you for the challenge, I learned about `allow="autoplay"` while answering your question. – zer00ne Dec 20 '18 at 20:33
  • ooh that is cool I am learning too this iframe , html5 videos and post messages, here is another thread with post messages [thread](https://stackoverflow.com/questions/53876735/how-to-add-multiple-events-for-input-in-post-messages) – The Dead Man Dec 20 '18 at 22:12
  • 1
    Hi @user9964622 FYI I deleted [`005611.mp4`](https://storage04.dropshots.com/photos6000/photos/1381926/20170326/005611.mp4) which is why it's skipped in my demo. – zer00ne Dec 20 '18 at 23:15