2014-07-17 16:45:12 +02:00
( function ( $ ) {
var webshims = window . webshims ;
setTimeout ( function ( ) {
webshims . isReady ( 'geolocation' , true ) ;
} ) ;
var domWrite = function ( ) {
setTimeout ( function ( ) {
throw ( 'document.write is overwritten by geolocation shim. This method is incompatible with this plugin' ) ;
} , 1 ) ;
} ,
id = 0
;
var geoOpts = webshims . cfg . geolocation || { } ;
if ( ! navigator . geolocation ) {
navigator . geolocation = { } ;
}
$ . extend ( navigator . geolocation , ( function ( ) {
var pos ;
var api = {
getCurrentPosition : function ( success , error , opts ) {
var locationAPIs = 2 ,
errorTimer ,
googleTimer ,
calledEnd ,
createAjax ,
endCallback = function ( ) {
if ( calledEnd ) { return ; }
if ( pos ) {
calledEnd = true ;
success ( $ . extend ( { timestamp : new Date ( ) . getTime ( ) } , pos ) ) ;
resetCallback ( ) ;
if ( window . JSON && window . sessionStorage ) {
try {
sessionStorage . setItem ( 'storedGeolocationData654321' , JSON . stringify ( pos ) ) ;
} catch ( e ) { }
}
} else if ( error && ! locationAPIs ) {
calledEnd = true ;
resetCallback ( ) ;
error ( { code : 2 , message : "POSITION_UNAVAILABLE" } ) ;
}
} ,
googleCallback = function ( ) {
locationAPIs -- ;
getGoogleCoords ( ) ;
endCallback ( ) ;
} ,
resetCallback = function ( ) {
$ ( document ) . off ( 'google-loader' , resetCallback ) ;
clearTimeout ( googleTimer ) ;
clearTimeout ( errorTimer ) ;
} ,
getGoogleCoords = function ( ) {
if ( pos || ! window . google || ! google . loader || ! google . loader . ClientLocation ) { return false ; }
var cl = google . loader . ClientLocation ;
pos = {
coords : {
latitude : cl . latitude ,
longitude : cl . longitude ,
altitude : null ,
accuracy : 43000 ,
altitudeAccuracy : null ,
heading : parseInt ( 'NaN' , 10 ) ,
velocity : null
} ,
//extension similiar to FF implementation
address : $ . extend ( { streetNumber : '' , street : '' , premises : '' , county : '' , postalCode : '' } , cl . address )
} ;
return true ;
} ,
getInitCoords = function ( ) {
if ( pos ) { return ; }
getGoogleCoords ( ) ;
if ( pos || ! window . JSON || ! window . sessionStorage ) { return ; }
try {
pos = sessionStorage . getItem ( 'storedGeolocationData654321' ) ;
pos = ( pos ) ? JSON . parse ( pos ) : false ;
if ( ! pos . coords ) { pos = false ; }
} catch ( e ) {
pos = false ;
}
}
;
getInitCoords ( ) ;
if ( ! pos ) {
if ( geoOpts . confirmText && ! confirm ( geoOpts . confirmText . replace ( '{location}' , location . hostname ) ) ) {
if ( error ) {
error ( { code : 1 , message : "PERMISSION_DENIED" } ) ;
}
return ;
}
2014-09-03 00:57:03 +02:00
$ . ajax ( {
url : 'http://freegeoip.net/json/' ,
dataType : 'jsonp' ,
cache : true ,
jsonp : 'callback' ,
success : function ( data ) {
locationAPIs -- ;
if ( ! data ) { return ; }
pos = pos || {
coords : {
latitude : data . latitude ,
longitude : data . longitude ,
altitude : null ,
accuracy : 43000 ,
altitudeAccuracy : null ,
heading : parseInt ( 'NaN' , 10 ) ,
velocity : null
} ,
//extension similiar to FF implementation
address : {
city : data . city ,
country : data . country _name ,
countryCode : data . country _code ,
county : "" ,
postalCode : data . zipcode ,
premises : "" ,
region : data . region _name ,
street : "" ,
streetNumber : ""
}
} ;
endCallback ( ) ;
} ,
error : function ( ) {
locationAPIs -- ;
endCallback ( ) ;
}
} ) ;
2014-07-17 16:45:12 +02:00
clearTimeout ( googleTimer ) ;
if ( ! window . google || ! window . google . loader ) {
googleTimer = setTimeout ( function ( ) {
//destroys document.write!!!
if ( geoOpts . destroyWrite ) {
document . write = domWrite ;
document . writeln = domWrite ;
}
$ ( document ) . one ( 'google-loader' , googleCallback ) ;
webshims . loader . loadScript ( 'http://www.google.com/jsapi' , false , 'google-loader' ) ;
} , 800 ) ;
} else {
locationAPIs -- ;
}
} else {
setTimeout ( endCallback , 1 ) ;
return ;
}
if ( opts && opts . timeout ) {
errorTimer = setTimeout ( function ( ) {
resetCallback ( ) ;
if ( error ) {
error ( { code : 3 , message : "TIMEOUT" } ) ;
}
} , opts . timeout ) ;
} else {
errorTimer = setTimeout ( function ( ) {
locationAPIs = 0 ;
endCallback ( ) ;
} , 10000 ) ;
}
} ,
clearWatch : $ . noop
} ;
api . watchPosition = function ( a , b , c ) {
api . getCurrentPosition ( a , b , c ) ;
id ++ ;
return id ;
} ;
return api ;
} ) ( ) ) ;
2014-09-03 00:57:03 +02:00
2014-07-17 16:45:12 +02:00
webshims . isReady ( 'geolocation' , true ) ;
} ) ( webshims . $ ) ;
; webshims . register ( 'details' , function ( $ , webshims , window , doc , undefined , options ) {
var isInterActiveSummary = function ( summary ) {
var details = $ ( summary ) . parent ( 'details' ) ;
if ( details [ 0 ] && details . children ( ':first' ) . get ( 0 ) === summary ) {
return details ;
}
} ;
var bindDetailsSummary = function ( summary , details ) {
summary = $ ( summary ) ;
details = $ ( details ) ;
var oldSummary = $ . data ( details [ 0 ] , 'summaryElement' ) ;
$ . data ( summary [ 0 ] , 'detailsElement' , details ) ;
if ( ! oldSummary || summary [ 0 ] !== oldSummary [ 0 ] ) {
if ( oldSummary ) {
if ( oldSummary . hasClass ( 'fallback-summary' ) ) {
oldSummary . remove ( ) ;
} else {
oldSummary
. off ( '.summaryPolyfill' )
. removeData ( 'detailsElement' )
. removeAttr ( 'role' )
. removeAttr ( 'tabindex' )
. removeAttr ( 'aria-expanded' )
. removeClass ( 'summary-button' )
. find ( 'span.details-open-indicator' )
. remove ( )
;
}
}
$ . data ( details [ 0 ] , 'summaryElement' , summary ) ;
details . prop ( 'open' , details . prop ( 'open' ) ) ;
}
} ;
var getSummary = function ( details ) {
var summary = $ . data ( details , 'summaryElement' ) ;
if ( ! summary ) {
summary = $ ( details ) . children ( 'summary:first-child' ) ;
if ( ! summary [ 0 ] ) {
$ ( details ) . prependPolyfill ( '<summary class="fallback-summary">' + options . text + '</summary>' ) ;
summary = $ . data ( details , 'summaryElement' ) ;
} else {
bindDetailsSummary ( summary , details ) ;
}
}
return summary ;
} ;
// var isOriginalPrevented = function(e){
// var src = e.originalEvent;
// if(!src){return e.isDefaultPrevented();}
//
// return src.defaultPrevented || src.returnValue === false ||
// src.getPreventDefault && src.getPreventDefault();
// };
webshims . createElement ( 'summary' , function ( ) {
var details = isInterActiveSummary ( this ) ;
if ( ! details || $ . data ( this , 'detailsElement' ) ) { return ; }
var timer ;
var stopNativeClickTest ;
var tabindex = $ . attr ( this , 'tabIndex' ) || '0' ;
bindDetailsSummary ( this , details ) ;
$ ( this )
. on ( {
'focus.summaryPolyfill' : function ( ) {
$ ( this ) . addClass ( 'summary-has-focus' ) ;
} ,
'blur.summaryPolyfill' : function ( ) {
$ ( this ) . removeClass ( 'summary-has-focus' ) ;
} ,
'mouseenter.summaryPolyfill' : function ( ) {
$ ( this ) . addClass ( 'summary-has-hover' ) ;
} ,
'mouseleave.summaryPolyfill' : function ( ) {
$ ( this ) . removeClass ( 'summary-has-hover' ) ;
} ,
'click.summaryPolyfill' : function ( e ) {
var details = isInterActiveSummary ( this ) ;
if ( details ) {
if ( ! stopNativeClickTest && e . originalEvent ) {
stopNativeClickTest = true ;
e . stopImmediatePropagation ( ) ;
e . preventDefault ( ) ;
$ ( this ) . trigger ( 'click' ) ;
stopNativeClickTest = false ;
return false ;
} else {
clearTimeout ( timer ) ;
timer = setTimeout ( function ( ) {
if ( ! e . isDefaultPrevented ( ) ) {
details . prop ( 'open' , ! details . prop ( 'open' ) ) ;
}
} , 0 ) ;
}
}
} ,
'keydown.summaryPolyfill' : function ( e ) {
if ( ( e . keyCode == 13 || e . keyCode == 32 ) && ! e . isDefaultPrevented ( ) ) {
stopNativeClickTest = true ;
e . preventDefault ( ) ;
$ ( this ) . trigger ( 'click' ) ;
stopNativeClickTest = false ;
}
}
} )
. attr ( { tabindex : tabindex , role : 'button' } )
. prepend ( '<span class="details-open-indicator" />' )
;
webshims . moveToFirstEvent ( this , 'click' ) ;
} ) ;
var initDetails ;
webshims . defineNodeNamesBooleanProperty ( 'details' , 'open' , function ( val ) {
var summary = $ ( $ . data ( this , 'summaryElement' ) ) ;
if ( ! summary ) { return ; }
var action = ( val ) ? 'removeClass' : 'addClass' ;
var details = $ ( this ) ;
if ( ! initDetails && options . animate ) {
details . stop ( ) . css ( { width : '' , height : '' } ) ;
var start = {
width : details . width ( ) ,
height : details . height ( )
} ;
}
summary . attr ( 'aria-expanded' , '' + val ) ;
details [ action ] ( 'closed-details-summary' ) . children ( ) . not ( summary [ 0 ] ) [ action ] ( 'closed-details-child' ) ;
if ( ! initDetails && options . animate ) {
var end = {
width : details . width ( ) ,
height : details . height ( )
} ;
details . css ( start ) . animate ( end , {
complete : function ( ) {
$ ( this ) . css ( { width : '' , height : '' } ) ;
}
} ) ;
}
} ) ;
webshims . createElement ( 'details' , function ( ) {
initDetails = true ;
var summary = getSummary ( this ) ;
$ . prop ( this , 'open' , $ . prop ( this , 'open' ) ) ;
initDetails = false ;
} ) ;
} ) ;
; webshims . register ( 'mediaelement-jaris' , function ( $ , webshims , window , document , undefined , options ) {
"use strict" ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var mediaelement = webshims . mediaelement ;
var swfmini = window . swfmini ;
var support = webshims . support ;
var hasNative = support . mediaelement ;
2014-08-01 01:38:33 +02:00
var hasFlash = swfmini . hasFlashPlayerVersion ( '11.3' ) ;
2014-07-17 16:45:12 +02:00
var loadedSwf = 0 ;
var needsLoadPreload = 'ActiveXObject' in window && hasNative ;
var getProps = {
paused : true ,
ended : false ,
currentSrc : '' ,
duration : window . NaN ,
readyState : 0 ,
networkState : 0 ,
videoHeight : 0 ,
videoWidth : 0 ,
seeking : false ,
error : null ,
buffered : {
start : function ( index ) {
if ( index ) {
webshims . error ( 'buffered index size error' ) ;
return ;
}
return 0 ;
} ,
end : function ( index ) {
if ( index ) {
webshims . error ( 'buffered index size error' ) ;
return ;
}
return 0 ;
} ,
length : 0
}
} ;
var getPropKeys = Object . keys ( getProps ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var getSetProps = {
currentTime : 0 ,
volume : 1 ,
muted : false
} ;
var getSetPropKeys = Object . keys ( getSetProps ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var playerStateObj = $ . extend ( {
isActive : 'html5' ,
2014-08-01 01:38:33 +02:00
activating : 'html5' ,
2014-07-17 16:45:12 +02:00
wasSwfReady : false ,
2014-08-01 01:38:33 +02:00
_usermedia : null ,
2014-07-17 16:45:12 +02:00
_bufferedEnd : 0 ,
_bufferedStart : 0 ,
currentTime : 0 ,
lastCalledTime : - 500 ,
_ppFlag : undefined ,
_calledMeta : false ,
lastDuration : 0 ,
_timeDif : 0.3
} , getProps , getSetProps ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var getSwfDataFromElem = function ( elem ) {
try {
( elem . nodeName ) ;
} catch ( er ) {
return null ;
}
var data = webshims . data ( elem , 'mediaelement' ) ;
return ( data && data . isActive == 'third' ) ? data : null ;
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var trigger = function ( elem , evt ) {
evt = $ . Event ( evt ) ;
evt . preventDefault ( ) ;
$ . event . trigger ( evt , undefined , elem ) ;
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var playerSwfPath = options . playerPath || webshims . cfg . basePath + "swf/" + ( options . playerName || 'JarisFLVPlayer.swf' ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
webshims . extendUNDEFProp ( options . params , {
allowscriptaccess : 'always' ,
allowfullscreen : 'true' ,
wmode : 'transparent' ,
allowNetworking : 'all'
} ) ;
webshims . extendUNDEFProp ( options . vars , {
controltype : '1' ,
jsapi : '1'
} ) ;
webshims . extendUNDEFProp ( options . attrs , {
bgcolor : '#000000'
} ) ;
2014-08-01 01:38:33 +02:00
options . playerPath = playerSwfPath ;
2014-07-17 16:45:12 +02:00
var setReadyState = function ( readyState , data ) {
if ( readyState < 3 ) {
clearTimeout ( data . _canplaythroughTimer ) ;
}
if ( readyState >= 3 && data . readyState < 3 ) {
data . readyState = readyState ;
trigger ( data . _elem , 'canplay' ) ;
if ( ! data . paused ) {
trigger ( data . _elem , 'playing' ) ;
}
clearTimeout ( data . _canplaythroughTimer ) ;
data . _canplaythroughTimer = setTimeout ( function ( ) {
setReadyState ( 4 , data ) ;
} , 4000 ) ;
}
if ( readyState >= 4 && data . readyState < 4 ) {
data . readyState = readyState ;
trigger ( data . _elem , 'canplaythrough' ) ;
}
data . readyState = readyState ;
} ;
var callSeeked = function ( data ) {
if ( data . seeking && Math . abs ( data . currentTime - data . _lastSeektime ) < 2 ) {
data . seeking = false ;
$ ( data . _elem ) . triggerHandler ( 'seeked' ) ;
}
} ;
2014-08-01 01:38:33 +02:00
2014-09-03 00:57:03 +02:00
mediaelement . jarisEvent = mediaelement . jarisEvent || { } ;
2014-07-17 16:45:12 +02:00
var localConnectionTimer ;
var onEvent = {
onPlayPause : function ( jaris , data , override ) {
var playing , type ;
2014-07-20 02:43:13 +02:00
var idled = data . paused || data . ended ;
2014-09-03 00:57:03 +02:00
2014-07-17 16:45:12 +02:00
if ( override == null ) {
try {
playing = data . api . api _get ( "isPlaying" ) ;
} catch ( e ) { }
} else {
playing = override ;
}
2014-07-20 02:43:13 +02:00
if ( playing == idled || playing == null ) {
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . paused = ! playing ;
type = data . paused ? 'pause' : 'play' ;
data . _ppFlag = true ;
trigger ( data . _elem , type ) ;
2014-09-03 00:57:03 +02:00
}
if ( ! data . paused || playing == idled || playing == null ) {
2014-07-17 16:45:12 +02:00
if ( data . readyState < 3 ) {
setReadyState ( 3 , data ) ;
}
2014-09-03 00:57:03 +02:00
}
if ( ! data . paused ) {
trigger ( data . _elem , 'playing' ) ;
2014-07-17 16:45:12 +02:00
}
} ,
onSeek : function ( jaris , data ) {
data . _lastSeektime = jaris . seekTime ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . seeking = true ;
$ ( data . _elem ) . triggerHandler ( 'seeking' ) ;
clearTimeout ( data . _seekedTimer ) ;
data . _seekedTimer = setTimeout ( function ( ) {
callSeeked ( data ) ;
data . seeking = false ;
} , 300 ) ;
} ,
onConnectionFailed : function ( jaris , data ) {
mediaelement . setError ( data . _elem , 'flash connection error' ) ;
} ,
onNotBuffering : function ( jaris , data ) {
setReadyState ( 3 , data ) ;
} ,
onDataInitialized : function ( jaris , data ) {
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var oldDur = data . duration ;
var durDelta ;
data . duration = jaris . duration ;
if ( oldDur == data . duration || isNaN ( data . duration ) ) { return ; }
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( data . _calledMeta && ( ( durDelta = Math . abs ( data . lastDuration - data . duration ) ) < 2 ) ) { return ; }
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . videoHeight = jaris . height ;
data . videoWidth = jaris . width ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( ! data . networkState ) {
data . networkState = 2 ;
}
if ( data . readyState < 1 ) {
setReadyState ( 1 , data ) ;
}
clearTimeout ( data . _durationChangeTimer ) ;
if ( data . _calledMeta && data . duration ) {
data . _durationChangeTimer = setTimeout ( function ( ) {
data . lastDuration = data . duration ;
trigger ( data . _elem , 'durationchange' ) ;
} , durDelta > 50 ? 0 : durDelta > 9 ? 9 : 99 ) ;
} else {
data . lastDuration = data . duration ;
if ( data . duration ) {
trigger ( data . _elem , 'durationchange' ) ;
}
if ( ! data . _calledMeta ) {
trigger ( data . _elem , 'loadedmetadata' ) ;
}
if ( data . duration > 1 && data . duration < 140 ) {
data . _timeDif = 0.2 ;
} else if ( data . duration < 600 ) {
data . _timeDif = 0.25 ;
} else {
data . _timeDif = 0.30 ;
}
}
data . _calledMeta = true ;
} ,
onBuffering : function ( jaris , data ) {
if ( data . ended ) {
data . ended = false ;
}
setReadyState ( 1 , data ) ;
trigger ( data . _elem , 'waiting' ) ;
} ,
onTimeUpdate : function ( jaris , data ) {
var timeDif = data . currentTime - data . lastCalledTime ;
if ( data . ended ) {
data . ended = false ;
}
if ( data . readyState < 3 ) {
setReadyState ( 3 , data ) ;
trigger ( data . _elem , 'playing' ) ;
}
if ( data . seeking ) {
callSeeked ( data ) ;
}
if ( timeDif > data . _timeDif || timeDif < - 0.3 ) {
data . lastCalledTime = data . currentTime ;
$ . event . trigger ( 'timeupdate' , undefined , data . _elem , true ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
} ,
onProgress : function ( jaris , data ) {
if ( data . ended ) {
data . ended = false ;
}
if ( ! data . duration || isNaN ( data . duration ) ) {
return ;
}
var percentage = jaris . loaded / jaris . total ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( percentage > 0.02 && percentage < 0.2 ) {
setReadyState ( 3 , data ) ;
} else if ( percentage > 0.2 ) {
if ( percentage > 0.95 ) {
percentage = 1 ;
data . networkState = 1 ;
}
setReadyState ( 4 , data ) ;
}
if ( data . _bufferedEnd && ( data . _bufferedEnd > percentage ) ) {
data . _bufferedStart = data . currentTime || 0 ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . _bufferedEnd = percentage ;
data . buffered . length = 1 ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
$ . event . trigger ( 'progress' , undefined , data . _elem , true ) ;
} ,
onPlaybackFinished : function ( jaris , data ) {
if ( data . readyState < 4 ) {
setReadyState ( 4 , data ) ;
}
data . ended = true ;
trigger ( data . _elem , 'ended' ) ;
} ,
onVolumeChange : function ( jaris , data ) {
if ( data . volume != jaris . volume || data . muted != jaris . mute ) {
data . volume = jaris . volume ;
data . muted = jaris . mute ;
trigger ( data . _elem , 'volumechange' ) ;
}
} ,
ready : ( function ( ) {
var testAPI = function ( data ) {
var passed = true ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
try {
data . api . api _get ( 'volume' ) ;
} catch ( er ) {
passed = false ;
}
return passed ;
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
return function ( jaris , data ) {
var i = 0 ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var doneFn = function ( ) {
if ( i > 9 ) {
data . tryedReframeing = 0 ;
return ;
}
i ++ ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . tryedReframeing ++ ;
if ( testAPI ( data ) ) {
data . wasSwfReady = true ;
data . tryedReframeing = 0 ;
startAutoPlay ( data ) ;
workActionQueue ( data ) ;
} else if ( data . tryedReframeing < 6 ) {
if ( data . tryedReframeing < 3 ) {
data . reframeTimer = setTimeout ( doneFn , 9 ) ;
data . shadowElem . css ( { overflow : 'visible' } ) ;
setTimeout ( function ( ) {
data . shadowElem . css ( { overflow : 'hidden' } ) ;
} , 1 ) ;
} else {
data . shadowElem . css ( { overflow : 'hidden' } ) ;
$ ( data . _elem ) . mediaLoad ( ) ;
}
} else {
clearTimeout ( data . reframeTimer ) ;
webshims . error ( "reframing error" ) ;
}
} ;
if ( ! data || ! data . api ) { return ; }
if ( ! data . tryedReframeing ) {
data . tryedReframeing = 0 ;
}
clearTimeout ( localConnectionTimer ) ;
clearTimeout ( data . reframeTimer ) ;
data . shadowElem . removeClass ( 'flashblocker-assumed' ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( ! i ) {
doneFn ( ) ;
} else {
data . reframeTimer = setTimeout ( doneFn , 9 ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
} ;
} ) ( )
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
onEvent . onMute = onEvent . onVolumeChange ;
2014-08-01 01:38:33 +02:00
mediaelement . onEvent = onEvent ;
2014-07-17 16:45:12 +02:00
var workActionQueue = function ( data ) {
var actionLen = data . actionQueue . length ;
var i = 0 ;
var operation ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( actionLen && data . isActive == 'third' ) {
while ( data . actionQueue . length && actionLen > i ) {
i ++ ;
operation = data . actionQueue . shift ( ) ;
try {
data . api [ operation . fn ] . apply ( data . api , operation . args ) ;
} catch ( er ) {
webshims . warn ( er ) ;
}
}
}
if ( data . actionQueue . length ) {
data . actionQueue = [ ] ;
}
} ;
var startAutoPlay = function ( data ) {
if ( ! data ) { return ; }
if ( ( data . _ppFlag === undefined && ( $ . prop ( data . _elem , 'autoplay' ) ) || ! data . paused ) ) {
setTimeout ( function ( ) {
if ( data . isActive == 'third' && ( data . _ppFlag === undefined || ! data . paused ) ) {
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
try {
$ ( data . _elem ) . play ( ) ;
data . _ppFlag = true ;
} catch ( er ) { }
}
} , 1 ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( data . muted ) {
$ . prop ( data . _elem , 'muted' , true ) ;
}
if ( data . volume != 1 ) {
$ . prop ( data . _elem , 'volume' , data . volume ) ;
}
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var addMediaToStopEvents = $ . noop ;
if ( hasNative ) {
var stopEvents = {
play : 1 ,
playing : 1
} ;
var hideEvtArray = [ 'play' , 'pause' , 'playing' , 'loadstart' , 'canplay' , 'progress' , 'waiting' , 'ended' , 'loadedmetadata' , 'durationchange' , 'emptied' ] ;
var hidevents = hideEvtArray . map ( function ( evt ) {
return evt + '.webshimspolyfill' ;
} ) . join ( ' ' ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var hidePlayerEvents = function ( event ) {
var data = webshims . data ( event . target , 'mediaelement' ) ;
if ( ! data ) { return ; }
var isNativeHTML5 = ( event . originalEvent && event . originalEvent . type === event . type ) ;
if ( isNativeHTML5 == ( data . activating == 'third' ) ) {
event . stopImmediatePropagation ( ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( stopEvents [ event . type ] ) {
if ( data . isActive != data . activating ) {
$ ( event . target ) . pause ( ) ;
} else if ( isNativeHTML5 ) {
( $ . prop ( event . target , 'pause' ) . _supvalue || $ . noop ) . apply ( event . target ) ;
}
}
}
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
addMediaToStopEvents = function ( elem ) {
$ ( elem )
. off ( hidevents )
. on ( hidevents , hidePlayerEvents )
;
hideEvtArray . forEach ( function ( evt ) {
webshims . moveToFirstEvent ( elem , evt ) ;
} ) ;
} ;
addMediaToStopEvents ( document ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
mediaelement . setActive = function ( elem , type , data ) {
if ( ! data ) {
data = webshims . data ( elem , 'mediaelement' ) ;
}
if ( ! data || data . isActive == type ) { return ; }
if ( type != 'html5' && type != 'third' ) {
webshims . warn ( 'wrong type for mediaelement activating: ' + type ) ;
}
var shadowData = webshims . data ( elem , 'shadowData' ) ;
data . activating = type ;
$ ( elem ) . pause ( ) ;
data . isActive = type ;
if ( type == 'third' ) {
shadowData . shadowElement = shadowData . shadowFocusElement = data . shadowElem [ 0 ] ;
$ ( elem ) . addClass ( 'swf-api-active nonnative-api-active' ) . hide ( ) . getShadowElement ( ) . show ( ) ;
} else {
$ ( elem ) . removeClass ( 'swf-api-active nonnative-api-active' ) . show ( ) . getShadowElement ( ) . hide ( ) ;
shadowData . shadowElement = shadowData . shadowFocusElement = false ;
}
$ ( elem ) . trigger ( 'mediaelementapichange' ) ;
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var resetSwfProps = ( function ( ) {
2014-08-01 01:38:33 +02:00
var resetProtoProps = [ '_calledMeta' , 'lastDuration' , '_bufferedEnd' , 'lastCalledTime' , '_usermedia' , '_bufferedStart' , '_ppFlag' , 'currentSrc' , 'currentTime' , 'duration' , 'ended' , 'networkState' , 'paused' , 'seeking' , 'videoHeight' , 'videoWidth' ] ;
2014-07-17 16:45:12 +02:00
var len = resetProtoProps . length ;
return function ( data ) {
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( ! data ) { return ; }
clearTimeout ( data . _seekedTimer ) ;
var lenI = len ;
var networkState = data . networkState ;
setReadyState ( 0 , data ) ;
clearTimeout ( data . _durationChangeTimer ) ;
while ( -- lenI > - 1 ) {
delete data [ resetProtoProps [ lenI ] ] ;
}
data . actionQueue = [ ] ;
data . buffered . length = 0 ;
if ( networkState ) {
trigger ( data . _elem , 'emptied' ) ;
}
} ;
} ) ( ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var getComputedDimension = ( function ( ) {
var dimCache = { } ;
var getVideoDims = function ( data ) {
var ret , poster , img ;
if ( dimCache [ data . currentSrc ] ) {
ret = dimCache [ data . currentSrc ] ;
} else if ( data . videoHeight && data . videoWidth ) {
dimCache [ data . currentSrc ] = {
width : data . videoWidth ,
height : data . videoHeight
} ;
ret = dimCache [ data . currentSrc ] ;
} else if ( ( poster = $ . attr ( data . _elem , 'poster' ) ) ) {
ret = dimCache [ poster ] ;
if ( ! ret ) {
img = document . createElement ( 'img' ) ;
img . onload = function ( ) {
dimCache [ poster ] = {
width : this . width ,
height : this . height
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( dimCache [ poster ] . height && dimCache [ poster ] . width ) {
setElementDimension ( data , $ . prop ( data . _elem , 'controls' ) ) ;
} else {
delete dimCache [ poster ] ;
}
img . onload = null ;
} ;
img . src = poster ;
if ( img . complete && img . onload ) {
img . onload ( ) ;
}
}
}
return ret || { width : 300 , height : data . _elemNodeName == 'video' ? 150 : 50 } ;
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var getCssStyle = function ( elem , style ) {
return elem . style [ style ] || ( elem . currentStyle && elem . currentStyle [ style ] ) || ( window . getComputedStyle && ( window . getComputedStyle ( elem , null ) || { } ) [ style ] ) || '' ;
} ;
var minMaxProps = [ 'minWidth' , 'maxWidth' , 'minHeight' , 'maxHeight' ] ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var addMinMax = function ( elem , ret ) {
var i , prop ;
var hasMinMax = false ;
for ( i = 0 ; i < 4 ; i ++ ) {
prop = getCssStyle ( elem , minMaxProps [ i ] ) ;
if ( parseFloat ( prop , 10 ) ) {
hasMinMax = true ;
ret [ minMaxProps [ i ] ] = prop ;
}
}
return hasMinMax ;
} ;
var retFn = function ( data ) {
2014-08-01 01:38:33 +02:00
var videoDims , ratio ;
2014-07-17 16:45:12 +02:00
var elem = data . _elem ;
var autos = {
width : getCssStyle ( elem , 'width' ) == 'auto' ,
height : getCssStyle ( elem , 'height' ) == 'auto'
} ;
var ret = {
width : ! autos . width && $ ( elem ) . width ( ) ,
height : ! autos . height && $ ( elem ) . height ( )
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( autos . width || autos . height ) {
videoDims = getVideoDims ( data ) ;
ratio = videoDims . width / videoDims . height ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( autos . width && autos . height ) {
ret . width = videoDims . width ;
ret . height = videoDims . height ;
} else if ( autos . width ) {
ret . width = ret . height * ratio ;
} else if ( autos . height ) {
ret . height = ret . width / ratio ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( addMinMax ( elem , ret ) ) {
data . shadowElem . css ( ret ) ;
if ( autos . width ) {
ret . width = data . shadowElem . height ( ) * ratio ;
2014-08-01 01:38:33 +02:00
}
2014-07-17 16:45:12 +02:00
if ( autos . height ) {
ret . height = ( ( autos . width ) ? ret . width : data . shadowElem . width ( ) ) / ratio ;
}
if ( autos . width && autos . height ) {
data . shadowElem . css ( ret ) ;
ret . height = data . shadowElem . width ( ) / ratio ;
ret . width = ret . height * ratio ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . shadowElem . css ( ret ) ;
ret . width = data . shadowElem . height ( ) * ratio ;
ret . height = ret . width / ratio ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
}
if ( ! webshims . support . mediaelement ) {
ret . width = data . shadowElem . width ( ) ;
ret . height = data . shadowElem . height ( ) ;
}
}
}
return ret ;
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
return retFn ;
} ) ( ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var setElementDimension = function ( data , hasControls ) {
var dims ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var box = data . shadowElem ;
$ ( data . _elem ) [ hasControls ? 'addClass' : 'removeClass' ] ( 'webshims-controls' ) ;
if ( data . isActive == 'third' || data . activating == 'third' ) {
if ( data . _elemNodeName == 'audio' && ! hasControls ) {
box . css ( { width : 0 , height : 0 } ) ;
} else {
data . _elem . style . display = '' ;
dims = getComputedDimension ( data ) ;
data . _elem . style . display = 'none' ;
box . css ( dims ) ;
}
}
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var bufferSrc = ( function ( ) {
var preloads = {
'' : 1 ,
'auto' : 1
} ;
return function ( elem ) {
var preload = $ . attr ( elem , 'preload' ) ;
if ( preload == null || preload == 'none' || $ . prop ( elem , 'autoplay' ) ) {
return false ;
}
preload = $ . prop ( elem , 'preload' ) ;
return ! ! ( preloads [ preload ] || ( preload == 'metadata' && $ ( elem ) . is ( '.preload-in-doubt, video:not([poster])' ) ) ) ;
} ;
} ) ( ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var regs = {
2014-08-01 01:38:33 +02:00
A : /&/g ,
a : /&/g ,
e : /\=/g ,
q : /\?/g
} ,
replaceVar = function ( val ) {
return ( val . replace ) ? val . replace ( regs . A , '%26' ) . replace ( regs . a , '%26' ) . replace ( regs . e , '%3D' ) . replace ( regs . q , '%3F' ) : val ;
} ;
2014-07-17 16:45:12 +02:00
if ( 'matchMedia' in window ) {
var allowMediaSorting = false ;
try {
allowMediaSorting = window . matchMedia ( 'only all' ) . matches ;
} catch ( er ) { }
if ( allowMediaSorting ) {
mediaelement . sortMedia = function ( src1 , src2 ) {
try {
src1 = ! src1 . media || matchMedia ( src1 . media ) . matches ;
src2 = ! src2 . media || matchMedia ( src2 . media ) . matches ;
} catch ( er ) {
return 0 ;
}
2014-08-01 01:38:33 +02:00
return src1 == src2 ?
2014-07-17 16:45:12 +02:00
0 :
src1 ? - 1
2014-08-01 01:38:33 +02:00
: 1 ;
2014-07-17 16:45:12 +02:00
} ;
}
}
2014-08-01 01:38:33 +02:00
mediaelement . resetSwfProps = resetSwfProps ;
2014-07-17 16:45:12 +02:00
mediaelement . createSWF = function ( elem , canPlaySrc , data ) {
if ( ! hasFlash ) {
setTimeout ( function ( ) {
$ ( elem ) . mediaLoad ( ) ; //<- this should produce a mediaerror
} , 1 ) ;
return ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var attrStyle = { } ;
if ( loadedSwf < 1 ) {
loadedSwf = 1 ;
} else {
loadedSwf ++ ;
}
if ( ! data ) {
data = webshims . data ( elem , 'mediaelement' ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( ( attrStyle . height = $ . attr ( elem , 'height' ) || '' ) || ( attrStyle . width = $ . attr ( elem , 'width' ) || '' ) ) {
$ ( elem ) . css ( attrStyle ) ;
webshims . warn ( "width or height content attributes used. Webshims prefers the usage of CSS (computed styles or inline styles) to detect size of a video/audio. It's really more powerfull." ) ;
}
2014-08-01 01:38:33 +02:00
var box ;
var streamRequest = canPlaySrc . streamrequest ;
var isStream = canPlaySrc . type == 'jarisplayer/stream' ;
2014-07-17 16:45:12 +02:00
var hasControls = $ . prop ( elem , 'controls' ) ;
var elemId = 'jarisplayer-' + webshims . getID ( elem ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var elemNodeName = elem . nodeName . toLowerCase ( ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var setDimension = function ( ) {
if ( data . isActive == 'third' ) {
setElementDimension ( data , $ . prop ( elem , 'controls' ) ) ;
}
} ;
2014-08-01 01:38:33 +02:00
if ( isStream && ! streamRequest ) {
webshim . usermedia . attach ( elem , canPlaySrc , data ) ;
return ;
}
2014-07-17 16:45:12 +02:00
if ( data && data . swfCreated ) {
mediaelement . setActive ( elem , 'third' , data ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . currentSrc = '' ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . shadowElem . html ( '<div id="' + elemId + '">' ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . api = false ;
data . actionQueue = [ ] ;
box = data . shadowElem ;
resetSwfProps ( data ) ;
data . currentSrc = canPlaySrc . srcProp ;
} else {
$ ( document . getElementById ( 'wrapper-' + elemId ) ) . remove ( ) ;
box = $ ( '<div class="polyfill-' + ( elemNodeName ) + ' polyfill-mediaelement ' + webshims . shadowClass + '" id="wrapper-' + elemId + '"><div id="' + elemId + '"></div>' )
. css ( {
position : 'relative' ,
overflow : 'hidden'
} )
;
data = webshims . data ( elem , 'mediaelement' , webshims . objectCreate ( playerStateObj , {
actionQueue : {
value : [ ]
} ,
shadowElem : {
value : box
} ,
_elemNodeName : {
value : elemNodeName
} ,
_elem : {
value : elem
} ,
currentSrc : {
2014-08-01 01:38:33 +02:00
value : streamRequest ? '' : canPlaySrc . srcProp
2014-07-17 16:45:12 +02:00
} ,
swfCreated : {
value : true
} ,
id : {
value : elemId . replace ( /-/g , '' )
} ,
buffered : {
value : {
start : function ( index ) {
if ( index >= data . buffered . length ) {
webshims . error ( 'buffered index size error' ) ;
return ;
}
return 0 ;
} ,
end : function ( index ) {
if ( index >= data . buffered . length ) {
webshims . error ( 'buffered index size error' ) ;
return ;
}
return ( ( data . duration - data . _bufferedStart ) * data . _bufferedEnd ) + data . _bufferedStart ;
} ,
length : 0
}
}
} ) ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
box . insertBefore ( elem ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( hasNative ) {
$ . extend ( data , { volume : $ . prop ( elem , 'volume' ) , muted : $ . prop ( elem , 'muted' ) , paused : $ . prop ( elem , 'paused' ) } ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
webshims . addShadowDom ( elem , box ) ;
if ( ! webshims . data ( elem , 'mediaelement' ) ) {
webshims . data ( elem , 'mediaelement' , data ) ;
}
addMediaToStopEvents ( elem ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
mediaelement . setActive ( elem , 'third' , data ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
setElementDimension ( data , hasControls ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
$ ( elem )
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
. on ( {
'updatemediaelementdimensions loadedmetadata emptied' : setDimension ,
'remove' : function ( e ) {
if ( ! e . originalEvent && mediaelement . jarisEvent [ data . id ] && mediaelement . jarisEvent [ data . id ] . elem == elem ) {
delete mediaelement . jarisEvent [ data . id ] ;
clearTimeout ( localConnectionTimer ) ;
clearTimeout ( data . flashBlock ) ;
}
}
} )
. onWSOff ( 'updateshadowdom' , setDimension )
;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( mediaelement . jarisEvent [ data . id ] && mediaelement . jarisEvent [ data . id ] . elem != elem ) {
webshims . error ( 'something went wrong' ) ;
return ;
} else if ( ! mediaelement . jarisEvent [ data . id ] ) {
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
mediaelement . jarisEvent [ data . id ] = function ( jaris ) {
if ( jaris . type == 'ready' ) {
var onReady = function ( ) {
if ( data . api ) {
if ( ! data . paused ) {
data . api . api _play ( ) ;
}
if ( bufferSrc ( elem ) ) {
data . api . api _preload ( ) ;
}
onEvent . ready ( jaris , data ) ;
}
} ;
if ( data . api ) {
onReady ( ) ;
} else {
setTimeout ( onReady , 9 ) ;
}
} else {
data . currentTime = jaris . position ;
if ( data . api ) {
if ( ! data . _calledMeta && isNaN ( jaris . duration ) && data . duration != jaris . duration && isNaN ( data . duration ) ) {
onEvent . onDataInitialized ( jaris , data ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( ! data . _ppFlag && jaris . type != 'onPlayPause' ) {
onEvent . onPlayPause ( jaris , data ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( onEvent [ jaris . type ] ) {
onEvent [ jaris . type ] ( jaris , data ) ;
}
}
data . duration = jaris . duration ;
}
} ;
mediaelement . jarisEvent [ data . id ] . elem = elem ;
}
2014-08-01 01:38:33 +02:00
createSwf ( elem , canPlaySrc , data , elemId , hasControls , elemNodeName ) ;
if ( ! streamRequest ) {
trigger ( data . _elem , 'loadstart' ) ;
}
} ;
var createSwf = function ( elem , canPlaySrc , data , elemId , hasControls , elemNodeName ) {
var vars , elemVars , params , attrs ;
var isRtmp = canPlaySrc . type == 'audio/rtmp' || canPlaySrc . type == 'video/rtmp' ;
var isUserStream = canPlaySrc . type == 'jarisplayer/stream' ;
vars = $ . extend ( { } , options . vars , {
poster : replaceVar ( $ . attr ( elem , 'poster' ) && $ . prop ( elem , 'poster' ) || '' ) ,
source : replaceVar ( canPlaySrc . streamId || canPlaySrc . srcProp ) ,
server : replaceVar ( canPlaySrc . server || '' )
} ) ;
elemVars = $ ( elem ) . data ( 'vars' ) || { } ;
$ . extend ( vars ,
2014-07-17 16:45:12 +02:00
{
id : elemId ,
evtId : data . id ,
2014-08-01 01:38:33 +02:00
controls : '' + ( ! isUserStream && hasControls ) ,
2014-07-17 16:45:12 +02:00
autostart : 'false' ,
nodename : elemNodeName
} ,
elemVars
) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( isRtmp ) {
vars . streamtype = 'rtmp' ;
2014-08-01 01:38:33 +02:00
} else if ( isUserStream ) {
vars . streamtype = 'usermedia' ;
2014-07-17 16:45:12 +02:00
} else if ( canPlaySrc . type == 'audio/mpeg' || canPlaySrc . type == 'audio/mp3' ) {
vars . type = 'audio' ;
vars . streamtype = 'file' ;
} else if ( canPlaySrc . type == 'video/youtube' ) {
vars . streamtype = 'youtube' ;
}
2014-08-01 01:38:33 +02:00
attrs = $ . extend (
{ } ,
options . attrs ,
{
name : elemId ,
id : elemId
} ,
$ ( elem ) . data ( 'attrs' )
) ;
params = $ . extend (
{ } ,
options . params ,
$ ( elem ) . data ( 'params' )
) ;
2014-07-17 16:45:12 +02:00
options . changeSWF ( vars , elem , canPlaySrc , data , 'embed' ) ;
clearTimeout ( data . flashBlock ) ;
2014-08-01 01:38:33 +02:00
2014-09-03 00:57:03 +02:00
swfmini . embedSWF ( playerSwfPath , elemId , "100%" , "100%" , "11.3" , false , vars , params , attrs , function ( swfData ) {
2014-07-17 16:45:12 +02:00
if ( swfData . success ) {
var fBlocker = function ( ) {
2014-09-03 00:57:03 +02:00
if ( ( ! swfData . ref . parentNode ) || swfData . ref . style . display == "none" ) {
2014-07-17 16:45:12 +02:00
$ ( elem ) . trigger ( 'flashblocker' ) ;
webshims . warn ( "flashblocker assumed" ) ;
}
$ ( swfData . ref ) . css ( { 'minHeight' : '2px' , 'minWidth' : '2px' , display : 'block' } ) ;
} ;
data . api = swfData . ref ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( ! hasControls ) {
$ ( swfData . ref ) . attr ( 'tabindex' , '-1' ) . css ( 'outline' , 'none' ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . flashBlock = setTimeout ( fBlocker , 99 ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( ! localConnectionTimer ) {
clearTimeout ( localConnectionTimer ) ;
localConnectionTimer = setTimeout ( function ( ) {
fBlocker ( ) ;
var flash = $ ( swfData . ref ) ;
if ( flash [ 0 ] . offsetWidth > 1 && flash [ 0 ] . offsetHeight > 1 && location . protocol . indexOf ( 'file:' ) === 0 ) {
webshims . error ( "Add your local development-directory to the local-trusted security sandbox: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html" ) ;
} else if ( flash [ 0 ] . offsetWidth < 2 || flash [ 0 ] . offsetHeight < 2 ) {
webshims . warn ( "JS-SWF connection can't be established on hidden or unconnected flash objects" ) ;
}
flash = null ;
} , 8000 ) ;
}
2014-08-01 01:38:33 +02:00
if ( isUserStream ) {
webshim . usermedia . request ( elem , canPlaySrc , data ) ;
}
2014-07-17 16:45:12 +02:00
}
} ) ;
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
var queueSwfMethod = function ( elem , fn , args , data ) {
data = data || getSwfDataFromElem ( elem ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( data ) {
if ( data . api && data . api [ fn ] ) {
data . api [ fn ] . apply ( data . api , args || [ ] ) ;
} else {
//todo add to queue
data . actionQueue . push ( { fn : fn , args : args } ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( data . actionQueue . length > 10 ) {
setTimeout ( function ( ) {
if ( data . actionQueue . length > 5 ) {
data . actionQueue . shift ( ) ;
}
} , 99 ) ;
}
}
return data ;
}
return false ;
} ;
2014-08-01 01:38:33 +02:00
mediaelement . queueSwfMethod = queueSwfMethod ;
2014-07-17 16:45:12 +02:00
[ 'audio' , 'video' ] . forEach ( function ( nodeName ) {
var descs = { } ;
var mediaSup ;
var createGetProp = function ( key ) {
if ( nodeName == 'audio' && ( key == 'videoHeight' || key == 'videoWidth' ) ) { return ; }
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
descs [ key ] = {
get : function ( ) {
var data = getSwfDataFromElem ( this ) ;
if ( data ) {
return data [ key ] ;
} else if ( hasNative && mediaSup [ key ] . prop . _supget ) {
return mediaSup [ key ] . prop . _supget . apply ( this ) ;
} else {
return playerStateObj [ key ] ;
}
} ,
writeable : false
} ;
} ;
var createGetSetProp = function ( key , setFn ) {
createGetProp ( key ) ;
delete descs [ key ] . writeable ;
descs [ key ] . set = setFn ;
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
createGetSetProp ( 'seeking' ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
createGetSetProp ( 'volume' , function ( v ) {
var data = getSwfDataFromElem ( this ) ;
if ( data ) {
v *= 1 ;
if ( ! isNaN ( v ) ) {
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( v < 0 || v > 1 ) {
webshims . error ( 'volume greater or less than allowed ' + ( v / 100 ) ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
queueSwfMethod ( this , 'api_volume' , [ v ] , data ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( data . volume != v ) {
data . volume = v ;
trigger ( data . _elem , 'volumechange' ) ;
}
data = null ;
2014-08-01 01:38:33 +02:00
}
2014-07-17 16:45:12 +02:00
} else if ( mediaSup . volume . prop . _supset ) {
return mediaSup . volume . prop . _supset . apply ( this , arguments ) ;
}
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
createGetSetProp ( 'muted' , function ( m ) {
var data = getSwfDataFromElem ( this ) ;
if ( data ) {
m = ! ! m ;
queueSwfMethod ( this , 'api_muted' , [ m ] , data ) ;
if ( data . muted != m ) {
data . muted = m ;
trigger ( data . _elem , 'volumechange' ) ;
}
data = null ;
} else if ( mediaSup . muted . prop . _supset ) {
return mediaSup . muted . prop . _supset . apply ( this , arguments ) ;
}
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
createGetSetProp ( 'currentTime' , function ( t ) {
var data = getSwfDataFromElem ( this ) ;
if ( data ) {
t *= 1 ;
if ( ! isNaN ( t ) ) {
queueSwfMethod ( this , 'api_seek' , [ t ] , data ) ;
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
} else if ( mediaSup . currentTime . prop . _supset ) {
return mediaSup . currentTime . prop . _supset . apply ( this , arguments ) ;
}
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
[ 'play' , 'pause' ] . forEach ( function ( fn ) {
descs [ fn ] = {
value : function ( ) {
var data = getSwfDataFromElem ( this ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( data ) {
if ( data . stopPlayPause ) {
clearTimeout ( data . stopPlayPause ) ;
}
queueSwfMethod ( this , fn == 'play' ? 'api_play' : 'api_pause' , [ ] , data ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
data . _ppFlag = true ;
if ( data . paused != ( fn != 'play' ) ) {
data . paused = fn != 'play' ;
trigger ( data . _elem , fn ) ;
}
} else if ( mediaSup [ fn ] . prop . _supvalue ) {
return mediaSup [ fn ] . prop . _supvalue . apply ( this , arguments ) ;
}
}
} ;
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
getPropKeys . forEach ( createGetProp ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
webshims . onNodeNamesPropertyModify ( nodeName , 'controls' , function ( val , boolProp ) {
var data = getSwfDataFromElem ( this ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
$ ( this ) [ boolProp ? 'addClass' : 'removeClass' ] ( 'webshims-controls' ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( data ) {
if ( nodeName == 'audio' ) {
setElementDimension ( data , boolProp ) ;
}
queueSwfMethod ( this , 'api_controls' , [ boolProp ] , data ) ;
}
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
webshims . onNodeNamesPropertyModify ( nodeName , 'preload' , function ( val ) {
var data , baseData , elem ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( bufferSrc ( this ) ) {
data = getSwfDataFromElem ( this ) ;
if ( data ) {
queueSwfMethod ( this , 'api_preload' , [ ] , data ) ;
} else if ( needsLoadPreload && this . paused && ! this . error && ! $ . data ( this , 'mediaerror' ) && ! this . readyState && ! this . networkState && ! this . autoplay && $ ( this ) . is ( ':not(.nonnative-api-active)' ) ) {
elem = this ;
baseData = webshims . data ( elem , 'mediaelementBase' ) || webshims . data ( elem , 'mediaelementBase' , { } ) ;
clearTimeout ( baseData . loadTimer ) ;
baseData . loadTimer = setTimeout ( function ( ) {
$ ( elem ) . mediaLoad ( ) ;
} , 9 ) ;
}
}
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
mediaSup = webshims . defineNodeNameProperties ( nodeName , descs , 'prop' ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
if ( ! support . mediaDefaultMuted ) {
webshims . defineNodeNameProperties ( nodeName , {
defaultMuted : {
get : function ( ) {
return $ . attr ( this , 'muted' ) != null ;
} ,
set : function ( val ) {
if ( val ) {
$ . attr ( this , 'muted' , '' ) ;
} else {
$ ( this ) . removeAttr ( 'muted' ) ;
}
}
}
} , 'prop' ) ;
}
} ) ;
2014-08-01 01:38:33 +02:00
var addCanvasBridge = function ( ) {
if ( ! window . CanvasRenderingContext2D ) {
return false ;
}
var _drawImage = CanvasRenderingContext2D . prototype . drawImage ;
var slice = Array . prototype . slice ;
var isVideo = {
video : 1 ,
VIDEO : 1
} ;
var tested = { } ;
if ( ! _drawImage ) {
webshim . error ( 'canvas.drawImage feature is needed. In IE8 flashvanvas pro can be used' ) ;
}
2014-09-03 00:57:03 +02:00
CanvasRenderingContext2D . prototype . wsImageComplete = function ( cb ) {
if ( this . _wsIsLoading ) {
if ( ! this . _wsLoadingCbs ) {
this . _wsLoadingCbs = [ ] ;
}
this . _wsLoadingCbs . push ( cb ) ;
} else {
cb . call ( this , this ) ;
}
} ;
2014-08-01 01:38:33 +02:00
CanvasRenderingContext2D . prototype . drawImage = function ( elem ) {
2014-09-03 00:57:03 +02:00
var data , img , args , imgData , hadCachedImg ;
2014-08-01 01:38:33 +02:00
var context = this ;
if ( isVideo [ elem . nodeName ] && ( data = webshims . data ( elem , 'mediaelement' ) ) && data . isActive == 'third' && data . api . api _image ) {
try {
imgData = data . api . api _image ( ) ;
} catch ( er ) {
webshims . error ( er ) ;
}
if ( ! tested [ data . currentSrc ] ) {
tested [ data . currentSrc ] = true ;
if ( imgData == null ) {
webshims . error ( 'video has to be same origin or a crossdomain.xml has to be provided. Video has to be visible for flash API' ) ;
}
}
args = slice . call ( arguments , 1 ) ;
2014-09-03 00:57:03 +02:00
if ( options . canvasSync && data . canvasImg ) {
args . unshift ( data . canvasImg ) ;
_drawImage . apply ( context , args ) ;
args = slice . call ( arguments , 1 ) ;
hadCachedImg = true ;
}
img = document . createElement ( 'img' ) ;
2014-08-01 01:38:33 +02:00
//todo find a performant sync way
img . onload = function ( ) {
args . unshift ( this ) ;
img . onload = null ;
2014-09-03 00:57:03 +02:00
if ( options . canvasSync ) {
data . canvasImg = img ;
if ( hadCachedImg && options . noDoubbleDraw ) {
return ;
}
}
_drawImage . apply ( context , args ) ;
context . _wsIsLoading = false ;
if ( context . _wsLoadingCbs && context . _wsLoadingCbs . length ) {
while ( context . _wsLoadingCbs . length ) {
context . _wsLoadingCbs . shift ( ) . call ( context , context ) ;
}
}
2014-08-01 01:38:33 +02:00
} ;
img . src = 'data:image/jpeg;base64,' + imgData ;
2014-09-03 00:57:03 +02:00
this . _wsIsLoading = true ;
if ( img . complete && img . onload ) {
2014-08-01 01:38:33 +02:00
img . onload ( ) ;
}
return ;
}
return _drawImage . apply ( this , arguments ) ;
} ;
return true ;
} ;
if ( ! addCanvasBridge ( ) ) {
webshims . ready ( 'canvas' , addCanvasBridge ) ;
}
2014-07-17 16:45:12 +02:00
if ( hasFlash && $ . cleanData ) {
var oldClean = $ . cleanData ;
var objElem = document . createElement ( 'object' ) ;
var noRemove = {
SetVariable : 1 ,
GetVariable : 1 ,
SetReturnValue : 1 ,
GetReturnValue : 1
} ;
var flashNames = {
object : 1 ,
OBJECT : 1
} ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
$ . cleanData = function ( elems ) {
var i , len , prop ;
var ret = oldClean . apply ( this , arguments ) ;
if ( elems && ( len = elems . length ) && loadedSwf ) {
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
for ( i = 0 ; i < len ; i ++ ) {
if ( flashNames [ elems [ i ] . nodeName ] && 'api_destroy' in elems [ i ] ) {
loadedSwf -- ;
try {
elems [ i ] . api _destroy ( ) ;
if ( elems [ i ] . readyState == 4 ) {
for ( prop in elems [ i ] ) {
if ( ! noRemove [ prop ] && ! objElem [ prop ] && typeof elems [ i ] [ prop ] == "function" ) {
elems [ i ] [ prop ] = null ;
}
}
}
} catch ( er ) { console . log ( er ) ; }
}
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
}
return ret ;
} ;
}
if ( ! hasNative ) {
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
[ 'poster' , 'src' ] . forEach ( function ( prop ) {
webshims . defineNodeNamesProperty ( prop == 'src' ? [ 'audio' , 'video' , 'source' ] : [ 'video' ] , prop , {
//attr: {},
reflect : true ,
propType : 'src'
} ) ;
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
webshims . defineNodeNamesProperty ( [ 'audio' , 'video' ] , 'preload' , {
reflect : true ,
propType : 'enumarated' ,
defaultValue : '' ,
limitedTo : [ '' , 'auto' , 'metadata' , 'none' ]
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
webshims . reflectProperties ( 'source' , [ 'type' , 'media' ] ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
[ 'autoplay' , 'controls' ] . forEach ( function ( name ) {
webshims . defineNodeNamesBooleanProperty ( [ 'audio' , 'video' ] , name ) ;
} ) ;
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
webshims . defineNodeNamesProperties ( [ 'audio' , 'video' ] , {
HAVE _CURRENT _DATA : {
value : 2
} ,
HAVE _ENOUGH _DATA : {
value : 4
} ,
HAVE _FUTURE _DATA : {
value : 3
} ,
HAVE _METADATA : {
value : 1
} ,
HAVE _NOTHING : {
value : 0
} ,
NETWORK _EMPTY : {
value : 0
} ,
NETWORK _IDLE : {
value : 1
} ,
NETWORK _LOADING : {
value : 2
} ,
NETWORK _NO _SOURCE : {
value : 3
}
2014-08-01 01:38:33 +02:00
2014-07-17 16:45:12 +02:00
} , 'prop' ) ;
if ( hasFlash ) {
webshims . ready ( 'WINDOWLOAD' , function ( ) {
setTimeout ( function ( ) {
if ( ! loadedSwf ) {
document . createElement ( 'img' ) . src = playerSwfPath ;
}
} , 9 ) ;
} ) ;
}
} else if ( ! ( 'media' in document . createElement ( 'source' ) ) ) {
webshims . reflectProperties ( 'source' , [ 'media' ] ) ;
}
if ( hasNative && hasFlash && ! options . preferFlash ) {
var switchErrors = {
3 : 1 ,
4 : 1
} ;
var switchOptions = function ( e ) {
var media , error , parent ;
if (
( $ ( e . target ) . is ( 'audio, video' ) || ( ( parent = e . target . parentNode ) && $ ( 'source' , parent ) . last ( ) [ 0 ] == e . target ) ) &&
2014-08-01 01:38:33 +02:00
( media = $ ( e . target ) . closest ( 'audio, video' ) ) && ! media . hasClass ( 'nonnative-api-active' )
2014-07-17 16:45:12 +02:00
) {
error = media . prop ( 'error' ) ;
setTimeout ( function ( ) {
2014-07-20 02:43:13 +02:00
if ( ! media . hasClass ( 'nonnative-api-active' ) ) {
2014-07-17 16:45:12 +02:00
if ( error && switchErrors [ error . code ] ) {
options . preferFlash = true ;
document . removeEventListener ( 'error' , switchOptions , true ) ;
$ ( 'audio, video' ) . each ( function ( ) {
webshims . mediaelement . selectSource ( this ) ;
} ) ;
webshims . error ( "switching mediaelements option to 'preferFlash', due to an error with native player: " + e . target . currentSrc + " Mediaerror: " + media . prop ( 'error' ) + ' error.code: ' + error . code ) ;
}
webshims . warn ( 'There was a mediaelement error. Run the following line in your console to get more info: webshim.mediaelement.loadDebugger();' )
}
} ) ;
}
} ;
document . addEventListener ( 'error' , switchOptions , true ) ;
setTimeout ( function ( ) {
$ ( 'audio, video' ) . each ( function ( ) {
var error = $ . prop ( this , 'error' ) ;
if ( error && switchErrors [ error ] ) {
switchOptions ( { target : this } ) ;
}
} ) ;
} ) ;
}
} ) ;
; 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 ) {
var removed = [ ] ;
var added = [ ] ;
var newTracks = [ ] ;
var i , len ;
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 ] ) ;
}
}
if ( removed . length || added . length ) {
trackList . splice ( 0 ) ;
for ( i = 0 , len = newTracks . length ; i < len ; i ++ ) {
trackList . push ( newTracks [ i ] ) ;
}
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' ) ;
}
}
} ;
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' ) ;
}
} ) ;