I'm using code found here:


to lazy load the preview image for youtube videos within JComments. I have it working pretty good and looking like I want it to and it saves a massive amount of data from being unnecessarily downloaded, but for some reason the first video always gets skipped and left with no image and is unclickable. The rest work just as they're supposed to.

I have two sections the comments appear on, the other is a custom made profile page and is separate from JComments, and the same thing happens to the first video on the lists there as well. Any thoughts on why this is happening?

Here is js being used on site:

( function() {

    var youtube = document.querySelectorAll( ".youtube" );

    for (var i = 0; i < youtube.length; i++) {

        var source = "https://img.youtube.com/vi/"+ youtube[i].dataset.embed +"/hqdefault.jpg";

        var image = new Image();
            image.src = source;
            image.addEventListener( "load", function() {
                youtube[ i ].appendChild( image );
            }( i ) );

        youtube[i].addEventListener( "click", function() {

            var iframe = document.createElement( "iframe" );
                iframe.setAttribute( "frameborder", "0" );
                iframe.setAttribute( "allowfullscreen", "" );
                iframe.setAttribute( "src", "https://www.youtube.com/embed/"+ this.dataset.embed +"?rel=0&showinfo=0&autoplay=1" );

            this.innerHTML = "";
            this.appendChild( iframe );
        } );    

} )();

This is what the html looks like in custom bbcode, identifier is stripped out from pattern.




<div class="wrapper">
<div class="youtube" data-embed="{IDENTIFIER}">
<div class="play-button"></div>

and the profile str_replace is in 2 arrays, but looks like this

...., "https://www.youtube.com/watch?v=", "[youtube]", "[/youtube]",.....

replaced by

...., "", '<center><div class="wrapper"><div class="youtube" data-embed="', '"><div class="play-button"></div></div></div></center>',.....  

Extra info J! 3.9.1 PHP 7.1.25 OS Linux I JComments 3.0.7

  • Can you help us to follow the process/breakdown by offering the data that is stored in your youtube variable? Maybe there is some interference with your html? Please post your html so that we can have a look at the actual DOM being processed. Furthermore, source is a single-use variable, so I recommend not declaring it (this won't fix the issue of course). Jan 12, 2019 at 3:13
  • What is youtube[i].dataset.embed on the first iteration? Does youtube[0] have dataset.embed data? Jan 12, 2019 at 3:17
  • Are you getting any console log errors?
    – Lodder
    Jan 12, 2019 at 10:10
  • Ok so I feel stupid, decided to see what would would happen if I put the script after the comment instead of before the comment and it fixed the problem. No idea why I never thought to do that before.
    – Mythic
    Jan 12, 2019 at 16:05
  • It looks obvious now, since the first iteration ran before the document was ready. If you place the javascript above html. That’s the only reason I can see from this. I myself many times forget these basic things too... :)
    – Zollie
    Jan 13, 2019 at 12:29

1 Answer 1


Put the script after the html instead of before (in /components/com_jcomments/tpl/default/tpl_comment.php).

If only half of the preview images show up and the rest are stock youtube images, change the image source in the javascript to hqdefault.jpg (instead of sddefault.jpg from code source).

An option to load content on click for bootstrap collapse would have been a better solution in my case, but as far as I can see it is not available.

Here's the css used if anyone wants to keep their videos around 400px wide, it's a little different than the source.

.wrapper {
    max-width: 400px;
    margin: 0 auto;
    padding: 0 20px;

.youtube {
    background-color: #000;
    margin-top: 0px;
    position: relative;
    padding-top: 56.25%;
    overflow: hidden;
    cursor: pointer;
.youtube img {
    width: 100%;
    top: -16.82%;
    left: 0;
    opacity: 0.7;
.youtube .play-button {
    width: 90px;
    height: 60px;
    background-color: #333;
    box-shadow: 0 0 30px rgba( 0,0,0,0.6 );
    z-index: 1;
    opacity: 0.8;
    border-radius: 20px;
.youtube .play-button:before {
    content: "";
    border-style: solid;
    border-width: 15px 0 15px 26.0px;
    border-color: transparent transparent transparent #fff;
.youtube img,
.youtube .play-button {
    cursor: pointer;
.youtube img,
.youtube iframe,
.youtube .play-button,
.youtube .play-button:before {
    position: absolute;
.youtube .play-button,
.youtube .play-button:before {
    top: 50%;
    left: 50%;
    transform: translate3d( -50%, -50%, 0 );
.youtube iframe {
    height: 100%;
    width: 100%;
    top: 0;
    left: 0;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.