Category Archives: JavaScript

Brightcove Embed Code and Events

10 Mar 2016

Another unique thing for me today – this time getting the Brightcove media player playing in a CBT that we’re developing. I originally setup the framework for this project and handed it off to other developers to complete but it has come back around to me since incorporating the Brightcove video player turned out to be problematic.

When the project landed back at my desk the video wasnt working and the PM was waiting for the client to send over the Brightcove iFrame code (the client didnt reveal they had a brightcove account until later). The iFrame was easy to setup but the assumption that it was what the project required was wrong – we’re hiding the navigation thereby forcing the end-user to watch the video which means we need to register some sort of “video end” event so that we know when to re-enable the UI. Since the iFrame’s source came from another domain we of course ran afoul of the cross domain policy preventing any interaction with the iFramed contents.

Digging into Brightcove’s docs I saw the “embed” option and started down that path: first, I needed to embed the code, next I needed to register the desired event.

Embed the Video HTML

I didn’t see the Brightcove console but from what the client gave us I could tell that there must be a section that provies sample embed code. You will want that code as it contains the Video ID (UID for the video), Account number (your Brightcove account), and the Player value (tells the Brightcove JS which video tag to use).

  

For my specific implementation the above was kept in an external HTML template file. I then pulled it and updated the necessary values. Once the HTML was ready to be inserted a simple $(‘#my-element-ID’).html(template-code-here) added it to the page.

Note that the video ID should must be inserted into the above for this to work (well, for this particular way of doing things) as it tells the Brightcove JS what video to use. What happens next is that we create a video player instance.

Init the Video

Per the Brightcove docs they create a script element, assign values to various properties and then add it to the page. A few things to note:

  1. We need to know when the Brightcove script has loaded
  2. We need to create a reference to the video player
  3. We need to assign a callback to the video player’s ended event

So with that in mind here’s the function I wrote (note the comments).

...
  var bc = function(accountID,playerID){
    var that = this;
    this.mPlayer = null;
    this.brightcove = {
      accountId : accountID, // your account ID here
      playerId : playerID // your player ID here
    }

    function addBrightCoveScript(){
      // create the element
      var s = document.createElement('script');

      // add the element to the page
      $('#my-wrapper').append(s);

      // set the onload
      s.onload = function(e){

        // the script has loaded, now lets detect the video player instantiation
        videojs('mPlayer').ready(function(){

          // cool, we know that the video player exists, lets get a reference to it
          that.mPlayer = videojs('mPlayer');

          // using the reference lets add a listener, in this case we are listening for the "ended" event
          that.mPlayer.one('ended',function(e){
            // the video has ended - do something here  
          });
        });
      };

    // now update the script tag
    s.src = '//players.brightcove.net/' + that.brightcove.accountId + '/' + that.brightcove.playerId + '_default/index.min.js';
  }
...

You will see what appears to be a typo: that.mplayer.one. The “one” is not a typo, per the Brightcove API registering an event with the “one” method will result in the listener detecting the event a single time. When that happens the listener removes itself thereby relieving me of the burden of doing it myself.

Following the above you should be good to go for modern HTML5-capable browsers.

Angular and Scrolling Content

15 Oct 2015

I’m currently enrolled at Thinkful.com in the Angular course. I’m well over half-way through and have been applying Angular to my work projects with great success. One thing that I needed to do was to have scrolling views in my hybrid apps while having other areas of the app remain static. My future goals involve using Ionic – which handles scrolling easily enough, and I suspect, in the exact same way I’ve done it here – but I’m a logical step-by-step kind of guy so for now I’m content with learning Angular and rolling my own UI. That being the case I thought to search for the “Angular” way of getting views to scroll and tried a few of the custom directives available on the Internet.

The easiest to set up was ng-scrollable which technically worked but lacked the finesse of the vaunted iScroll. I also tried angular-iscroll but without much success. I reverted to the usually reliable iScroll but Angular didn’t want to play nicely with it. I then reverted to ng-scrollable thinking I could revisit it and proceeded with my other layout duties only to find that ng-scrollable injected too much crap into the DOM which broke a previously working flex-box-based layout. Attempts to rectify the layout proved to be a waste of time. So, I removed ng-scrollable and instead pursued a native / pure css solution.

The Technique

So lets get back to what I wanted – native-like smooth scrolling with inertia. The answer can be found via CSS by creating a class with the following properties (your wrapping container must have a set width / height, and a setting of “overflow:hidden” on the wrapper will kill scrolling):

.scrollable {
    overflow-x: hidden; // Control how to clip the container's content.
    overflow-y: scroll;
    -ms-overflow-style: -ms-autohiding-scrollbar; // configure overflow scrolling behavior for IE 10
    -webkit-overflow-scrolling: touch; // The magic happens here
}

Each of the above styles are configured as follows:

  • -webkit-overflow-scrolling
    • auto – Non-inertia scrolling. Scrolling stops as soon as your finger no longer touches the screen.
    • touch – Use inertia-based scrolling, the faster you flick the scrollable content the faster it scrolls but continues to a deaccelration scroll whne your finger stops touching the screen. I find this to be the desired behavior as its closest to native on Mobile.
  • overflow-x, overflow-y – These properties specify how to treat overflowing content via one of the following values:

    • visible – Indicates the content is not clipped, it may be rendered outside the content box.
    • hidden – Indicates the content is clipped and no scrollbars are provided.
    • scroll – Indicates the content is clipped and desktop browsers use scrollbars whether or not any content is clipped. For hybrid application development the scrolling behavior mimics native scrolling where scroll bars don’t appear unless you interact with the scrollable content. On Android at least the scrollbar overlaps content so you should add padding to account for it. On desktop the scrollbars use up additional space within the scrolling wrapper.
    • auto – Depends on the user agent – meaning that you should expect the native behavor for the overflowing content.

I’m not too concerned with IE in my hybrid app development but here are the configuration options none-the-less:

  • -ms-overflow-style – Sets the scrolling behavior for overflowing elements in IE (copied from MS).

    • auto – Indicates the element inherits its -ms-overflow-style from its parent element
    • none – Indicates the element does not display scrollbars or panning indicators, even when its content overflows. Unlike overflow: hidden, elements with -ms-overflow-style: none can still be scrolled via touch panning, keyboard, or mouse wheel.
    • scrollbar – Indicates the element displays a classic scrollbar-type control when its content overflows.
    • -ms-autohiding-scrollbar – Indicates the element displays auto-hiding scrollbars during mouse interactions and panning indicators during touch and keyboard interactions.

Notes

If using this on Android / PhoneGap be sure to install the Crosswalk plugin so that you don’t have to worry about compatibility with older webkits.

Also, it is worth noting that sometimes it wont work unless you apply the webkit-specific styling directly to the element like so:

<div id="comeContent" style="-webkit-ovrflow-scrolling: touch;">...

Also worth noting is that if the content of the scrolling element changes that you may need to force the content heights to be recalculate on iOS by inserting a psuedo-element using a simple calc() function to determine its new height:

#comeContent:before {
  content:'';
  width: 1px;
  float: left; // remove from the document flow
  height: calc(100% + 1px); // force the recalculation of the container's height
  margin-left: -1px; // remove from view
}

Other methods of forcing a screen redraw may work as well.

Simple Twitter Timeline Data

26 Sep 2015

We’re all familiar with how to embed a Twitter timeline – which is to simply copy the Widget code from Twitter and paste into your site. Twitter then drops in an iframe and you have a timeline.

The alternative is to use the twitter API to pull a timeline and then deal with OAUTH.

Or, you could just scrape a timeline out of the GET response that an iframed timeline’s HREF creates which is what I’ve done here. The key to this working at all is that Twitter’s iframe-embedding method creates a GET request that returns a JSONP payload. JSONP allows developers to circumvent cross domain restrictions which is why embedding a timeline works.

Knowing that I can successfully retrieve timeline data and that the data will be sent to a callback of my choosing (the “P” in “JSONP”) all I needed to do was to parse out the useful information – parse it out because the response we get back is not in JSON notation but a string of html. Parsing is a pain though so I decided to use jQuery to convert the string to a DOM object so that I can search for the nodes by traversing the DOM tree for the bits of information that I need.

Updated 4/11/2016 to reflect the latest Twitter changes

Here’s an example, use the timeline ID below or enter your own.

Note that we’re limited to the 20 most recent tweets. I convert everything to an array of tweet objects as illustrated below:

twttr_updated_jsonp

You can get the code here: https://github.com/r-luna/simple_twitter_timeline or simply view this page’s source.

All you need is the ID of the timeline, a callback of your own making, and jQuery to get this to work.

In this example you can see that the function to get your timeline data is namespaced to twtrUtil. To get your timeline call twtrUtil.getTimeline(CALLBACK_HERE,ID_HERE):

    function handleResponse(o){
        console.log(o);
        $('#response').html(JSON.stringify(o));
    }
        
    function getTimeline(){
        var id = $('input[name="id"]').val();
        twtrUtil.getTimeline(handleResponse,id);
    }

Your next thought would be “how do I get a twitter timeline id?”. Its easy to do, just create a widget in your Twitter account, find the public timeline that you want to use, then create the Widget. Once created the Widget ID appears in the URL of the widget create success page. The ID identifies the widget which of course is setup to show the timeline that you selected.

See this example URL which illustrates where to find the ID:

  • https://twitter.com/settings/widgets/646067303877115905/edit?focus_textarea=1&notice=WIDGET_CREATED

Finding the ID’s of All Calendars attached to a Google Account

14 Sep 2015

If you work with Google Calendars you know that you need to specify the ID of a calendar in order to be able to update it. A small modification to the code provided by Google will print all your calendar objects to the console and then you can find the specific calendar’s ID.

Be sure to read this over at Google: Authentication using the Google APIs Client Library for JavaScript. Specifically you need to generate the access keys for your application before you can call the calendar.calendarList.list method to see all the calendars in your account.

I won’t walk through the whole thing – see below and note the comments (As an aside this was relevant to something I did that inserted calendar entries into a Google calendar – see this repo).


    var CLIENT_ID = 'your_client_id'
    var SCOPES = ['https://www.googleapis.com/auth/calendar'];


    // Check if current user has authorized this application.
    function checkAuth() {
        gapi.auth.authorize(
          {
            'client_id': CLIENT_ID,
            'scope': SCOPES,
            'immediate': true
          }, handleAuthResult);
    }


    //* Handle response from authorization server.
    //* @param {Object} authResult Authorization result.
    function handleAuthResult(authResult) {
        var authorizeDiv = document.getElementById('authorize-div');
        if (authResult && !authResult.error) {
          // Hide auth UI, then load client library.
          authorizeDiv.style.display = 'none';
          loadCalendarApi();
        } else {
          // Show auth UI, allowing the user to initiate authorization by
          // clicking authorize button.
          authorizeDiv.style.display = 'inline';
        }
    }


    //* Initiate auth flow in response to user clicking authorize button.
    //* @param {Event} event Button click event.
    function handleAuthClick(event) {
        gapi.auth.authorize(
          {client_id: CLIENT_ID, scope: SCOPES, immediate: false},
          handleAuthResult);
        return false;
    }
	  

    //* Load Google Calendar client library. List upcoming events
    //* once client library is loaded.
    function loadCalendarApi() {
        // Now get the list of calendars for the primary google account
        gapi.client.load('calendar', 'v3', function() {
            var request = gapi.client.calendar.calendarList.list({
		 'calendarId': 'primary'
		 });
		 request.execute(function(resp) {
		 for (var i = 0; i < resp.items.length; i++) {
		    console.log(resp.items[i]);
                }
            });
        });
    }

Also, place the following in your html:

    <div id="authorize-div" style="display: ">
      <span>Authorize access to Google Calendar API
      <!--Button for the user to click to initiate auth sequence -->
      <button id="authorize-button" onclick="handleAuthClick(event)">
        Authorize
      </button>
    </div>
    <pre id="output"></pre>

Replacing Logical OR with Void and Logical AND

09 Sep 2015

I enjoy perusing other people’s code to see how they approach whatever it is that they are trying to solve. The follow simplified function caught my eye:

function someFunc(a){
   void 0===a.prop&&(a.prop=20);
}

Looks like some esoteric stuff but makes a lot of sense when written like this:

function someFunc(a){
    a.prop = a.prop || 20;
}

Functionally these two expressions mean the same thing. The difference is that the author of the first line is being clever 😉

The two expressions listed above read as follows in plain english: if a.prop is equal to undefined then create the property if it doesn’t exist and set its value to 20, or just set its value to 20..

The second example is much easier to read but the first is what we’re interested in so lets dissect its meaning.

First, this part needs to be understood:

void 0

This represents the global primitive property undefined. Why write it like this? Well, it used to be that you could overwrite undefined by design or by mistake meaning that you could never rely on it being what it should be (though usually you could) – writing it like this guarantees that you would always be dealing with the true undefined primitive value. Modern browsers don’t allow you to do overwrite undefined anymore.

Next is:

===

Which of course is the strict equal operator which checks to ensure that the operands or not only equal but of the same type.

Next:

a.prop

Of course this is a reference to the value held by the prop property of the a object.

So then, the author is comparing undefined to a.prop. This will return true or false. Ok, not so clever until we get to the next part:

&&(a.prop=20)

This is where it all comes together – note the logical AND operator &&. As you would expect it evaluates the expression on the left first and this is the key to how this bit of code works. These are the two possible outcomes of evaluating the left expression:

  • For the expression void 0===a.prop&&(a.prop=20);

    1. if a.prop is undefined then we must evaluate the expression on the right! Since the right operand is grouped by parenthesis it must first be evaluated to determine its truthiness. By evaluating it we are setting a default value for a.prop.
       
    2. if a.prop is not undefined then the left operand is false and nothing happens! Consider that both operands of the logical AND operator are evaluated only if the left operand is true. If the left operand is false then the right operand is ignored.

Pretty cool way of making use of the && operator!

As a side note, if the property was missing from the object we would also get undefined so the code here would first create the property then set its default value.