Shut off video and close window

Hello. I could use some help with something that I cannot solve using just CSS.

I have a photo gallery with thumbnails, and when you click on a thumbnail CSS converts it to a modal window that takes up the whole screen. (Done by styleing li:target)

Then I have a “Close” link on this modal window to switch back to the normal gallery mode.

The problem is that when I have a video, if you click on the “Close” link the window closes and returns back to the gallery, but the video keeps playing, so you end up back in the gallery and hear “voices” which is bad!

Full disclosure, I don’t know Javascript, and am hoping someone could be kind enough to help me copy & paste some code to solve this issue.

Specifically, I guess I need Javascript to tell the video to stop playing first, and then return back to my gallery.

Thanks.

I don’t think that you can stop video, but you can definitely pause it.

Just get a reference to the video element then pause it.

const modal = document.querySelector("#modalWindow");
const video = modal.querySelector("video");
video.pause();

Will that solve my problem?

Currently, when you click on the close link the window adjusts from modal to regular gallery, but you can still hear the audio playing even though I don’t see the video.

@Paul_Wilkins,

Attached is a simple sample of my website.

sp_video-on-modal.zip (598.9 KB)

Some questions…

1.) How exactly would I incorporate your code?

2.) Do I or users have to install Javascript for your code to work?

3.) And how well supported will your code be across browsers and OS’s? (The last thing I want to do is use Javascript and have it blow up when people view my site!)

Thanks.

@coothead,

Could you please explain the code you shared with me…

( function( d ) {
  'use strict';

   d.getElementsByClassName('closeWindow')[ 0 ].addEventListener( 'click',
      function() {
            d.getElementById('videoFrame').pause();
            d.getElementById('videoFrame').load();
         }, false );
   
 }( document ));

It looks like if you click on the “Close” link which is tied to this…

<a class='closeWindow' href='#containerMast_fixed'>Close</a>

Then the code targets the element below…

<video controls id='videoFrame'>

And either “pauses” it or “loads” it.

I don’t understand these parts…

( function( d ) {

or

}( document ));

or

'use strict';

Also, is there a way to “kill” all activities/processes related to the video player?

I ask, because I seem to get this random error where when I load my gallery I see this message in the bottom of the browser that says “Transferring data from localhost…” and it never goes away, and I see these 3 dots cycling in the Firefox tab and sometimes videos won’t load…

I have been looking over my PHP and HTML and don’t see any issues there…


P.S. @coothead, can I put your “scripts” folder anywhere? I ask because I have a more complex folder structure than the simple examples we have been sharing. Is your Javascript intelligent enough to work from anywhere, or des it have to be located at a certain level with respect to my “photo-gallery.php” script?

I’ll supply a more detailed update on the code to use with your HTML code.

No.

Not everyone has JavaScript, which is nicely detailed in this flowchart of Everyone has JavaScript, right?

That’s why I ensure that the JavaScript that I use, doesn’t break anything that’s currently working.
If the JavaScript doesn’t break for any reason (typically for less than 1% of visitors) then they can just make do as if the JavaScript wasn’t there in the first place, either by pausing the video before leaving the link, or by reloading the page.

1 Like

In more detail, when the close button is clicked, we want to run some code when the click event occurs.

Find the close link

Here’s the close link that you have in your HTML code.

                        <a class='closeWindow' href='#'>Close</a>

In JavaScript we need to search the loaded HTML document for the close link:

var closeLink = document.querySelector(".closeWindow");

But when you have multiple close links on that page, regardless of whether they are visible or not, that only gets the first close link.

Find all close links

We can easily deal with that by searching for all close links on the page, and loop through each of them instead.

I’ll use ... in the code to show that the code is not complete, and that we’ll be adding more code soon to fill that section in.

        var closeLinks = document.querySelectorAll(".closeWindow");
        closeLinks.forEach(function addCloseHandler(closeLink) {
            ...
        });

Add an even handler

Now that we can access each of the close links, we can add an event handler to them.

        var closeLinks = document.querySelectorAll(".closeWindow");
        closeLinks.forEach(function addCloseHandler(closeLink) {
            closeLink.addEventListener("click", stopVideoHandler);
        });

Find the video

The stopVideoHandler refers to a function that gets run when someone clicks on a stop link. That function receives an event object that contains information about what occurred.

        function stopVideoHandler(evt) {
            ...
        }

In this case, we want to start at the close link that was clicked, and from there find the video.

        function stopVideoHandler(evt) {
            var closeLink = evt.target;
            ...
        }

In the HTML code, the video is just below the close link.

                    <div>
                        <!-- Menu Items -->
                        <a class='closeWindow' href='#'>Close</a>
                        
                        <!-- Video -->
                        <video controls class=''>
                            <source src='video/MOMOLAND - BBoom BBoom.mp4' />
                        </video>
                    </div>

Yes, I use the Kpop video BBoom BBoom as a test video. Try to test with things that you like.

To make the code more reliable, instead of just going down the DOM to the next HTML element, I will instead go up to the parent of the close link, and from there search for the video.

        function stopVideoHandler(evt) {
            var closeLink = evt.target;
            var video = closeLink.parentNode.querySelector("video");
            ...
        }

Stop the video

And now that we’ve found the relevant video, we can stop it.

Well, pause it. Web browsers don’t have a stop command for videos, but they do have a pause command.

        function stopVideoHandler(evt) {
            var link = evt.target;
            var video = link.parentNode.querySelector("video");
            video.pause();
        }

And that’s all the scripting that we need to get that working.

Put it in a <script> tag at the end of the body, and that works with your page.

<body>
    ...
    <script>
        function stopVideoHandler(evt) {
            var  link = evt.target;
            var video = link.parentNode.querySelector("video");
            video.pause();
        }
        function addCloseHandler(closeLink) {
            closeLink.addEventListener("click", stopVideoHandler);
        }
        var closeLinks = document.querySelectorAll(".closeWindow");
        closeLinks.forEach(addCloseHandler);
    </script>    
</body>

That code works regardless of if you have one close link or hundreds of them.

Next steps

Just pausing the video means that after someone closes a link then comes back to it, the video will still be paused where they left it. That might not be suitable.

You might instead want the video to reset back to the start of the video when they open the link again. That can be done quite easily, which I’ll get to in the next post.

1 Like

To reset a video element so that it returns back to the start, after pausing it you can add a copy of the video, then remove the initial one that was paused.

The copy of the video will then load it self from the start when someone goes back to it.

Before doing that, I’ll move the pause video code to a separate function, because I’ll be adding a few things to it.

Here, the commented-out lines show an old line of code before it gets updated. The commented-out lines are not needed in your code at all, and only help to demonstrate what was there before it got replaced.

        function stopVideo(video) {
            video.pause();
        }
        function stopVideoHandler(evt) {
            var closeLink = evt.target;
            var video = closeLink.parentNode.querySelector("video");
            // video.pause();
            stopVideo(video);
        }

We can now update the stopVideo function so that it adds another video element, and removes the old one.

There is no delete command for HTML elements, but from its parent we can add or remove.

        function stopVideo(video) {
            var newVideo = video.cloneNode(true);
            video.pause();
            video.parentNode.insertBefore(newVideo, video);
            video.parentNode.removeChild(video);
        }

And now the video isn’t paused where it stopped when someone goes back to it. Instead, it starts from the beginning again.

1 Like

@Paul_Wilkins,

Thanks you so much for all of the help and explanation!!!

I have to say that your last post was a bit overwhelming, which I why I keep avoiding Javascript. But it is good to get a start off with it thanks to your help.

Why do I put the Javascript at the end of the my webpage?

Since I am technically using PHP, can I use an include and put your script in its own file?

Is there an easier way to reset a video? Sometimes there is.

Instead of removing the old video and adding a new one, we can just set the currentTime property on the video to zero, so that it seeks back to the beginning.

        function stopVideo(video) {
            video.pause();
            video.currentTime = 0;
        }

The updated scripting code to achieve this is:

        function stopVideo(video) {
            video.pause();
            video.currentTime = 0;
        }
        function stopVideoHandler(evt) {
            var closeLink = evt.target;
            var video = closeLink.parentNode.querySelector("video");
            stopVideo(video);
        }
        function addCloseHandler(closeLink) {
            closeLink.addEventListener("click", stopVideoHandler);
        }
        var closeLinks = document.querySelectorAll(".closeWindow");
        closeLinks.forEach(addCloseHandler);

Each line of HTML code is processed in order from top to bottom. JavaScript runs on a page as the page is loading. When the JavaScript runs, nothing below the script is known to exist.

Because of that, it really helps for the HTML code to exist on the page above the JavaScript, when the code runs.

The usual way that scripting code is added is not via PHP includes, but by referring to a script file in the HTML code.

For example:

<script src="js/pauseVideos.js"></script>

So I would add that line at the end of the HTML < body > in my “photo-gallery.php” script?

1 Like

And to be clear, this is the final Javascript code…

    <script>
        function stopVideo(video) {
            video.pause();
			video.currentTime = 0;
        }
		
        function stopVideoHandler(evt) {
            var closeLink = evt.target;
            var video = closeLink.parentNode.querySelector("video");
            stopVideo(video);
        }

        function addCloseHandler(closeLink) {
            closeLink.addEventListener("click", stopVideoHandler);
        }
		
        var closeLinks = document.querySelectorAll(".closeWindow");
        closeLinks.forEach(addCloseHandler);
    </script>    

Yes, like this:

    </div><!-- End of #containerBody -->
    <script src="js/stopVideos.js"></script>
</body>
1 Like

Not quite.

The <script> and </script> tags are not javascript code. Those do not go in the separate scripting file.

1 Like

NetBeans just pointed that put to me! :lol:

What is the syntax to add comments?

That’s double slashes.

Try to avoid comments that say what is happening.

This is a very bad comment for example:

// adds 1 to counter
counter += 1;

Instead, try to explain why something is happening, for example

function stopVideo(video) {
    // web browsers don't have stop, so we pause instead
    video.pause();
    video.currentTime = 0;
}
1 Like

Well, you probably wouldn’t approve of my comments. I tend to put nearly as many comments as code, but it helps me later on.