2014-07-17 16:45:12 +02:00
/ * ! S W F M i n i - a S W F O b j e c t 2 . 2 c u t d o w n v e r s i o n f o r w e b s h i m s
*
* based on SWFObject v2 . 2 < http : //code.google.com/p/swfobject/>
is released under the MIT License < http : //www.opensource.org/licenses/mit-license.php>
* /
var swfmini = function ( ) {
var wasRemoved = function ( ) { webshims . error ( 'This method was removed from swfmini' ) ; } ;
var UNDEF = "undefined" ,
OBJECT = "object" ,
webshims = window . webshims ,
SHOCKWAVE _FLASH = "Shockwave Flash" ,
SHOCKWAVE _FLASH _AX = "ShockwaveFlash.ShockwaveFlash" ,
FLASH _MIME _TYPE = "application/x-shockwave-flash" ,
win = window ,
doc = document ,
nav = navigator ,
plugin = false ,
domLoadFnArr = [ main ] ,
isDomLoaded = false ,
autoHideShow = true ,
/ * C e n t r a l i z e d f u n c t i o n f o r b r o w s e r f e a t u r e d e t e c t i o n
- User agent string detection is only used when no good alternative is possible
- Is executed directly for optimal performance
* /
ua = function ( ) {
var w3cdom = typeof doc . getElementById != UNDEF && typeof doc . getElementsByTagName != UNDEF && typeof doc . createElement != UNDEF ,
u = nav . userAgent . toLowerCase ( ) ,
p = nav . platform . toLowerCase ( ) ,
windows = p ? /win/ . test ( p ) : /win/ . test ( u ) ,
mac = p ? /mac/ . test ( p ) : /mac/ . test ( u ) ,
webkit = /webkit/ . test ( u ) ? parseFloat ( u . replace ( /^.*webkit\/(\d+(\.\d+)?).*$/ , "$1" ) ) : false , // returns either the webkit version or false if not webkit
ie = ! + "\v1" , // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
playerVersion = [ 0 , 0 , 0 ] ,
d = null ;
if ( typeof nav . plugins != UNDEF && typeof nav . plugins [ SHOCKWAVE _FLASH ] == OBJECT ) {
d = nav . plugins [ SHOCKWAVE _FLASH ] . description ;
if ( d && ! ( typeof nav . mimeTypes != UNDEF && nav . mimeTypes [ FLASH _MIME _TYPE ] && ! nav . mimeTypes [ FLASH _MIME _TYPE ] . enabledPlugin ) ) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
plugin = true ;
ie = false ; // cascaded feature detection for Internet Explorer
d = d . replace ( /^.*\s+(\S+\s+\S+$)/ , "$1" ) ;
playerVersion [ 0 ] = parseInt ( d . replace ( /^(.*)\..*$/ , "$1" ) , 10 ) ;
playerVersion [ 1 ] = parseInt ( d . replace ( /^.*\.(.*)\s.*$/ , "$1" ) , 10 ) ;
playerVersion [ 2 ] = /[a-zA-Z]/ . test ( d ) ? parseInt ( d . replace ( /^.*[a-zA-Z]+(.*)$/ , "$1" ) , 10 ) : 0 ;
}
}
else if ( typeof win . ActiveXObject != UNDEF ) {
try {
var a = new ActiveXObject ( SHOCKWAVE _FLASH _AX ) ;
if ( a ) { // a will return null when ActiveX is disabled
d = a . GetVariable ( "$version" ) ;
if ( d ) {
ie = true ; // cascaded feature detection for Internet Explorer
d = d . split ( " " ) [ 1 ] . split ( "," ) ;
playerVersion = [ parseInt ( d [ 0 ] , 10 ) , parseInt ( d [ 1 ] , 10 ) , parseInt ( d [ 2 ] , 10 ) ] ;
}
}
}
catch ( e ) { }
}
return { w3 : w3cdom , pv : playerVersion , wk : webkit , ie : ie , win : windows , mac : mac } ;
} ( ) ;
function callDomLoadFunctions ( ) {
if ( isDomLoaded ) { return ; }
isDomLoaded = true ;
var dl = domLoadFnArr . length ;
for ( var i = 0 ; i < dl ; i ++ ) {
domLoadFnArr [ i ] ( ) ;
}
}
function addDomLoadEvent ( fn ) {
if ( isDomLoaded ) {
fn ( ) ;
}
else {
domLoadFnArr [ domLoadFnArr . length ] = fn ; // Array.push() is only available in IE5.5+
}
}
/ * M a i n f u n c t i o n
- Will preferably execute onDomLoad , otherwise onload ( as a fallback )
* /
function main ( ) {
if ( plugin ) {
testPlayerVersion ( ) ;
}
}
/ * D e t e c t t h e F l a s h P l a y e r v e r s i o n f o r n o n - I n t e r n e t E x p l o r e r b r o w s e r s
- Detecting the plug - in version via the object element is more precise than using the plugins collection item ' s description :
a . Both release and build numbers can be detected
b . Avoid wrong descriptions by corrupt installers provided by Adobe
c . Avoid wrong descriptions by multiple Flash Player entries in the plugin Array , caused by incorrect browser imports
- Disadvantage of this method is that it depends on the availability of the DOM , while the plugins collection is immediately available
* /
function testPlayerVersion ( ) {
var b = doc . getElementsByTagName ( "body" ) [ 0 ] ;
var o = createElement ( OBJECT ) ;
o . setAttribute ( "type" , FLASH _MIME _TYPE ) ;
var t = b . appendChild ( o ) ;
if ( t ) {
var counter = 0 ;
( function ( ) {
if ( typeof t . GetVariable != UNDEF ) {
var d = t . GetVariable ( "$version" ) ;
if ( d ) {
d = d . split ( " " ) [ 1 ] . split ( "," ) ;
ua . pv = [ parseInt ( d [ 0 ] , 10 ) , parseInt ( d [ 1 ] , 10 ) , parseInt ( d [ 2 ] , 10 ) ] ;
}
}
else if ( counter < 10 ) {
counter ++ ;
setTimeout ( arguments . callee , 10 ) ;
return ;
}
b . removeChild ( o ) ;
t = null ;
} ) ( ) ;
}
}
function createElement ( el ) {
return doc . createElement ( el ) ;
}
/ * F l a s h P l a y e r a n d S W F c o n t e n t v e r s i o n m a t c h i n g
* /
function hasPlayerVersion ( rv ) {
var pv = ua . pv , v = rv . split ( "." ) ;
v [ 0 ] = parseInt ( v [ 0 ] , 10 ) ;
v [ 1 ] = parseInt ( v [ 1 ] , 10 ) || 0 ; // supports short notation, e.g. "9" instead of "9.0.0"
v [ 2 ] = parseInt ( v [ 2 ] , 10 ) || 0 ;
return ( pv [ 0 ] > v [ 0 ] || ( pv [ 0 ] == v [ 0 ] && pv [ 1 ] > v [ 1 ] ) || ( pv [ 0 ] == v [ 0 ] && pv [ 1 ] == v [ 1 ] && pv [ 2 ] >= v [ 2 ] ) ) ? true : false ;
}
webshims . ready ( 'DOM' , callDomLoadFunctions ) ;
webshims . loader . addModule ( 'swfmini-embed' , { d : [ 'swfmini' ] } ) ;
var loadEmbed = hasPlayerVersion ( '9.0.0' ) ?
function ( ) {
webshims . loader . loadList ( [ 'swfmini-embed' ] ) ;
return true ;
} :
webshims . $ . noop
;
if ( ! webshims . support . mediaelement ) {
loadEmbed ( ) ;
} else {
webshims . ready ( 'WINDOWLOAD' , loadEmbed ) ;
}
return {
/ * P u b l i c A P I
- Reference : http : //code.google.com/p/swfobject/wiki/documentation
* /
registerObject : wasRemoved ,
getObjectById : wasRemoved ,
embedSWF : function ( swfUrlStr , replaceElemIdStr , widthStr , heightStr , swfVersionStr , xiSwfUrlStr , flashvarsObj , parObj , attObj , callbackFn ) {
var args = arguments ;
if ( loadEmbed ( ) ) {
webshims . ready ( 'swfmini-embed' , function ( ) {
swfmini . embedSWF . apply ( swfmini , args ) ;
} ) ;
} else if ( callbackFn ) {
callbackFn ( { success : false , id : replaceElemIdStr } ) ;
}
} ,
switchOffAutoHideShow : function ( ) {
autoHideShow = false ;
} ,
ua : ua ,
getFlashPlayerVersion : function ( ) {
return { major : ua . pv [ 0 ] , minor : ua . pv [ 1 ] , release : ua . pv [ 2 ] } ;
} ,
hasFlashPlayerVersion : hasPlayerVersion ,
createSWF : function ( attObj , parObj , replaceElemIdStr ) {
if ( ua . w3 ) {
return createSWF ( attObj , parObj , replaceElemIdStr ) ;
}
else {
return undefined ;
}
} ,
showExpressInstall : wasRemoved ,
removeSWF : wasRemoved ,
createCSS : wasRemoved ,
addDomLoadEvent : addDomLoadEvent ,
addLoadEvent : wasRemoved ,
// For internal usage only
expressInstallCallback : wasRemoved
} ;
} ( ) ;
webshims . isReady ( 'swfmini' , true ) ;
; ( function ( webshims ) {
"use strict" ;
var support = webshims . support ;
var hasNative = support . mediaelement ;
var supportsLoop = false ;
var bugs = webshims . bugs ;
var swfType = 'mediaelement-jaris' ;
var loadSwf = function ( ) {
webshims . ready ( swfType , function ( ) {
if ( ! webshims . mediaelement . createSWF ) {
webshims . mediaelement . loadSwf = true ;
webshims . reTest ( [ swfType ] , hasNative ) ;
}
} ) ;
} ;
var wsCfg = webshims . cfg ;
var options = wsCfg . mediaelement ;
var isIE = navigator . userAgent . indexOf ( 'MSIE' ) != - 1 ;
if ( ! options ) {
webshims . error ( "mediaelement wasn't implemented but loaded" ) ;
return ;
}
if ( hasNative ) {
var videoElem = document . createElement ( 'video' ) ;
support . videoBuffered = ( 'buffered' in videoElem ) ;
support . mediaDefaultMuted = ( 'defaultMuted' in videoElem ) ;
supportsLoop = ( 'loop' in videoElem ) ;
support . mediaLoop = supportsLoop ;
webshims . capturingEvents ( [ 'play' , 'playing' , 'waiting' , 'paused' , 'ended' , 'durationchange' , 'loadedmetadata' , 'canplay' , 'volumechange' ] ) ;
if ( ! support . videoBuffered || ! supportsLoop || ( ! support . mediaDefaultMuted && isIE && 'ActiveXObject' in window ) ) {
webshims . addPolyfill ( 'mediaelement-native-fix' , {
d : [ 'dom-support' ]
} ) ;
webshims . loader . loadList ( [ 'mediaelement-native-fix' ] ) ;
}
}
if ( support . track && ! bugs . track ) {
( function ( ) {
if ( ! bugs . track ) {
if ( window . VTTCue && ! window . TextTrackCue ) {
window . TextTrackCue = window . VTTCue ;
} else if ( ! window . VTTCue ) {
window . VTTCue = window . TextTrackCue ;
}
try {
new VTTCue ( 2 , 3 , '' ) ;
} catch ( e ) {
bugs . track = true ;
}
}
} ) ( ) ;
}
2014-09-03 00:57:03 +02:00
if ( window . CanvasRenderingContext2D && CanvasRenderingContext2D . prototype ) {
CanvasRenderingContext2D . prototype . wsImageComplete = function ( cb ) {
cb . call ( this , this ) ;
} ;
}
2014-07-17 16:45:12 +02:00
webshims . register ( 'mediaelement-core' , function ( $ , webshims , window , document , undefined , options ) {
2014-08-01 01:38:33 +02:00
var hasSwf = swfmini . hasFlashPlayerVersion ( '11.3' ) ;
2014-07-17 16:45:12 +02:00
var mediaelement = webshims . mediaelement ;
2014-09-03 00:57:03 +02:00
var allowYtLoading = false ;
2014-07-17 16:45:12 +02:00
mediaelement . parseRtmp = function ( data ) {
var src = data . src . split ( '://' ) ;
var paths = src [ 1 ] . split ( '/' ) ;
var i , len , found ;
data . server = src [ 0 ] + '://' + paths [ 0 ] + '/' ;
data . streamId = [ ] ;
for ( i = 1 , len = paths . length ; i < len ; i ++ ) {
if ( ! found && paths [ i ] . indexOf ( ':' ) !== - 1 ) {
paths [ i ] = paths [ i ] . split ( ':' ) [ 1 ] ;
found = true ;
}
if ( ! found ) {
data . server += paths [ i ] + '/' ;
} else {
data . streamId . push ( paths [ i ] ) ;
}
}
if ( ! data . streamId . length ) {
webshims . error ( 'Could not parse rtmp url' ) ;
}
data . streamId = data . streamId . join ( '/' ) ;
} ;
var getSrcObj = function ( elem , nodeName ) {
elem = $ ( elem ) ;
var src = { src : elem . attr ( 'src' ) || '' , elem : elem , srcProp : elem . prop ( 'src' ) } ;
var tmp ;
if ( ! src . src ) { return src ; }
tmp = elem . attr ( 'data-server' ) ;
if ( tmp != null ) {
src . server = tmp ;
}
tmp = elem . attr ( 'type' ) || elem . attr ( 'data-type' ) ;
if ( tmp ) {
src . type = tmp ;
src . container = $ . trim ( tmp . split ( ';' ) [ 0 ] ) ;
} else {
if ( ! nodeName ) {
nodeName = elem [ 0 ] . nodeName . toLowerCase ( ) ;
if ( nodeName == 'source' ) {
nodeName = ( elem . closest ( 'video, audio' ) [ 0 ] || { nodeName : 'video' } ) . nodeName . toLowerCase ( ) ;
}
}
if ( src . server ) {
src . type = nodeName + '/rtmp' ;
src . container = nodeName + '/rtmp' ;
} else {
tmp = mediaelement . getTypeForSrc ( src . src , nodeName , src ) ;
if ( tmp ) {
src . type = tmp ;
src . container = tmp ;
}
}
}
tmp = elem . attr ( 'media' ) ;
if ( tmp ) {
src . media = tmp ;
}
if ( src . type == 'audio/rtmp' || src . type == 'video/rtmp' ) {
if ( src . server ) {
src . streamId = src . src ;
} else {
mediaelement . parseRtmp ( src ) ;
}
}
return src ;
} ;
var hasYt = ! hasSwf && ( 'postMessage' in window ) && hasNative ;
var loadTrackUi = function ( ) {
if ( loadTrackUi . loaded ) { return ; }
loadTrackUi . loaded = true ;
if ( ! options . noAutoTrack ) {
webshims . ready ( 'WINDOWLOAD' , function ( ) {
loadThird ( ) ;
webshims . loader . loadList ( [ 'track-ui' ] ) ;
} ) ;
}
} ;
var loadYt = ( function ( ) {
var loaded ;
return function ( ) {
if ( loaded || ! hasYt ) { return ; }
loaded = true ;
2014-09-03 00:57:03 +02:00
if ( allowYtLoading ) {
webshims . loader . loadScript ( "https://www.youtube.com/player_api" ) ;
}
2014-07-17 16:45:12 +02:00
$ ( function ( ) {
webshims . _polyfill ( [ "mediaelement-yt" ] ) ;
} ) ;
} ;
} ) ( ) ;
var loadThird = function ( ) {
if ( hasSwf ) {
loadSwf ( ) ;
} else {
loadYt ( ) ;
}
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
webshims . addPolyfill ( 'mediaelement-yt' , {
test : ! hasYt ,
d : [ 'dom-support' ]
} ) ;
mediaelement . mimeTypes = {
audio : {
//ogm shouldn´ t be used!
'audio/ogg' : [ 'ogg' , 'oga' , 'ogm' ] ,
'audio/ogg;codecs="opus"' : 'opus' ,
'audio/mpeg' : [ 'mp2' , 'mp3' , 'mpga' , 'mpega' ] ,
'audio/mp4' : [ 'mp4' , 'mpg4' , 'm4r' , 'm4a' , 'm4p' , 'm4b' , 'aac' ] ,
'audio/wav' : [ 'wav' ] ,
'audio/3gpp' : [ '3gp' , '3gpp' ] ,
'audio/webm' : [ 'webm' ] ,
'audio/fla' : [ 'flv' , 'f4a' , 'fla' ] ,
'application/x-mpegURL' : [ 'm3u8' , 'm3u' ]
} ,
video : {
//ogm shouldn´ t be used!
'video/ogg' : [ 'ogg' , 'ogv' , 'ogm' ] ,
'video/mpeg' : [ 'mpg' , 'mpeg' , 'mpe' ] ,
'video/mp4' : [ 'mp4' , 'mpg4' , 'm4v' ] ,
'video/quicktime' : [ 'mov' , 'qt' ] ,
'video/x-msvideo' : [ 'avi' ] ,
'video/x-ms-asf' : [ 'asf' , 'asx' ] ,
'video/flv' : [ 'flv' , 'f4v' ] ,
'video/3gpp' : [ '3gp' , '3gpp' ] ,
'video/webm' : [ 'webm' ] ,
'application/x-mpegURL' : [ 'm3u8' , 'm3u' ] ,
'video/MP2T' : [ 'ts' ]
}
}
;
mediaelement . mimeTypes . source = $ . extend ( { } , mediaelement . mimeTypes . audio , mediaelement . mimeTypes . video ) ;
mediaelement . getTypeForSrc = function ( src , nodeName ) {
if ( src . indexOf ( 'youtube.com/watch?' ) != - 1 || src . indexOf ( 'youtube.com/v/' ) != - 1 ) {
return 'video/youtube' ;
}
2014-08-01 01:38:33 +02:00
if ( ! src . indexOf ( 'mediastream:' ) || ! src . indexOf ( 'blob:http' ) ) {
return 'usermedia' ;
}
if ( ! src . indexOf ( 'webshimstream' ) ) {
return 'jarisplayer/stream' ;
}
if ( ! src . indexOf ( 'rtmp' ) ) {
2014-07-17 16:45:12 +02:00
return nodeName + '/rtmp' ;
}
src = src . split ( '?' ) [ 0 ] . split ( '#' ) [ 0 ] . split ( '.' ) ;
src = src [ src . length - 1 ] ;
var mt ;
$ . each ( mediaelement . mimeTypes [ nodeName ] , function ( mimeType , exts ) {
if ( exts . indexOf ( src ) !== - 1 ) {
mt = mimeType ;
return false ;
}
} ) ;
return mt ;
} ;
2014-08-01 01:38:33 +02:00
mediaelement . srces = function ( mediaElem ) {
var srces = [ ] ;
2014-07-17 16:45:12 +02:00
mediaElem = $ ( mediaElem ) ;
2014-08-01 01:38:33 +02:00
var nodeName = mediaElem [ 0 ] . nodeName . toLowerCase ( ) ;
var src = getSrcObj ( mediaElem , nodeName ) ;
if ( ! src . src ) {
$ ( 'source' , mediaElem ) . each ( function ( ) {
src = getSrcObj ( this , nodeName ) ;
if ( src . src ) { srces . push ( src ) ; }
} ) ;
2014-07-17 16:45:12 +02:00
} else {
2014-08-01 01:38:33 +02:00
srces . push ( src ) ;
2014-07-17 16:45:12 +02:00
}
2014-08-01 01:38:33 +02:00
return srces ;
2014-07-17 16:45:12 +02:00
} ;
2014-08-01 01:38:33 +02:00
mediaelement . swfMimeTypes = [ 'video/3gpp' , 'video/x-msvideo' , 'video/quicktime' , 'video/x-m4v' , 'video/mp4' , 'video/m4p' , 'video/x-flv' , 'video/flv' , 'audio/mpeg' , 'audio/aac' , 'audio/mp4' , 'audio/x-m4a' , 'audio/m4a' , 'audio/mp3' , 'audio/x-fla' , 'audio/fla' , 'youtube/flv' , 'video/jarisplayer' , 'jarisplayer/jarisplayer' , 'jarisplayer/stream' , 'video/youtube' , 'video/rtmp' , 'audio/rtmp' ] ;
2014-07-17 16:45:12 +02:00
mediaelement . canThirdPlaySrces = function ( mediaElem , srces ) {
var ret = '' ;
if ( hasSwf || hasYt ) {
mediaElem = $ ( mediaElem ) ;
srces = srces || mediaelement . srces ( mediaElem ) ;
$ . each ( srces , function ( i , src ) {
if ( src . container && src . src && ( ( hasSwf && mediaelement . swfMimeTypes . indexOf ( src . container ) != - 1 ) || ( hasYt && src . container == 'video/youtube' ) ) ) {
ret = src ;
return false ;
}
} ) ;
}
return ret ;
} ;
var nativeCanPlayType = { } ;
mediaelement . canNativePlaySrces = function ( mediaElem , srces ) {
var ret = '' ;
if ( hasNative ) {
mediaElem = $ ( mediaElem ) ;
var nodeName = ( mediaElem [ 0 ] . nodeName || '' ) . toLowerCase ( ) ;
var nativeCanPlay = ( nativeCanPlayType [ nodeName ] || { prop : { _supvalue : false } } ) . prop . _supvalue || mediaElem [ 0 ] . canPlayType ;
if ( ! nativeCanPlay ) { return ret ; }
srces = srces || mediaelement . srces ( mediaElem ) ;
$ . each ( srces , function ( i , src ) {
2014-08-01 01:38:33 +02:00
if ( src . type == 'usermedia' || ( src . type && nativeCanPlay . call ( mediaElem [ 0 ] , src . type ) ) ) {
2014-07-17 16:45:12 +02:00
ret = src ;
return false ;
}
} ) ;
}
return ret ;
} ;
var emptyType = ( /^\s*application\/octet\-stream\s*$/i ) ;
var getRemoveEmptyType = function ( ) {
var ret = emptyType . test ( $ . attr ( this , 'type' ) || '' ) ;
if ( ret ) {
$ ( this ) . removeAttr ( 'type' ) ;
}
return ret ;
} ;
mediaelement . setError = function ( elem , message ) {
if ( $ ( 'source' , elem ) . filter ( getRemoveEmptyType ) . length ) {
webshims . error ( '"application/octet-stream" is a useless mimetype for audio/video. Please change this attribute.' ) ;
try {
$ ( elem ) . mediaLoad ( ) ;
} catch ( er ) { }
} else {
if ( ! message ) {
message = "can't play sources" ;
}
$ ( elem ) . pause ( ) . data ( 'mediaerror' , message ) ;
webshims . error ( 'mediaelementError: ' + message + '. Run the following line in your console to get more info: webshim.mediaelement.loadDebugger();' ) ;
setTimeout ( function ( ) {
if ( $ ( elem ) . data ( 'mediaerror' ) ) {
$ ( elem ) . addClass ( 'media-error' ) . trigger ( 'mediaerror' ) ;
}
} , 1 ) ;
}
} ;
var handleThird = ( function ( ) {
var requested ;
var readyType = hasSwf ? swfType : 'mediaelement-yt' ;
return function ( mediaElem , ret , data ) {
//readd to ready
webshims . ready ( readyType , function ( ) {
if ( mediaelement . createSWF && $ ( mediaElem ) . parent ( ) [ 0 ] ) {
mediaelement . createSWF ( mediaElem , ret , data ) ;
} else if ( ! requested ) {
requested = true ;
loadThird ( ) ;
handleThird ( mediaElem , ret , data ) ;
}
} ) ;
if ( ! requested && hasYt && ! mediaelement . createSWF ) {
2014-09-03 00:57:03 +02:00
allowYtLoading = true ;
2014-07-17 16:45:12 +02:00
loadYt ( ) ;
}
} ;
} ) ( ) ;
var activate = {
native : function ( elem , src , data ) {
if ( data && data . isActive == 'third' ) {
mediaelement . setActive ( elem , 'html5' , data ) ;
}
} ,
third : handleThird
} ;
var stepSources = function ( elem , data , srces ) {
var i , src ;
var testOrder = [ { test : 'canNativePlaySrces' , activate : 'native' } , { test : 'canThirdPlaySrces' , activate : 'third' } ] ;
if ( options . preferFlash || ( data && data . isActive == 'third' ) ) {
testOrder . reverse ( ) ;
}
for ( i = 0 ; i < 2 ; i ++ ) {
src = mediaelement [ testOrder [ i ] . test ] ( elem , srces ) ;
if ( src ) {
activate [ testOrder [ i ] . activate ] ( elem , src , data ) ;
break ;
}
}
if ( ! src ) {
mediaelement . setError ( elem , false ) ;
if ( data && data . isActive == 'third' ) {
mediaelement . setActive ( elem , 'html5' , data ) ;
}
}
} ;
var stopParent = /^(?:embed|object|datalist|picture)$/i ;
var selectSource = function ( elem , data ) {
var baseData = webshims . data ( elem , 'mediaelementBase' ) || webshims . data ( elem , 'mediaelementBase' , { } ) ;
var _srces = mediaelement . srces ( elem ) ;
var parent = elem . parentNode ;
clearTimeout ( baseData . loadTimer ) ;
$ ( elem ) . removeClass ( 'media-error' ) ;
$ . data ( elem , 'mediaerror' , false ) ;
if ( ! _srces . length || ! parent || parent . nodeType != 1 || stopParent . test ( parent . nodeName || '' ) ) { return ; }
data = data || webshims . data ( elem , 'mediaelement' ) ;
if ( mediaelement . sortMedia ) {
_srces . sort ( mediaelement . sortMedia ) ;
}
stepSources ( elem , data , _srces ) ;
} ;
mediaelement . selectSource = selectSource ;
$ ( document ) . on ( 'ended' , function ( e ) {
var data = webshims . data ( e . target , 'mediaelement' ) ;
if ( supportsLoop && ( ! data || data . isActive == 'html5' ) && ! $ . prop ( e . target , 'loop' ) ) { return ; }
setTimeout ( function ( ) {
if ( $ . prop ( e . target , 'paused' ) || ! $ . prop ( e . target , 'loop' ) ) { return ; }
$ ( e . target ) . prop ( 'currentTime' , 0 ) . play ( ) ;
} ) ;
} ) ;
var handleMedia = false ;
var initMediaElements = function ( ) {
var testFixMedia = function ( ) {
if ( webshims . implement ( this , 'mediaelement' ) ) {
selectSource ( this ) ;
if ( ! support . mediaDefaultMuted && $ . attr ( this , 'muted' ) != null ) {
$ . prop ( this , 'muted' , true ) ;
}
}
} ;
webshims . ready ( 'dom-support' , function ( ) {
handleMedia = true ;
if ( ! supportsLoop ) {
webshims . defineNodeNamesBooleanProperty ( [ 'audio' , 'video' ] , 'loop' ) ;
}
[ 'audio' , 'video' ] . forEach ( function ( nodeName ) {
var supLoad ;
supLoad = webshims . defineNodeNameProperty ( nodeName , 'load' , {
prop : {
value : function ( ) {
var data = webshims . data ( this , 'mediaelement' ) ;
selectSource ( this , data ) ;
if ( hasNative && ( ! data || data . isActive == 'html5' ) && supLoad . prop . _supvalue ) {
supLoad . prop . _supvalue . apply ( this , arguments ) ;
}
if ( ! loadTrackUi . loaded && this . querySelector ( 'track' ) ) {
loadTrackUi ( ) ;
}
$ ( this ) . triggerHandler ( 'wsmediareload' ) ;
}
}
} ) ;
nativeCanPlayType [ nodeName ] = webshims . defineNodeNameProperty ( nodeName , 'canPlayType' , {
prop : {
value : function ( type ) {
var ret = '' ;
if ( hasNative && nativeCanPlayType [ nodeName ] . prop . _supvalue ) {
ret = nativeCanPlayType [ nodeName ] . prop . _supvalue . call ( this , type ) ;
if ( ret == 'no' ) {
ret = '' ;
}
}
if ( ! ret && hasSwf ) {
type = $ . trim ( ( type || '' ) . split ( ';' ) [ 0 ] ) ;
if ( mediaelement . swfMimeTypes . indexOf ( type ) != - 1 ) {
ret = 'maybe' ;
}
}
if ( ! ret && hasYt && type == 'video/youtube' ) {
ret = 'maybe' ;
}
return ret ;
}
}
} ) ;
} ) ;
webshims . onNodeNamesPropertyModify ( [ 'audio' , 'video' ] , [ 'src' , 'poster' ] , {
set : function ( ) {
var elem = this ;
var baseData = webshims . data ( elem , 'mediaelementBase' ) || webshims . data ( elem , 'mediaelementBase' , { } ) ;
clearTimeout ( baseData . loadTimer ) ;
baseData . loadTimer = setTimeout ( function ( ) {
selectSource ( elem ) ;
elem = null ;
} , 9 ) ;
}
} ) ;
webshims . addReady ( function ( context , insertedElement ) {
var media = $ ( 'video, audio' , context )
. add ( insertedElement . filter ( 'video, audio' ) )
. each ( testFixMedia )
;
if ( ! loadTrackUi . loaded && $ ( 'track' , media ) . length ) {
loadTrackUi ( ) ;
}
media = null ;
} ) ;
} ) ;
if ( hasNative && ! handleMedia ) {
webshims . addReady ( function ( context , insertedElement ) {
if ( ! handleMedia ) {
$ ( 'video, audio' , context )
. add ( insertedElement . filter ( 'video, audio' ) )
. each ( function ( ) {
if ( ! mediaelement . canNativePlaySrces ( this ) ) {
2014-09-03 00:57:03 +02:00
allowYtLoading = true ;
2014-07-17 16:45:12 +02:00
loadThird ( ) ;
handleMedia = true ;
return false ;
}
} )
;
}
} ) ;
}
} ;
mediaelement . loadDebugger = function ( ) {
webshims . ready ( 'dom-support' , function ( ) {
webshims . loader . loadScript ( 'mediaelement-debug' ) ;
} ) ;
} ;
if ( ( { noCombo : 1 , media : 1 } ) [ webshims . cfg . debug ] ) {
$ ( document ) . on ( 'mediaerror' , function ( e ) {
mediaelement . loadDebugger ( ) ;
} ) ;
}
2014-09-03 00:57:03 +02:00
2014-07-17 16:45:12 +02:00
//set native implementation ready, before swf api is retested
if ( hasNative ) {
webshims . isReady ( 'mediaelement-core' , true ) ;
initMediaElements ( ) ;
webshims . ready ( 'WINDOWLOAD mediaelement' , loadThird ) ;
} else {
webshims . ready ( swfType , initMediaElements ) ;
}
webshims . ready ( 'track' , loadTrackUi ) ;
2014-07-20 02:43:13 +02:00
if ( document . readyState == 'complete' ) {
webshims . isReady ( 'WINDOWLOAD' , true ) ;
}
2014-07-17 16:45:12 +02:00
} ) ;
} ) ( webshims ) ;
; webshims . register ( 'track' , function ( $ , webshims , window , document , undefined ) {
"use strict" ;
var mediaelement = webshims . mediaelement ;
var id = new Date ( ) . getTime ( ) ;
//descriptions are not really shown, but they are inserted into the dom
var showTracks = { subtitles : 1 , captions : 1 , descriptions : 1 } ;
var dummyTrack = $ ( '<track />' ) ;
var support = webshims . support ;
var supportTrackMod = support . ES5 && support . objectAccessor ;
var createEventTarget = function ( obj ) {
var eventList = { } ;
obj . addEventListener = function ( name , fn ) {
if ( eventList [ name ] ) {
webshims . error ( 'always use $.on to the shimed event: ' + name + ' already bound fn was: ' + eventList [ name ] + ' your fn was: ' + fn ) ;
}
eventList [ name ] = fn ;
} ;
obj . removeEventListener = function ( name , fn ) {
if ( eventList [ name ] && eventList [ name ] != fn ) {
webshims . error ( 'always use $.on/$.off to the shimed event: ' + name + ' already bound fn was: ' + eventList [ name ] + ' your fn was: ' + fn ) ;
}
if ( eventList [ name ] ) {
delete eventList [ name ] ;
}
} ;
return obj ;
} ;
var cueListProto = {
getCueById : function ( id ) {
var cue = null ;
for ( var i = 0 , len = this . length ; i < len ; i ++ ) {
if ( this [ i ] . id === id ) {
cue = this [ i ] ;
break ;
}
}
return cue ;
}
} ;
var numericModes = {
0 : 'disabled' ,
1 : 'hidden' ,
2 : 'showing'
} ;
var textTrackProto = {
shimActiveCues : null ,
_shimActiveCues : null ,
activeCues : null ,
cues : null ,
kind : 'subtitles' ,
label : '' ,
language : '' ,
id : '' ,
mode : 'disabled' ,
oncuechange : null ,
toString : function ( ) {
return "[object TextTrack]" ;
} ,
addCue : function ( cue ) {
if ( ! this . cues ) {
this . cues = mediaelement . createCueList ( ) ;
} else {
var lastCue = this . cues [ this . cues . length - 1 ] ;
if ( lastCue && lastCue . startTime > cue . startTime ) {
webshims . error ( "cue startTime higher than previous cue's startTime" ) ;
2014-09-03 00:57:03 +02:00
return ;
2014-07-17 16:45:12 +02:00
}
}
2014-09-03 00:57:03 +02:00
if ( cue . startTime >= cue . endTime ) {
webshim . error ( 'startTime >= endTime of cue: ' + cue . text ) ;
}
2014-07-17 16:45:12 +02:00
if ( cue . track && cue . track . removeCue ) {
cue . track . removeCue ( cue ) ;
}
cue . track = this ;
this . cues . push ( cue ) ;
} ,
//ToDo: make it more dynamic
removeCue : function ( cue ) {
var cues = this . cues || [ ] ;
var i = 0 ;
var len = cues . length ;
if ( cue . track != this ) {
webshims . error ( "cue not part of track" ) ;
return ;
}
for ( ; i < len ; i ++ ) {
if ( cues [ i ] === cue ) {
cues . splice ( i , 1 ) ;
cue . track = null ;
break ;
}
}
if ( cue . track ) {
webshims . error ( "cue not part of track" ) ;
return ;
}
} / * ,
DISABLED : 'disabled' ,
OFF : 'disabled' ,
HIDDEN : 'hidden' ,
SHOWING : 'showing' ,
ERROR : 3 ,
LOADED : 2 ,
LOADING : 1 ,
NONE : 0 * /
} ;
var copyProps = [ 'kind' , 'label' , 'srclang' ] ;
var copyName = { srclang : 'language' } ;
var updateMediaTrackList = function ( baseData , trackList ) {
2014-11-05 21:25:18 +01:00
var i , len ;
var callChange = false ;
2014-07-17 16:45:12 +02:00
var removed = [ ] ;
var added = [ ] ;
var newTracks = [ ] ;
if ( ! baseData ) {
baseData = webshims . data ( this , 'mediaelementBase' ) || webshims . data ( this , 'mediaelementBase' , { } ) ;
}
if ( ! trackList ) {
baseData . blockTrackListUpdate = true ;
trackList = $ . prop ( this , 'textTracks' ) ;
baseData . blockTrackListUpdate = false ;
}
clearTimeout ( baseData . updateTrackListTimer ) ;
$ ( 'track' , this ) . each ( function ( ) {
var track = $ . prop ( this , 'track' ) ;
newTracks . push ( track ) ;
if ( trackList . indexOf ( track ) == - 1 ) {
added . push ( track ) ;
}
} ) ;
if ( baseData . scriptedTextTracks ) {
for ( i = 0 , len = baseData . scriptedTextTracks . length ; i < len ; i ++ ) {
newTracks . push ( baseData . scriptedTextTracks [ i ] ) ;
if ( trackList . indexOf ( baseData . scriptedTextTracks [ i ] ) == - 1 ) {
added . push ( baseData . scriptedTextTracks [ i ] ) ;
}
}
}
for ( i = 0 , len = trackList . length ; i < len ; i ++ ) {
if ( newTracks . indexOf ( trackList [ i ] ) == - 1 ) {
removed . push ( trackList [ i ] ) ;
}
}
2014-11-05 21:25:18 +01:00
2014-07-17 16:45:12 +02:00
if ( removed . length || added . length ) {
trackList . splice ( 0 ) ;
for ( i = 0 , len = newTracks . length ; i < len ; i ++ ) {
trackList . push ( newTracks [ i ] ) ;
2014-11-05 21:25:18 +01:00
2014-07-17 16:45:12 +02:00
}
for ( i = 0 , len = removed . length ; i < len ; i ++ ) {
$ ( [ trackList ] ) . triggerHandler ( $ . Event ( { type : 'removetrack' , track : removed [ i ] } ) ) ;
}
for ( i = 0 , len = added . length ; i < len ; i ++ ) {
$ ( [ trackList ] ) . triggerHandler ( $ . Event ( { type : 'addtrack' , track : added [ i ] } ) ) ;
}
2014-09-03 00:57:03 +02:00
//todo: remove
2014-07-17 16:45:12 +02:00
if ( baseData . scriptedTextTracks || removed . length ) {
$ ( this ) . triggerHandler ( 'updatetrackdisplay' ) ;
}
}
2014-11-05 21:25:18 +01:00
for ( i = 0 , len = trackList . length ; i < len ; i ++ ) {
if ( trackList [ i ] . _ _wsmode != trackList [ i ] . mode ) {
trackList [ i ] . _ _wsmode = trackList [ i ] . mode ;
callChange = true ;
}
}
if ( callChange ) {
$ ( [ trackList ] ) . triggerHandler ( 'change' ) ;
}
2014-07-17 16:45:12 +02:00
} ;
var refreshTrack = function ( track , trackData ) {
if ( ! trackData ) {
trackData = webshims . data ( track , 'trackData' ) ;
}
if ( trackData && ! trackData . isTriggering ) {
trackData . isTriggering = true ;
setTimeout ( function ( ) {
$ ( track ) . closest ( 'audio, video' ) . triggerHandler ( 'updatetrackdisplay' ) ;
trackData . isTriggering = false ;
2014-09-03 00:57:03 +02:00
} , 9 ) ;
2014-07-17 16:45:12 +02:00
}
} ;
var isDefaultTrack = ( function ( ) {
var defaultKinds = {
subtitles : {
subtitles : 1 ,
captions : 1
} ,
descriptions : { descriptions : 1 } ,
chapters : { chapters : 1 }
} ;
defaultKinds . captions = defaultKinds . subtitles ;
return function ( track ) {
var kind , firstDefaultTrack ;
var isDefault = $ . prop ( track , 'default' ) ;
if ( isDefault && ( kind = $ . prop ( track , 'kind' ) ) != 'metadata' ) {
firstDefaultTrack = $ ( track )
. parent ( )
. find ( 'track[default]' )
. filter ( function ( ) {
return ! ! ( defaultKinds [ kind ] [ $ . prop ( this , 'kind' ) ] ) ;
} ) [ 0 ]
;
if ( firstDefaultTrack != track ) {
isDefault = false ;
webshims . error ( 'more than one default track of a specific kind detected. Fall back to default = false' ) ;
}
}
return isDefault ;
} ;
} ) ( ) ;
var emptyDiv = $ ( '<div />' ) [ 0 ] ;
function VTTCue ( startTime , endTime , text ) {
if ( arguments . length != 3 ) {
webshims . error ( "wrong arguments.length for VTTCue.constructor" ) ;
}
this . startTime = startTime ;
this . endTime = endTime ;
this . text = text ;
this . onenter = null ;
this . onexit = null ;
this . pauseOnExit = false ;
this . track = null ;
this . id = null ;
this . getCueAsHTML = ( function ( ) {
var lastText = "" ;
var parsedText = "" ;
var fragment ;
return function ( ) {
var i , len ;
if ( ! fragment ) {
fragment = document . createDocumentFragment ( ) ;
}
if ( lastText != this . text ) {
lastText = this . text ;
parsedText = mediaelement . parseCueTextToHTML ( lastText ) ;
emptyDiv . innerHTML = parsedText ;
for ( i = 0 , len = emptyDiv . childNodes . length ; i < len ; i ++ ) {
fragment . appendChild ( emptyDiv . childNodes [ i ] . cloneNode ( true ) ) ;
}
}
return fragment . cloneNode ( true ) ;
} ;
} ) ( ) ;
}
window . VTTCue = VTTCue ;
window . TextTrackCue = function ( ) {
webshims . error ( "Use VTTCue constructor instead of abstract TextTrackCue constructor." ) ;
VTTCue . apply ( this , arguments ) ;
} ;
window . TextTrackCue . prototype = VTTCue . prototype ;
mediaelement . createCueList = function ( ) {
return $ . extend ( [ ] , cueListProto ) ;
} ;
mediaelement . parseCueTextToHTML = ( function ( ) {
var tagSplits = /(<\/?[^>]+>)/ig ;
var allowedTags = /^(?:c|v|ruby|rt|b|i|u)/ ;
var regEnd = /\<\s*\// ;
var addToTemplate = function ( localName , attribute , tag , html ) {
var ret ;
if ( regEnd . test ( html ) ) {
ret = '</' + localName + '>' ;
} else {
tag . splice ( 0 , 1 ) ;
ret = '<' + localName + ' ' + attribute + '="' + ( tag . join ( ' ' ) . replace ( /\"/g , '"' ) ) + '">' ;
}
return ret ;
} ;
var replacer = function ( html ) {
var tag = html . replace ( /[<\/>]+/ig , "" ) . split ( /[\s\.]+/ ) ;
if ( tag [ 0 ] ) {
tag [ 0 ] = tag [ 0 ] . toLowerCase ( ) ;
if ( allowedTags . test ( tag [ 0 ] ) ) {
if ( tag [ 0 ] == 'c' ) {
html = addToTemplate ( 'span' , 'class' , tag , html ) ;
} else if ( tag [ 0 ] == 'v' ) {
html = addToTemplate ( 'q' , 'title' , tag , html ) ;
}
} else {
html = "" ;
}
}
return html ;
} ;
return function ( cueText ) {
return cueText . replace ( tagSplits , replacer ) ;
} ;
} ) ( ) ;
var mapTtmlToVtt = function ( i ) {
var content = i + '' ;
var begin = this . getAttribute ( 'begin' ) || '' ;
var end = this . getAttribute ( 'end' ) || '' ;
var text = $ . trim ( $ . text ( this ) ) ;
if ( ! /\./ . test ( begin ) ) {
begin += '.000' ;
}
if ( ! /\./ . test ( end ) ) {
end += '.000' ;
}
content += '\n' ;
content += begin + ' --> ' + end + '\n' ;
content += text ;
return content ;
} ;
var ttmlTextToVTT = function ( ttml ) {
ttml = $ . parseXML ( ttml ) || [ ] ;
return $ ( ttml ) . find ( '[begin][end]' ) . map ( mapTtmlToVtt ) . get ( ) . join ( '\n\n' ) || '' ;
} ;
var loadingTracks = 0 ;
mediaelement . loadTextTrack = function ( mediaelem , track , trackData , _default ) {
var loadEvents = 'play playing loadedmetadata loadstart' ;
var obj = trackData . track ;
var load = function ( ) {
var error , ajax , createAjax ;
var isDisabled = obj . mode == 'disabled' ;
var videoState = ! ! ( $ . prop ( mediaelem , 'readyState' ) > 0 || $ . prop ( mediaelem , 'networkState' ) == 2 || ! $ . prop ( mediaelem , 'paused' ) ) ;
var src = ( ! isDisabled || videoState ) && ( $ . attr ( track , 'src' ) && $ . prop ( track , 'src' ) ) ;
if ( src ) {
$ ( mediaelem ) . off ( loadEvents , load ) . off ( 'updatetrackdisplay' , load ) ;
if ( ! trackData . readyState ) {
error = function ( ) {
loadingTracks -- ;
trackData . readyState = 3 ;
obj . cues = null ;
obj . activeCues = obj . shimActiveCues = obj . _shimActiveCues = null ;
$ ( track ) . triggerHandler ( 'error' ) ;
} ;
trackData . readyState = 1 ;
try {
obj . cues = mediaelement . createCueList ( ) ;
obj . activeCues = obj . shimActiveCues = obj . _shimActiveCues = mediaelement . createCueList ( ) ;
loadingTracks ++ ;
createAjax = function ( ) {
ajax = $ . ajax ( {
dataType : 'text' ,
url : src ,
success : function ( text ) {
loadingTracks -- ;
var contentType = ajax . getResponseHeader ( 'content-type' ) || '' ;
if ( ! contentType . indexOf ( 'application/xml' ) ) {
text = ttmlTextToVTT ( text ) ;
} else if ( contentType . indexOf ( 'text/vtt' ) ) {
webshims . error ( 'set the mime-type of your WebVTT files to text/vtt. see: http://dev.w3.org/html5/webvtt/#text/vtt' ) ;
}
mediaelement . parseCaptions ( text , obj , function ( cues ) {
if ( cues && 'length' in cues ) {
trackData . readyState = 2 ;
$ ( track ) . triggerHandler ( 'load' ) ;
$ ( mediaelem ) . triggerHandler ( 'updatetrackdisplay' ) ;
} else {
error ( ) ;
}
} ) ;
} ,
error : error
} ) ;
} ;
2014-09-03 00:57:03 +02:00
if ( isDisabled ) {
setTimeout ( createAjax , loadingTracks * 2 ) ;
2014-07-17 16:45:12 +02:00
} else {
2014-09-03 00:57:03 +02:00
createAjax ( ) ;
2014-07-17 16:45:12 +02:00
}
} catch ( er ) {
error ( ) ;
webshims . error ( er ) ;
}
}
}
} ;
trackData . readyState = 0 ;
obj . shimActiveCues = null ;
obj . _shimActiveCues = null ;
obj . activeCues = null ;
obj . cues = null ;
$ ( mediaelem ) . on ( loadEvents , load ) ;
if ( _default ) {
obj . mode = showTracks [ obj . kind ] ? 'showing' : 'hidden' ;
load ( ) ;
} else {
$ ( mediaelem ) . on ( 'updatetrackdisplay' , load ) ;
}
} ;
mediaelement . createTextTrack = function ( mediaelem , track ) {
var obj , trackData ;
if ( track . nodeName ) {
trackData = webshims . data ( track , 'trackData' ) ;
if ( trackData ) {
refreshTrack ( track , trackData ) ;
obj = trackData . track ;
}
}
if ( ! obj ) {
obj = createEventTarget ( webshims . objectCreate ( textTrackProto ) ) ;
if ( ! supportTrackMod ) {
copyProps . forEach ( function ( copyProp ) {
var prop = $ . prop ( track , copyProp ) ;
if ( prop ) {
obj [ copyName [ copyProp ] || copyProp ] = prop ;
}
} ) ;
}
if ( track . nodeName ) {
if ( supportTrackMod ) {
copyProps . forEach ( function ( copyProp ) {
webshims . defineProperty ( obj , copyName [ copyProp ] || copyProp , {
get : function ( ) {
return $ . prop ( track , copyProp ) ;
}
} ) ;
} ) ;
}
obj . id = $ ( track ) . prop ( 'id' ) ;
trackData = webshims . data ( track , 'trackData' , { track : obj } ) ;
mediaelement . loadTextTrack ( mediaelem , track , trackData , isDefaultTrack ( track ) ) ;
} else {
if ( supportTrackMod ) {
copyProps . forEach ( function ( copyProp ) {
webshims . defineProperty ( obj , copyName [ copyProp ] || copyProp , {
value : track [ copyProp ] ,
writeable : false
} ) ;
} ) ;
}
obj . cues = mediaelement . createCueList ( ) ;
obj . activeCues = obj . _shimActiveCues = obj . shimActiveCues = mediaelement . createCueList ( ) ;
obj . mode = 'hidden' ;
obj . readyState = 2 ;
}
if ( obj . kind == 'subtitles' && ! obj . language ) {
webshims . error ( 'you must provide a language for track in subtitles state' ) ;
}
obj . _ _wsmode = obj . mode ;
2014-08-01 01:38:33 +02:00
webshims . defineProperty ( obj , '_wsUpdateMode' , {
value : function ( ) {
$ ( mediaelem ) . triggerHandler ( 'updatetrackdisplay' ) ;
} ,
enumerable : false
} ) ;
2014-07-17 16:45:12 +02:00
}
return obj ;
} ;
2014-08-01 01:38:33 +02:00
if ( ! $ . propHooks . mode ) {
$ . propHooks . mode = {
set : function ( obj , value ) {
obj . mode = value ;
if ( obj . _wsUpdateMode && obj . _wsUpdateMode . call ) {
obj . _wsUpdateMode ( ) ;
}
return obj . mode ;
}
} ;
}
2014-07-17 16:45:12 +02:00
/ *
taken from :
Captionator 0.5 . 1 [ CaptionCrunch ]
Christopher Giffard , 2011
Share and enjoy
https : //github.com/cgiffard/Captionator
modified for webshims
* /
mediaelement . parseCaptionChunk = ( function ( ) {
// Set up timestamp parsers
var WebVTTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s*(.*)/ ;
var WebVTTDEFAULTSCueParser = /^(DEFAULTS|DEFAULT)\s+\-\-\>\s+(.*)/g ;
var WebVTTSTYLECueParser = /^(STYLE|STYLES)\s+\-\-\>\s*\n([\s\S]*)/g ;
var WebVTTCOMMENTCueParser = /^(COMMENT|COMMENTS)\s+\-\-\>\s+(.*)/g ;
var SRTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})[\.\,](\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})[\.\,](\d+)\s*(.*)/ ;
return function ( subtitleElement , objectCount ) {
var subtitleParts , timeIn , timeOut , html , timeData , subtitlePartIndex , id ;
var timestampMatch , tmpCue ;
// WebVTT Special Cue Logic
if ( WebVTTDEFAULTSCueParser . exec ( subtitleElement ) || WebVTTCOMMENTCueParser . exec ( subtitleElement ) || WebVTTSTYLECueParser . exec ( subtitleElement ) ) {
return null ;
}
subtitleParts = subtitleElement . split ( /\n/g ) ;
// Trim off any blank lines (logically, should only be max. one, but loop to be sure)
while ( ! subtitleParts [ 0 ] . replace ( /\s+/ig , "" ) . length && subtitleParts . length > 0 ) {
subtitleParts . shift ( ) ;
}
if ( subtitleParts [ 0 ] . match ( /^\s*[a-z0-9-\_]+\s*$/ig ) ) {
// The identifier becomes the cue ID (when *we* load the cues from file. Programatically created cues can have an ID of whatever.)
id = String ( subtitleParts . shift ( ) . replace ( /\s*/ig , "" ) ) ;
}
for ( subtitlePartIndex = 0 ; subtitlePartIndex < subtitleParts . length ; subtitlePartIndex ++ ) {
var timestamp = subtitleParts [ subtitlePartIndex ] ;
if ( ( timestampMatch = WebVTTTimestampParser . exec ( timestamp ) ) || ( timestampMatch = SRTTimestampParser . exec ( timestamp ) ) ) {
// WebVTT
timeData = timestampMatch . slice ( 1 ) ;
timeIn = parseInt ( ( timeData [ 0 ] || 0 ) * 60 * 60 , 10 ) + // Hours
parseInt ( ( timeData [ 1 ] || 0 ) * 60 , 10 ) + // Minutes
parseInt ( ( timeData [ 2 ] || 0 ) , 10 ) + // Seconds
parseFloat ( "0." + ( timeData [ 3 ] || 0 ) ) ; // MS
timeOut = parseInt ( ( timeData [ 4 ] || 0 ) * 60 * 60 , 10 ) + // Hours
parseInt ( ( timeData [ 5 ] || 0 ) * 60 , 10 ) + // Minutes
parseInt ( ( timeData [ 6 ] || 0 ) , 10 ) + // Seconds
parseFloat ( "0." + ( timeData [ 7 ] || 0 ) ) ; // MS
/ *
if ( timeData [ 8 ] ) {
cueSettings = timeData [ 8 ] ;
}
* /
}
// We've got the timestamp - return all the other unmatched lines as the raw subtitle data
subtitleParts = subtitleParts . slice ( 0 , subtitlePartIndex ) . concat ( subtitleParts . slice ( subtitlePartIndex + 1 ) ) ;
break ;
}
if ( ! timeIn && ! timeOut ) {
// We didn't extract any time information. Assume the cue is invalid!
webshims . warn ( "couldn't extract time information: " + [ timeIn , timeOut , subtitleParts . join ( "\n" ) , id ] . join ( ' ; ' ) ) ;
return null ;
}
/ *
// Consolidate cue settings, convert defaults to object
var compositeCueSettings =
cueDefaults
. reduce ( function ( previous , current , index , array ) {
previous [ current . split ( ":" ) [ 0 ] ] = current . split ( ":" ) [ 1 ] ;
return previous ;
} , { } ) ;
// Loop through cue settings, replace defaults with cue specific settings if they exist
compositeCueSettings =
cueSettings
. split ( /\s+/g )
. filter ( function ( set ) { return set && ! ! set . length ; } )
// Convert array to a key/val object
. reduce ( function ( previous , current , index , array ) {
previous [ current . split ( ":" ) [ 0 ] ] = current . split ( ":" ) [ 1 ] ;
return previous ;
} , compositeCueSettings ) ;
// Turn back into string like the VTTCue constructor expects
cueSettings = "" ;
for ( var key in compositeCueSettings ) {
if ( compositeCueSettings . hasOwnProperty ( key ) ) {
cueSettings += ! ! cueSettings . length ? " " : "" ;
cueSettings += key + ":" + compositeCueSettings [ key ] ;
}
}
* /
// The remaining lines are the subtitle payload itself (after removing an ID if present, and the time);
html = subtitleParts . join ( "\n" ) ;
tmpCue = new VTTCue ( timeIn , timeOut , html ) ;
if ( id ) {
tmpCue . id = id ;
}
return tmpCue ;
} ;
} ) ( ) ;
mediaelement . parseCaptions = function ( captionData , track , complete ) {
var cue , lazyProcess , regWevVTT , startDate , isWEBVTT ;
mediaelement . createCueList ( ) ;
if ( captionData ) {
regWevVTT = /^WEBVTT(\s*FILE)?/ig ;
lazyProcess = function ( i , len ) {
for ( ; i < len ; i ++ ) {
cue = captionData [ i ] ;
if ( regWevVTT . test ( cue ) ) {
isWEBVTT = true ;
} else if ( cue . replace ( /\s*/ig , "" ) . length ) {
cue = mediaelement . parseCaptionChunk ( cue , i ) ;
if ( cue ) {
track . addCue ( cue ) ;
}
}
if ( startDate < ( new Date ( ) . getTime ( ) ) - 30 ) {
i ++ ;
setTimeout ( function ( ) {
startDate = new Date ( ) . getTime ( ) ;
lazyProcess ( i , len ) ;
} , 90 ) ;
break ;
}
}
if ( i >= len ) {
if ( ! isWEBVTT ) {
webshims . error ( 'please use WebVTT format. This is the standard' ) ;
}
complete ( track . cues ) ;
}
} ;
captionData = captionData . replace ( /\r\n/g , "\n" ) ;
setTimeout ( function ( ) {
captionData = captionData . replace ( /\r/g , "\n" ) ;
setTimeout ( function ( ) {
startDate = new Date ( ) . getTime ( ) ;
captionData = captionData . split ( /\n\n+/g ) ;
lazyProcess ( 0 , captionData . length ) ;
} , 9 ) ;
} , 9 ) ;
} else {
webshims . error ( "Required parameter captionData not supplied." ) ;
}
} ;
mediaelement . createTrackList = function ( mediaelem , baseData ) {
baseData = baseData || webshims . data ( mediaelem , 'mediaelementBase' ) || webshims . data ( mediaelem , 'mediaelementBase' , { } ) ;
if ( ! baseData . textTracks ) {
baseData . textTracks = [ ] ;
webshims . defineProperties ( baseData . textTracks , {
onaddtrack : { value : null } ,
onremovetrack : { value : null } ,
onchange : { value : null } ,
getTrackById : {
value : function ( id ) {
var track = null ;
for ( var i = 0 ; i < baseData . textTracks . length ; i ++ ) {
if ( id == baseData . textTracks [ i ] . id ) {
track = baseData . textTracks [ i ] ;
break ;
}
}
return track ;
}
}
} ) ;
createEventTarget ( baseData . textTracks ) ;
$ ( mediaelem ) . on ( 'updatetrackdisplay' , function ( ) {
var track ;
for ( var i = 0 ; i < baseData . textTracks . length ; i ++ ) {
track = baseData . textTracks [ i ] ;
if ( track . _ _wsmode != track . mode ) {
track . _ _wsmode = track . mode ;
$ ( [ baseData . textTracks ] ) . triggerHandler ( 'change' ) ;
}
}
} ) ;
}
return baseData . textTracks ;
} ;
if ( ! support . track ) {
webshims . defineNodeNamesBooleanProperty ( [ 'track' ] , 'default' ) ;
webshims . reflectProperties ( [ 'track' ] , [ 'srclang' , 'label' ] ) ;
webshims . defineNodeNameProperties ( 'track' , {
src : {
//attr: {},
reflect : true ,
propType : 'src'
}
} ) ;
}
webshims . defineNodeNameProperties ( 'track' , {
kind : {
attr : support . track ? {
set : function ( value ) {
var trackData = webshims . data ( this , 'trackData' ) ;
this . setAttribute ( 'data-kind' , value ) ;
if ( trackData ) {
trackData . attrKind = value ;
}
} ,
get : function ( ) {
var trackData = webshims . data ( this , 'trackData' ) ;
if ( trackData && ( 'attrKind' in trackData ) ) {
return trackData . attrKind ;
}
return this . getAttribute ( 'kind' ) ;
}
} : { } ,
reflect : true ,
propType : 'enumarated' ,
defaultValue : 'subtitles' ,
limitedTo : [ 'subtitles' , 'captions' , 'descriptions' , 'chapters' , 'metadata' ]
}
} ) ;
$ . each ( copyProps , function ( i , copyProp ) {
var name = copyName [ copyProp ] || copyProp ;
webshims . onNodeNamesPropertyModify ( 'track' , copyProp , function ( ) {
var trackData = webshims . data ( this , 'trackData' ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( trackData ) {
if ( copyProp == 'kind' ) {
refreshTrack ( this , trackData ) ;
}
if ( ! supportTrackMod ) {
trackData . track [ name ] = $ . prop ( this , copyProp ) ;
}
}
} ) ;
} ) ;
webshims . onNodeNamesPropertyModify ( 'track' , 'src' , function ( val ) {
if ( val ) {
var data = webshims . data ( this , 'trackData' ) ;
var media ;
if ( data ) {
media = $ ( this ) . closest ( 'video, audio' ) ;
if ( media [ 0 ] ) {
mediaelement . loadTextTrack ( media , this , data ) ;
}
}
}
} ) ;
//
webshims . defineNodeNamesProperties ( [ 'track' ] , {
ERROR : {
value : 3
} ,
LOADED : {
value : 2
} ,
LOADING : {
value : 1
} ,
NONE : {
value : 0
} ,
readyState : {
get : function ( ) {
return ( webshims . data ( this , 'trackData' ) || { readyState : 0 } ) . readyState ;
} ,
writeable : false
} ,
track : {
get : function ( ) {
return mediaelement . createTextTrack ( $ ( this ) . closest ( 'audio, video' ) [ 0 ] , this ) ;
} ,
writeable : false
}
} , 'prop' ) ;
webshims . defineNodeNamesProperties ( [ 'audio' , 'video' ] , {
textTracks : {
get : function ( ) {
var media = this ;
var baseData = webshims . data ( media , 'mediaelementBase' ) || webshims . data ( media , 'mediaelementBase' , { } ) ;
var tracks = mediaelement . createTrackList ( media , baseData ) ;
if ( ! baseData . blockTrackListUpdate ) {
updateMediaTrackList . call ( media , baseData , tracks ) ;
}
return tracks ;
} ,
writeable : false
} ,
addTextTrack : {
value : function ( kind , label , lang ) {
var textTrack = mediaelement . createTextTrack ( this , {
kind : dummyTrack . prop ( 'kind' , kind || '' ) . prop ( 'kind' ) ,
label : label || '' ,
srclang : lang || ''
} ) ;
var baseData = webshims . data ( this , 'mediaelementBase' ) || webshims . data ( this , 'mediaelementBase' , { } ) ;
if ( ! baseData . scriptedTextTracks ) {
baseData . scriptedTextTracks = [ ] ;
}
baseData . scriptedTextTracks . push ( textTrack ) ;
updateMediaTrackList . call ( this ) ;
return textTrack ;
}
}
} , 'prop' ) ;
//wsmediareload
var thUpdateList = function ( e ) {
if ( $ ( e . target ) . is ( 'audio, video' ) ) {
var baseData = webshims . data ( e . target , 'mediaelementBase' ) ;
if ( baseData ) {
clearTimeout ( baseData . updateTrackListTimer ) ;
baseData . updateTrackListTimer = setTimeout ( function ( ) {
updateMediaTrackList . call ( e . target , baseData ) ;
} , 0 ) ;
}
}
} ;
var getNativeReadyState = function ( trackElem , textTrack ) {
return textTrack . readyState || trackElem . readyState ;
} ;
var stopOriginalEvent = function ( e ) {
if ( e . originalEvent ) {
e . stopImmediatePropagation ( ) ;
}
} ;
var hideNativeTracks = function ( ) {
if ( webshims . implement ( this , 'track' ) ) {
var kind ;
var origTrack = this . track ;
if ( origTrack ) {
if ( ! webshims . bugs . track && ( origTrack . mode || getNativeReadyState ( this , origTrack ) ) ) {
$ . prop ( this , 'track' ) . mode = numericModes [ origTrack . mode ] || origTrack . mode ;
}
//disable track from showing + remove UI
kind = $ . prop ( this , 'kind' ) ;
origTrack . mode = ( typeof origTrack . mode == 'string' ) ? 'disabled' : 0 ;
this . kind = 'metadata' ;
$ ( this ) . attr ( { kind : kind } ) ;
}
$ ( this ) . on ( 'load error' , stopOriginalEvent ) ;
}
} ;
webshims . addReady ( function ( context , insertedElement ) {
var insertedMedia = insertedElement . filter ( 'video, audio, track' ) . closest ( 'audio, video' ) ;
$ ( 'video, audio' , context )
. add ( insertedMedia )
. each ( function ( ) {
updateMediaTrackList . call ( this ) ;
} )
. on ( 'emptied updatetracklist wsmediareload' , thUpdateList )
. each ( function ( ) {
if ( support . track ) {
var shimedTextTracks = $ . prop ( this , 'textTracks' ) ;
var origTextTracks = this . textTracks ;
if ( shimedTextTracks . length != origTextTracks . length ) {
webshims . warn ( "textTracks couldn't be copied" ) ;
}
$ ( 'track' , this ) . each ( hideNativeTracks ) ;
}
} )
;
insertedMedia . each ( function ( ) {
var media = this ;
var baseData = webshims . data ( media , 'mediaelementBase' ) ;
if ( baseData ) {
clearTimeout ( baseData . updateTrackListTimer ) ;
baseData . updateTrackListTimer = setTimeout ( function ( ) {
updateMediaTrackList . call ( media , baseData ) ;
} , 9 ) ;
}
} ) ;
} ) ;
if ( support . texttrackapi ) {
$ ( 'video, audio' ) . trigger ( 'trackapichange' ) ;
}
} ) ;