UNPKG

webshim

Version:

modular capability-based polyfill loading libary, which extends jQuery with HTML5 features in legacy browsers

1,933 lines (1,732 loc) 69.6 kB
(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; } $.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(); } }); 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; })()); 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"; var mediaelement = webshims.mediaelement; var swfmini = window.swfmini; var support = webshims.support; var hasNative = support.mediaelement; var hasFlash = swfmini.hasFlashPlayerVersion('11.3'); 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); var getSetProps = { currentTime: 0, volume: 1, muted: false }; var getSetPropKeys = Object.keys(getSetProps); var playerStateObj = $.extend({ isActive: 'html5', activating: 'html5', wasSwfReady: false, _usermedia: null, _bufferedEnd: 0, _bufferedStart: 0, currentTime: 0, lastCalledTime: -500, _ppFlag: undefined, _calledMeta: false, lastDuration: 0, _timeDif: 0.3 }, getProps, getSetProps); var getSwfDataFromElem = function(elem){ try { (elem.nodeName); } catch(er){ return null; } var data = webshims.data(elem, 'mediaelement'); return (data && data.isActive == 'third') ? data : null; }; var trigger = function(elem, evt){ evt = $.Event(evt); evt.preventDefault(); $.event.trigger(evt, undefined, elem); }; var playerSwfPath = options.playerPath || webshims.cfg.basePath + "swf/" + (options.playerName || 'JarisFLVPlayer.swf'); 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' }); options.playerPath = playerSwfPath; 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'); } }; mediaelement.jarisEvent = mediaelement.jarisEvent || {}; var localConnectionTimer; var onEvent = { onPlayPause: function(jaris, data, override){ var playing, type; var idled = data.paused || data.ended; if(override == null){ try { playing = data.api.api_get("isPlaying"); } catch(e){} } else { playing = override; } if(playing == idled || playing == null){ data.paused = !playing; type = data.paused ? 'pause' : 'play'; data._ppFlag = true; trigger(data._elem, type); } if(!data.paused || playing == idled || playing == null){ if(data.readyState < 3){ setReadyState(3, data); } } if(!data.paused){ trigger(data._elem, 'playing'); } }, onSeek: function(jaris, data){ data._lastSeektime = jaris.seekTime; 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){ var oldDur = data.duration; var durDelta; data.duration = jaris.duration; if(oldDur == data.duration || isNaN(data.duration)){return;} if(data._calledMeta && ((durDelta = Math.abs(data.lastDuration - data.duration)) < 2)){return;} data.videoHeight = jaris.height; data.videoWidth = jaris.width; 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); } }, onProgress: function(jaris, data){ if(data.ended){ data.ended = false; } if(!data.duration || isNaN(data.duration)){ return; } var percentage = jaris.loaded / jaris.total; 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; } data._bufferedEnd = percentage; data.buffered.length = 1; $.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; try { data.api.api_get('volume'); } catch(er){ passed = false; } return passed; }; return function(jaris, data){ var i = 0; var doneFn = function(){ if(i > 9){ data.tryedReframeing = 0; return; } i++; 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'); if(!i){ doneFn(); } else { data.reframeTimer = setTimeout(doneFn, 9); } }; })() }; onEvent.onMute = onEvent.onVolumeChange; mediaelement.onEvent = onEvent; var workActionQueue = function(data){ var actionLen = data.actionQueue.length; var i = 0; var operation; 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)){ try { $(data._elem).play(); data._ppFlag = true; } catch(er){} } }, 1); } if(data.muted){ $.prop(data._elem, 'muted', true); } if(data.volume != 1){ $.prop(data._elem, 'volume', data.volume); } }; 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(' '); 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(); if(stopEvents[event.type]){ if(data.isActive != data.activating){ $(event.target).pause(); } else if(isNativeHTML5){ ($.prop(event.target, 'pause')._supvalue || $.noop).apply(event.target); } } } }; addMediaToStopEvents = function(elem){ $(elem) .off(hidevents) .on(hidevents, hidePlayerEvents) ; hideEvtArray.forEach(function(evt){ webshims.moveToFirstEvent(elem, evt); }); }; addMediaToStopEvents(document); } 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'); }; var resetSwfProps = (function(){ var resetProtoProps = ['_calledMeta', 'lastDuration', '_bufferedEnd', 'lastCalledTime', '_usermedia', '_bufferedStart', '_ppFlag', 'currentSrc', 'currentTime', 'duration', 'ended', 'networkState', 'paused', 'seeking', 'videoHeight', 'videoWidth']; var len = resetProtoProps.length; return function(data){ 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'); } }; })(); 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 }; 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}; }; 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']; 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){ var videoDims, ratio; 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() }; if(autos.width || autos.height){ videoDims = getVideoDims(data); ratio = videoDims.width / videoDims.height; 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; } if(addMinMax(elem, ret)){ data.shadowElem.css(ret); if(autos.width){ ret.width = data.shadowElem.height() * ratio; } 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; data.shadowElem.css(ret); ret.width = data.shadowElem.height() * ratio; ret.height = ret.width / ratio; } if(!webshims.support.mediaelement){ ret.width = data.shadowElem.width(); ret.height = data.shadowElem.height(); } } } return ret; }; return retFn; })(); var setElementDimension = function(data, hasControls){ var dims; 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); } } }; 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])'))); }; })(); var regs = { A: /&amp;/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; }; 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; } return src1 == src2 ? 0 : src1 ? -1 : 1; }; } } mediaelement.resetSwfProps = resetSwfProps; mediaelement.createSWF = function( elem, canPlaySrc, data ){ if(!hasFlash){ setTimeout(function(){ $(elem).mediaLoad(); //<- this should produce a mediaerror }, 1); return; } var attrStyle = {}; if(loadedSwf < 1){ loadedSwf = 1; } else { loadedSwf++; } if(!data){ data = webshims.data(elem, 'mediaelement'); } 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."); } var box; var streamRequest = canPlaySrc.streamrequest; var isStream = canPlaySrc.type == 'jarisplayer/stream'; var hasControls = $.prop(elem, 'controls'); var elemId = 'jarisplayer-'+ webshims.getID(elem); var elemNodeName = elem.nodeName.toLowerCase(); var setDimension = function(){ if(data.isActive == 'third'){ setElementDimension(data, $.prop(elem, 'controls')); } }; if(isStream && !streamRequest){ webshim.usermedia.attach(elem, canPlaySrc, data); return; } if(data && data.swfCreated){ mediaelement.setActive(elem, 'third', data); data.currentSrc = ''; data.shadowElem.html('<div id="'+ elemId +'">'); 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: { value: streamRequest ? '' : canPlaySrc.srcProp }, 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 } } })); box.insertBefore(elem); if(hasNative){ $.extend(data, {volume: $.prop(elem, 'volume'), muted: $.prop(elem, 'muted'), paused: $.prop(elem, 'paused')}); } webshims.addShadowDom(elem, box); if(!webshims.data(elem, 'mediaelement')){ webshims.data(elem, 'mediaelement', data); } addMediaToStopEvents(elem); mediaelement.setActive(elem, 'third', data); setElementDimension(data, hasControls); $(elem) .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) ; } if(mediaelement.jarisEvent[data.id] && mediaelement.jarisEvent[data.id].elem != elem){ webshims.error('something went wrong'); return; } else if(!mediaelement.jarisEvent[data.id]){ 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); } if(!data._ppFlag && jaris.type != 'onPlayPause'){ onEvent.onPlayPause(jaris, data); } if(onEvent[jaris.type]){ onEvent[jaris.type](jaris, data); } } data.duration = jaris.duration; } }; mediaelement.jarisEvent[data.id].elem = elem; } 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, { id: elemId, evtId: data.id, controls: ''+(!isUserStream && hasControls), autostart: 'false', nodename: elemNodeName }, elemVars ); if(isRtmp){ vars.streamtype = 'rtmp'; } else if(isUserStream){ vars.streamtype = 'usermedia'; } 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'; } attrs = $.extend( {}, options.attrs, { name: elemId, id: elemId }, $(elem).data('attrs') ); params = $.extend( {}, options.params, $(elem).data('params') ); options.changeSWF(vars, elem, canPlaySrc, data, 'embed'); clearTimeout(data.flashBlock); swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "11.3", false, vars, params, attrs, function(swfData){ if(swfData.success){ var fBlocker = function(){ if((!swfData.ref.parentNode) || swfData.ref.style.display == "none"){ $(elem).trigger('flashblocker'); webshims.warn("flashblocker assumed"); } $(swfData.ref).css({'minHeight': '2px', 'minWidth': '2px', display: 'block'}); }; data.api = swfData.ref; if(!hasControls){ $(swfData.ref).attr('tabindex', '-1').css('outline', 'none'); } data.flashBlock = setTimeout(fBlocker, 99); 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); } if(isUserStream){ webshim.usermedia.request(elem, canPlaySrc, data); } } }); }; var queueSwfMethod = function(elem, fn, args, data){ data = data || getSwfDataFromElem(elem); 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}); if(data.actionQueue.length > 10){ setTimeout(function(){ if(data.actionQueue.length > 5){ data.actionQueue.shift(); } }, 99); } } return data; } return false; }; mediaelement.queueSwfMethod = queueSwfMethod; ['audio', 'video'].forEach(function(nodeName){ var descs = {}; var mediaSup; var createGetProp = function(key){ if(nodeName == 'audio' && (key == 'videoHeight' || key == 'videoWidth')){return;} 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; }; createGetSetProp('seeking'); createGetSetProp('volume', function(v){ var data = getSwfDataFromElem(this); if(data){ v *= 1; if(!isNaN(v)){ if(v < 0 || v > 1){ webshims.error('volume greater or less than allowed '+ (v / 100)); } queueSwfMethod(this, 'api_volume', [v], data); if(data.volume != v){ data.volume = v; trigger(data._elem, 'volumechange'); } data = null; } } else if(mediaSup.volume.prop._supset) { return mediaSup.volume.prop._supset.apply(this, arguments); } }); 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); } }); createGetSetProp('currentTime', function(t){ var data = getSwfDataFromElem(this); if(data){ t *= 1; if (!isNaN(t)) { queueSwfMethod(this, 'api_seek', [t], data); } } else if(mediaSup.currentTime.prop._supset) { return mediaSup.currentTime.prop._supset.apply(this, arguments); } }); ['play', 'pause'].forEach(function(fn){ descs[fn] = { value: function(){ var data = getSwfDataFromElem(this); if(data){ if(data.stopPlayPause){ clearTimeout(data.stopPlayPause); } queueSwfMethod(this, fn == 'play' ? 'api_play' : 'api_pause', [], data); 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); } } }; }); getPropKeys.forEach(createGetProp); webshims.onNodeNamesPropertyModify(nodeName, 'controls', function(val, boolProp){ var data = getSwfDataFromElem(this); $(this)[boolProp ? 'addClass' : 'removeClass']('webshims-controls'); if(data){ if(nodeName == 'audio'){ setElementDimension(data, boolProp); } queueSwfMethod(this, 'api_controls', [boolProp], data); } }); webshims.onNodeNamesPropertyModify(nodeName, 'preload', function(val){ var data, baseData, elem; 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); } } }); mediaSup = webshims.defineNodeNameProperties(nodeName, descs, 'prop'); 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'); } }); 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 = {}; var addToBlob = function(){ var desc = webshim.defineNodeNameProperty('canvas', 'toBlob', { prop: { value: function(){ var context = $(this).callProp('getContext', ['2d']); var that = this; var args = arguments; var cb = function(){ return desc.prop._supvalue.apply(that, args); }; if(context.wsImageComplete && context._wsIsLoading){ context.wsImageComplete(cb); } else { return cb(); } } } }); }; if(!_drawImage){ webshim.error('canvas.drawImage feature is needed. In IE8 flashvanvas pro can be used'); } CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ if(this._wsIsLoading){ if(!this._wsLoadingCbs){ this._wsLoadingCbs = []; } this._wsLoadingCbs.push(cb); } else { cb.call(this, this); } }; CanvasRenderingContext2D.prototype.drawImage = function(elem){ var data, img, args, imgData, hadCachedImg; 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); if(options.canvasSync && data.canvasImg){ args.unshift(data.canvasImg); _drawImage.apply(context, args); args = slice.call(arguments, 1); hadCachedImg = true; } img = document.createElement('img'); //todo find a performant sync way img.onload = function(){ args.unshift(this); img.onload = null; 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); } } }; img.src = 'data:image/jpeg;base64,'+imgData; this._wsIsLoading = true; if(img.complete && img.onload){ img.onload(); } return; } return _drawImage.apply(this, arguments); }; if(!document.createElement('canvas').toBlob){ webshims.ready('filereader', addToBlob); } else { addToBlob(); } return true; }; if(!addCanvasBridge()){ webshims.ready('canvas', addCanvasBridge); } 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 }; $.cleanData = function(elems){ var i, len, prop; var ret = oldClean.apply(this, arguments); if(elems && (len = elems.length) && loadedSwf){ 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);} } } } return ret; }; } if(!hasNative){ ['poster', 'src'].forEach(function(prop){ webshims.defineNodeNamesProperty(prop == 'src' ? ['audio', 'video', 'source'] : ['video'], prop, { //attr: {}, reflect: true, propType: 'src' }); }); webshims.defineNodeNamesProperty(['audio', 'video'], 'preload', { reflect: true, propType: 'enumarated', defaultValue: '', limitedTo: ['', 'auto', 'metadata', 'none'] }); webshims.reflectProperties('source', ['type', 'media']); ['autoplay', 'controls'].forEach(function(name){ webshims.defineNodeNamesBooleanProperty(['audio', 'video'], name); }); 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 } }, '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)) && (media = $(e.target).closest('audio, video')) && !media.hasClass('nonnative-api-active') ){ error = media.prop('error'); setTimeout(function(){ if(!media.hasClass('nonnative-api-active')){ 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"); return; } } if(cue.startTime >= cue.endTime ){ webshim.error('startTime >= endTime of cue: '+ cue.text); } 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 i, len; var callChange = false; 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]); } } 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]})); } //todo: remove if(baseData.scriptedTextTracks || removed.length){ $(this).triggerHandler('updatetrackdisplay'); } } 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'); } }; 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; }, 9); } }; var isDefaultTrack = (function(){ var defaultKinds = { subtitles: { subtitles: 1, captions: 1 }, descriptions: {descriptions: 1}, chapters: {chapters: 1} }; defaultKinds.captions = defaultKinds.subtitles; return function(track){ var ki