// vim: ts=4 sts=4 sw=4 expandtab // -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License // -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project) // -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA // -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License // -- Gozala Irakli Gozalishvili Copyright (C) 2010 MIT License // -- kitcambridge Kit Cambridge Copyright (C) 2011 MIT License // -- kossnocorp Sasha Koss XXX TODO License or CLA // -- bryanforbes Bryan Forbes XXX TODO License or CLA // -- killdream Quildreen Motta Copyright (C) 2011 MIT Licence // -- michaelficarra Michael Ficarra Copyright (C) 2011 3-clause BSD License // -- sharkbrainguy Gerard Paapu Copyright (C) 2011 MIT License // -- bbqsrc Brendan Molloy XXX TODO License or CLA // -- iwyg XXX TODO License or CLA // -- DomenicDenicola Domenic Denicola XXX TODO License or CLA // -- xavierm02 Montillet Xavier XXX TODO License or CLA // -- Raynos Raynos XXX TODO License or CLA // -- samsonjs Sami Samhuri XXX TODO License or CLA // -- rwldrn Rick Waldron Copyright (C) 2011 MIT License // -- lexer Alexey Zakharov XXX TODO License or CLA /*! Copyright (c) 2009, 280 North Inc. http://280north.com/ MIT License. http://github.com/280north/narwhal/blob/master/README.md */ (function (undefined) { /** * Brings an environment as close to ECMAScript 5 compliance * as is possible with the facilities of erstwhile engines. * * ES5 Draft * http://www.ecma-international.org/publications/files/drafts/tc39-2009-050.pdf * * NOTE: this is a draft, and as such, the URL is subject to change. If the * link is broken, check in the parent directory for the latest TC39 PDF. * http://www.ecma-international.org/publications/files/drafts/ * * Previous ES5 Draft * http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf * This is a broken link to the previous draft of ES5 on which most of the * numbered specification references and quotes herein were taken. Updating * these references and quotes to reflect the new document would be a welcome * volunteer project. * * @module */ /*whatsupdoc*/ // Shortcut to an often accessed properties, in order to avoid multiple // dereference that costs universally. // _Please note: Shortcuts are defined after `Function.prototype.bind` as we // us it in defining shortcuts. var call = Function.prototype.call; var prototypeOfArray = Array.prototype; var prototypeOfObject = Object.prototype; var slice = prototypeOfArray.slice; var owns; var toString; // ES-5 15.3.4.5 // http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf if (!Function.prototype.bind) { Function.prototype.bind = function (that) { // .length is 1 // 1. Let Target be the this value. var target = this; // 2. If IsCallable(Target) is false, throw a TypeError exception. if (typeof target != "function") throw new TypeError(); // TODO message // 3. Let A be a new (possibly empty) internal list of all of the // argument values provided after thisArg (arg1, arg2 etc), in order. // XXX slicedArgs will stand in for "A" if used var args = slice.call(arguments, 1); // for normal call // 4. Let F be a new native ECMAScript object. // 9. Set the [[Prototype]] internal property of F to the standard // built-in Function prototype object as specified in 15.3.3.1. // 10. Set the [[Call]] internal property of F as described in // 15.3.4.5.1. // 11. Set the [[Construct]] internal property of F as described in // 15.3.4.5.2. // 12. Set the [[HasInstance]] internal property of F as described in // 15.3.4.5.3. // 13. The [[Scope]] internal property of F is unused and need not // exist. var bound = function () { if (this instanceof bound) { // 15.3.4.5.2 [[Construct]] // When the [[Construct]] internal method of a function object, // F that was created using the bind function is called with a // list of arguments ExtraArgs the following steps are taken: // 1. Let target be the value of F's [[TargetFunction]] // internal property. // 2. If target has no [[Construct]] internal method, a // TypeError exception is thrown. // 3. Let boundArgs be the value of F's [[BoundArgs]] internal // property. // 4. Let args be a new list containing the same values as the // list boundArgs in the same order followed by the same // values as the list ExtraArgs in the same order. var F = function(){}; F.prototype = target.prototype; var self = new F; var result = target.apply( self, args.concat(slice.call(arguments)) ); if (result !== null && Object(result) === result) return result; return self; } else { // 15.3.4.5.1 [[Call]] // When the [[Call]] internal method of a function object, F, // which was created using the bind function is called with a // this value and a list of arguments ExtraArgs the following // steps are taken: // 1. Let boundArgs be the value of F's [[BoundArgs]] internal // property. // 2. Let boundThis be the value of F's [[BoundThis]] internal // property. // 3. Let target be the value of F's [[TargetFunction]] internal // property. // 4. Let args be a new list containing the same values as the list // boundArgs in the same order followed by the same values as // the list ExtraArgs in the same order. 5. Return the // result of calling the [[Call]] internal method of target // providing boundThis as the this value and providing args // as the arguments. // equiv: target.call(this, ...boundArgs, ...args) return target.apply( that, args.concat(slice.call(arguments)) ); } }; // XXX bound.length is never writable, so don't even try // // 16. The length own property of F is given attributes as specified in // 15.3.5.1. // TODO // 17. Set the [[Extensible]] internal property of F to true. // TODO // 18. Call the [[DefineOwnProperty]] internal method of F with // arguments "caller", PropertyDescriptor {[[Value]]: null, // [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: // false}, and false. // TODO // 19. Call the [[DefineOwnProperty]] internal method of F with // arguments "arguments", PropertyDescriptor {[[Value]]: null, // [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: // false}, and false. // TODO // NOTE Function objects created using Function.prototype.bind do not // have a prototype property. // XXX can't delete it in pure-js. return bound; }; } toString = call.bind(prototypeOfObject.toString); owns = call.bind(prototypeOfObject.hasOwnProperty); // // Array // ===== // // ES5 15.4.3.2 if (!Array.isArray) { Array.isArray = function (obj) { return toString(obj) == "[object Array]"; }; } // The IsCallable() check in the Array functions // has been replaced with a strict check on the // internal class of the object to trap cases where // the provided function was actually a regular // expression literal, which in V8 and // JavaScriptCore is a typeof "function". Only in // V8 are regular expression literals permitted as // reduce parameters, so it is desirable in the // general case for the shim to match the more // strict and common behavior of rejecting regular // expressions. // ES5 15.4.4.18 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach if (!Array.prototype.forEach) { Array.prototype.forEach = function (fun /*, thisp*/) { var self = toObject(this), thisp = arguments[1], i = 0, length = self.length >>> 0; // If no callback function or if callback is not a callable function if (toString(fun) != "[object Function]") { throw new TypeError(); // TODO message } while (i < length) { if (i in self) { // Invoke the callback function with call, passing arguments: // context, property value, property key, thisArg object context fun.call(thisp, self[i], i, self); } i++; } }; } // ES5 15.4.4.19 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map if (!Array.prototype.map) { Array.prototype.map = function (fun /*, thisp*/) { var self = toObject(this), length = self.length >>> 0, result = Array(length), thisp = arguments[1]; // If no callback function or if callback is not a callable function if (toString(fun) != "[object Function]") { throw new TypeError(); // TODO message } for (var i = 0; i < length; i++) { if (i in self) result[i] = fun.call(thisp, self[i], i, self); } return result; }; } // ES5 15.4.4.20 if (!Array.prototype.filter) { Array.prototype.filter = function (fun /*, thisp */) { var self = toObject(this), length = self.length >>> 0, result = [], thisp = arguments[1]; // If no callback function or if callback is not a callable function if (toString(fun) != "[object Function]") { throw new TypeError(); // TODO message } for (var i = 0; i < length; i++) { if (i in self && fun.call(thisp, self[i], i, self)) result.push(self[i]); } return result; }; } // ES5 15.4.4.16 if (!Array.prototype.every) { Array.prototype.every = function (fun /*, thisp */) { var self = toObject(this), length = self.length >>> 0, thisp = arguments[1]; // If no callback function or if callback is not a callable function if (toString(fun) != "[object Function]") { throw new TypeError(); // TODO message } for (var i = 0; i < length; i++) { if (i in self && !fun.call(thisp, self[i], i, self)) return false; } return true; }; } // ES5 15.4.4.17 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some if (!Array.prototype.some) { Array.prototype.some = function (fun /*, thisp */) { var self = toObject(this), length = self.length >>> 0, thisp = arguments[1]; // If no callback function or if callback is not a callable function if (toString(fun) != "[object Function]") { throw new TypeError(); // TODO message } for (var i = 0; i < length; i++) { if (i in self && fun.call(thisp, self[i], i, self)) return true; } return false; }; } // ES5 15.4.4.21 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce if (!Array.prototype.reduce) { Array.prototype.reduce = function (fun /*, initial*/) { var self = toObject(this), length = self.length >>> 0; // If no callback function or if callback is not a callable function if (toString(fun) != "[object Function]") { throw new TypeError(); // TODO message } // no value to return if no initial value and an empty array if (!length && arguments.length == 1) throw new TypeError(); // TODO message var i = 0; var result; if (arguments.length >= 2) { result = arguments[1]; } else { do { if (i in self) { result = self[i++]; break; } // if array contains no values, no initial value to return if (++i >= length) throw new TypeError(); // TODO message } while (true); } for (; i < length; i++) { if (i in self) result = fun.call(void 0, result, self[i], i, self); } return result; }; } // ES5 15.4.4.22 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight if (!Array.prototype.reduceRight) { Array.prototype.reduceRight = function (fun /*, initial*/) { var self = toObject(this), length = self.length >>> 0; // If no callback function or if callback is not a callable function if (toString(fun) != "[object Function]") { throw new TypeError(); // TODO message } // no value to return if no initial value, empty array if (!length && arguments.length == 1) throw new TypeError(); // TODO message var result, i = length - 1; if (arguments.length >= 2) { result = arguments[1]; } else { do { if (i in self) { result = self[i--]; break; } // if array contains no values, no initial value to return if (--i < 0) throw new TypeError(); // TODO message } while (true); } do { if (i in this) result = fun.call(void 0, result, self[i], i, self); } while (i--); return result; }; } // ES5 15.4.4.14 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (sought /*, fromIndex */ ) { var self = toObject(this), length = self.length >>> 0; if (!length) return -1; var i = 0; if (arguments.length > 1) i = toInteger(arguments[1]); // handle negative indices i = i >= 0 ? i : length - Math.abs(i); for (; i < length; i++) { if (i in self && self[i] === sought) { return i; } } return -1; }; } // ES5 15.4.4.15 if (!Array.prototype.lastIndexOf) { Array.prototype.lastIndexOf = function (sought /*, fromIndex */) { var self = toObject(this), length = self.length >>> 0; if (!length) return -1; var i = length - 1; if (arguments.length > 1) i = toInteger(arguments[1]); // handle negative indices i = i >= 0 ? i : length - Math.abs(i); for (; i >= 0; i--) { if (i in self && sought === self[i]) return i; } return -1; }; } // // Array // ===== // // ES5 15.4.4.12 // http://es5.github.com/#x15.4.4.12 // Default value for second param // [bugfix, ielt9, old browsers] // IE < 9 bug: [1,2].splice(0).join("") == "" but should be "12" if([1,2].splice(0).length != 2) { var _origArraySplice = Array.prototype.splice; Array.prototype.splice = function(start, deleteCount) { if(!arguments.length)return []; return _origArraySplice.apply(this, [ start === void 0 ? 0 : start, deleteCount === void 0 ? (this.length - start) : deleteCount ].concat(slice.call(arguments, 2))) }; } // // Object // ====== // // ES5 15.2.3.14 // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation if (!Object.keys) { var hasDontEnumBug = true, dontEnums = [ "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "constructor" ], dontEnumsLength = dontEnums.length; for (var key in {"toString": null}) hasDontEnumBug = false; Object.keys = function keys(object) { if ((typeof object != "object" && typeof object != "function") || object === null) throw new TypeError("Object.keys called on a non-object"); var keys = []; for (var name in object) { if (owns(object, name)) { keys.push(name); } } if (hasDontEnumBug) { for (var i = 0, ii = dontEnumsLength; i < ii; i++) { var dontEnum = dontEnums[i]; if (owns(object, dontEnum)) { keys.push(dontEnum); } } } return keys; }; } // // Date // ==== // // ES5 15.9.5.43 // Format a Date object as a string according to a simplified subset of the ISO 8601 // standard as defined in 15.9.1.15. if (!Date.prototype.toISOString) { Date.prototype.toISOString = function toISOString() { var result, length, value; if (!isFinite(this)) throw new RangeError; // the date time string format is specified in 15.9.1.15. result = [this.getUTCFullYear(), this.getUTCMonth() + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()]; length = result.length; while (length--) { value = result[length]; // pad months, days, hours, minutes, and seconds to have two digits. if (value < 10) result[length] = "0" + value; } // pad milliseconds to have three digits. return result.slice(0, 3).join("-") + "T" + result.slice(3).join(":") + "." + ("000" + this.getUTCMilliseconds()).slice(-3) + "Z"; } } // ES5 15.9.4.4 if (!Date.now) { Date.now = function now() { return new Date().getTime(); }; } // ES5 15.9.5.44 if (!Date.prototype.toJSON) { Date.prototype.toJSON = function toJSON(key) { // This function provides a String representation of a Date object for // use by JSON.stringify (15.12.3). When the toJSON method is called // with argument key, the following steps are taken: // 1. Let O be the result of calling ToObject, giving it the this // value as its argument. // 2. Let tv be ToPrimitive(O, hint Number). // 3. If tv is a Number and is not finite, return null. // XXX // 4. Let toISO be the result of calling the [[Get]] internal method of // O with argument "toISOString". // 5. If IsCallable(toISO) is false, throw a TypeError exception. if (typeof this.toISOString != "function") throw new TypeError(); // TODO message // 6. Return the result of calling the [[Call]] internal method of // toISO with O as the this value and an empty argument list. return this.toISOString(); // NOTE 1 The argument is ignored. // NOTE 2 The toJSON function is intentionally generic; it does not // require that its this value be a Date object. Therefore, it can be // transferred to other kinds of objects for use as a method. However, // it does require that any such object have a toISOString method. An // object is free to use the argument key to filter its // stringification. }; } // // String // ====== // // ES5 15.5.4.20 var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + "\u2029\uFEFF"; if (!String.prototype.trim || ws.trim()) { // http://blog.stevenlevithan.com/archives/faster-trim-javascript // http://perfectionkills.com/whitespace-deviations/ ws = "[" + ws + "]"; var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), trimEndRegexp = new RegExp(ws + ws + "*$"); String.prototype.trim = function trim() { return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); }; } // ES5 15.5.4.14 // http://es5.github.com/#x15.5.4.14 // [bugfix, chrome] // If separator is undefined, then the result array contains just one String, which is the this value (converted to a String). If limit is not undefined, then the output array is truncated so that it contains no more than limit elements. // "0".split(undefined, 0) -> [] if("0".split(void 0, 0).length) { var oldSplit = String.prototype.split; String.prototype.split = function(separator, limit) { if(separator === void 0 && limit === 0)return []; return oldSplit.apply(this, arguments); } } // ECMA-262, 3rd B.2.3 // Note an ECMAScript standart, although ECMAScript 3rd Edition has a non-normative section suggesting uniform semantics // and it should be normalized across all browsers // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE if("".substr && "0b".substr(-1) !== "b") { var oldSubstr = String.prototype.substr; /** * Get the substring of a string * @param {integer} start where to start the substring * @param {integer} length how many characters to return * @return {string} */ String.prototype.substr = function(start, length) { return oldSubstr.call(this, start < 0 ? (start = this.length + start) < 0 ? 0 : start : start, length); } } // // Util // ====== // // http://jsperf.com/to-integer var toInteger = function (n) { n = +n; if (n !== n) // isNaN n = -1; else if (n !== 0 && n !== (1/0) && n !== -(1/0)) n = (n > 0 || -1) * Math.floor(Math.abs(n)); return n; }; var prepareString = "a"[0] != "a", // ES5 9.9 toObject = function (o) { if (o == null) { // this matches both null and undefined throw new TypeError(); // TODO message } // If the implementation doesn't support by-index access of // string characters (ex. IE < 7), split the string if (prepareString && typeof o == "string" && o) { return o.split(""); } return Object(o); }; })(); (function($, shims){ var defineProperty = 'defineProperty'; var advancedObjectProperties = !!(Object.create && Object.defineProperties && Object.getOwnPropertyDescriptor); //safari5 has defineProperty-interface, but it can't be used on dom-object //only do this test in non-IE browsers, because this hurts dhtml-behavior in some IE8 versions if (advancedObjectProperties && !$.browser.msie && Object[defineProperty] && Object.prototype.__defineGetter__) { (function(){ try { var foo = document.createElement('foo'); Object[defineProperty](foo, 'bar', { get: function(){ return true; } }); advancedObjectProperties = !!foo.bar; } catch (e) { advancedObjectProperties = false; } foo = null; })(); } Modernizr.objectAccessor = !!((advancedObjectProperties || (Object.prototype.__defineGetter__ && Object.prototype.__lookupSetter__)) && (!$.browser.opera || shims.browserVersion >= 11)); Modernizr.advancedObjectProperties = advancedObjectProperties; if((!advancedObjectProperties || !Object.create || !Object.defineProperties || !Object.getOwnPropertyDescriptor || !Object.defineProperty)){ var call = Function.prototype.call; var prototypeOfObject = Object.prototype; var owns = call.bind(prototypeOfObject.hasOwnProperty); shims.objectCreate = function(proto, props, opts, no__proto__){ var o; var f = function(){}; f.prototype = proto; o = new f(); if(!no__proto__ && !('__proto__' in o) && !Modernizr.objectAccessor){ o.__proto__ = proto; } if(props){ shims.defineProperties(o, props); } if(opts){ o.options = jQuery.extend(true, {}, o.options || {}, opts); opts = o.options; } if(o._create && jQuery.isFunction(o._create)){ o._create(opts); } return o; }; shims.defineProperties = function(object, props){ for (var name in props) { if (owns(props, name)) { shims.defineProperty(object, name, props[name]); } } return object; }; var descProps = ['configurable', 'enumerable', 'writable']; shims.defineProperty = function(proto, property, descriptor){ if(typeof descriptor != "object" || descriptor === null){return proto;} if(owns(descriptor, "value")){ proto[property] = descriptor.value; return proto; } if(proto.__defineGetter__){ if (typeof descriptor.get == "function") { proto.__defineGetter__(property, descriptor.get); } if (typeof descriptor.set == "function"){ proto.__defineSetter__(property, descriptor.set); } } return proto; }; shims.getPrototypeOf = function (object) { return Object.getPrototypeOf && Object.getPrototypeOf(object) || object.__proto__ || object.constructor && object.constructor.prototype; }; //based on http://www.refactory.org/s/object_getownpropertydescriptor/view/latest shims.getOwnPropertyDescriptor = function(obj, prop){ if (typeof obj !== "object" && typeof obj !== "function" || obj === null){ throw new TypeError("Object.getOwnPropertyDescriptor called on a non-object"); } var descriptor; if(Object.defineProperty && Object.getOwnPropertyDescriptor){ try{ descriptor = Object.getOwnPropertyDescriptor(obj, prop); return descriptor; } catch(e){} } descriptor = { configurable: true, enumerable: true, writable: true, value: undefined }; var getter = obj.__lookupGetter__ && obj.__lookupGetter__(prop), setter = obj.__lookupSetter__ && obj.__lookupSetter__(prop) ; if (!getter && !setter) { // not an accessor so return prop if(!owns(obj, prop)){ return; } descriptor.value = obj[prop]; return descriptor; } // there is an accessor, remove descriptor.writable; populate descriptor.get and descriptor.set delete descriptor.writable; delete descriptor.value; descriptor.get = descriptor.set = undefined; if(getter){ descriptor.get = getter; } if(setter){ descriptor.set = setter; } return descriptor; }; } })(jQuery, jQuery.webshims); (function($, Modernizr, webshims){ "use strict"; var hasNative = Modernizr.audio && Modernizr.video; var supportsLoop = false; var options = webshims.cfg.mediaelement; var bugs = webshims.bugs; var swfType = options.player == 'jwplayer' ? 'mediaelement-swf' : 'mediaelement-jaris' var loadSwf = function(){ webshims.ready(swfType, function(){ if(!webshims.mediaelement.createSWF){ webshims.mediaelement.loadSwf = true; webshims.reTest([swfType], hasNative); } }); }; var hasSwf; if(hasNative){ var videoElem = document.createElement('video'); Modernizr.videoBuffered = ('buffered' in videoElem); supportsLoop = ('loop' in videoElem); webshims.capturingEvents(['play', 'playing', 'waiting', 'paused', 'ended', 'durationchange', 'loadedmetadata', 'canplay', 'volumechange']); if(!Modernizr.videoBuffered){ webshims.addPolyfill('mediaelement-native-fix', { f: 'mediaelement', test: Modernizr.videoBuffered, d: ['dom-support'] }); webshims.reTest('mediaelement-native-fix'); } } if(hasNative && !options.preferFlash){ var switchOptions = function(e){ var parent = e.target.parentNode; if(!options.preferFlash && ($(e.target).is('audio, video') || (parent && $('source:last', parent)[0] == e.target)) ){ webshims.ready('DOM mediaelement', function(){ if(hasSwf){ loadSwf(); } webshims.ready('WINDOWLOAD '+swfType, function(){ setTimeout(function(){ if(hasSwf && !options.preferFlash && webshims.mediaelement.createSWF && !$(e.target).closest('audio, video').is('.nonnative-api-active')){ options.preferFlash = true; document.removeEventListener('error', switchOptions, true); $('audio, video').mediaLoad(); webshims.info("switching mediaelements option to 'preferFlash', due to an error with native player: "+e.target.src); } else if(!hasSwf){ document.removeEventListener('error', switchOptions, true); } }, 20); }); }); } }; document.addEventListener('error', switchOptions, true); $('audio, video').each(function(){ if(this.error){ switchOptions({target: this}); } }); } bugs.track = false; if(Modernizr.track){ (function(){ if(!bugs.track){ bugs.track = typeof $('')[0].readyState != 'number'; } if(!bugs.track){ try { new TextTrackCue(2, 3, ''); } catch(e){ bugs.track = true; } } var trackOptions = webshims.cfg.track; var trackListener = function(e){ $(e.target).filter('track').each(changeApi); }; var changeApi = function(){ if(bugs.track || (!trackOptions.override && $.prop(this, 'readyState') == 3)){ trackOptions.override = true; webshims.reTest('track'); document.removeEventListener('error', trackListener, true); if(this && $.nodeName(this, 'track')){ webshims.error("track support was overwritten. Please check your vtt including your vtt mime-type"); } else { webshims.info("track support was overwritten. due to bad browser support"); } } }; var detectTrackError = function(){ document.addEventListener('error', trackListener, true); if(bugs.track){ changeApi(); } else { $('track').each(changeApi); } }; if(!trackOptions.override){ if(webshims.isReady('track')){ detectTrackError(); } else { $(detectTrackError); } } })(); } webshims.register('mediaelement-core', function($, webshims, window, document, undefined){ hasSwf = swfobject.hasFlashPlayerVersion('9.0.115'); var mediaelement = webshims.mediaelement; var getSrcObj = function(elem, nodeName){ elem = $(elem); var src = {src: elem.attr('src') || '', elem: elem, srcProp: elem.prop('src')}; if(!src.src){return src;} var tmp = elem.attr('type'); if(tmp){ src.type = tmp; src.container = $.trim(tmp.split(';')[0]); } else { if(!nodeName){ nodeName = elem[0].nodeName.toLowerCase(); if(nodeName == 'source'){ nodeName = (elem.closest('video, audio')[0] || {nodeName: 'video'}).nodeName.toLowerCase(); } } tmp = mediaelement.getTypeForSrc(src.src, nodeName ); if(tmp){ src.type = tmp; src.container = tmp; } } tmp = elem.attr('media'); if(tmp){ src.media = tmp; } return src; }; var hasYt = !hasSwf && ('postMessage' in window) && hasNative; var loadYt = (function(){ var loaded; return function(){ if(loaded || !hasYt){return;} loaded = true; webshims.loader.loadScript("https://www.youtube.com/player_api"); $(function(){ webshims.polyfill("mediaelement-yt"); }); }; })(); var loadThird = function(){ if(hasSwf){ loadSwf(); } else { loadYt(); } }; webshims.addPolyfill('mediaelement-yt', { test: !hasYt, d: ['dom-support'] }); mediaelement.mimeTypes = { audio: { //ogm shouldn´t be used! 'audio/ogg': ['ogg','oga', 'ogm'], 'audio/ogg;codecs="opus"': 'opus', 'audio/mpeg': ['mp2','mp3','mpga','mpega'], 'audio/mp4': ['mp4','mpg4', 'm4r', 'm4a', 'm4p', 'm4b', 'aac'], 'audio/wav': ['wav'], 'audio/3gpp': ['3gp','3gpp'], 'audio/webm': ['webm'], 'audio/fla': ['flv', 'f4a', 'fla'], 'application/x-mpegURL': ['m3u8', 'm3u'] }, video: { //ogm shouldn´t be used! 'video/ogg': ['ogg','ogv', 'ogm'], 'video/mpeg': ['mpg','mpeg','mpe'], 'video/mp4': ['mp4','mpg4', 'm4v'], 'video/quicktime': ['mov','qt'], 'video/x-msvideo': ['avi'], 'video/x-ms-asf': ['asf', 'asx'], 'video/flv': ['flv', 'f4v'], 'video/3gpp': ['3gp','3gpp'], 'video/webm': ['webm'], 'application/x-mpegURL': ['m3u8', 'm3u'], 'video/MP2T': ['ts'] } } ; mediaelement.mimeTypes.source = $.extend({}, mediaelement.mimeTypes.audio, mediaelement.mimeTypes.video); mediaelement.getTypeForSrc = function(src, nodeName){ if(src.indexOf('youtube.com/watch?') != -1 || src.indexOf('youtube.com/v/') != -1){ return 'video/youtube'; } src = src.split('?')[0].split('.'); src = src[src.length - 1]; var mt; $.each(mediaelement.mimeTypes[nodeName], function(mimeType, exts){ if(exts.indexOf(src) !== -1){ mt = mimeType; return false; } }); return mt; }; mediaelement.srces = function(mediaElem, srces){ mediaElem = $(mediaElem); if(!srces){ srces = []; var nodeName = mediaElem[0].nodeName.toLowerCase(); var src = getSrcObj(mediaElem, nodeName); if(!src.src){ $('source', mediaElem).each(function(){ src = getSrcObj(this, nodeName); if(src.src){srces.push(src);} }); } else { srces.push(src); } return srces; } else { mediaElem.removeAttr('src').removeAttr('type').find('source').remove(); if(!$.isArray(srces)){ srces = [srces]; } srces.forEach(function(src){ var source = document.createElement('source'); if(typeof src == 'string'){ src = {src: src}; } source.setAttribute('src', src.src); if(src.type){ source.setAttribute('type', src.type); } if(src.media){ source.setAttribute('media', src.media); } mediaElem.append(source); }); } }; $.fn.loadMediaSrc = function(srces, poster){ return this.each(function(){ if(poster !== undefined){ $(this).removeAttr('poster'); if(poster){ $.attr(this, 'poster', poster); } } mediaelement.srces(this, srces); $(this).mediaLoad(); }); }; mediaelement.swfMimeTypes = ['video/3gpp', 'video/x-msvideo', 'video/quicktime', 'video/x-m4v', 'video/mp4', 'video/m4p', 'video/x-flv', 'video/flv', 'audio/mpeg', 'audio/aac', 'audio/mp4', 'audio/x-m4a', 'audio/m4a', 'audio/mp3', 'audio/x-fla', 'audio/fla', 'youtube/flv', 'jwplayer/jwplayer', 'video/youtube']; mediaelement.canThirdPlaySrces = function(mediaElem, srces){ var ret = ''; if(hasSwf || hasYt){ mediaElem = $(mediaElem); srces = srces || mediaelement.srces(mediaElem); $.each(srces, function(i, src){ if(src.container && src.src && ((hasSwf && mediaelement.swfMimeTypes.indexOf(src.container) != -1) || (hasYt && src.container == 'video/youtube'))){ ret = src; return false; } }); } return ret; }; var nativeCanPlayType = {}; mediaelement.canNativePlaySrces = function(mediaElem, srces){ var ret = ''; if(hasNative){ mediaElem = $(mediaElem); var nodeName = (mediaElem[0].nodeName || '').toLowerCase(); if(!nativeCanPlayType[nodeName]){return ret;} srces = srces || mediaelement.srces(mediaElem); $.each(srces, function(i, src){ if(src.type && nativeCanPlayType[nodeName].prop._supvalue.call(mediaElem[0], src.type) ){ ret = src; return false; } }); } return ret; }; mediaelement.setError = function(elem, message){ if(!message){ message = "can't play sources"; } $(elem).pause().data('mediaerror', message); webshims.warn('mediaelementError: '+ message); setTimeout(function(){ if($(elem).data('mediaerror')){ $(elem).trigger('mediaerror'); } }, 1); }; var handleThird = (function(){ var requested; return function( mediaElem, ret, data ){ webshims.ready(hasSwf ? swfType : 'mediaelement-yt', function(){ if(mediaelement.createSWF){ mediaelement.createSWF( mediaElem, ret, data ); } else if(!requested) { requested = true; loadThird(); //readd to ready handleThird( mediaElem, ret, data ); } }); if(!requested && hasYt && !mediaelement.createSWF){ loadYt(); } }; })(); var stepSources = function(elem, data, useSwf, _srces, _noLoop){ var ret; if(useSwf || (useSwf !== false && data && data.isActive == 'third')){ ret = mediaelement.canThirdPlaySrces(elem, _srces); if(!ret){ if(_noLoop){ mediaelement.setError(elem, false); } else { stepSources(elem, data, false, _srces, true); } } else { handleThird(elem, ret, data); } } else { ret = mediaelement.canNativePlaySrces(elem, _srces); if(!ret){ if(_noLoop){ mediaelement.setError(elem, false); if(data && data.isActive == 'third') { mediaelement.setActive(elem, 'html5', data); } } else { stepSources(elem, data, true, _srces, true); } } else if(data && data.isActive == 'third') { mediaelement.setActive(elem, 'html5', data); } } }; var stopParent = /^(?:embed|object|datalist)$/i; var selectSource = function(elem, data){ var baseData = webshims.data(elem, 'mediaelementBase') || webshims.data(elem, 'mediaelementBase', {}); var _srces = mediaelement.srces(elem); var parent = elem.parentNode; clearTimeout(baseData.loadTimer); $.data(elem, 'mediaerror', false); if(!_srces.length || !parent || parent.nodeType != 1 || stopParent.test(parent.nodeName || '')){return;} data = data || webshims.data(elem, 'mediaelement'); stepSources(elem, data, options.preferFlash || undefined, _srces); }; $(document).on('ended', function(e){ var data = webshims.data(e.target, 'mediaelement'); if( supportsLoop && (!data || data.isActive == 'html5') && !$.prop(e.target, 'loop')){return;} setTimeout(function(){ if( $.prop(e.target, 'paused') || !$.prop(e.target, 'loop') ){return;} $(e.target).prop('currentTime', 0).play(); }, 1); }); if(!supportsLoop){ webshims.defineNodeNamesBooleanProperty(['audio', 'video'], 'loop'); } ['audio', 'video'].forEach(function(nodeName){ var supLoad = webshims.defineNodeNameProperty(nodeName, 'load', { prop: { value: function(){ var data = webshims.data(this, 'mediaelement'); selectSource(this, data); if(hasNative && (!data || data.isActive == 'html5') && supLoad.prop._supvalue){ supLoad.prop._supvalue.apply(this, arguments); } } } }); nativeCanPlayType[nodeName] = webshims.defineNodeNameProperty(nodeName, 'canPlayType', { prop: { value: function(type){ var ret = ''; if(hasNative && nativeCanPlayType[nodeName].prop._supvalue){ ret = nativeCanPlayType[nodeName].prop._supvalue.call(this, type); if(ret == 'no'){ ret = ''; } } if(!ret && hasSwf){ type = $.trim((type || '').split(';')[0]); if(mediaelement.swfMimeTypes.indexOf(type) != -1){ ret = 'maybe'; } } return ret; } } }); }); webshims.onNodeNamesPropertyModify(['audio', 'video'], ['src', 'poster'], { set: function(){ var elem = this; var baseData = webshims.data(elem, 'mediaelementBase') || webshims.data(elem, 'mediaelementBase', {}); clearTimeout(baseData.loadTimer); baseData.loadTimer = setTimeout(function(){ selectSource(elem); elem = null; }, 9); } }); var initMediaElements = function(){ webshims.addReady(function(context, insertedElement){ $('video, audio', context) .add(insertedElement.filter('video, audio')) .each(function(){ if($.browser.msie && webshims.browserVersion > 8 && $.prop(this, 'paused') && !$.prop(this, 'readyState') && $(this).is('audio[preload="none"][controls]:not([autoplay])')){ $(this).prop('preload', 'metadata').mediaLoad(); } else { selectSource(this); } if(hasNative){ var bufferTimer; var lastBuffered; var elem = this; var getBufferedString = function(){ var buffered = $.prop(elem, 'buffered'); if(!buffered){return;} var bufferString = ""; for(var i = 0, len = buffered.length; i < len;i++){ bufferString += buffered.end(i); } return bufferString; }; var testBuffer = function(){ var buffered = getBufferedString(); if(buffered != lastBuffered){ lastBuffered = buffered; $(elem).triggerHandler('progress'); } }; $(this) .on({ 'play loadstart progress': function(e){ if(e.type == 'progress'){ lastBuffered = getBufferedString(); } clearTimeout(bufferTimer); bufferTimer = setTimeout(testBuffer, 999); }, 'emptied stalled mediaerror abort suspend': function(e){ if(e.type == 'emptied'){ lastBuffered = false; } clearTimeout(bufferTimer); } }) ; } }) ; }); }; if(Modernizr.track && !bugs.track){ webshims.defineProperty(TextTrack.prototype, 'shimActiveCues', { get: function(){ return this._shimActiveCues || this.activeCues; } }); } //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); initMediaElements(); webshims.ready('WINDOWLOAD mediaelement', loadThird); } else { webshims.ready(swfType, initMediaElements); } $(function(){ webshims.loader.loadList(['track-ui']); }); }); })(jQuery, Modernizr, jQuery.webshims);/* * todos: * - decouple muted/volume (needs improvement) * - implement video <-> flashcanvas pro API * - improve buffered-property with youtube/rtmp * - use jwplayer5 api instead of old flash4 api */ jQuery.webshims.register('mediaelement-swf', function($, webshims, window, document, undefined, options){ "use strict"; var SENDEVENT = 'sendEvent'; var mediaelement = webshims.mediaelement; var swfobject = window.swfobject; var hasNative = Modernizr.audio && Modernizr.video; var hasFlash = swfobject.hasFlashPlayerVersion('9.0.115'); var loadedSwf = 0; var getProps = { paused: true, ended: false, currentSrc: '', duration: window.NaN, readyState: 0, networkState: 0, videoHeight: 0, videoWidth: 0, 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, _bufferedEnd: 0, _bufferedStart: 0, _metadata: false, _durationCalcs: -1, _callMeta: false, currentTime: 0, _ppFlag: undefined }, getProps, getSetProps); var idRep = /^jwplayer-/; var getSwfDataFromID = function(id){ var elem = document.getElementById(id.replace(idRep, '')); if(!elem){return;} var data = webshims.data(elem, 'mediaelement'); return data.isActive == 'third' ? data : null; }; 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 + "jwplayer/" + (options.playerName || "player.swf"); var jwplugin = options.pluginPath || webshims.cfg.basePath +'swf/jwwebshims.swf'; webshims.extendUNDEFProp(options.params, { allowscriptaccess: 'always', allowfullscreen: 'true', wmode: 'transparent' }); webshims.extendUNDEFProp(options.vars, { screencolor: 'ffffffff' }); webshims.extendUNDEFProp(options.attrs, { bgcolor: '#000000' }); var getDuration = function(data, obj){ var curDuration = data.duration; if(curDuration && data._durationCalcs > 0){return;} try { data.duration = data.jwapi.getPlaylist()[0].duration; if(!data.duration || data.duration <= 0 || data.duration === data._lastDuration){ data.duration = curDuration; } } catch(er){} if(data.duration && data.duration != data._lastDuration){ trigger(data._elem, 'durationchange'); if(data._elemNodeName == 'audio' || data._callMeta){ mediaelement.jwEvents.Model.META($.extend({duration: data.duration}, obj), data); } data._durationCalcs--; } else { data._durationCalcs++; } }; var setReadyState = function(readyState, data){ if(readyState < 3){ clearTimeout(data._canplaythroughTimer); } if(readyState >= 3 && data.readyState < 3){ data.readyState = readyState; trigger(data._elem, 'canplay'); 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; }; $.extend($.event.customEvent, { updatemediaelementdimensions: true, flashblocker: true, swfstageresize: true, mediaelementapichange: true }); mediaelement.jwEvents = { View: { PLAY: function(obj){ var data = getSwfDataFromID(obj.id); if(!data || data.stopPlayPause){return;} data._ppFlag = true; if(data.paused == obj.state){ data.paused = !obj.state; if(data.ended){ data.ended = false; } trigger(data._elem, obj.state ? 'play' : 'pause'); } } }, Model: { BUFFER: function(obj){ var data = getSwfDataFromID(obj.id); if(!data || !('percentage' in obj) || data._bufferedEnd == obj.percentage){return;} data.networkState = (obj.percentage == 100) ? 1 : 2; if(isNaN(data.duration) || (obj.percentage > 5 && obj.percentage < 25) || (obj.percentage === 100)){ getDuration(data, obj); } if(data.ended){ data.ended = false; } if(!data.duration){ return; } if(obj.percentage > 2 && obj.percentage < 20){ setReadyState(3, data); } else if(obj.percentage > 20){ setReadyState(4, data); } if(data._bufferedEnd && (data._bufferedEnd > obj.percentage)){ data._bufferedStart = data.currentTime || 0; } data._bufferedEnd = obj.percentage; data.buffered.length = 1; if(obj.percentage == 100){ data.networkState = 1; setReadyState(4, data); } $.event.trigger('progress', undefined, data._elem, true); }, META: function(obj, data){ data = data && data.networkState ? data : getSwfDataFromID(obj.id); if(!data){return;} if( !('duration' in obj) ){ data._callMeta = true; return; } if( data._metadata && (!obj.height || data.videoHeight == obj.height) && (obj.duration === data.duration) ){return;} data._metadata = true; var oldDur = data.duration; if(obj.duration){ data.duration = obj.duration; } data._lastDuration = data.duration; if(obj.height || obj.width){ data.videoHeight = obj.height || 0; data.videoWidth = obj.width || 0; } if(!data.networkState){ data.networkState = 2; } if(data.readyState < 1){ setReadyState(1, data); } if(data.duration && oldDur !== data.duration){ trigger(data._elem, 'durationchange'); } trigger(data._elem, 'loadedmetadata'); }, TIME: function(obj){ var data = getSwfDataFromID(obj.id); if(!data || data.currentTime === obj.position){return;} data.currentTime = obj.position; if(data.duration && data.duration < data.currentTime){ getDuration(data, obj); } if(data.readyState < 2){ setReadyState(2, data); } if(data.ended){ data.ended = false; } trigger(data._elem, 'timeupdate'); }, STATE: function(obj){ var data = getSwfDataFromID(obj.id); if(!data){return;} switch(obj.newstate) { case 'BUFFERING': if(data.ended){ data.ended = false; } setReadyState(1, data); trigger(data._elem, 'waiting'); break; case 'PLAYING': data.paused = false; data._ppFlag = true; if(!data.duration){ getDuration(data, obj); } if(data.readyState < 3){ setReadyState(3, data); } if(data.ended){ data.ended = false; } trigger(data._elem, 'playing'); break; case 'PAUSED': if(!data.paused && !data.stopPlayPause){ data.paused = true; data._ppFlag = true; trigger(data._elem, 'pause'); } break; case 'COMPLETED': if(data.readyState < 4){ setReadyState(4, data); } data.ended = true; trigger(data._elem, 'ended'); break; } } } ,Controller: { ERROR: function(obj){ var data = getSwfDataFromID(obj.id); if(!data){return;} mediaelement.setError(data._elem, obj.message); }, SEEK: function(obj){ var data = getSwfDataFromID(obj.id); if(!data){return;} if(data.ended){ data.ended = false; } if(data.paused){ try { data.jwapi[SENDEVENT]('play', 'false'); } catch(er){} } if(data.currentTime != obj.position){ data.currentTime = obj.position; trigger(data._elem, 'timeupdate'); } }, VOLUME: function(obj){ var data = getSwfDataFromID(obj.id); if(!data){return;} var newVolume = obj.percentage / 100; if(data.volume == newVolume){return;} data.volume = newVolume; trigger(data._elem, 'volumechange'); }, MUTE: function(obj){ if(obj.state){return;} var data = getSwfDataFromID(obj.id); if(!data){return;} if(data.muted == obj.state){return;} data.muted = obj.state; trigger(data._elem, 'volumechange'); } } }; var initEvents = function(data){ var passed = true; $.each(mediaelement.jwEvents, function(mvcName, evts){ $.each(evts, function(evtName){ try { data.jwapi['add'+ mvcName +'Listener'](evtName, 'jQuery.webshims.mediaelement.jwEvents.'+ mvcName +'.'+ evtName); } catch(er){ passed = false; return false; } }); }); return passed; }; 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(); data.jwapi[operation.fn].apply(data.jwapi, operation.args); } } 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(); } catch(er){} } }, 1); } }; mediaelement.playerResize = function(id){ if(!id){return;} var elem = document.getElementById(id.replace(idRep, '')); if(elem){ $(elem).triggerHandler('swfstageresize'); } elem = null; }; $(document).on('emptied', function(e){ var data = getSwfDataFromElem(e.target); startAutoPlay(data); }); var localConnectionTimer; mediaelement.jwPlayerReady = function(jwData){ var data = getSwfDataFromID(jwData.id); var passed = true; var i = 0; var doneFn = function(){ if(i > 9){return;} i++; if(initEvents(data)){ if(!data.wasSwfReady){ var version = parseFloat( jwData.version, 10); if(version < 5.1 || version >= 6){ webshims.warn('mediaelement-swf is only testet with jwplayer 5.6+'); } } else { $(data._elem).mediaLoad(); } data.wasSwfReady = true; data.tryedReframeing = 0; workActionQueue(data); startAutoPlay(data); } else { clearTimeout(data.reframeTimer); data.reframeTimer = setTimeout(doneFn, 9 * i); if(i > 2 && data.tryedReframeing < 9){ data.tryedReframeing++; data.shadowElem.css({overflow: 'visible'}); setTimeout(function(){ data.shadowElem.css({overflow: 'hidden'}); }, 16); } } }; if(!data || !data.jwapi){return;} if(!data.tryedReframeing){ data.tryedReframeing = 0; } clearTimeout(localConnectionTimer); data.jwData = jwData; data.shadowElem.removeClass('flashblocker-assumed'); $.prop(data._elem, 'volume', data.volume); $.prop(data._elem, 'muted', data.muted); doneFn(); }; var addMediaToStopEvents = $.noop; if(hasNative){ var stopEvents = { play: 1, playing: 1 }; var hideEvtArray = ['play', 'pause', 'playing', '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] && data.isActive != data.activating){ $(event.target).pause(); } } }; 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 = ['_bufferedEnd', '_bufferedStart', '_metadata', '_ppFlag', 'currentSrc', 'currentTime', 'duration', 'ended', 'networkState', 'paused', 'videoHeight', 'videoWidth', '_callMeta', '_durationCalcs']; var len = resetProtoProps.length; return function(data){ if(!data){return;} var lenI = len; var networkState = data.networkState; setReadyState(0, data); while(--lenI){ delete data[resetProtoProps[lenI]]; } data.actionQueue = []; data.buffered.length = 0; if(networkState){ trigger(data._elem, 'emptied'); } }; })(); var setElementDimension = function(data, hasControls){ var elem = data._elem; var box = data.shadowElem; $(elem)[hasControls ? 'addClass' : 'removeClass']('webshims-controls'); if(data._elemNodeName == 'audio' && !hasControls){ box.css({width: 0, height: 0}); } else { box.css({ width: elem.style.width || $(elem).width(), height: elem.style.height || $(elem).height() }); } }; mediaelement.createSWF = function( elem, canPlaySrc, data ){ if(!hasFlash){ setTimeout(function(){ $(elem).mediaLoad(); //<- this should produce a mediaerror }, 1); return; } if(loadedSwf < 1){ loadedSwf = 1; } else { loadedSwf++; } var vars = $.extend({}, options.vars, { image: $.prop(elem, 'poster') || '', file: canPlaySrc.srcProp }); var elemVars = $(elem).data('vars') || {}; if(!data){ data = webshims.data(elem, 'mediaelement'); } if(data && data.swfCreated){ mediaelement.setActive(elem, 'third', data); resetSwfProps(data); data.currentSrc = canPlaySrc.srcProp; $.extend(vars, elemVars); options.changeSWF(vars, elem, canPlaySrc, data, 'load'); queueSwfMethod(elem, SENDEVENT, ['LOAD', vars]); return; } var hasControls = $.prop(elem, 'controls'); var elemId = 'jwplayer-'+ webshims.getID(elem); var params = $.extend( {}, options.params, $(elem).data('params') ); var elemNodeName = elem.nodeName.toLowerCase(); var attrs = $.extend( {}, options.attrs, { name: elemId, id: elemId }, $(elem).data('attrs') ); var box = $('