Refreshing the page between videos

Technology
Player API
Edition
Express, Pro, Enterprise

I was recently asked how to initiate a page refresh in between videos. The solution I came up with provided a good workout with several different and useful parts of the Player API, so I thought it would be beneficial to share this solution as an example to the community. As we work through the solution, we'll examine:

  • gaining access to the videoList and tabBar components
  • knowing when a video completes
  • knowing when a viewer clicks on a title
  • figuring out which video they clicked on
  • knowing which playlist is currently selected, and
  • using the selected video and playlist information with the player's built-in deep linking functionality

A few assumptions

This note assumes you are working with a Brightcove player that supports multiple playlists and is published using JavaScript. Make sure that you have assigned some playlists to the player and have checked the "Enabled ActionScript/JavaScript APIs" box in the player's settings. For this to be helpful you should have a moderate understanding of JavaScript and have gone through the Using JavaScript with the Player API document in the Brightcove Support Center.

Summary

We want to write the code that will know when a new video is clicked on by a viewer and optionally, when a video finishes playing. When a viewer clicks on a new video, either in the same playlist or another playlist, we want to know about it so we can establish what video was clicked and what playlist that video is in. If we know this information, then we can refresh the page and include the video ID and playlist ID in the URL so the player will start playing this video when it reloads. Similarly, when a video completes, we want to know what video would play next so we can send the same information in the URL so the player begins playing the next video when it reloads. This functionality can be seen live here: http://files.brightcove.com/dev/refreshing-page-between-videos/index.html. You can download this zip file, which includes the source code for this page.

The Code

To start, publish the player on the page using the JavaScript publishing code available in the Publishing module, making sure to add in the APIModules_all.js script element in the publishing code. It should look something like this:

<!-- Start of Brightcove Player -->

<div style="display:none"></div>

<!--

By use of this code snippet, I agree to the Brightcove Publisher T and C

found at http://corp.brightcove.com/legal/terms_publisher.cfm.

-->

<script language="JavaScript" type="text/javascript" 
        src="http://admin.brightcove.com/js/BrightcoveExperiences.js">
</script>
<script type="text/javascript" 
        src="http://admin.brightcove.com/js/APIModules_all.js">
</script> 

<object id="myExperience" class="BrightcoveExperience">
     <param name="bgcolor" value="#FFFFFF" />
     <param name="width" value="966" />
     <param name="height" value="546" />
     <param name="playerID" value="12075764001" />
     <param name="publisherID" value="1370912864"/>
     <param name="isVid" value="true" />
     <param name="isUI" value="true" />
</object>

<!-- End of Brightcove Player -->

All of the remaining code needs to be added to an appropriate script tag. Start by adding global variables to hold the references to the player, its API modules, and its components.

// Set up Global variables

var player;
var video, exp;
var videoList, tabBar;

Then create an onTemplateLoaded() event handler which the player will execute when it loads. In this block, you will get references to the player, the Video Player API module, and the Experience API module. You will also set up event listeners for templateReady and mediaComplete. If you only want to refresh the page when someone actually clicks a title, you should not add the event listener for VIDEO_COMPLETE and not include the onVideoComplete event handler that will be discussed later.

function onTemplateLoaded(pPlayer) {
     // Get a reference to the player
     player = bcPlayer.getPlayer(pPlayer);

     // Get references to the player modules
     video = player.getModule(APIModules.VIDEO_PLAYER);
     exp = player.getModule(APIModules.EXPERIENCE);

     // Register event listeners
     exp.addEventListener(BCExperienceEvent.TEMPLATE_READY, onTemplateReady);
     video.addEventListener(BCVideoEvent.VIDEO_COMPLETE, onVideoComplete);
}

Next you need to create an event handler for the onTemplateReady event which will be executed when the player is fully initialized and ready to be interacted with via the Player APIs. In this handler method, we will be grabbing references to the videoList component and the playlistTabs component. These components will provide us with helpful information later about what playlist is selected and which titles are playing and which are next in line to play. Also, now that we have a reference to the videoList component, you can add an event listener for the elementClick event. This is what specifies the code to be run when a viewer clicks on a title.

function onTemplateReady(e) {
     // Get a reference to the videoList component
     videoList = exp.getElementByID("videoList");

     // Register event listener for elementClick event
     videoList.addEventListener("elementClick", onElementClick);

     // Get a reference to the tabBar component
     tabBar = exp.getElementByID("playlistTabs");
}

Now that we've got everything in place, we just need to add a method that will handle when someone clicks on a new video, and optionally, another that executes when a video completes. In both situations we will need to find out what the next video to play is and then append a video ID and a playlist ID to the new URL. This way when the player loads after the refres,h the appropriate video will play on the appropriate playlist. Here is the elementClick handler:

function onElementClick(e) {
     // Event Object contains the VideoDTO for the clicked video
     var selectedVideo = e.elementData;

     // Requests the currently selected playlist from the tabBar component
     var selectedLineup = tabBar.getSelectedData();

     // Get the current page URL remove any existing URL parameter
     var fullURL = document.location.toString();

     if(fullURL.indexOf("?") \!= \-1) {
          var urlPath = fullURL.substring(0,fullURL.indexOf("?"));
     } else { 
          var urlPath = fullURL; 
     }

     // Refresh the page adding the current playlist and video to the URL
     document.location = urlPath +
                         "?bclid=" + selectedLineup.id +
                         "&bctid=" + selectedVideo.id;
}

And here is the mediaComplete handler:

function onVideoComplete(e) {

     // Remove the event listener for mediaComplete as it can trigger two times
     video.removeEventListener(BCVideoEvent.VIDEO_COMPLETE, onVideoComplete);

     // Stop the next video so it doesn't begin playing before the page refreshes
     video.stop();

     // Get the VideoDTO for the next video in the playlist
     if (videoList.getSelectedIndex()+1 == videoList.getNumItems())
        { videoList.setSelectedIndex(0); 
     } else { videoList.next(); }
     var nextVideo = videoList.getSelectedData();

     // Requests the currenetly selected playlist from the tabBar component
     var selectedLineup = tabBar.getSelectedData();

     // Get the current page URL remove any existing URL parameter
     var fullURL = document.location.toString();

     if(fullURL.indexOf("?") \!= \-1) {
          var urlPath = fullURL.substring(0,fullURL.indexOf("?"));
     } else { 
          var urlPath = fullURL; 
     }

     // Refresh the page adding the current playlist and video to the URL
     document.location = urlPath +
                         "?bclid=" + selectedLineup.id +
                          "&bctid=" + nextVideo.id;

}

Lastly I think it's important to provide a quick explanation of the URL creation. Because the code starts with the current page URL, it can not simply add the new bctid and bclid parameters to the URL. If it did, then the URL would contain duplicates of the parameters on the first reload, and triplicates on the second reload.

To resolve this issue, the code above takes the current URL and trims off any URL parameters that it finds. For example:

http://files.brightcove.com/dev/?bclid=123456789&bctid=123456790

would be trimmed to

http://files.brightcove.com/dev/

Then, being left with just the path itself, the code can add the new key/value pairs to the URL.

http://files.brightcove.com/dev/?bclid=123456791&bctid=123456792

If your website utilizes URL parameters other than bctid and bclid, you will need to alter this code to be more thorough. Instead of simply cutting off all parameters from the URL, you would need to extract all of the parameters and remove only the bctid and bclid that will be added in again.