bumped popcorn version. bugslaying-after-r417-merge
authorhamidouk
Thu, 08 Dec 2011 12:29:04 +0100
branchbugslaying-after-r417-merge
changeset 429 e84a7100cc3f
parent 428 9246dce433f8
child 430 c0b529ae20d2
bumped popcorn version.
src/js/libs/popcorn.js
--- a/src/js/libs/popcorn.js	Thu Dec 08 11:23:08 2011 +0100
+++ b/src/js/libs/popcorn.js	Thu Dec 08 12:29:04 2011 +0100
@@ -10,7 +10,7 @@
           "addTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId " +
           "timeUpdate plugin removePlugin compose effect parser xhr getJSONP getScript" ).split(/\s+/);
 
-    while( methods.length ) {
+    while ( methods.length ) {
       global.Popcorn[ methods.shift() ] = function() {};
     }
     return;
@@ -58,6 +58,61 @@
       };
   }()),
 
+  refresh = function( obj ) {
+    var currentTime = obj.media.currentTime,
+      animation = obj.options.frameAnimation,
+      disabled = obj.data.disabled,
+      tracks = obj.data.trackEvents,
+      animating = tracks.animating,
+      start = tracks.startIndex,
+      registryByName = Popcorn.registryByName,
+      animIndex = 0,
+      byStart, natives, type;
+
+    start = Math.min( start + 1, tracks.byStart.length - 2 );
+
+    while ( start > 0 && tracks.byStart[ start ] ) {
+
+      byStart = tracks.byStart[ start ];
+      natives = byStart._natives;
+      type = natives && natives.type;
+
+      if ( !natives ||
+          ( !!registryByName[ type ] || !!obj[ type ] ) ) {
+
+        if ( ( byStart.start <= currentTime && byStart.end > currentTime ) &&
+                disabled.indexOf( type ) === -1 ) {
+
+          if ( !byStart._running ) {
+            byStart._running = true;
+            natives.start.call( obj, null, byStart );
+
+            // if the 'frameAnimation' option is used,
+            // push the current byStart object into the `animating` cue
+            if ( animation &&
+                ( byStart && byStart._running && byStart.natives.frame ) ) {
+
+              natives.frame.call( obj, null, byStart, currentTime );
+            }
+          }
+        } else if ( byStart._running === true ) {
+
+          byStart._running = false;
+          natives.end.call( obj, null, byStart );
+
+          if ( animation && byStart._natives.frame ) {
+            animIndex = animating.indexOf( byStart );
+            if ( animIndex >= 0 ) {
+              animating.splice( animIndex, 1 );
+            }
+          }
+        }
+      }
+
+      start--;
+    }
+  },
+
   //  Declare constructor
   //  Returns an instance object.
   Popcorn = function( entity, options ) {
@@ -147,6 +202,9 @@
 
       this.data = {
 
+        // Executed by either timeupdate event or in rAF loop
+        timeUpdate: Popcorn.nop,
+
         // Allows disabling a plugin per instance
         disabled: [],
 
@@ -188,7 +246,7 @@
       //  Wrap true ready check
       var isReady = function( that ) {
 
-        var duration, videoDurationPlus, animate;
+        var duration, videoDurationPlus;
 
         if ( that.media.readyState >= 2 ) {
           //  Adding padding to the front and end of the arrays
@@ -208,25 +266,25 @@
             //  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 () {
+            that.data.timeUpdate = function () {
 
               Popcorn.timeUpdate( that, {} );
 
               that.trigger( "timeupdate" );
 
-              requestAnimFrame( animate );
+              !that.isDestroyed && requestAnimFrame( that.data.timeUpdate );
             };
 
-            requestAnimFrame( animate );
+            !that.isDestroyed && requestAnimFrame( that.data.timeUpdate );
 
           } else {
 
-            that.data.timeUpdateFunction = function( event ) {
+            that.data.timeUpdate = function( event ) {
               Popcorn.timeUpdate( that, event );
             };
 
             if ( !that.isDestroyed ) {
-              that.media.addEventListener( "timeupdate", that.data.timeUpdateFunction, false );
+              that.media.addEventListener( "timeupdate", that.data.timeUpdate, false );
             }
           }
         } else {
@@ -357,6 +415,8 @@
         disabled.push( plugin );
       }
 
+      refresh( instance );
+
       return instance;
     },
     enable: function( instance, plugin ) {
@@ -368,6 +428,8 @@
         disabled.splice( index, 1 );
       }
 
+      refresh( instance );
+
       return instance;
     },
     destroy: function( instance ) {
@@ -384,7 +446,7 @@
       }
 
       if ( !instance.isDestroyed ) {
-        instance.media.removeEventListener( "timeupdate", instance.data.timeUpdateFunction, false );
+        instance.data.timeUpdate && instance.media.removeEventListener( "timeupdate", instance.data.timeUpdate, false );
         instance.isDestroyed = true;
       }
     }
@@ -780,25 +842,60 @@
     //  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 );
+        startIndex, endIndex,
+        currentTime;
+
+    for ( startIndex = byStart.length - 1; startIndex >= 0; startIndex-- ) {
+
+      if ( track.start >= byStart[ startIndex ].start ) {
+        byStart.splice( startIndex + 1, 0, track );
+        break;
+      }
+    }
+
+    for ( endIndex = byEnd.length - 1; endIndex >= 0; endIndex-- ) {
+
+      if ( track.end > byEnd[ endIndex ].end ) {
+        byEnd.splice( endIndex + 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;
+    // Display track event immediately if it's enabled and current
+    if ( track._natives &&
+        ( !!Popcorn.registryByName[ track._natives.type ] || !!obj[ track._natives.type ] ) ) {
+
+      currentTime = obj.media.currentTime;
+      if ( track.end > currentTime &&
+        track.start <= currentTime &&
+        obj.data.disabled.indexOf( track._natives.type ) === -1 ) {
+
+        track._running = true;
+        track._natives.start.call( obj, null, track );
+
+        if ( obj.options.frameAnimation &&
+          track._natives.frame ) {
+
+          obj.data.trackEvents.animating.push( track );
+          track._natives.frame.call( obj, null, track, currentTime );
+        }
       }
     }
 
-    this.timeUpdate( obj, null );
+    // update startIndex and endIndex
+    if ( startIndex <= obj.data.trackEvents.startIndex &&
+      track.start <= obj.data.trackEvents.previousUpdateTime ) {
+
+      obj.data.trackEvents.startIndex++;
+    }
+
+    if ( endIndex <= obj.data.trackEvents.endIndex &&
+      track.end < obj.data.trackEvents.previousUpdateTime ) {
+
+      obj.data.trackEvents.endIndex++;
+    }
+
+    this.timeUpdate( obj, null, true );
 
     // Store references to user added trackevents in ref table
     if ( track._id ) {
@@ -1209,6 +1306,19 @@
       natives.start = natives.start || natives[ "in" ];
       natives.end = natives.end || natives[ "out" ];
 
+      // extend teardown to always call end if running
+      natives._teardown = combineFn(function() {
+
+        var args = slice.call( arguments );
+
+        // end function signature is not the same as teardown,
+        // put null on the front of arguments for the event parameter
+        args.unshift( null );
+
+        // only call end if event is running
+        args[ 1 ]._running && natives.end.apply( this, args );
+      }, natives._teardown );
+
       // Check for previously set default options
       defaults = this.options.defaults && this.options.defaults[ options._natives && options._natives.type ];
 
@@ -1364,6 +1474,7 @@
         if ( Popcorn.registry[ registryIdx ].name === name ) {
           Popcorn.registry.splice( registryIdx, 1 );
           delete Popcorn.registryByName[ name ];
+          delete Popcorn.manifest[ name ];
 
           // delete the plugin
           delete obj[ name ];
@@ -1554,10 +1665,18 @@
 
           basePlayer[ val ] = (function( value ) {
 
-            return function() {
-
-              return container[ value ].apply( container, arguments );
-            };
+            // this is a stupid ugly kludgy hack in honour of Safari
+            // in Safari a NodeList is a function, not an object
+            if ( "length" in container[ value ] && !container[ value ].call ) {
+
+              return container[ value ];
+            } else {
+
+              return function() {
+
+                return container[ value ].apply( container, arguments );
+              };
+            }
           }( val ));
         } else {
 
@@ -1797,7 +1916,8 @@
 
   Popcorn.xhr.httpData = function( settings ) {
 
-    var data, json = null;
+    var data, json = null,
+        parser, xml = null;
 
     settings.ajax.onreadystatechange = function() {
 
@@ -1815,6 +1935,22 @@
           json: json
         };
 
+        // Normalize: data.xml is non-null in IE9 regardless of if response is valid xml
+        if ( !data.xml || !data.xml.documentElement ) {
+          data.xml = null;
+
+          try {
+            parser = new DOMParser();
+            xml = parser.parseFromString( settings.ajax.responseText, "text/xml" );
+
+            if ( !xml.getElementsByTagName( "parsererror" ).length ) {
+              data.xml = xml;
+            }
+          } catch ( e ) {
+            // data.xml remains null
+          }
+        }
+
         //  If a dataType was specified, return that type of data
         if ( settings.dataType ) {
           data = data[ settings.dataType ];
@@ -2046,7 +2182,7 @@
 
   //  Protected API methods
   Popcorn.protect = {
-    natives: getItems() 
+    natives: getItems()
   };
 
   //  Exposes Popcorn to global context