vendor/assets/javascripts/webshims/shims/combos/22.js in webshims-rails-0.4.3 vs vendor/assets/javascripts/webshims/shims/combos/22.js in webshims-rails-0.4.4

- old
+ new

@@ -1,2409 +1,2296 @@ -// 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 loadSwf = function(){ - webshims.ready('mediaelement-swf', function(){ - if(!webshims.mediaelement.createSWF){ - webshims.modules["mediaelement-swf"].test = $.noop; - webshims.reTest(["mediaelement-swf"], 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 mediaelement-swf', 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 $('<track />')[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 ? 'mediaelement-swf' : '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).bind('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) - .bind('play loadstart progress', function(e){ - if(e.type == 'progress'){ - lastBuffered = getBufferedString(); - } - clearTimeout(bufferTimer); - bufferTimer = setTimeout(testBuffer, 999); - }) - .bind('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('mediaelement-swf', 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.jwParams, { - allowscriptaccess: 'always', - allowfullscreen: 'true', - wmode: 'transparent' - }); - webshims.extendUNDEFProp(options.jwVars, { - screencolor: 'ffffffff' - }); - webshims.extendUNDEFProp(options.jwAttrs, { - 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); - } - }; - - var startIntrinsicDimension = function(data){ - if(!data || data._elemNodeName != 'video'){return;} - var img; - var widthAuto; - var heightAuto; - var lastIntrinsicSize = {}; - var shadowElem; - var errorTimer; - var blockResize; - var lastSize; - var setSize = function(width, height){ - if(!height || !width || height < 1 || width < 1 || data.isActive != 'third'){return;} - if(img){ - img.remove(); - img = false; - } - lastIntrinsicSize.width = width; - lastIntrinsicSize.height = height; - clearTimeout(errorTimer); - widthAuto = data._elem.style.width == 'auto'; - heightAuto = data._elem.style.height == 'auto'; - - if(!widthAuto && !heightAuto){return;} - var curSize; - shadowElem = shadowElem || $(data._elem).getShadowElement(); - var cur; - if(widthAuto && !heightAuto){ - cur = shadowElem.height(); - width *= cur / height; - height = cur; - } else if(!widthAuto && heightAuto){ - cur = shadowElem.width(); - height *= cur / width; - width = cur; - } - blockResize = true; - setTimeout(function(){ - blockResize = false; - }, 9); - - shadowElem.css({width: width, height: height}); - }; - var setPosterSrc = function(){ - if(data.isActive != 'third' || ($.prop(data._elem, 'readyState') && $.prop(this, 'videoWidth'))){return;} - var posterSrc = $.prop(data._elem, 'poster'); - if(!posterSrc){return;} - widthAuto = data._elem.style.width == 'auto'; - heightAuto = data._elem.style.height == 'auto'; - if(!widthAuto && !heightAuto){return;} - if(img){ - img.remove(); - img = false; - } - img = $('<img style="position: absolute; height: auto; width: auto; top: 0px; left: 0px; visibility: hidden;" />'); - img - .bind('load error alreadycomplete', function(e){ - clearTimeout(errorTimer); - - var elem = this; - var width = elem.naturalWidth || elem.width || elem.offsetWidth; - var height = elem.naturalHeight || elem.height || elem.offsetHeight; - - if(height && width){ - setSize(width, height); - elem = null; - } else { - setTimeout(function(){ - width = elem.naturalWidth || elem.width || elem.offsetWidth; - height = elem.naturalHeight || elem.height || elem.offsetHeight; - setSize(width, height); - if(img){ - img.remove(); - img = false; - } - elem = null; - }, 9); - } - $(this).unbind(); - }) - .prop('src', posterSrc) - .appendTo('body') - .each(function(){ - if(this.complete || this.error){ - $(this).triggerHandler('alreadycomplete'); - } else { - clearTimeout(errorTimer); - errorTimer = setTimeout(function(){ - $(data._elem).triggerHandler('error'); - }, 9999); - } - }) - ; - }; - - $(data._elem) - .bind('loadedmetadata', function(){ - setSize($.prop(this, 'videoWidth'), $.prop(this, 'videoHeight')); - }) - .bind('emptied', setPosterSrc) - .bind('swfstageresize updatemediaelementdimensions', function(){ - if(blockResize){return;} - setSize(lastIntrinsicSize.width, lastIntrinsicSize.height); - }) - .bind('emptied', function(){ - lastIntrinsicSize = {}; - }) - .triggerHandler('swfstageresize') - ; - - setPosterSrc(); - if($.prop(data._elem, 'readyState')){ - setSize($.prop(data._elem, 'videoWidth'), $.prop(data._elem, 'videoHeight')); - } - }; - - mediaelement.playerResize = function(id){ - if(!id){return;} - var elem = document.getElementById(id.replace(idRep, '')); - - if(elem){ - $(elem).triggerHandler('swfstageresize'); - } - elem = null; - }; - - - $(document).bind('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) - .unbind(hidevents) - .bind(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.jwVars, { - image: $.prop(elem, 'poster') || '', - file: canPlaySrc.srcProp - }); - var elemVars = $(elem).data('jwvars') || {}; - - 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.changeJW(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.jwParams, - $(elem).data('jwparams') - ); - var elemNodeName = elem.nodeName.toLowerCase(); - var attrs = $.extend( - {}, - options.jwAttrs, - { - name: elemId, - id: elemId - }, - $(elem).data('jwattrs') - ); - var box = $('<div class="polyfill-'+ (elemNodeName) +' polyfill-mediaelement" 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: canPlaySrc.srcProp - }, - swfCreated: { - value: true - }, - 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 / 100) + data._bufferedStart; - }, - length: 0 - } - } - })); - - setElementDimension(data, hasControls); - - box.insertBefore(elem); - - if(hasNative){ - $.extend(data, {volume: $.prop(elem, 'volume'), muted: $.prop(elem, 'muted')}); - } - - $.extend(vars, - { - id: elemId, - controlbar: hasControls ? options.jwVars.controlbar || (elemNodeName == 'video' ? 'over' : 'bottom') : (elemNodeName == 'video') ? 'none' : 'bottom', - icons: ''+ (hasControls && elemNodeName == 'video') - }, - elemVars, - {playerready: 'jQuery.webshims.mediaelement.jwPlayerReady'} - ); - if(vars.plugins){ - vars.plugins += ','+jwplugin; - } else { - vars.plugins = jwplugin; - } - - - webshims.addShadowDom(elem, box); - - addMediaToStopEvents(elem); - - mediaelement.setActive(elem, 'third', data); - - options.changeJW(vars, elem, canPlaySrc, data, 'embed'); - - $(elem).bind('updatemediaelementdimensions updateshadowdom', function(){ - setElementDimension(data, $.prop(elem, 'controls')); - }); - - startIntrinsicDimension(data); - - swfobject.embedSWF(playerSwfPath, elemId, "100%", "100%", "9.0.0", false, vars, params, attrs, function(swfData){ - - if(swfData.success){ - data.jwapi = swfData.ref; - - if(!hasControls){ - $(swfData.ref).attr('tabindex', '-1').css('outline', 'none'); - } - setTimeout(function(){ - if((!swfData.ref.parentNode && box[0].parentNode) || swfData.ref.style.display == "none"){ - box.addClass('flashblocker-assumed'); - $(elem).trigger('flashblocker'); - webshims.warn("flashblocker assumed"); - } - $(swfData.ref).css({'minHeight': '2px', 'minWidth': '2px', display: 'block'}); - }, 9); - if(!localConnectionTimer){ - clearTimeout(localConnectionTimer); - localConnectionTimer = setTimeout(function(){ - 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); - } - } - }); - }; - - - var queueSwfMethod = function(elem, fn, args, data){ - data = data || getSwfDataFromElem(elem); - if(data){ - if(data.jwapi && data.jwapi[fn]){ - data.jwapi[fn].apply(data.jwapi, 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; - }; - - ['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('volume', function(v){ - var data = getSwfDataFromElem(this); - if(data){ - v *= 100; - if(!isNaN(v)){ - var muted = data.muted; - if(v < 0 || v > 100){ - webshims.error('volume greater or less than allowed '+ (v / 100)); - } - - queueSwfMethod(this, SENDEVENT, ['VOLUME', v], data); - if(muted){ - try { - data.jwapi.sendEvent('mute', 'true'); - } catch(er){} - } - v /= 100; - if(data.volume == v || data.isActive != 'third'){return;} - 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, SENDEVENT, ['mute', ''+m], data); - if(data.muted == m || data.isActive != 'third'){return;} - 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)) { - if(data.paused){ - clearTimeout(data.stopPlayPause); - data.stopPlayPause = setTimeout(function(){ - data.paused = true; - data.stopPlayPause = false; - }, 50); - } - queueSwfMethod(this, SENDEVENT, ['SEEK', '' + t], data); - - if(data.paused){ - if(data.readyState > 0){ - data.currentTime = t; - trigger(data._elem, 'timeupdate'); - } - try { - data.jwapi[SENDEVENT]('play', 'false'); - } catch(er){} - - } - } - - } 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, SENDEVENT, ['play', fn == 'play'], data); - setTimeout(function(){ - if(data.isActive == 'third'){ - data._ppFlag = true; - if(data.paused != (fn != 'play')){ - data.paused = fn != 'play'; - trigger(data._elem, fn); - } - } - }, 1); - } 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){ - try { - queueSwfMethod(this, boolProp ? 'showControls' : 'hideControls', [nodeName], data); - } catch(er){ - webshims.warn("you need to generate a crossdomain.xml"); - } - if(nodeName == 'audio'){ - setElementDimension(data, boolProp); - } - $(data.jwapi).attr('tabindex', boolProp ? '0' : '-1'); - } - }); - - mediaSup = webshims.defineNodeNameProperties(nodeName, descs, 'prop'); - }); - - if(hasFlash){ - var oldClean = $.cleanData; - var gcBrowser = $.browser.msie && webshims.browserVersion < 9; - var flashNames = { - object: 1, - OBJECT: 1 - }; - $.cleanData = function(elems){ - var i, len, prop; - if(elems && (len = elems.length) && loadedSwf){ - - for(i = 0; i < len; i++){ - if(flashNames[elems[i].nodeName]){ - if(SENDEVENT in elems[i]){ - loadedSwf--; - try { - elems[i][SENDEVENT]('play', false); - } catch(er){} - } - if(gcBrowser){ - try { - for (prop in elems[i]) { - if (typeof elems[i][prop] == "function") { - elems[i][prop] = null; - } - } - } catch(er){} - } - } - } - - } - return oldClean.apply(this, arguments); - }; - } - - if(!hasNative){ - - ['poster', 'src'].forEach(function(prop){ - webshims.defineNodeNamesProperty(prop == 'src' ? ['audio', 'video', 'source'] : ['video'], prop, { - //attr: {}, - reflect: true, - propType: 'src' - }); - }); - - - ['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'); - } - +// 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 $('<track />')[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 = $('<div class="polyfill-'+ (elemNodeName) +' polyfill-mediaelement" 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: canPlaySrc.srcProp + }, + swfCreated: { + value: true + }, + 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 / 100) + data._bufferedStart; + }, + length: 0 + } + } + })); + + setElementDimension(data, hasControls); + + box.insertBefore(elem); + + if(hasNative){ + $.extend(data, {volume: $.prop(elem, 'volume'), muted: $.prop(elem, 'muted')}); + } + + $.extend(vars, + { + id: elemId, + controlbar: hasControls ? options.vars.controlbar || (elemNodeName == 'video' ? 'over' : 'bottom') : (elemNodeName == 'video') ? 'none' : 'bottom', + icons: ''+ (hasControls && elemNodeName == 'video') + }, + elemVars, + {playerready: 'jQuery.webshims.mediaelement.jwPlayerReady'} + ); + if(vars.plugins){ + vars.plugins += ','+jwplugin; + } else { + vars.plugins = jwplugin; + } + + + webshims.addShadowDom(elem, box); + + addMediaToStopEvents(elem); + + mediaelement.setActive(elem, 'third', data); + + options.changeSWF(vars, elem, canPlaySrc, data, 'embed'); + + $(elem).on('updatemediaelementdimensions updateshadowdom', function(){ + setElementDimension(data, $.prop(elem, 'controls')); + }); + + + swfobject.embedSWF(playerSwfPath, elemId, "100%", "100%", "9.0.0", false, vars, params, attrs, function(swfData){ + + if(swfData.success){ + data.jwapi = swfData.ref; + + if(!hasControls){ + $(swfData.ref).attr('tabindex', '-1').css('outline', 'none'); + } + setTimeout(function(){ + if((!swfData.ref.parentNode && box[0].parentNode) || swfData.ref.style.display == "none"){ + box.addClass('flashblocker-assumed'); + $(elem).trigger('flashblocker'); + webshims.warn("flashblocker assumed"); + } + $(swfData.ref).css({'minHeight': '2px', 'minWidth': '2px', display: 'block'}); + }, 9); + if(!localConnectionTimer){ + clearTimeout(localConnectionTimer); + localConnectionTimer = setTimeout(function(){ + 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); + } + } + }); + }; + + + var queueSwfMethod = function(elem, fn, args, data){ + data = data || getSwfDataFromElem(elem); + if(data){ + if(data.jwapi && data.jwapi[fn]){ + data.jwapi[fn].apply(data.jwapi, 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; + }; + + ['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('volume', function(v){ + var data = getSwfDataFromElem(this); + if(data){ + v *= 100; + if(!isNaN(v)){ + var muted = data.muted; + if(v < 0 || v > 100){ + webshims.error('volume greater or less than allowed '+ (v / 100)); + } + + queueSwfMethod(this, SENDEVENT, ['VOLUME', v], data); + if(muted){ + try { + data.jwapi.sendEvent('mute', 'true'); + } catch(er){} + } + v /= 100; + if(data.volume == v || data.isActive != 'third'){return;} + 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, SENDEVENT, ['mute', ''+m], data); + if(data.muted == m || data.isActive != 'third'){return;} + 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)) { + if(data.paused){ + clearTimeout(data.stopPlayPause); + data.stopPlayPause = setTimeout(function(){ + data.paused = true; + data.stopPlayPause = false; + }, 50); + } + queueSwfMethod(this, SENDEVENT, ['SEEK', '' + t], data); + + if(data.paused){ + if(data.readyState > 0){ + data.currentTime = t; + trigger(data._elem, 'timeupdate'); + } + try { + data.jwapi[SENDEVENT]('play', 'false'); + } catch(er){} + + } + } + + } 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, SENDEVENT, ['play', fn == 'play'], data); + setTimeout(function(){ + if(data.isActive == 'third'){ + data._ppFlag = true; + if(data.paused != (fn != 'play')){ + data.paused = fn != 'play'; + trigger(data._elem, fn); + } + } + }, 1); + } 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){ + try { + queueSwfMethod(this, boolProp ? 'showControls' : 'hideControls', [nodeName], data); + } catch(er){ + webshims.warn("you need to generate a crossdomain.xml"); + } + if(nodeName == 'audio'){ + setElementDimension(data, boolProp); + } + $(data.jwapi).attr('tabindex', boolProp ? '0' : '-1'); + } + }); + + mediaSup = webshims.defineNodeNameProperties(nodeName, descs, 'prop'); + }); + + if(hasFlash){ + var oldClean = $.cleanData; + var gcBrowser = $.browser.msie && webshims.browserVersion < 9; + var flashNames = { + object: 1, + OBJECT: 1 + }; + $.cleanData = function(elems){ + var i, len, prop; + if(elems && (len = elems.length) && loadedSwf){ + + for(i = 0; i < len; i++){ + if(flashNames[elems[i].nodeName]){ + if(SENDEVENT in elems[i]){ + loadedSwf--; + try { + elems[i][SENDEVENT]('play', false); + } catch(er){} + } + if(gcBrowser){ + try { + for (prop in elems[i]) { + if (typeof elems[i][prop] == "function") { + elems[i][prop] = null; + } + } + } catch(er){} + } + } + } + + } + return oldClean.apply(this, arguments); + }; + } + + if(!hasNative){ + + ['poster', 'src'].forEach(function(prop){ + webshims.defineNodeNamesProperty(prop == 'src' ? ['audio', 'video', 'source'] : ['video'], prop, { + //attr: {}, + reflect: true, + propType: 'src' + }); + }); + + + ['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'); + } }); \ No newline at end of file