src/js/libs/popcorn.js
branchno-popcorn
changeset 388 30277c1e3d46
parent 387 d1fe53ad8d72
child 389 2f855c3efd48
--- a/src/js/libs/popcorn.js	Fri Dec 02 11:06:30 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2055 +0,0 @@
-(function(global, document) {
-
-  // Popcorn.js does not support archaic browsers
-  if ( !document.addEventListener ) {
-    global.Popcorn = {
-      isSupported: false
-    };
-
-    var methods = ( "forEach extend effects error guid sizeOf isArray nop position disable enable destroy " +
-          "addTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId " +
-          "timeUpdate plugin removePlugin compose effect parser xhr getJSONP getScript" ).split(/\s+/);
-
-    while( methods.length ) {
-      global.Popcorn[ methods.shift() ] = function() {};
-    }
-    return;
-  }
-
-  var
-
-  AP = Array.prototype,
-  OP = Object.prototype,
-
-  forEach = AP.forEach,
-  slice = AP.slice,
-  hasOwn = OP.hasOwnProperty,
-  toString = OP.toString,
-
-  // Copy global Popcorn (may not exist)
-  _Popcorn = global.Popcorn,
-
-  //  ID string matching
-  rIdExp  = /^(#([\w\-\_\.]+))$/,
-
-  //  Ready fn cache
-  readyStack = [],
-  readyBound = false,
-  readyFired = false,
-
-  //  Non-public internal data object
-  internal = {
-    events: {
-      hash: {},
-      apis: {}
-    }
-  },
-
-  //  Non-public `requestAnimFrame`
-  //  http://paulirish.com/2011/requestanimationframe-for-smart-animating/
-  requestAnimFrame = (function(){
-    return global.requestAnimationFrame ||
-      global.webkitRequestAnimationFrame ||
-      global.mozRequestAnimationFrame ||
-      global.oRequestAnimationFrame ||
-      global.msRequestAnimationFrame ||
-      function( callback, element ) {
-        global.setTimeout( callback, 16 );
-      };
-  }()),
-
-  //  Declare constructor
-  //  Returns an instance object.
-  Popcorn = function( entity, options ) {
-    //  Return new Popcorn object
-    return new Popcorn.p.init( entity, options || null );
-  };
-
-  //  Popcorn API version, automatically inserted via build system.
-  Popcorn.version = "@VERSION";
-
-  //  Boolean flag allowing a client to determine if Popcorn can be supported
-  Popcorn.isSupported = true;
-
-  //  Instance caching
-  Popcorn.instances = [];
-
-  //  Declare a shortcut (Popcorn.p) to and a definition of
-  //  the new prototype for our Popcorn constructor
-  Popcorn.p = Popcorn.prototype = {
-
-    init: function( entity, options ) {
-
-      var matches;
-
-      //  Supports Popcorn(function () { /../ })
-      //  Originally proposed by Daniel Brooks
-
-      if ( typeof entity === "function" ) {
-
-        //  If document ready has already fired
-        if ( document.readyState === "interactive" || document.readyState === "complete" ) {
-
-          entity( document, Popcorn );
-
-          return;
-        }
-        //  Add `entity` fn to ready stack
-        readyStack.push( entity );
-
-        //  This process should happen once per page load
-        if ( !readyBound ) {
-
-          //  set readyBound flag
-          readyBound = true;
-
-          var DOMContentLoaded  = function() {
-
-            readyFired = true;
-
-            //  Remove global DOM ready listener
-            document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
-
-            //  Execute all ready function in the stack
-            for ( var i = 0, readyStackLength = readyStack.length; i < readyStackLength; i++ ) {
-
-              readyStack[ i ].call( document, Popcorn );
-
-            }
-            //  GC readyStack
-            readyStack = null;
-          };
-
-          //  Register global DOM ready listener
-          document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
-        }
-
-        return;
-      }
-
-      //  Check if entity is a valid string id
-      matches = rIdExp.exec( entity );
-
-      //  Get media element by id or object reference
-      this.media = matches && matches.length && matches[ 2 ] ?
-                     document.getElementById( matches[ 2 ] ) :
-                     entity;
-
-      //  Create an audio or video element property reference
-      this[ ( this.media.nodeName && this.media.nodeName.toLowerCase() ) || "video" ] = this.media;
-
-      //  Register new instance
-      Popcorn.instances.push( this );
-
-      this.options = options || {};
-
-      this.isDestroyed = false;
-
-      this.data = {
-
-        // Allows disabling a plugin per instance
-        disabled: [],
-
-        // Stores DOM event queues by type
-        events: {},
-
-        // Stores Special event hooks data
-        hooks: {},
-
-        // Store track event history data
-        history: [],
-
-        // Stores ad-hoc state related data]
-        state: {
-          volume: this.media.volume
-        },
-
-        // Store track event object references by trackId
-        trackRefs: {},
-
-        // Playback track event queues
-        trackEvents: {
-          byStart: [{
-
-            start: -1,
-            end: -1
-          }],
-          byEnd: [{
-            start: -1,
-            end: -1
-          }],
-          animating: [],
-          startIndex: 0,
-          endIndex: 0,
-          previousUpdateTime: -1
-        }
-      };
-
-      //  Wrap true ready check
-      var isReady = function( that ) {
-
-        var duration, videoDurationPlus, animate;
-
-        if ( that.media.readyState >= 2 ) {
-          //  Adding padding to the front and end of the arrays
-          //  this is so we do not fall off either end
-
-          duration = that.media.duration;
-          //  Check for no duration info (NaN)
-          videoDurationPlus = duration != duration ? Number.MAX_VALUE : duration + 1;
-
-          Popcorn.addTrackEvent( that, {
-            start: videoDurationPlus,
-            end: videoDurationPlus
-          });
-
-          if ( that.options.frameAnimation ) {
-            //  if Popcorn is created with frameAnimation option set to true,
-            //  requestAnimFrame is used instead of "timeupdate" media event.
-            //  This is for greater frame time accuracy, theoretically up to
-            //  60 frames per second as opposed to ~4 ( ~every 15-250ms)
-            animate = function () {
-
-              Popcorn.timeUpdate( that, {} );
-
-              that.trigger( "timeupdate" );
-
-              requestAnimFrame( animate );
-            };
-
-            requestAnimFrame( animate );
-
-          } else {
-
-            that.data.timeUpdateFunction = function( event ) {
-              Popcorn.timeUpdate( that, event );
-            };
-
-            if ( !that.isDestroyed ) {
-              that.media.addEventListener( "timeupdate", that.data.timeUpdateFunction, false );
-            }
-          }
-        } else {
-          global.setTimeout(function() {
-            isReady( that );
-          }, 1 );
-        }
-      };
-
-      isReady( this );
-
-      return this;
-    }
-  };
-
-  //  Extend constructor prototype to instance prototype
-  //  Allows chaining methods to instances
-  Popcorn.p.init.prototype = Popcorn.p;
-
-  Popcorn.forEach = function( obj, fn, context ) {
-
-    if ( !obj || !fn ) {
-      return {};
-    }
-
-    context = context || this;
-
-    var key, len;
-
-    // Use native whenever possible
-    if ( forEach && obj.forEach === forEach ) {
-      return obj.forEach( fn, context );
-    }
-
-    if ( toString.call( obj ) === "[object NodeList]" ) {
-      for ( key = 0, len = obj.length; key < len; key++ ) {
-        fn.call( context, obj[ key ], key, obj );
-      }
-      return obj;
-    }
-
-    for ( key in obj ) {
-      if ( hasOwn.call( obj, key ) ) {
-        fn.call( context, obj[ key ], key, obj );
-      }
-    }
-    return obj;
-  };
-
-  Popcorn.extend = function( obj ) {
-    var dest = obj, src = slice.call( arguments, 1 );
-
-    Popcorn.forEach( src, function( copy ) {
-      for ( var prop in copy ) {
-        dest[ prop ] = copy[ prop ];
-      }
-    });
-
-    return dest;
-  };
-
-
-  // A Few reusable utils, memoized onto Popcorn
-  Popcorn.extend( Popcorn, {
-    noConflict: function( deep ) {
-
-      if ( deep ) {
-        global.Popcorn = _Popcorn;
-      }
-
-      return Popcorn;
-    },
-    error: function( msg ) {
-      throw new Error( msg );
-    },
-    guid: function( prefix ) {
-      Popcorn.guid.counter++;
-      return  ( prefix ? prefix : "" ) + ( +new Date() + Popcorn.guid.counter );
-    },
-    sizeOf: function( obj ) {
-      var size = 0;
-
-      for ( var prop in obj ) {
-        size++;
-      }
-
-      return size;
-    },
-    isArray: Array.isArray || function( array ) {
-      return toString.call( array ) === "[object Array]";
-    },
-
-    nop: function() {},
-
-    position: function( elem ) {
-
-      var clientRect = elem.getBoundingClientRect(),
-          bounds = {},
-          doc = elem.ownerDocument,
-          docElem = document.documentElement,
-          body = document.body,
-          clientTop, clientLeft, scrollTop, scrollLeft, top, left;
-
-      //  Determine correct clientTop/Left
-      clientTop = docElem.clientTop || body.clientTop || 0;
-      clientLeft = docElem.clientLeft || body.clientLeft || 0;
-
-      //  Determine correct scrollTop/Left
-      scrollTop = ( global.pageYOffset && docElem.scrollTop || body.scrollTop );
-      scrollLeft = ( global.pageXOffset && docElem.scrollLeft || body.scrollLeft );
-
-      //  Temp top/left
-      top = Math.ceil( clientRect.top + scrollTop - clientTop );
-      left = Math.ceil( clientRect.left + scrollLeft - clientLeft );
-
-      for ( var p in clientRect ) {
-        bounds[ p ] = Math.round( clientRect[ p ] );
-      }
-
-      return Popcorn.extend({}, bounds, { top: top, left: left });
-    },
-
-    disable: function( instance, plugin ) {
-
-      var disabled = instance.data.disabled;
-
-      if ( disabled.indexOf( plugin ) === -1 ) {
-        disabled.push( plugin );
-      }
-
-      return instance;
-    },
-    enable: function( instance, plugin ) {
-
-      var disabled = instance.data.disabled,
-          index = disabled.indexOf( plugin );
-
-      if ( index > -1 ) {
-        disabled.splice( index, 1 );
-      }
-
-      return instance;
-    },
-    destroy: function( instance ) {
-      var events = instance.data.events,
-          singleEvent, item, fn;
-
-      //  Iterate through all events and remove them
-      for ( item in events ) {
-        singleEvent = events[ item ];
-        for ( fn in singleEvent ) {
-          delete singleEvent[ fn ];
-        }
-        events[ item ] = null;
-      }
-
-      if ( !instance.isDestroyed ) {
-        instance.media.removeEventListener( "timeupdate", instance.data.timeUpdateFunction, false );
-        instance.isDestroyed = true;
-      }
-    }
-  });
-
-  //  Memoized GUID Counter
-  Popcorn.guid.counter = 1;
-
-  //  Factory to implement getters, setters and controllers
-  //  as Popcorn instance methods. The IIFE will create and return
-  //  an object with defined methods
-  Popcorn.extend(Popcorn.p, (function() {
-
-      var methods = "load play pause currentTime playbackRate volume duration preload playbackRate " +
-                    "autoplay loop controls muted buffered readyState seeking paused played seekable ended",
-          ret = {};
-
-
-      //  Build methods, store in object that is returned and passed to extend
-      Popcorn.forEach( methods.split( /\s+/g ), function( name ) {
-
-        ret[ name ] = function( arg ) {
-
-          if ( typeof this.media[ name ] === "function" ) {
-
-            // Support for shorthanded play(n)/pause(n) jump to currentTime
-            // If arg is not null or undefined and called by one of the
-            // allowed shorthandable methods, then set the currentTime
-            // Supports time as seconds or SMPTE
-            if ( arg != null && /play|pause/.test( name ) ) {
-              this.media.currentTime = Popcorn.util.toSeconds( arg );
-            }
-
-            this.media[ name ]();
-
-            return this;
-          }
-
-
-          if ( arg != null ) {
-
-            this.media[ name ] = arg;
-
-            return this;
-          }
-
-          return this.media[ name ];
-        };
-      });
-
-      return ret;
-
-    })()
-  );
-
-  Popcorn.forEach( "enable disable".split(" "), function( method ) {
-    Popcorn.p[ method ] = function( plugin ) {
-      return Popcorn[ method ]( this, plugin );
-    };
-  });
-
-  Popcorn.extend(Popcorn.p, {
-
-    //  Rounded currentTime
-    roundTime: function() {
-      return -~this.media.currentTime;
-    },
-
-    //  Attach an event to a single point in time
-    exec: function( time, fn ) {
-
-      //  Creating a one second track event with an empty end
-      Popcorn.addTrackEvent( this, {
-        start: time,
-        end: time + 1,
-        _running: false,
-        _natives: {
-          start: fn || Popcorn.nop,
-          end: Popcorn.nop,
-          type: "exec"
-        }
-      });
-
-      return this;
-    },
-
-    // Mute the calling media, optionally toggle
-    mute: function( toggle ) {
-
-      var event = toggle == null || toggle === true ? "muted" : "unmuted";
-
-      // If `toggle` is explicitly `false`,
-      // unmute the media and restore the volume level
-      if ( event === "unmuted" ) {
-        this.media.muted = false;
-        this.media.volume = this.data.state.volume;
-      }
-
-      // If `toggle` is either null or undefined,
-      // save the current volume and mute the media element
-      if ( event === "muted" ) {
-        this.data.state.volume = this.media.volume;
-        this.media.muted = true;
-      }
-
-      // Trigger either muted|unmuted event
-      this.trigger( event );
-
-      return this;
-    },
-
-    // Convenience method, unmute the calling media
-    unmute: function( toggle ) {
-
-      return this.mute( toggle == null ? false : !toggle );
-    },
-
-    // Get the client bounding box of an instance element
-    position: function() {
-      return Popcorn.position( this.media );
-    },
-
-    // Toggle a plugin's playback behaviour (on or off) per instance
-    toggle: function( plugin ) {
-      return Popcorn[ this.data.disabled.indexOf( plugin ) > -1 ? "enable" : "disable" ]( this, plugin );
-    },
-
-    // Set default values for plugin options objects per instance
-    defaults: function( plugin, defaults ) {
-
-      // If an array of default configurations is provided,
-      // iterate and apply each to this instance
-      if ( Popcorn.isArray( plugin ) ) {
-
-        Popcorn.forEach( plugin, function( obj ) {
-          for ( var name in obj ) {
-            this.defaults( name, obj[ name ] );
-          }
-        }, this );
-
-        return this;
-      }
-
-      if ( !this.options.defaults ) {
-        this.options.defaults = {};
-      }
-
-      if ( !this.options.defaults[ plugin ] ) {
-        this.options.defaults[ plugin ] = {};
-      }
-
-      Popcorn.extend( this.options.defaults[ plugin ], defaults );
-
-      return this;
-    }
-  });
-
-  Popcorn.Events  = {
-    UIEvents: "blur focus focusin focusout load resize scroll unload",
-    MouseEvents: "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave click dblclick",
-    Events: "loadstart progress suspend emptied stalled play pause " +
-            "loadedmetadata loadeddata waiting playing canplay canplaythrough " +
-            "seeking seeked timeupdate ended ratechange durationchange volumechange"
-  };
-
-  Popcorn.Events.Natives = Popcorn.Events.UIEvents + " " +
-                           Popcorn.Events.MouseEvents + " " +
-                           Popcorn.Events.Events;
-
-  internal.events.apiTypes = [ "UIEvents", "MouseEvents", "Events" ];
-
-  // Privately compile events table at load time
-  (function( events, data ) {
-
-    var apis = internal.events.apiTypes,
-    eventsList = events.Natives.split( /\s+/g ),
-    idx = 0, len = eventsList.length, prop;
-
-    for( ; idx < len; idx++ ) {
-      data.hash[ eventsList[idx] ] = true;
-    }
-
-    apis.forEach(function( val, idx ) {
-
-      data.apis[ val ] = {};
-
-      var apiEvents = events[ val ].split( /\s+/g ),
-      len = apiEvents.length,
-      k = 0;
-
-      for ( ; k < len; k++ ) {
-        data.apis[ val ][ apiEvents[ k ] ] = true;
-      }
-    });
-  })( Popcorn.Events, internal.events );
-
-  Popcorn.events = {
-
-    isNative: function( type ) {
-      return !!internal.events.hash[ type ];
-    },
-    getInterface: function( type ) {
-
-      if ( !Popcorn.events.isNative( type ) ) {
-        return false;
-      }
-
-      var eventApi = internal.events,
-        apis = eventApi.apiTypes,
-        apihash = eventApi.apis,
-        idx = 0, len = apis.length, api, tmp;
-
-      for ( ; idx < len; idx++ ) {
-        tmp = apis[ idx ];
-
-        if ( apihash[ tmp ][ type ] ) {
-          api = tmp;
-          break;
-        }
-      }
-      return api;
-    },
-    //  Compile all native events to single array
-    all: Popcorn.Events.Natives.split( /\s+/g ),
-    //  Defines all Event handling static functions
-    fn: {
-      trigger: function( type, data ) {
-
-        var eventInterface, evt;
-        //  setup checks for custom event system
-        if ( this.data.events[ type ] && Popcorn.sizeOf( this.data.events[ type ] ) ) {
-
-          eventInterface  = Popcorn.events.getInterface( type );
-
-          if ( eventInterface ) {
-
-            evt = document.createEvent( eventInterface );
-            evt.initEvent( type, true, true, global, 1 );
-
-            this.media.dispatchEvent( evt );
-
-            return this;
-          }
-
-          //  Custom events
-          Popcorn.forEach( this.data.events[ type ], function( obj, key ) {
-
-            obj.call( this, data );
-
-          }, this );
-
-        }
-
-        return this;
-      },
-      listen: function( type, fn ) {
-
-        var self = this,
-            hasEvents = true,
-            eventHook = Popcorn.events.hooks[ type ],
-            origType = type,
-            tmp;
-
-        if ( !this.data.events[ type ] ) {
-          this.data.events[ type ] = {};
-          hasEvents = false;
-        }
-
-        // Check and setup event hooks
-        if ( eventHook ) {
-
-          // Execute hook add method if defined
-          if ( eventHook.add ) {
-            eventHook.add.call( this, {}, fn );
-          }
-
-          // Reassign event type to our piggyback event type if defined
-          if ( eventHook.bind ) {
-            type = eventHook.bind;
-          }
-
-          // Reassign handler if defined
-          if ( eventHook.handler ) {
-            tmp = fn;
-
-            fn = function wrapper( event ) {
-              eventHook.handler.call( self, event, tmp );
-            };
-          }
-
-          // assume the piggy back event is registered
-          hasEvents = true;
-
-          // Setup event registry entry
-          if ( !this.data.events[ type ] ) {
-            this.data.events[ type ] = {};
-            // Toggle if the previous assumption was untrue
-            hasEvents = false;
-          }
-        }
-
-        //  Register event and handler
-        this.data.events[ type ][ fn.name || ( fn.toString() + Popcorn.guid() ) ] = fn;
-
-        // only attach one event of any type
-        if ( !hasEvents && Popcorn.events.all.indexOf( type ) > -1 ) {
-
-          this.media.addEventListener( type, function( event ) {
-
-            Popcorn.forEach( self.data.events[ type ], function( obj, key ) {
-              if ( typeof obj === "function" ) {
-                obj.call( self, event );
-              }
-            });
-
-          }, false);
-        }
-        return this;
-      },
-      unlisten: function( type, fn ) {
-
-        if ( this.data.events[ type ] && this.data.events[ type ][ fn ] ) {
-
-          delete this.data.events[ type ][ fn ];
-
-          return this;
-        }
-
-        this.data.events[ type ] = null;
-
-        return this;
-      }
-    },
-    hooks: {
-      canplayall: {
-        bind: "canplaythrough",
-        add: function( event, callback ) {
-
-          var state = false;
-
-          if ( this.media.readyState ) {
-
-            callback.call( this, event );
-
-            state = true;
-          }
-
-          this.data.hooks.canplayall = {
-            fired: state
-          };
-        },
-        // declare special handling instructions
-        handler: function canplayall( event, callback ) {
-
-          if ( !this.data.hooks.canplayall.fired ) {
-            // trigger original user callback once
-            callback.call( this, event );
-
-            this.data.hooks.canplayall.fired = true;
-          }
-        }
-      }
-    }
-  };
-
-  //  Extend Popcorn.events.fns (listen, unlisten, trigger) to all Popcorn instances
-  Popcorn.forEach( [ "trigger", "listen", "unlisten" ], function( key ) {
-    Popcorn.p[ key ] = Popcorn.events.fn[ key ];
-  });
-
-  // Internal Only - Adds track events to the instance object
-  Popcorn.addTrackEvent = function( obj, track ) {
-
-    // Determine if this track has default options set for it
-    // If so, apply them to the track object
-    if ( track && track._natives && track._natives.type &&
-        ( obj.options.defaults && obj.options.defaults[ track._natives.type ] ) ) {
-
-      track = Popcorn.extend( {}, obj.options.defaults[ track._natives.type ], track );
-    }
-
-    if ( track._natives ) {
-      //  Supports user defined track event id
-      track._id = !track.id ? Popcorn.guid( track._natives.type ) : track.id;
-
-      //  Push track event ids into the history
-      obj.data.history.push( track._id );
-    }
-
-    track.start = Popcorn.util.toSeconds( track.start, obj.options.framerate );
-    track.end   = Popcorn.util.toSeconds( track.end, obj.options.framerate );
-
-    //  Store this definition in an array sorted by times
-    var byStart = obj.data.trackEvents.byStart,
-        byEnd = obj.data.trackEvents.byEnd,
-        idx;
-
-    for ( idx = byStart.length - 1; idx >= 0; idx-- ) {
-
-      if ( track.start >= byStart[ idx ].start ) {
-        byStart.splice( idx + 1, 0, track );
-        break;
-      }
-    }
-
-    for ( idx = byEnd.length - 1; idx >= 0; idx-- ) {
-
-      if ( track.end > byEnd[ idx ].end ) {
-        byEnd.splice( idx + 1, 0, track );
-        break;
-      }
-    }
-
-    this.timeUpdate( obj, null );
-
-    // Store references to user added trackevents in ref table
-    if ( track._id ) {
-      Popcorn.addTrackEvent.ref( obj, track );
-    }
-  };
-
-  // Internal Only - Adds track event references to the instance object's trackRefs hash table
-  Popcorn.addTrackEvent.ref = function( obj, track ) {
-    obj.data.trackRefs[ track._id ] = track;
-
-    return obj;
-  };
-
-  Popcorn.removeTrackEvent  = function( obj, trackId ) {
-
-    var historyLen = obj.data.history.length,
-        indexWasAt = 0,
-        byStart = [],
-        byEnd = [],
-        animating = [],
-        history = [];
-
-    Popcorn.forEach( obj.data.trackEvents.byStart, function( o, i, context ) {
-      // Preserve the original start/end trackEvents
-      if ( !o._id ) {
-        byStart.push( obj.data.trackEvents.byStart[i] );
-        byEnd.push( obj.data.trackEvents.byEnd[i] );
-      }
-
-      // Filter for user track events (vs system track events)
-      if ( o._id ) {
-
-        // Filter for the trackevent to remove
-        if ( o._id !== trackId ) {
-          byStart.push( obj.data.trackEvents.byStart[i] );
-          byEnd.push( obj.data.trackEvents.byEnd[i] );
-        }
-
-        //  Capture the position of the track being removed.
-        if ( o._id === trackId ) {
-          indexWasAt = i;
-          o._natives._teardown && o._natives._teardown.call( obj, o );
-        }
-      }
-
-    });
-
-    if ( obj.data.trackEvents.animating.length ) {
-      Popcorn.forEach( obj.data.trackEvents.animating, function( o, i, context ) {
-        // Preserve the original start/end trackEvents
-        if ( !o._id ) {
-          animating.push( obj.data.trackEvents.animating[i] );
-        }
-
-        // Filter for user track events (vs system track events)
-        if ( o._id ) {
-          // Filter for the trackevent to remove
-          if ( o._id !== trackId ) {
-            animating.push( obj.data.trackEvents.animating[i] );
-          }
-        }
-      });
-    }
-
-    //  Update
-    if ( indexWasAt <= obj.data.trackEvents.startIndex ) {
-      obj.data.trackEvents.startIndex--;
-    }
-
-    if ( indexWasAt <= obj.data.trackEvents.endIndex ) {
-      obj.data.trackEvents.endIndex--;
-    }
-
-    obj.data.trackEvents.byStart = byStart;
-    obj.data.trackEvents.byEnd = byEnd;
-    obj.data.trackEvents.animating = animating;
-
-    for ( var i = 0; i < historyLen; i++ ) {
-      if ( obj.data.history[ i ] !== trackId ) {
-        history.push( obj.data.history[ i ] );
-      }
-    }
-
-    // Update ordered history array
-    obj.data.history = history;
-
-    // Update track event references
-    Popcorn.removeTrackEvent.ref( obj, trackId );
-  };
-
-  // Internal Only - Removes track event references from instance object's trackRefs hash table
-  Popcorn.removeTrackEvent.ref = function( obj, trackId ) {
-    delete obj.data.trackRefs[ trackId ];
-
-    return obj;
-  };
-
-  // Return an array of track events bound to this instance object
-  Popcorn.getTrackEvents = function( obj ) {
-
-    var trackevents = [],
-      refs = obj.data.trackEvents.byStart,
-      length = refs.length,
-      idx = 0,
-      ref;
-
-    for ( ; idx < length; idx++ ) {
-      ref = refs[ idx ];
-      // Return only user attributed track event references
-      if ( ref._id ) {
-        trackevents.push( ref );
-      }
-    }
-
-    return trackevents;
-  };
-
-  // Internal Only - Returns an instance object's trackRefs hash table
-  Popcorn.getTrackEvents.ref = function( obj ) {
-    return obj.data.trackRefs;
-  };
-
-  // Return a single track event bound to this instance object
-  Popcorn.getTrackEvent = function( obj, trackId ) {
-    return obj.data.trackRefs[ trackId ];
-  };
-
-  // Internal Only - Returns an instance object's track reference by track id
-  Popcorn.getTrackEvent.ref = function( obj, trackId ) {
-    return obj.data.trackRefs[ trackId ];
-  };
-
-  Popcorn.getLastTrackEventId = function( obj ) {
-    return obj.data.history[ obj.data.history.length - 1 ];
-  };
-
-  Popcorn.timeUpdate = function( obj, event ) {
-
-    var currentTime = obj.media.currentTime,
-        previousTime = obj.data.trackEvents.previousUpdateTime,
-        tracks = obj.data.trackEvents,
-        animating = tracks.animating,
-        end = tracks.endIndex,
-        start = tracks.startIndex,
-        animIndex = 0,
-
-        registryByName = Popcorn.registryByName,
-
-        byEnd, byStart, byAnimate, natives, type;
-
-    //  Playbar advancing
-    if ( previousTime <= currentTime ) {
-
-      while ( tracks.byEnd[ end ] && tracks.byEnd[ end ].end <= currentTime ) {
-
-        byEnd = tracks.byEnd[ end ];
-        natives = byEnd._natives;
-        type = natives && natives.type;
-
-        //  If plugin does not exist on this instance, remove it
-        if ( !natives ||
-            ( !!registryByName[ type ] ||
-              !!obj[ type ] ) ) {
-
-          if ( byEnd._running === true ) {
-            byEnd._running = false;
-            natives.end.call( obj, event, byEnd );
-          }
-
-          end++;
-        } else {
-          // remove track event
-          Popcorn.removeTrackEvent( obj, byEnd._id );
-          return;
-        }
-      }
-
-      while ( tracks.byStart[ start ] && tracks.byStart[ start ].start <= currentTime ) {
-
-        byStart = tracks.byStart[ start ];
-        natives = byStart._natives;
-        type = natives && natives.type;
-
-        //  If plugin does not exist on this instance, remove it
-        if ( !natives ||
-            ( !!registryByName[ type ] ||
-              !!obj[ type ] ) ) {
-
-          if ( byStart.end > currentTime &&
-                byStart._running === false &&
-                  obj.data.disabled.indexOf( type ) === -1 ) {
-
-            byStart._running = true;
-            natives.start.call( obj, event, byStart );
-
-            // If the `frameAnimation` option is used,
-            // push the current byStart object into the `animating` cue
-            if ( obj.options.frameAnimation &&
-                ( byStart && byStart._running && byStart._natives.frame ) ) {
-
-              animating.push( byStart );
-            }
-          }
-          start++;
-        } else {
-          // remove track event
-          Popcorn.removeTrackEvent( obj, byStart._id );
-          return;
-        }
-      }
-
-      // If the `frameAnimation` option is used, iterate the animating track
-      // and execute the `frame` callback
-      if ( obj.options.frameAnimation ) {
-        while ( animIndex < animating.length ) {
-
-          byAnimate = animating[ animIndex ];
-
-          if ( !byAnimate._running ) {
-            animating.splice( animIndex, 1 );
-          } else {
-            byAnimate._natives.frame.call( obj, event, byAnimate, currentTime );
-            animIndex++;
-          }
-        }
-      }
-
-    // Playbar receding
-    } else if ( previousTime > currentTime ) {
-
-      while ( tracks.byStart[ start ] && tracks.byStart[ start ].start > currentTime ) {
-
-        byStart = tracks.byStart[ start ];
-        natives = byStart._natives;
-        type = natives && natives.type;
-
-        // if plugin does not exist on this instance, remove it
-        if ( !natives ||
-            ( !!registryByName[ type ] ||
-              !!obj[ type ] ) ) {
-
-          if ( byStart._running === true ) {
-            byStart._running = false;
-            natives.end.call( obj, event, byStart );
-          }
-          start--;
-        } else {
-          // remove track event
-          Popcorn.removeTrackEvent( obj, byStart._id );
-          return;
-        }
-      }
-
-      while ( tracks.byEnd[ end ] && tracks.byEnd[ end ].end > currentTime ) {
-
-        byEnd = tracks.byEnd[ end ];
-        natives = byEnd._natives;
-        type = natives && natives.type;
-
-        // if plugin does not exist on this instance, remove it
-        if ( !natives ||
-            ( !!registryByName[ type ] ||
-              !!obj[ type ] ) ) {
-
-          if ( byEnd.start <= currentTime &&
-                byEnd._running === false  &&
-                  obj.data.disabled.indexOf( type ) === -1 ) {
-
-            byEnd._running = true;
-            natives.start.call( obj, event, byEnd );
-
-            // If the `frameAnimation` option is used,
-            // push the current byEnd object into the `animating` cue
-            if ( obj.options.frameAnimation &&
-                  ( byEnd && byEnd._running && byEnd._natives.frame ) ) {
-
-              animating.push( byEnd );
-            }
-          }
-          end--;
-        } else {
-          // remove track event
-          Popcorn.removeTrackEvent( obj, byEnd._id );
-          return;
-        }
-      }
-
-      // If the `frameAnimation` option is used, iterate the animating track
-      // and execute the `frame` callback
-      if ( obj.options.frameAnimation ) {
-        while ( animIndex < animating.length ) {
-
-          byAnimate = animating[ animIndex ];
-
-          if ( !byAnimate._running ) {
-            animating.splice( animIndex, 1 );
-          } else {
-            byAnimate._natives.frame.call( obj, event, byAnimate, currentTime );
-            animIndex++;
-          }
-        }
-      }
-    // time bar is not moving ( video is paused )
-    }
-
-    tracks.endIndex = end;
-    tracks.startIndex = start;
-    tracks.previousUpdateTime = currentTime;
-  };
-
-  //  Map and Extend TrackEvent functions to all Popcorn instances
-  Popcorn.extend( Popcorn.p, {
-
-    getTrackEvents: function() {
-      return Popcorn.getTrackEvents.call( null, this );
-    },
-
-    getTrackEvent: function( id ) {
-      return Popcorn.getTrackEvent.call( null, this, id );
-    },
-
-    getLastTrackEventId: function() {
-      return Popcorn.getLastTrackEventId.call( null, this );
-    },
-
-    removeTrackEvent: function( id ) {
-
-      Popcorn.removeTrackEvent.call( null, this, id );
-      return this;
-    },
-
-    removePlugin: function( name ) {
-      Popcorn.removePlugin.call( null, this, name );
-      return this;
-    },
-
-    timeUpdate: function( event ) {
-      Popcorn.timeUpdate.call( null, this, event );
-      return this;
-    },
-
-    destroy: function() {
-      Popcorn.destroy.call( null, this );
-      return this;
-    }
-  });
-
-  //  Plugin manifests
-  Popcorn.manifest = {};
-  //  Plugins are registered
-  Popcorn.registry = [];
-  Popcorn.registryByName = {};
-  //  An interface for extending Popcorn
-  //  with plugin functionality
-  Popcorn.plugin = function( name, definition, manifest ) {
-
-    if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) {
-      Popcorn.error( "'" + name + "' is a protected function name" );
-      return;
-    }
-
-    //  Provides some sugar, but ultimately extends
-    //  the definition into Popcorn.p
-    var reserved = [ "start", "end" ],
-        plugin = {},
-        setup,
-        isfn = typeof definition === "function",
-        methods = [ "_setup", "_teardown", "start", "end", "frame" ];
-
-    // combines calls of two function calls into one
-    var combineFn = function( first, second ) {
-
-      first = first || Popcorn.nop;
-      second = second || Popcorn.nop;
-
-      return function() {
-        first.apply( this, arguments );
-        second.apply( this, arguments );
-      };
-    };
-
-    //  If `manifest` arg is undefined, check for manifest within the `definition` object
-    //  If no `definition.manifest`, an empty object is a sufficient fallback
-    Popcorn.manifest[ name ] = manifest = manifest || definition.manifest || {};
-
-    // apply safe, and empty default functions
-    methods.forEach(function( method ) {
-      definition[ method ] = safeTry( definition[ method ] || Popcorn.nop, name );
-    });
-
-    var pluginFn = function( setup, options ) {
-
-      if ( !options ) {
-        return this;
-      }
-
-      //  Storing the plugin natives
-      var natives = options._natives = {},
-          compose = "",
-          defaults, originalOpts, manifestOpts, mergedSetupOpts;
-
-      Popcorn.extend( natives, setup );
-
-      options._natives.type = name;
-      options._running = false;
-
-      natives.start = natives.start || natives[ "in" ];
-      natives.end = natives.end || natives[ "out" ];
-
-      // Check for previously set default options
-      defaults = this.options.defaults && this.options.defaults[ options._natives && options._natives.type ];
-
-      // default to an empty string if no effect exists
-      // split string into an array of effects
-      options.compose = options.compose && options.compose.split( " " ) || [];
-      options.effect = options.effect && options.effect.split( " " ) || [];
-
-      // join the two arrays together
-      options.compose = options.compose.concat( options.effect );
-
-      options.compose.forEach(function( composeOption ) {
-
-        // if the requested compose is garbage, throw it away
-        compose = Popcorn.compositions[ composeOption ] || {};
-
-        // extends previous functions with compose function
-        methods.forEach(function( method ) {
-          natives[ method ] = combineFn( natives[ method ], compose[ method ] );
-        });
-      });
-
-      //  Ensure a manifest object, an empty object is a sufficient fallback
-      options._natives.manifest = manifest;
-
-      //  Checks for expected properties
-      if ( !( "start" in options ) ) {
-        options.start = options[ "in" ] || 0;
-      }
-
-      if ( !( "end" in options ) ) {
-        options.end = options[ "out" ] || this.duration() || Number.MAX_VALUE;
-      }
-
-      // Merge with defaults if they exist, make sure per call is prioritized
-      mergedSetupOpts = defaults ? Popcorn.extend( {}, defaults, options ) :
-                          options;
-
-      // Resolves 239, 241, 242
-      if ( !mergedSetupOpts.target ) {
-
-        //  Sometimes the manifest may be missing entirely
-        //  or it has an options object that doesn't have a `target` property
-        manifestOpts = "options" in manifest && manifest.options;
-
-        mergedSetupOpts.target = manifestOpts && "target" in manifestOpts && manifestOpts.target;
-      }
-
-      // Trigger _setup method if exists
-      options._natives._setup && options._natives._setup.call( this, mergedSetupOpts );
-
-      // Create new track event for this instance
-      Popcorn.addTrackEvent( this, Popcorn.extend( mergedSetupOpts, options ) );
-
-      //  Future support for plugin event definitions
-      //  for all of the native events
-      Popcorn.forEach( setup, function( callback, type ) {
-
-        if ( type !== "type" ) {
-
-          if ( reserved.indexOf( type ) === -1 ) {
-
-            this.listen( type, callback );
-          }
-        }
-
-      }, this );
-
-      return this;
-    };
-
-    //  Assign new named definition
-    plugin[ name ] = function( options ) {
-      return pluginFn.call( this, isfn ? definition.call( this, options ) : definition,
-                                  options );
-    };
-
-    //  Extend Popcorn.p with new named definition
-    Popcorn.extend( Popcorn.p, plugin );
-
-    //  Push into the registry
-    var entry = {
-      fn: plugin[ name ],
-      definition: definition,
-      base: definition,
-      parents: [],
-      name: name
-    };
-    Popcorn.registry.push(
-       Popcorn.extend( plugin, entry, {
-        type: name
-      })
-    );
-    Popcorn.registryByName[ name ] = entry;
-
-    return plugin;
-  };
-
-  // Storage for plugin function errors
-  Popcorn.plugin.errors = [];
-
-  // Returns wrapped plugin function
-  function safeTry( fn, pluginName ) {
-    return function() {
-
-      //  When Popcorn.plugin.debug is true, do not suppress errors
-      if ( Popcorn.plugin.debug ) {
-        return fn.apply( this, arguments );
-      }
-
-      try {
-        return fn.apply( this, arguments );
-      } catch ( ex ) {
-
-        // Push plugin function errors into logging queue
-        Popcorn.plugin.errors.push({
-          plugin: pluginName,
-          thrown: ex,
-          source: fn.toString()
-        });
-
-        // Trigger an error that the instance can listen for
-        // and react to
-        this.trigger( "error", Popcorn.plugin.errors );
-      }
-    };
-  }
-
-  // Debug-mode flag for plugin development
-  Popcorn.plugin.debug = false;
-
-  //  removePlugin( type ) removes all tracks of that from all instances of popcorn
-  //  removePlugin( obj, type ) removes all tracks of type from obj, where obj is a single instance of popcorn
-  Popcorn.removePlugin = function( obj, name ) {
-
-    //  Check if we are removing plugin from an instance or from all of Popcorn
-    if ( !name ) {
-
-      //  Fix the order
-      name = obj;
-      obj = Popcorn.p;
-
-      if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) {
-        Popcorn.error( "'" + name + "' is a protected function name" );
-        return;
-      }
-
-      var registryLen = Popcorn.registry.length,
-          registryIdx;
-
-      // remove plugin reference from registry
-      for ( registryIdx = 0; registryIdx < registryLen; registryIdx++ ) {
-        if ( Popcorn.registry[ registryIdx ].name === name ) {
-          Popcorn.registry.splice( registryIdx, 1 );
-          delete Popcorn.registryByName[ name ];
-
-          // delete the plugin
-          delete obj[ name ];
-
-          // plugin found and removed, stop checking, we are done
-          return;
-        }
-      }
-
-    }
-
-    var byStart = obj.data.trackEvents.byStart,
-        byEnd = obj.data.trackEvents.byEnd,
-        animating = obj.data.trackEvents.animating,
-        idx, sl;
-
-    // remove all trackEvents
-    for ( idx = 0, sl = byStart.length; idx < sl; idx++ ) {
-
-      if ( ( byStart[ idx ] && byStart[ idx ]._natives && byStart[ idx ]._natives.type === name ) &&
-                ( byEnd[ idx ] && byEnd[ idx ]._natives && byEnd[ idx ]._natives.type === name ) ) {
-
-        byStart[ idx ]._natives._teardown && byStart[ idx ]._natives._teardown.call( obj, byStart[ idx ] );
-
-        byStart.splice( idx, 1 );
-        byEnd.splice( idx, 1 );
-
-        // update for loop if something removed, but keep checking
-        idx--; sl--;
-        if ( obj.data.trackEvents.startIndex <= idx ) {
-          obj.data.trackEvents.startIndex--;
-          obj.data.trackEvents.endIndex--;
-        }
-      }
-    }
-
-    //remove all animating events
-    for ( idx = 0, sl = animating.length; idx < sl; idx++ ) {
-
-      if ( animating[ idx ] && animating[ idx ]._natives && animating[ idx ]._natives.type === name ) {
-
-        animating.splice( idx, 1 );
-
-        // update for loop if something removed, but keep checking
-        idx--; sl--;
-      }
-    }
-
-  };
-
-  Popcorn.compositions = {};
-
-  //  Plugin inheritance
-  Popcorn.compose = function( name, definition, manifest ) {
-
-    //  If `manifest` arg is undefined, check for manifest within the `definition` object
-    //  If no `definition.manifest`, an empty object is a sufficient fallback
-    Popcorn.manifest[ name ] = manifest = manifest || definition.manifest || {};
-
-    // register the effect by name
-    Popcorn.compositions[ name ] = definition;
-  };
-
-  Popcorn.plugin.effect = Popcorn.effect = Popcorn.compose;
-
-  // stores parsers keyed on filetype
-  Popcorn.parsers = {};
-
-  // An interface for extending Popcorn
-  // with parser functionality
-  Popcorn.parser = function( name, type, definition ) {
-
-    if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) {
-      Popcorn.error( "'" + name + "' is a protected function name" );
-      return;
-    }
-
-    // fixes parameters for overloaded function call
-    if ( typeof type === "function" && !definition ) {
-      definition = type;
-      type = "";
-    }
-
-    if ( typeof definition !== "function" || typeof type !== "string" ) {
-      return;
-    }
-
-    // Provides some sugar, but ultimately extends
-    // the definition into Popcorn.p
-
-    var natives = Popcorn.events.all,
-        parseFn,
-        parser = {};
-
-    parseFn = function( filename, callback ) {
-
-      if ( !filename ) {
-        return this;
-      }
-
-      var that = this;
-
-      Popcorn.xhr({
-        url: filename,
-        dataType: type,
-        success: function( data ) {
-
-          var tracksObject = definition( data ),
-              tracksData,
-              tracksDataLen,
-              tracksDef,
-              idx = 0;
-
-          tracksData = tracksObject.data || [];
-          tracksDataLen = tracksData.length;
-          tracksDef = null;
-
-          //  If no tracks to process, return immediately
-          if ( !tracksDataLen ) {
-            return;
-          }
-
-          //  Create tracks out of parsed object
-          for ( ; idx < tracksDataLen; idx++ ) {
-
-            tracksDef = tracksData[ idx ];
-
-            for ( var key in tracksDef ) {
-
-              if ( hasOwn.call( tracksDef, key ) && !!that[ key ] ) {
-
-                that[ key ]( tracksDef[ key ] );
-              }
-            }
-          }
-          if ( callback ) {
-            callback();
-          }
-        }
-      });
-
-      return this;
-    };
-
-    // Assign new named definition
-    parser[ name ] = parseFn;
-
-    // Extend Popcorn.p with new named definition
-    Popcorn.extend( Popcorn.p, parser );
-
-    // keys the function name by filetype extension
-    //Popcorn.parsers[ name ] = true;
-
-    return parser;
-  };
-
-  Popcorn.player = function( name, player ) {
-
-    player = player || {};
-
-    var playerFn = function( target, src, options ) {
-
-      options = options || {};
-
-      // List of events
-      var date = new Date() / 1000,
-          baselineTime = date,
-          currentTime = 0,
-          volume = 1,
-          muted = false,
-          events = {},
-
-          // The container div of the resource
-          container = document.getElementById( rIdExp.exec( target ) && rIdExp.exec( target )[ 2 ] ) ||
-                        document.getElementById( target ) ||
-                          target,
-          basePlayer = {},
-          timeout,
-          popcorn;
-
-      // copies a div into the media object
-      for( var val in container ) {
-
-        if ( typeof container[ val ] === "object" ) {
-
-          basePlayer[ val ] = container[ val ];
-        } else if ( typeof container[ val ] === "function" ) {
-
-          basePlayer[ val ] = (function( value ) {
-
-            return function() {
-
-              return container[ value ].apply( container, arguments );
-            };
-          }( val ));
-        } else {
-
-          Popcorn.player.defineProperty( basePlayer, val, {
-            get: (function( value ) {
-
-              return function() {
-
-                return container[ value ];
-              };
-            }( val )),
-            set: Popcorn.nop,
-            configurable: true
-          });
-        }
-      }
-
-      var timeupdate = function() {
-
-        date = new Date() / 1000;
-
-        if ( !basePlayer.paused ) {
-
-          basePlayer.currentTime = basePlayer.currentTime + ( date - baselineTime );
-          basePlayer.dispatchEvent( "timeupdate" );
-          timeout = setTimeout( timeupdate, 10 );
-        }
-
-        baselineTime = date;
-      };
-
-      basePlayer.play = function() {
-
-        this.paused = false;
-
-        if ( basePlayer.readyState >= 4 ) {
-
-          baselineTime = new Date() / 1000;
-          basePlayer.dispatchEvent( "play" );
-          timeupdate();
-        }
-      };
-
-      basePlayer.pause = function() {
-
-        this.paused = true;
-        basePlayer.dispatchEvent( "pause" );
-      };
-
-      Popcorn.player.defineProperty( basePlayer, "currentTime", {
-        get: function() {
-
-          return currentTime;
-        },
-        set: function( val ) {
-
-          // make sure val is a number
-          currentTime = +val;
-          basePlayer.dispatchEvent( "timeupdate" );
-          return currentTime;
-        },
-        configurable: true
-      });
-
-      Popcorn.player.defineProperty( basePlayer, "volume", {
-        get: function() {
-
-          return volume;
-        },
-        set: function( val ) {
-
-          // make sure val is a number
-          volume = +val;
-          basePlayer.dispatchEvent( "volumechange" );
-          return volume;
-        },
-        configurable: true
-      });
-
-      Popcorn.player.defineProperty( basePlayer, "muted", {
-        get: function() {
-
-          return muted;
-        },
-        set: function( val ) {
-
-          // make sure val is a number
-          muted = +val;
-          basePlayer.dispatchEvent( "volumechange" );
-          return muted;
-        },
-        configurable: true
-      });
-
-      // Adds an event listener to the object
-      basePlayer.addEventListener = function( evtName, fn ) {
-
-        if ( !events[ evtName ] ) {
-
-          events[ evtName ] = [];
-        }
-
-        events[ evtName ].push( fn );
-        return fn;
-      };
-
-      // Can take event object or simple string
-      basePlayer.dispatchEvent = function( oEvent ) {
-
-        var evt,
-            self = this,
-            eventInterface,
-            eventName = oEvent.type;
-
-        // A string was passed, create event object
-        if ( !eventName ) {
-
-          eventName = oEvent;
-          eventInterface  = Popcorn.events.getInterface( eventName );
-
-          if ( eventInterface ) {
-
-            evt = document.createEvent( eventInterface );
-            evt.initEvent( eventName, true, true, window, 1 );
-          }
-        }
-
-        Popcorn.forEach( events[ eventName ], function( val ) {
-
-          val.call( self, evt, self );
-        });
-      };
-
-      // Attempt to get src from playerFn parameter
-      basePlayer.src = src || "";
-      basePlayer.readyState = 0;
-      basePlayer.duration = 0;
-      basePlayer.paused = true;
-      basePlayer.ended = 0;
-
-      if ( player._setup ) {
-
-        player._setup.call( basePlayer, options );
-      } else {
-
-        // there is no setup, which means there is nothing to load
-        basePlayer.readyState = 4;
-        basePlayer.dispatchEvent( "load" );
-        basePlayer.dispatchEvent( "loadeddata" );
-      }
-
-      // when a custom player is loaded, load basePlayer state into custom player
-      basePlayer.addEventListener( "load", function() {
-
-        // if a player is not ready before currentTime is called, this will set it after it is ready
-        basePlayer.currentTime = currentTime;
-
-        // same as above with volume and muted
-        basePlayer.volume = volume;
-        basePlayer.muted = muted;
-      });
-
-      basePlayer.addEventListener( "loadeddata", function() {
-
-        // if play was called before player ready, start playing video
-        !basePlayer.paused && basePlayer.play();
-      });
-
-      popcorn = new Popcorn.p.init( basePlayer, options );
-
-      return popcorn;
-    };
-
-    Popcorn[ name ] = Popcorn[ name ] || playerFn;
-  };
-
-  Popcorn.player.defineProperty = Object.defineProperty || function( object, description, options ) {
-
-    object.__defineGetter__( description, options.get || Popcorn.nop );
-    object.__defineSetter__( description, options.set || Popcorn.nop );
-  };
-
-  //  Cache references to reused RegExps
-  var rparams = /\?/,
-  //  XHR Setup object
-  setup = {
-    url: "",
-    data: "",
-    dataType: "",
-    success: Popcorn.nop,
-    type: "GET",
-    async: true,
-    xhr: function() {
-      return new global.XMLHttpRequest();
-    }
-  };
-
-  Popcorn.xhr = function( options ) {
-
-    options.dataType = options.dataType && options.dataType.toLowerCase() || null;
-
-    if ( options.dataType &&
-         ( options.dataType === "jsonp" || options.dataType === "script" ) ) {
-
-      Popcorn.xhr.getJSONP(
-        options.url,
-        options.success,
-        options.dataType === "script"
-      );
-      return;
-    }
-
-    var settings = Popcorn.extend( {}, setup, options );
-
-    //  Create new XMLHttpRequest object
-    settings.ajax  = settings.xhr();
-
-    if ( settings.ajax ) {
-
-      if ( settings.type === "GET" && settings.data ) {
-
-        //  append query string
-        settings.url += ( rparams.test( settings.url ) ? "&" : "?" ) + settings.data;
-
-        //  Garbage collect and reset settings.data
-        settings.data = null;
-      }
-
-
-      settings.ajax.open( settings.type, settings.url, settings.async );
-      settings.ajax.send( settings.data || null );
-
-      return Popcorn.xhr.httpData( settings );
-    }
-  };
-
-
-  Popcorn.xhr.httpData = function( settings ) {
-
-    var data, json = null;
-
-    settings.ajax.onreadystatechange = function() {
-
-      if ( settings.ajax.readyState === 4 ) {
-
-        try {
-          json = JSON.parse( settings.ajax.responseText );
-        } catch( e ) {
-          //suppress
-        }
-
-        data = {
-          xml: settings.ajax.responseXML,
-          text: settings.ajax.responseText,
-          json: json
-        };
-
-        //  If a dataType was specified, return that type of data
-        if ( settings.dataType ) {
-          data = data[ settings.dataType ];
-        }
-
-
-        settings.success.call( settings.ajax, data );
-
-      }
-    };
-    return data;
-  };
-
-  Popcorn.xhr.getJSONP = function( url, success, isScript ) {
-
-    var head = document.head || document.getElementsByTagName( "head" )[ 0 ] || document.documentElement,
-      script = document.createElement( "script" ),
-      paramStr = url.split( "?" )[ 1 ],
-      isFired = false,
-      params = [],
-      callback, parts, callparam;
-
-    if ( paramStr && !isScript ) {
-      params = paramStr.split( "&" );
-    }
-
-    if ( params.length ) {
-      parts = params[ params.length - 1 ].split( "=" );
-    }
-
-    callback = params.length ? ( parts[ 1 ] ? parts[ 1 ] : parts[ 0 ]  ) : "jsonp";
-
-    if ( !paramStr && !isScript ) {
-      url += "?callback=" + callback;
-    }
-
-    if ( callback && !isScript ) {
-
-      //  If a callback name already exists
-      if ( !!window[ callback ] ) {
-        //  Create a new unique callback name
-        callback = Popcorn.guid( callback );
-      }
-
-      //  Define the JSONP success callback globally
-      window[ callback ] = function( data ) {
-        // Fire success callbacks
-        success && success( data );
-        isFired = true;
-      };
-
-      //  Replace callback param and callback name
-      url = url.replace( parts.join( "=" ), parts[ 0 ] + "=" + callback );
-    }
-
-    script.onload = function() {
-
-      //  Handling remote script loading callbacks
-      if ( isScript ) {
-        //  getScript
-        success && success();
-      }
-
-      //  Executing for JSONP requests
-      if ( isFired ) {
-        //  Garbage collect the callback
-        delete window[ callback ];
-      }
-      //  Garbage collect the script resource
-      head.removeChild( script );
-    };
-
-    script.src = url;
-
-    head.insertBefore( script, head.firstChild );
-
-    return;
-  };
-
-  Popcorn.getJSONP = Popcorn.xhr.getJSONP;
-
-  Popcorn.getScript = Popcorn.xhr.getScript = function( url, success ) {
-
-    return Popcorn.xhr.getJSONP( url, success, true );
-  };
-
-  Popcorn.util = {
-    // Simple function to parse a timestamp into seconds
-    // Acceptable formats are:
-    // HH:MM:SS.MMM
-    // HH:MM:SS;FF
-    // Hours and minutes are optional. They default to 0
-    toSeconds: function( timeStr, framerate ) {
-      // Hours and minutes are optional
-      // Seconds must be specified
-      // Seconds can be followed by milliseconds OR by the frame information
-      var validTimeFormat = /^([0-9]+:){0,2}[0-9]+([.;][0-9]+)?$/,
-          errorMessage = "Invalid time format",
-          digitPairs, lastIndex, lastPair, firstPair,
-          frameInfo, frameTime;
-
-      if ( typeof timeStr === "number" ) {
-        return timeStr;
-      }
-
-      if ( typeof timeStr === "string" &&
-            !validTimeFormat.test( timeStr ) ) {
-        Popcorn.error( errorMessage );
-      }
-
-      digitPairs = timeStr.split( ":" );
-      lastIndex = digitPairs.length - 1;
-      lastPair = digitPairs[ lastIndex ];
-
-      // Fix last element:
-      if ( lastPair.indexOf( ";" ) > -1 ) {
-
-        frameInfo = lastPair.split( ";" );
-        frameTime = 0;
-
-        if ( framerate && ( typeof framerate === "number" ) ) {
-          frameTime = parseFloat( frameInfo[ 1 ], 10 ) / framerate;
-        }
-
-        digitPairs[ lastIndex ] = parseInt( frameInfo[ 0 ], 10 ) + frameTime;
-      }
-
-      firstPair = digitPairs[ 0 ];
-
-      return {
-
-        1: parseFloat( firstPair, 10 ),
-
-        2: ( parseInt( firstPair, 10 ) * 60 ) +
-              parseFloat( digitPairs[ 1 ], 10 ),
-
-        3: ( parseInt( firstPair, 10 ) * 3600 ) +
-            ( parseInt( digitPairs[ 1 ], 10 ) * 60 ) +
-              parseFloat( digitPairs[ 2 ], 10 )
-
-      }[ digitPairs.length || 1 ];
-    }
-  };
-
-
-  // Initialize locale data
-  // Based on http://en.wikipedia.org/wiki/Language_localisation#Language_tags_and_codes
-  function initLocale( arg ) {
-
-    var locale = typeof arg === "string" ? arg : [ arg.language, arg.region ].join( "-" ),
-        parts = locale.split( "-" );
-
-    // Setup locale data table
-    return {
-      iso6391: locale,
-      language: parts[ 0 ] || "",
-      region: parts[ 1 ] || ""
-    };
-  }
-
-  // Declare locale data table
-  var localeData = initLocale( global.navigator.userLanguage || global.navigator.language );
-
-  Popcorn.locale = {
-
-    // Popcorn.locale.get()
-    // returns reference to privately
-    // defined localeData
-    get: function() {
-      return localeData;
-    },
-
-    // Popcorn.locale.set( string|object );
-    set: function( arg ) {
-
-      localeData = initLocale( arg );
-
-      Popcorn.locale.broadcast();
-
-      return localeData;
-    },
-
-    // Popcorn.locale.broadcast( type )
-    // Sends events to all popcorn media instances that are
-    // listening for locale events
-    broadcast: function( type ) {
-
-      var instances = Popcorn.instances,
-          length = instances.length,
-          idx = 0,
-          instance;
-
-      type = type || "locale:changed";
-
-      // Iterate all current instances
-      for ( ; idx < length; idx++ ) {
-        instance = instances[ idx ];
-
-        // For those instances with locale event listeners,
-        // trigger a locale change event
-        if ( type in instance.data.events  ) {
-          instance.trigger( type );
-        }
-      }
-    }
-  };
-
-  // alias for exec function
-  Popcorn.p.cue = Popcorn.p.exec;
-
-  function getItems() {
-
-    var item,
-        list = [];
-
-    if ( Object.keys ) {
-      list = Object.keys( Popcorn.p );
-    } else {
-
-      for ( item in Popcorn.p ) {
-        if ( hasOwn.call( Popcorn.p, item ) ) {
-          list.push( item );
-        }
-      }
-    }
-
-    return list.join( "," ).toLowerCase().split( ",");
-  }
-
-  //  Protected API methods
-  Popcorn.protect = {
-    natives: getItems() 
-  };
-
-  //  Exposes Popcorn to global context
-  global.Popcorn = Popcorn;
-
-})(window, window.document);