3

I need help with a particular bit of JS I'm using to make HTML5 videos play when in view.

The code:

$(document).ready(function() {
    // Get media - with autoplay disabled (audio or video)
    var media = $('#video1, #video2, #video3, #video4, #video5');
    var tolerancePixel = 10;

    function checkMedia(){
        // Get current browser top and bottom
        var scrollTop = $(window).scrollTop() + tolerancePixel;
        var scrollBottom = $(window).scrollTop() + $(window).height() - tolerancePixel;

        //if ($(window).scrollTop() > $(window).height() - 100) {
        media.each(function(index, el) {
            var yTopMedia = $(this).offset().top;
            var yBottomMedia = $(this).height() + yTopMedia;

            if(scrollTop < yBottomMedia && scrollBottom > yTopMedia){
                $(this).get(0).play();
            } else {
                $(this).get(0).pause();
            }
        });

        //}
    }
    $(document).on('scroll', checkMedia);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="height:500px"></div>
<video muted id="video4" class="lightbulbs" width="100%" height="auto">
<source src="http://www.ddi.com.au/culture/img/lightbulbs.mp4" type="video/mp4">
</video>
<div style="height:500px"></div>

I obtained this code from this answer: https://stackoverflow.com/a/26508106/10213848

My issue is that once the video is finished, it can be triggered again by scrolling upward. I need the video/s to only play once and not get triggered again.

Any help would be greatly appreciated.

Tom Cat
  • 31
  • 1
  • 2

2 Answers2

0

You can use a variable to mark whether the video had played. if it already played, do not play it again:

$(document).ready(function() {
    // Get media - with autoplay disabled (audio or video)
    var media = $('#video1, #video2, #video3, #video4, #video5');
    var tolerancePixel = 10;
    var hasPlayMap = {};
    function checkMedia(){
        // Get current browser top and bottom
        var scrollTop = $(window).scrollTop() + tolerancePixel;
        var scrollBottom = $(window).scrollTop() + $(window).height() - tolerancePixel;

        //if ($(window).scrollTop() > $(window).height() - 100) {
        media.each(function(index, el) {
            var yTopMedia = $(this).offset().top;
            var yBottomMedia = $(this).height() + yTopMedia;

            if(scrollTop < yBottomMedia && scrollBottom > yTopMedia){
                var thisId = $(this).attr("id");
                if (hasPlayMap[thisId]){
                   return;
                }
                hasPlayMap[thisId] = true;
                $(this).get(0).play();
            } else {
                $(this).get(0).pause();
            }
        });

        //}
    }
    $(document).on('scroll', checkMedia);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="height:500px"></div>
<video muted id="video4" class="lightbulbs" width="100%" height="auto">
<source src="http://www.ddi.com.au/culture/img/lightbulbs.mp4" type="video/mp4">
</video>
<div style="height:500px"></div>
bronze man
  • 1,470
  • 2
  • 15
  • 28
  • Thanks! Great solution, however doesn't seem to work when introducing the additional videos. Here's the page I'm working on (http://ddi.com.au/culture/) – Tom Cat Aug 12 '18 at 01:33
  • @TomCat Just use a hasPlayMap = {} and if (hasPlayMap[videoId]) ... can solve your problem. I have just update the post, you can use it. – bronze man Aug 12 '18 at 01:35
  • Sorry, JS noob here. How would I implement that? – Tom Cat Aug 12 '18 at 01:37
  • 1
    @bronzeman rather than setting a variable to `true/false` why not just use `this.ended` in your if condition? It will return the same thing... – NewToJS Aug 12 '18 at 01:38
  • 1
    @NewToJS That is working exactly how I need it... thanks so much! – Tom Cat Aug 12 '18 at 01:50
  • @bronzeman Thanks for your help too. I used your revised snippet which works, but once the videos are scrolled out of view while still playing, they stop (as required) but will not play to it's end after being scrolled back into view. Solution from NewToJS allows the video to complete, then not play again. – Tom Cat Aug 12 '18 at 01:54
  • Here is a simple example [**JsFiddle demo**](https://jsfiddle.net/New_To_JS/3pamb562/) - *Video link updated* – NewToJS Sep 28 '18 at 03:04
0

Sorry, I know this looks a lot like NewToJS' answer in the comments, sadly I was thinking of the same thing.

Since this is the effect you wanted, please do not green tick this since NewToJS got the answer first (granted, that is, if you had planned to).

You can set the video's onend event to set the video's onplay event:

document.querySelector('video').forEach(function(element) {
    // Set the onend event to...
    element.onend = function() {
        // ...set the onplay event to...
        this.onplay = function() {
            // ...stop playing video when the video starts playing
            this.pause();
            this.currentTime = 0;
        };
    };
});

Pure jQuery version:

$('video').each(function(ix, ele) {
    ele.addEventListener('end', function() {
        this.addEventListener('play', function() {
            ele.pause();
            ele.currentTime = 0;
        });
    });
});
Kitanga Nday
  • 3,517
  • 2
  • 17
  • 29