Stop YouTube video AND start timeline with one click on an image

I'm needing to run a Hype function for starting a timeline (playing it in reverse) while simultaneously stopping a YouTube video. The functionality is a "pop-up" dialog window that has a video. If the user plays the video and then clicks the "close" button to close the dialog window, the video keeps playing in the background. I need the video to stop playing and the animation (of the dialog window) to play in reverse when the close button is clicked.

The video is within an HTML widget and I currently have the below code that will successfully stop the YouTube video when playing but does not start the Hype timeline because I receive this error: "Can't find variable HYPE". If I use the close image outside the HTML widget of the video, I can start the timeline animation with that button, but not stop the video. Very frustrating.

<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>

<div id="closeButton" onclick="HYPE.documents['cross-sell-conditions-YouTube'].goToTimeInTimelineNamed(2, 'Main Timeline');" style="text-align:right;"><img src="https://www.footlevelers.com/rehabilitation/cross-sell-conditions%20YouTube.hyperesources/close-button-no-border.png" style="width:100px;"></div>


<iframe id="videoPlayer"
    width="420" height="237"
    src="https://www.youtube.com/embed/wkKmLVI2Spk?enablejsapi=1&rel=0&amp;showinfo=0&amp;autohide=1"
    frameborder="0"
    style="border: solid 4px #37474F"
></iframe>

<script type="text/javascript">
  var tag = document.createElement('script');
  tag.id = 'iframe-demo';
  tag.src = 'https://www.youtube.com/iframe_api';
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

  var player;
  function onYouTubeIframeAPIReady() {
player = new YT.Player('videoPlayer', {
});
  }
  function stopVideo(event) {
	player.stopVideo();
  }
  
  
$(document).ready(function(){
$('#closeButton').click(function(){
		stopVideo();
		//hypeDocument.showSceneNamed('AnkleFoot');
});
});

</script>

I'm guessing it's because I'm trying to reference Hype scripting tags within the HTML widget?

Attached is a test Hype document of what I have so far.
control youtube and start animation.zip (285.7 KB)

Thanks in advance!

Correct, HTML Widget elements in Hype are iframes and therefore can't directly use the HYPE object which is in the parent. There are two basic solutions:

  1. Use an unstyled Rectangle element. This is a <div> and gives you access. The script tags and stuff should work.
  2. Keep it as an HTML Widget, but preface your call with window.parent. to access it:
    <div id="closeButton" onclick="window.parent.HYPE.documents['cross-sell-conditions-YouTube'].goToTimeInTimelineNamed(2, 'Main Timeline');" style="text-align:right;">
    

Solution #1 is preferred if possible because iframes have a bit more overhead in browsers, and the youtube video itself is already going to go in an iframe. But solution #2 requires less change and will work too.


Side note 1: that the name of the HYPE.document is dependent on what you call the filename at export. In previews it is 'index' for example. If you only have one hype document on the page, a better way is to simply call the first document via something like: Object.values(HYPE.documents)[0]goToTimeInTimelineNamed(2, 'Main Timeline').

Side note 2: You're going to 2s in the Main Timeline, but as far as I can tell there's nothing at this point currently. I'm assuming there will be :slight_smile:.

Thanks Jonathan! That helped a ton. I was so close before. Didn't know the rectangle was a DIV and was able to get things to work using that method. I ran into another issue with the "close" image also being within a DIV. When I had the video in one rectangle/DIV and the close image within a separate rectangle/DIV, the close button didn't work with either a Hype click action applied or Javascript action – the "close" image within the DIV wouldn't close the dialog OR stop the video.

However, when I just used the "image" element in Hype for the close button, I was able to add the Hype action to start the timeline animation AND stop the video from playing!

Here's the video code in the rectangle/DIV:

<iframe id="videoPlayer" width="420" height="237" src="https://www.youtube.com/embed/wkKmLVI2Spk?enablejsapi=1&amp;rel=0&amp;showinfo=0&amp;autohide=1" frameborder="0" style="border: solid 4px #37474F"></iframe>

<script type="text/javascript">
  var tag = document.createElement('script');
  tag.id = 'iframe-demo';
  tag.src = 'https://www.youtube.com/iframe_api';
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

  var player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player('videoPlayer', {
    });
  }
  function stopVideo(event) {
	player.stopVideo();
  }
</script>

And I simply added this JavaScript action to the close button (as well as the start animation action):

stopVideo();

Thanks again!

Hi Jonathan,

I spoke too soon. I'm able to get one video to stop when hitting the close button. If I use this method on the other videos in the scene, they don't stop. I figured this was due to an ID conflict. So I changed the video iframe ID to be unique for each one, as well as changed other variable names to be unique. However, it still will only stop one of the videos and no others.

Here's an example of the code:

<iframe id="videoPlayerAnkPF" width="420" height="237" src="https://www.youtube.com/embed/sCgatB5ojQ4?enablejsapi=1&amp;rel=0&amp;showinfo=0&amp;autohide=1" frameborder="0" style="border: solid 4px #37474F"></iframe>

<script type="text/javascript">
  var tag = document.createElement('script');
  tag.id = 'iframe-videoAnkPF';
  tag.src = 'https://www.youtube.com/iframe_api';
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

  var playerAnkPF;
  function onYouTubeIframeAPIReady() {
    playerAnkPF = new YT.Player('videoPlayerAnkPF', {
    });
  }  
</script>

In the above script, the iframe id is unique, the script tag id is unique, the "player" variable name is unique, and the "onYouTubeIframeAPIReady" function is calling the unique iframe ID.

When doing this for two videos, only one will work at a time. As soon as I remove the above script for one of the videos, the other that used to not work, now works without any change to the code.

Any ideas how to get this to work on multiple videos within the scene?

I'm not sure... it could be a problem in the code being called multiple times due to being in the inner html (in which case you just need to make sure it is triggered once), or a problem with the setup/teardown of the youtube embed iframe. I'm happy to take a look if you post a zip of the current .hype document.

I got this HTML page (outside of Hype) working great with multiple YouTube videos and close buttons:

<body style="background-color: #333;">
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script type="text/javascript" src="https://www.youtube.com/iframe_api"></script>

<div id="closeButtonAnkPron" style="text-align:left;"><a href="javascript: void(0)"><img src="https://www.footlevelers.com/rehabilitation/cross-sell-conditions%20YouTube.hyperesources/close-button-no-border.png" style="width:100px;"></a></div>

<iframe id="videoPlayerAnkPron" width="420" height="237" src="https://www.youtube.com/embed/wkKmLVI2Spk?enablejsapi=1&amp;rel=0&amp;showinfo=0&amp;autohide=1" frameborder="0" style="border: solid 4px #37474F"></iframe>

<br /><br />

<div id="closeButtonAnkPF" style="text-align:left;"><a href="javascript: void(0)"><img src="https://www.footlevelers.com/rehabilitation/cross-sell-conditions%20YouTube.hyperesources/close-button-no-border.png" style="width:100px;"></a></div>

<iframe id="videoPlayerAnkPF" width="420" height="237" src="https://www.youtube.com/embed/sCgatB5ojQ4?enablejsapi=1&amp;rel=0&amp;showinfo=0&amp;autohide=1" frameborder="0" style="border: solid 4px #37474F"></iframe>

<script type="text/javascript">

	var player_AnkPron;
	var player_AnkPF;
	function onYouTubeIframeAPIReady() {
		player_AnkPron = new YT.Player('videoPlayerAnkPron', {});
		player_AnkPF = new YT.Player('videoPlayerAnkPF', {});
	}
  
	$(document).ready(function(){
	    $('#closeButtonAnkPron').click(function(){
			player_AnkPron.stopVideo();
	    });
	    $('#closeButtonAnkPF').click(function(){
			player_AnkPF.stopVideo();
	    });
	});

</script>

</body>

BUT... as soon as I add this solution to Hype it doesn't work! Attached is the Hype file.

You should see the Head HTML has the jQuery and YouTube iframe API reference as well as the script for controlling the YouTube videos. I also added unique IDs in Hype to the close buttons just like my HTML above so the jQuery "click" call should work.

Thanks again for looking into this!
multiple-YouTube-videos.zip (820.7 KB)

I have run so many tests my head's spinning. Multiple variations of code (as above) work fine by itself, apart from Hype. I added the exact code above in a rectangle/DIV within Hype and get this error...

Uncaught TypeError: Cannot read property 'stopVideo' of undefined
at HTMLDivElement.eval (eval at (HYPE-674.thin.min.js:100), :12:19)
at HTMLDivElement.dispatch (jquery-3.5.1.slim.min.js:2)

I just can't believe a functionality such as this is so flipping difficult in Hype. Is there an easier method?

Hi Jonathan. Were you able to download and test the "multiple-YouTube-videos.zip" file? I might see if Vimeo is a better API for Hype but would really like to get this working with YouTube videos. Thanks!

Hi Stephen,

This stopVideoFunction() you made works great when I attach it to each close button you have for the two videos:

multiple-YouTube-videos.hype.zip (852.8 KB)

Hi Daniel. Thanks for looking into this!

I just opened the same "multiple-YouTube-videos" Hype file I attached in this thread and when I add the "stopVideo" function to the close button and preview the file, I get the following error when I click the close button:

"Error in undefined: TypeError: player_AnkPron.stopVideo is not a function"

or

"Error in undefined: TypeError: player_AnkPF.stopVideo is not a function"

Did you modify the document in any other way? Are you just previewing the file (locally) or are you copying it on a web server and running from there? What browser are you using? Did you test in multiple browsers?

I've tried this file in both Safari and Brave and it will not work for anything. Consistently get the errors above... even when I remove one of the conditions/videos from the JavaScript. It just won't work no matter what I try.