0

I'm relatively new in web programming, and hence have problems keeping my code clean. Working on the last project, among other matters, I had to do the following:

  1. Autoplay on the main page one of eight available videos (for example, main-vid-3.webm);
  2. When it ends, start playing the next one (in that case, main-vid-4.webm);
  3. Then play the next video and so on. After the eighth video, main-vid-1 must be played.

If I started playing the next video right after the previous one ended, I had a lag since new video wasn't loaded yet. My solution of the problem:

  1. Two video tags on the page, one of them has display: none;
  2. When the video with display: block ends, it hides while the other video appears and starts playing;
  3. When that video is playing, source of the hidden video changes with JS and starts loading (but not playing yet);
  4. repeat step 2;

It worked, but my code (especially JS part and necessity of having two video tags on the page) doesn't seem for me clean and fine. Is there any better solution of the problem?

<section id="main-page-top">
  <video id="bgvid-<?php echo $vidId; ?>" autoplay width="100%">
   <source src="<?php echo get_template_directory_uri(); ?>/inc/main-vid-<?php echo $vidId; ?>.webm" type="video/webm">
  </video>
  <video id="bgvid-<?php echo ($vidId + 1); ?>" class="hidden" width="100%">
   <source src="<?php echo get_template_directory_uri(); ?>/inc/main-vid-<?php echo $vidIdAlt; ?>.webm" type="video/webm">
  </video>
</section>

document.getElementById('#main-page-top video:nth-child(1)').addEventListener('ended', function() {
  document.getElementById('#main-page-top video:nth-child(1)').style.display = "none";
  document.getElementById('#main-page-top video:nth-child(2)').style.display = "block";
  document.getElementById('#main-page-top video:nth-child(2)').play();
  var vidNum = parseInt(document.getElementById('#main-page-top video:nth-child(1)').id.substring(6));
  if (vidNum === 7) {
    vidNum = -1;
  } else if (vidNum === 8) {
    vidNum = 0;
  }
  document.getElementById('#main-page-top video:nth-child(1)').setAttribute('id', 'bgvid-' + (vidNum + 2));
  document.getElementById('#main-page-top video:nth-child(1) source').setAttribute('src', 'http://u0065000.isp.regruhosting.ru/template/inc/main-vid-' + (vidNum + 2) + '.webm');
  document.getElementById('#main-page-top video:nth-child(1)').setAttribute("poster", "http://u0065000.isp.regruhosting.ru/template/inc/main-vid-" + (vidNum + 2) + ".jpg");
  document.getElementById('#main-page-top video:nth-child(1)').load();
  document.getElementById('#main-page-top video:nth-child(1)').pause();
});

document.getElementById('#main-page-top video:nth-child(2)').addEventListener('ended', function() {
  document.getElementById('#main-page-top video:nth-child(2)').style.display = "none";
  document.getElementById('#main-page-top video:nth-child(1)').style.display = "block";
  document.getElementById('#main-page-top video:nth-child(1)').play();
  var vidNum = parseInt(document.getElementById('#main-page-top video:nth-child(2)').id.substring(6));
  if (vidNum === 7) {
    vidNum = -1;
  } else if (vidNum === 8) {
    vidNum = 0;
  }
  document.getElementById('#main-page-top video:nth-child(2)').setAttribute('id', 'bgvid-' + (vidNum + 2));
  document.getElementById('#main-page-top video:nth-child(2) source').setAttribute('src', 'http://u0065000.isp.regruhosting.ru/template/inc/main-vid-' + (vidNum + 2) + '.webm');
  document.getElementById('#main-page-top video:nth-child(2)').setAttribute("poster", "http://u0065000.isp.regruhosting.ru/template/inc/main-vid-" + (vidNum + 2) + ".jpg");
  document.getElementById('#main-page-top video:nth-child(2)').load();
  document.getElementById('#main-page-top video:nth-child(2)').pause();
});
Lzhelenin
  • 193
  • 4
  • 13
  • the two video tag part is fine, and likely needed, but the other part is severally over-repetitive, and you're using getElementById() instead of querySelector() – dandavis Mar 25 '15 at 22:44
  • Well, it was querySelector() before, that's why there are # in brackets before id. I've just read the article https://jsperf.com/getelementbyid-vs-queryselector/11 , test shows that getElementById works faster in cases like mine, so I decided to change code. I'll remove all the hash tags later. – Lzhelenin Mar 25 '15 at 23:12
  • the performance of either is meaningless; notice that the jsperf performs millions of runs, you perform a couple dozen. the larger point i wanted to make is that you only need one or two calls to such a method instead of dozens, and re-using the element ref will drastically cleanup your code. just define, ex `var e2=document.getElementById('#main-page-top video:nth-child(2)')` and then replace all occurrences of that long-winded line with just `e2`, ex: `e2.load(); e2.pause();` – dandavis Mar 26 '15 at 00:10
  • As @dandavis says, I think the two video tag approach is fine and is actually quite elegant. If you do want to move to a solution which does not involve 2 tags (and if you enjoy complicated Javascript code!) the HTML5 Media source extension mechanism should allow you do something similar - see this answer for an overview: http://stackoverflow.com/a/28717239/334402. And again, just in case it is not clear - I would personally stick with your two tag solution... – Mick Mar 26 '15 at 15:59

1 Answers1

0

Thank you guys. I can't find if I can mark your comments as right answers.

Now the code looks like this (added a function for fading in/out):

var vidFading = function(p1, p2) {
    $(p1).on('timeupdate', function(event) {
        var current = Math.round(event.target.currentTime * 1000);
        var total = Math.round(event.target.duration * 1000);

        if ((total - current) < 500) {
            $(this).fadeOut("slow");
            $(p2).fadeIn(1000);
        }
    });
}
var vidFoo = function(p1, p2) {
    var x = document.querySelector(p1);
    var x1 = document.querySelector(p1 + ' source')
    var y = document.querySelector(p2);
    y.play();
    var vidNum = parseInt(document.querySelector(p1).id.substring(6));
    if (vidNum === 7) {
        vidNum = -1;
    } else if (vidNum === 8) {
        vidNum = 0;
    }
    x.setAttribute('id', 'bgvid-' + (vidNum + 2));
    x1.setAttribute('src', 'http://u0065000.isp.regruhosting.ru/template/inc/main-vid-' + (vidNum + 2) + '.webm');
    x.setAttribute("poster", "http://u0065000.isp.regruhosting.ru/template/inc/main-vid-" + (vidNum + 2) + ".jpg");
    x.load();
    x.pause();
}


if (document.getElementById('main-page')) {

    vidFading('#main-page-vid video:nth-child(1)', '#main-page-vid video:nth-child(2)');
    vidFading('#main-page-vid video:nth-child(2)', '#main-page-vid video:nth-child(1)');

    document.querySelector('#main-page-vid video:nth-child(1)').addEventListener('ended', function() {
        vidFoo('#main-page-vid video:nth-child(1)', '#main-page-vid video:nth-child(2)');
    });

    document.querySelector('#main-page-vid video:nth-child(2)').addEventListener('ended', function() {
        vidFoo('#main-page-vid video:nth-child(2)', '#main-page-vid video:nth-child(1)');
    });
}
Lzhelenin
  • 193
  • 4
  • 13