Panopto API meets WordPress

Imagine you have some longer training videos but it’d be useful to provide discrete chunks. You might also want to provide some additional contextual information for particular video portions. Well, we wanted to be able to do that.1

This example uses the Panopto embed API and the Advanced Custom Fields repeater field to make this possible. It’s kind of fun and would be relatively easy to expand to take videos from other video hosts that have APIs (like YouTube).

You can play with the example here or just watch the video below.

Patterns that I like

Data Attributes

I like to use data attributes in scenarios like this where I have some pretty simple variables that I’ll get via PHP but will be using in javascript.

My navigation buttons are a good example of this. They end up looking like this on the HTML side.

<button class="jump-button" data-start="90" data-end="100" data-row="2">A second item</button>

The javascript can use those data attributes (jump, end, row) in ways that feel straight forward to me. The example below is a simplified version that shows how I’d get the start time2

let jumpButtons = document.querySelectorAll('.jump-button');//get all the elements with this class

jumpButtons.forEach((button) => {
  button.addEventListener('click', () => {
    let time = button.dataset.start;//get the jump data when the button is clicked 
  });
});

URL Parameters

Getting and setting data in the URL is often really useful. I do it with both javascript and PHP. In this case, we’ll look at javascript versions.

I use the getting option described in this article and show below.

function getUrlVars() {
    var vars = {};
    var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
        vars[key] = value;
    });
    return vars;
}

With that function, I can then access the time data this http://foo.com/playlist/more-playlist-title/?time=90 by doing the following.


function checkForTime(){
  if(getUrlVars()["time"]>0){//check for time
    const time = getUrlVars()["time"];//get time
    embedApi.seekTo(time);//go to that time
    showContentUrl(time);//show additional content
  }
}

I can set that variable via javascript without a page refresh by doing this. This function is called when the button is clicked and gets the time variable from the start time data attribute.

function appendTimeToUrl(time){
 window.history.replaceState(null, null, "?time="+time);
}

Query Selector

In javascript, querySelector can do any number of neat tricks. It turns out I can use data attributes to select elements. That came in handy here as I wanted to be able to show the additional content based on the URL time parameter. Since I wasn’t passing any other variable other than time, I needed to get the row ID. The following function lets me do that.

function showContentUrl(time){
  let button = document.querySelector('[data-start="'+time+'"]');
  let row = button.dataset.row;
  changeResources(row);
}

1 Or at least that’s how I understood things and thought it would be cool.

2 I originally named it ‘data-jump’ but changed it to ‘data-start’ as I wrote this. I often name variables poorly. It makes sense at the time to me but with programming it’s always better to be less funny and more understandable.

2 thoughts on “Panopto API meets WordPress

  1. Thanks for this, I am trying to do something similar for deep linking to longer YT videos in an HTML only space (I can insert scripts and css), and the use of the data parameters is helpful.

    Also, hi, Tom.

    1. Greetings Alan!

      I find the data attributes less hassle than doing the php/js meshing in WP. There may be lots of reasons that it’s a bad idea. I’m sure there are really angry people out there arguing against them.

      I’ll be interested to see what you do with YouTube. I may expand that theme to support additional video hosts. I have some old YouTube interactions in various places from the VCU days. I actually kind of like this one even though I have no memory of making it. Probably should just do it via H5P though.

Comments are closed.