Search code examples
javascripthtmljwplayerjwplayer7

JWplayer 7 - Add active class to current playing video


I am using JWplayer 7 (HTML5 render mode) in my site. I created a player with custom playlist, but cannot highlight current playing video when it has been clicked.

Is there any solution to add a custom class, like .active when click on a item of list.

This is my code to setup JWplayer.

var playerInstance = jwplayer("videoCont");
playerInstance.setup({
    image: "{PLAYLIST_IMAGE}",
    autostart: false,
    aspectratio: "16:9",
    playlist : "{NV_BASE_SITEURL}{MODULE_NAME}/player/{RAND_SS}{PLAYLIST_ID}-{PLIST_CHECKSS}-{RAND_SS}{FAKE_ID}/",
    controls: true,
    displaydescription: true,
    displaytitle: true,
    flashplayer: "{NV_BASE_SITEURL}themes/default/modules/{MODULE_NAME}/jwplayer/jwplayer.flash.swf",
    primary: "html5",
    repeat: false,
    skin: {"name": "stormtrooper"},
    stagevideo: false,
    stretching: "uniform",
    visualplaylist: true,
    width: "100%"
  });

And following code to generate custom player

var list = document.getElementById("show-list");
var html = list.innerHTML;
html +="<ul class='list-group'>"
playerInstance.on('ready',function(){
var playlist = playerInstance.getPlaylist();
for (var index=0;index<playlist.length;index++){
    var playindex = index +1;
    html += "<li class='list-group-item'><span>"+playlist[index].title+"</span><span class='pull-right'><label onclick='javascript:playThis("+index+")' title='Phát "+playlist[index].title+"' class='btn btn-default btn-xs'><i class='fa fa-play'></i></label><label class='btn btn-default btn-xs' href='"+playlist[index].link+"' title='Xem ở cửa sổ mới' target='_blank'><i class='fa fa-external-link-square'></i></label></span></li>"
    list.innerHTML = html;
}
html +="</ul>"
});
    function playThis(index) {
        playerInstance.playlistItem(index);
    }

SOLUTION : Based on an idea of @zer00ne

Add following code :

playerInstance.on('playlistItem', function() {
var playlist = playerInstance.getPlaylist();
var index = playerInstance.getPlaylistIndex();
var current_li = document.getElementById("play-items-"+index);
for(var i = 0; i < playlist.length; i++) {
        $('li[id^=play-items-]').removeClass( "active" )
}
current_li.classList.add('active');
});

before

function playThis(index) {
    playerInstance.playlistItem(index);
}

And edit html generate like this :

    html += "<li id='play-items-"+index+"' class='list-group-item'><span>"+playlist[index].title+"</span><span class='pull-right'><label onclick='javascript:playThis("+index+")' title='"+lang_play+" "+playlist[index].title+"' class='btn btn-primary btn-xs mgr_10'><i class='fa fa-play'></i></label><a href='"+playlist[index].link+"' title='"+lang_new_window+"' target='_blank'><label class='btn btn-default btn-xs'><i class='fa fa-external-link-square'></i></label></a></span></li>"

With adding id='play-items-"+index+"' to identify unique class for each item of list.


Solution

  • UPDATE

    Firefox has a problem with li[i], since it's a HTMLCollection (nodeList) and not live coming from querySelectorAll(). One extra step needs to be added in order to convert li[i] to a true Array. The update involves a function called nodeList2Array(sel).

    UPDATE

    I misinterpreted the OP's request:

    Is there any solution to add a custom class, like .active when click on a item of list.

    So what is needed is manipulation of the generated <li>s of the custom playlist.

    SOLUTION

    Add this after the the rest of the script:

    jw.on('playlistItem', function() {
        var playlist = jw.getPlaylist();
        var idx = jw.getPlaylistIndex();
        //var li = document.querySelectorAll('.group-list-item');
        var li = nodeList2Array('.group-list-item');
    
        for(var i = 0; i < playlist.length; i++) {
            if(i === idx) {
                li[i].classList.add('active');
            }
            else {
                li[i].classList.remove('active');
            }
        }
    });
    
    function nodeList2Array(sel) {
        var li = Array.prototype.slice.call(document.querySelectorAll(sel));
        return li;
    }
    

    DEMO

    !!!IMPORTANT PLEASE READ THIS!!!

    The following demo DEFINITELY WORKS, but you need to enter your own key in order for it to function. JW7 does not have a free version like JW6 does.

    var jw = jwplayer("media1");
    jw.setup({
      playlist: "https://content.jwplatform.com/feeds/13ShtP5m.rss",
      displaytitle: false,
      width: 680,
      height: 360
    });
    
    var list = document.querySelector(".group-list");
    var html = list.innerHTML;
    
    jw.on('ready', function() {
      var playlist = jw.getPlaylist();
      for (var idx = 0; idx < playlist.length; idx++) {
        html += "<li class='group-list-item' title='" + playlist[idx].title + "'><a href='javascript:playThis(" + idx + ");'><img height='75' width='120' src='" + playlist[idx].image + "'><figcaption>" + playlist[idx].title + "</figcaption></a></li>";
        list.innerHTML = html;
      }
    });
    
    //SOLUTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    jw.on('playlistItem', function() {
      var playlist = jw.getPlaylist();
      var idx = jw.getPlaylistIndex();
      var li = document.querySelectorAll('.group-list-item');
      for (var i = 0; i < playlist.length; i++) {
        if (i === idx) {
          li[i].classList.add('active');
        } else {
          li[i].classList.remove('active');
        }
      }
    });
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    function playThis(idx) {
      jw.playlistItem(idx);
    }
    html {
      box-sizing: border-box;
      font: 400 16px/2 small-caps"Trebuchet MS";
      height: 100vh;
      width: 100vw;
    }
    *,
    *:before,
    *:after {
      box-sizing: inherit;
      margin: 0;
      padding: 0;
      border: 0 solid transparent;
      outline: 0;
      text-indent: 0;
    }
    body {
      height: 100%;
      width: 100%;
      background: #000;
      color: #FFF;
      position: relative;
    }
    #main {
      margin: auto;
      width: 680px;
    }
    #frame1 {
      position: absolute;
      top: 12.5%;
      left: 25%;
    }
    .jwp {
      position: relative;
    }
    .group-list {
      position: relative;
      list-style-type: none;
      list-style-position: inside;
    }
    .group-list li {
      list-style: none;
      display: inline-block;
      float: left;
      padding: 15px 0 0 11px;
      line-height: 2;
    }
    .group-list a {
      text-decoration: none;
      display: inline-block;
      background: #000;
      border: 1px solid #666;
      border-radius: 8px;
      height: 75px;
      width: 120px;
      text-align: center;
    }
    .group-list a:hover,
    .group-list a:active {
      border: 1px solid #ff0046;
      border-radius: 8px;
      color: #FFF;
      background: hsla(180, 60%, 50%, .4);
    }
    img {
      display: block;
    }
    .active {
      background: hsla(180, 60%, 50%, .4);
      outline: 3px solid #0FF;
    }
    .active figcaption {
      color: #000;
    }
    <!doctype html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <title>JWplayer 7 - Add active class to current playing video</title>
      <meta name="SO33252950" content="http://stackoverflow.com/questions/33252950/jwplayer-7-add-active-class-to-current-playing-video">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    
      <script src="https://d1jtvmpy1cspce.cloudfront.net/lib/jw/7/jwplayer.js"></script>
      <script>
        jwplayer.key = "/*........::::::45_Alphanumerics::::::........*/"
      </script>
    </head>
    
    <body>
      <main id="main">
        <section id="frame1" class="frame">
          <div id="media1" class="jwp">Loading...</div>
          <ul id="list1" class="group-list"></ul>
        </section>
      </main>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    
    </body>
    
    </html>


    OLD


    Sure it's possible to add a class such as .active then apply styles that way, but JW7 has extensive CSS Skin documentation. I styled the skin using the technique detailed here:

    http://support.jwplayer.com/customer/en/portal/articles/2092249-sample-css-file

    DEMO

    https://glpro.s3.amazonaws.com/_util/smpte/jwp.html

    /* Allows you to adjust the color of the playlist item when hovering and has a different active style.*/
    
    .jw-skin-stormtrooper .jw-playlist-container .jw-option:hover,
    .jw-skin-stormtrooper .jw-playlist-container .jw-option.jw-active-option {
      background-color:  hsla(210,100%,20%,1);
    }
    
    /* Changes the color of the label when hovering.*/
    
    .jw-skin-stormtrooper .jw-playlist-container .jw-option:hover .jw-label {
      color: #0080ff;
    }
    
    /* Sets the color of the play icon of the currently playing playlist item.*/
    .jw-skin-stormtrooper .jw-playlist-container .jw-label .jw-icon-play {
      color: #0080ff;
    }
    
    /* Sets the color of the playlist title */
    .jw-skin-stormtrooper .jw-tooltip-title {
        background-color: #000;
        color: #fff
    }
    
    /* Style for playlist item, current time, qualities, and caption text.*/
    .jw-skin-stormtrooper .jw-text {
      color: #aed4ff;
    }
    
    /* Color for all buttons when they are inactive. This is over-ridden with the 
    inactive configuration in the skin block.*/
    .jw-skin-stormtrooper .jw-button-color {
      color: #cee2ec;
    }
    
    
    /* Color for all buttons for when they are hovered on. This is over-ridden with the 
    active configuration in the skin block.*/
    
    .jw-skin-stormtrooper .jw-button-color:hover {
      color: #00e;
    }
    
    
    /* Color for when HD/CD icons are toggled on. */
    .jw-skin-stormtrooper .jw-toggle {
      color:  #0080ff;
    }
    
    /* Color for when HD/CD icons are toggled off. */
    .jw-skin-stormtrooper .jw-toggle.jw-off {
      color: #ffffff;
    }