1

I am using ajax to append videos elements to a webpage. After a new video is appended, I noticed that some JavaScript & jQuery are not initializing.

There are 3 code snippets that I need to work together.

1st. Code Snippet for Ajax call 2nd. Code Snippet That Unmutes Video after it is played 3rd. Code Snippet plays video after first initial click or touch gesture anywhere on webpage.

1st Code Snippet The following code snippet is used to Append Videos via Ajax Calls after the user scrolls the page.

var step = 1;
var loading = false;

$(window).scroll(function() {
    if ($(window).scrollTop() >= $(document).height() - $(window).height() - 1900) {
        if (loading === false) {
            loading = true;
            $.ajax({
                url: 'HTTPS://ENTER URL HERE.COM' + step,
                success: function(data) {
                    step++;
                    $('main2').append(data);
                    loading = false;
                },
                dataType: 'html'
            });
        }
    }
});

I want the appended video to automatically start playing after the webpage is clicked or touched and for the video to unmute after it starts playing.

I've tried minor tweaks but have not been successful at getting this to work with "videos appended via ajax", however these codes work perfectly together when the video is already on the page during the initial load.

I need both of the code snippets below to work after ajax.

2nd Code Snippet ( Used to unmute html video with autoplay attribute after it starts)

$("video").on('play', function() {
    $("video").prop('muted', false);
});

$("video").on('pause', function() {
    $("video").prop('muted', true);
});

$("video").on('ended', function() {
    $("video").prop('muted', true);
});

3rd Code Snippet ( Used to Play Html Videos on webpage with a click or touch gesture. )

Object.defineProperty(HTMLMediaElement.prototype, 'playing', {
    get: function() {
        return !!(this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2);
    }
});

document.body.addEventListener("click", playVideoOnLowPower, {
    once: true
});
document.body.addEventListener("touchstart", playVideoOnLowPower, {
    once: true
});

function playVideoOnLowPower() {
    try {
        const videoElements = document.querySelectorAll("video");
        for (i = 0; i < videoElements.length; i++) {
            if (videoElements[i].playing) {
                // video is already playing so do nothing
                console.log('Playing');
            } else {
                // video is not playing so play video now
                videoElements[i].play();
                console.log('Not Playing');
            }
        }
    } catch (err) {
        console.log(err);
    }
}

UPDATE:

The additional function I added in the ajax call success workers like a charm for me. The only issue I have now is in the 3rd Code Snippet listed above, there is a Boolean attribute { once: true} attached to the event listener that only fires and calls the function once. If I remove the Boolean attribute the event listener fires on each click or touch start event and continuously calls the function assigned.

I need the event listener to fire once and only call the assigned function once "after each ajax call"

7
  • I do not understand the functionality you are asking about in the text I updated your question with from a comment. What is the expected behaviour and what is the actal behaviour?
    – mplungjan
    Commented Aug 7, 2023 at 6:55
  • @mplungjan "Code Snippet 3" plays all html videos after a CLICK or Touchstart event. After the first/ initial Click or Touchstart event the event listener is removed. I need to be able to rebind the event listeners. I tried the code below but was not successful. ` function dsdvideoEvents2() { document.body.addEventListener("click", playVideoOnLowPower, { once: true }); document.body.addEventListener("touchstart", playVideoOnLowPower, { once: true }); } `
    – DCM CODING
    Commented Aug 7, 2023 at 7:47
  • But why remove the event? That is my question. Also add the information to the question instead of comments
    – mplungjan
    Commented Aug 7, 2023 at 7:57
  • I want to remove the event because I have an infinite scroll effect on my website that loads more html videos via ajax, as the user scrolls down the page. After the ajax call renders the new html videos, the first Click or Touch Start events from "Code Snippet 3" starts all videos currently on the page at once, while another JS code snippet I have implemented pauses all the videos after they have started, then removes the src and reloads the html video to stop buffering. This trick works for auto playing html videos without them being muted & works on device in low power/ power saving mode.
    – DCM CODING
    Commented Aug 7, 2023 at 8:13
  • @mplungjan So because of this I need "Code Snippet 3" to run each time the ajax call renders the new set of html videos to the page so that the videos will continue to autoplay as the user scrolls without the videos being muted.
    – DCM CODING
    Commented Aug 7, 2023 at 8:16

1 Answer 1

-1

As you mentioned your 1st Code Snippet is appending new video. So, I assume main2 just a typo error and is an ID of an element (can be class also).

Since, you bind the video via ajax, but in your ajax success you just bind the video to $('main2') and you haven't re-bind an event to it. It will not have the event listeners automatically that you bind previously. So, you need to rebind the event after your $('main2').append(data); in ajax success.

See the following example:

Object.defineProperty(HTMLMediaElement.prototype, 'playing', {
  get: function() {
    return !!(this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2);
  }
});

document.body.addEventListener("click", playVideoOnLowPower, {
  once: true
});
document.body.addEventListener("touchstart", playVideoOnLowPower, {
  once: true
});

function playVideoOnLowPower() {
  try {
    const videoElements = document.querySelectorAll("video");
    for (i = 0; i < videoElements.length; i++) {
      if (videoElements[i].playing) {
        // video is already playing so do nothing
        console.log('Playing');
      } else {
        // video is not playing so play video now
        videoElements[i].play();
        console.log('Not Playing');
      }
    }
  } catch (err) {
    console.log(err);
  }
}


$.ajax({
  url: 'https://dummyjson.com/http/200/mov_bbb.mp4',
  success: function(data) {
    if (data.status == 200) {
      var videoHtml = `<video width="400" controls>
                           <source src="https://www.w3schools.com/html/${data.message}" type="video/mp4">
                       </video>`;
    }
    $('#main2').append(videoHtml);
    videoEvents()
  }
});


function videoEvents() {
  $("video").on('play', function() {
    $(this).prop('muted', false);
  });

  $("video").on('pause', function() {
    $(this).prop('muted', true);
  });

  $("video").on('ended', function() {
    $(this).prop('muted', true);
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="main2"></div>

8
  • 1
    If main2 (which is not a valid selector unless there is a <main2> tag) is static then the code should work since each click reads all the video tags
    – mplungjan
    Commented Aug 4, 2023 at 14:48
  • Still no need to rebind if the main2 is a static container. Delegation would be a better solution
    – mplungjan
    Commented Aug 4, 2023 at 14:54
  • Who do you mean here? You and I are the only ones and we are both voted down. If you mean me, then yeah sure. I would definitely vote down to get from 168,348 rep to 168,356 because that is so important ;)
    – mplungjan
    Commented Aug 6, 2023 at 14:03
  • @AlbertEinstein & @mplungjan I added an additional function "dsdvideoEvents" during the ajax calls success, that rebinds the events (See Below) ` $.ajax({ url: 'HTTPS://ENTER URL HERE.COM' + step, success: function(data) { step++; $('main2').append(data); loading = false; dsdvideoEvents(); }, dataType: 'html' }); } } }); ` ` function dsdvideoEvents (){ videoEvents(); videoEvents2(); } `
    – DCM CODING
    Commented Aug 6, 2023 at 22:29
  • @AlbertEinstein & @mplungjan The additional function I added in the ajax call success workers like a charm for me, The only issue I have now is in the ** 3rd Code Snippet ** listed above, there is a Boolean attribute ` { once: true} ` attached to the event listener that only fires and calls the function once. If I remove the Boolean attribute the event listener fires on each click or touch start event and continuously calls the function assigned. ((( I need the event listener to fire once and only call the assigned function once "after each ajax call" )))
    – DCM CODING
    Commented Aug 6, 2023 at 22:46

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.