vendor/assets/javascripts/webshims/shims/combos/12.js in webshims-rails-0.4.7 vs vendor/assets/javascripts/webshims/shims/combos/12.js in webshims-rails-1.10.3
- old
+ new
@@ -1,1108 +1,503 @@
-//DOM-Extension helper
-jQuery.webshims.register('dom-extend', function($, webshims, window, document, undefined){
- "use strict";
- //shortcus
- var modules = webshims.modules;
- var listReg = /\s*,\s*/;
+/*! SWFMini - a SWFObject 2.2 cut down version for webshims
+ *
+ * based on SWFObject v2.2 <http://code.google.com/p/swfobject/>
+ is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
+*/
+
+var swfmini = function() {
+
+ var UNDEF = "undefined",
+ OBJECT = "object",
+ webshims = jQuery.webshims,
+ SHOCKWAVE_FLASH = "Shockwave Flash",
+ SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
+ FLASH_MIME_TYPE = "application/x-shockwave-flash",
- //proxying attribute
- var olds = {};
- var havePolyfill = {};
- var extendedProps = {};
- var extendQ = {};
- var modifyProps = {};
+ win = window,
+ doc = document,
+ nav = navigator,
+
+ plugin = false,
+ domLoadFnArr = [main],
+ objIdArr = [],
+ listenersArr = [],
+ storedAltContent,
+ storedAltContentId,
+ storedCallbackFn,
+ storedCallbackObj,
+ isDomLoaded = false,
+ dynamicStylesheet,
+ dynamicStylesheetMedia,
+ autoHideShow = true,
- var oldVal = $.fn.val;
- var singleVal = function(elem, name, val, pass, _argless){
- return (_argless) ? oldVal.call($(elem)) : oldVal.call($(elem), val);
- };
-
- $.fn.onTrigger = function(evt, fn){
- return this.on(evt, fn).each(fn);
- };
-
- $.fn.val = function(val){
- var elem = this[0];
- if(arguments.length && val == null){
- val = '';
+ /* Centralized function for browser feature detection
+ - User agent string detection is only used when no good alternative is possible
+ - Is executed directly for optimal performance
+ */
+ ua = function() {
+ var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
+ u = nav.userAgent.toLowerCase(),
+ p = nav.platform.toLowerCase(),
+ windows = p ? /win/.test(p) : /win/.test(u),
+ mac = p ? /mac/.test(p) : /mac/.test(u),
+ webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
+ ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
+ playerVersion = [0,0,0],
+ d = null;
+ if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
+ d = nav.plugins[SHOCKWAVE_FLASH].description;
+ if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
+ plugin = true;
+ ie = false; // cascaded feature detection for Internet Explorer
+ d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
+ playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
+ playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
+ playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
+ }
}
- if(!arguments.length){
- if(!elem || elem.nodeType !== 1){return oldVal.call(this);}
- return $.prop(elem, 'value', val, 'val', true);
- }
- if($.isArray(val)){
- return oldVal.apply(this, arguments);
- }
- var isFunction = $.isFunction(val);
- return this.each(function(i){
- elem = this;
- if(elem.nodeType === 1){
- if(isFunction){
- var genVal = val.call( elem, i, $.prop(elem, 'value', undefined, 'val', true));
- if(genVal == null){
- genVal = '';
+ else if (typeof win.ActiveXObject != UNDEF) {
+ try {
+ var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
+ if (a) { // a will return null when ActiveX is disabled
+ d = a.GetVariable("$version");
+ if (d) {
+ ie = true; // cascaded feature detection for Internet Explorer
+ d = d.split(" ")[1].split(",");
+ playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
- $.prop(elem, 'value', genVal, 'val') ;
- } else {
- $.prop(elem, 'value', val, 'val');
}
}
- });
- };
+ catch(e) {}
+ }
+ return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
+ }();
- var dataID = '_webshimsLib'+ (Math.round(Math.random() * 1000));
- var elementData = function(elem, key, val){
- elem = elem.jquery ? elem[0] : elem;
- if(!elem){return val || {};}
- var data = $.data(elem, dataID);
- if(val !== undefined){
- if(!data){
- data = $.data(elem, dataID, {});
- }
- if(key){
- data[key] = val;
- }
+
+ function callDomLoadFunctions() {
+ if (isDomLoaded) { return; }
+ try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
+ var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
+ t.parentNode.removeChild(t);
}
+ catch (e) { return; }
+ isDomLoaded = true;
+ var dl = domLoadFnArr.length;
+ for (var i = 0; i < dl; i++) {
+ domLoadFnArr[i]();
+ }
+ }
+
+ function addDomLoadEvent(fn) {
+ if (isDomLoaded) {
+ fn();
+ }
+ else {
+ domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
+ }
+ }
+
+ /* Cross-browser onload
+ - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
+ - Will fire an event as soon as a web page including all of its assets are loaded
+ */
+ function addLoadEvent(fn) {
- return key ? data && data[key] : data;
- };
-
-
- [{name: 'getNativeElement', prop: 'nativeElement'}, {name: 'getShadowElement', prop: 'shadowElement'}, {name: 'getShadowFocusElement', prop: 'shadowFocusElement'}].forEach(function(data){
- $.fn[data.name] = function(){
- return this.map(function(){
- var shadowData = elementData(this, 'shadowData');
- return shadowData && shadowData[data.prop] || this;
- });
- };
- });
+ }
+ /* Main function
+ - Will preferably execute onDomLoad, otherwise onload (as a fallback)
+ */
+ function main() {
+ if (plugin) {
+ testPlayerVersion();
+ }
+ }
- ['removeAttr', 'prop', 'attr'].forEach(function(type){
- olds[type] = $[type];
- $[type] = function(elem, name, value, pass, _argless){
- var isVal = (pass == 'val');
- var oldMethod = !isVal ? olds[type] : singleVal;
- if( !elem || !havePolyfill[name] || elem.nodeType !== 1 || (!isVal && pass && type == 'attr' && $.attrFn[name]) ){
- return oldMethod(elem, name, value, pass, _argless);
- }
-
- var nodeName = (elem.nodeName || '').toLowerCase();
- var desc = extendedProps[nodeName];
- var curType = (type == 'attr' && (value === false || value === null)) ? 'removeAttr' : type;
- var propMethod;
- var oldValMethod;
- var ret;
-
-
- if(!desc){
- desc = extendedProps['*'];
- }
- if(desc){
- desc = desc[name];
- }
-
- if(desc){
- propMethod = desc[curType];
- }
-
- if(propMethod){
- if(name == 'value'){
- oldValMethod = propMethod.isVal;
- propMethod.isVal = isVal;
- }
- if(curType === 'removeAttr'){
- return propMethod.value.call(elem);
- } else if(value === undefined){
- return (propMethod.get) ?
- propMethod.get.call(elem) :
- propMethod.value
- ;
- } else if(propMethod.set) {
- if(type == 'attr' && value === true){
- value = name;
+ /* Detect the Flash Player version for non-Internet Explorer browsers
+ - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
+ a. Both release and build numbers can be detected
+ b. Avoid wrong descriptions by corrupt installers provided by Adobe
+ c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
+ - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
+ */
+ function testPlayerVersion() {
+ var b = doc.getElementsByTagName("body")[0];
+ var o = createElement(OBJECT);
+ o.setAttribute("type", FLASH_MIME_TYPE);
+ var t = b.appendChild(o);
+ if (t) {
+ var counter = 0;
+ (function(){
+ if (typeof t.GetVariable != UNDEF) {
+ var d = t.GetVariable("$version");
+ if (d) {
+ d = d.split(" ")[1].split(",");
+ ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
-
- ret = propMethod.set.call(elem, value);
}
- if(name == 'value'){
- propMethod.isVal = oldValMethod;
+ else if (counter < 10) {
+ counter++;
+ setTimeout(arguments.callee, 10);
+ return;
}
- } else {
- ret = oldMethod(elem, name, value, pass, _argless);
+ b.removeChild(o);
+ t = null;
+ })();
+ }
+ }
+
+
+ function getObjectById(objectIdStr) {
+ var r = null;
+ var o = getElementById(objectIdStr);
+ if (o && o.nodeName == "OBJECT") {
+ if (typeof o.SetVariable != UNDEF) {
+ r = o;
}
- if((value !== undefined || curType === 'removeAttr') && modifyProps[nodeName] && modifyProps[nodeName][name]){
-
- var boolValue;
- if(curType == 'removeAttr'){
- boolValue = false;
- } else if(curType == 'prop'){
- boolValue = !!(value);
- } else {
- boolValue = true;
+ else {
+ var n = o.getElementsByTagName(OBJECT)[0];
+ if (n) {
+ r = n;
}
-
- modifyProps[nodeName][name].forEach(function(fn){
- if(!fn.only || (fn.only = 'prop' && type == 'prop') || (fn.only == 'attr' && type != 'prop')){
- fn.call(elem, value, boolValue, (isVal) ? 'val' : curType, type);
- }
- });
}
- return ret;
- };
-
- extendQ[type] = function(nodeName, prop, desc){
-
- if(!extendedProps[nodeName]){
- extendedProps[nodeName] = {};
- }
- if(!extendedProps[nodeName][prop]){
- extendedProps[nodeName][prop] = {};
- }
- var oldDesc = extendedProps[nodeName][prop][type];
- var getSup = function(propType, descriptor, oDesc){
- if(descriptor && descriptor[propType]){
- return descriptor[propType];
+ }
+ return r;
+ }
+
+
+ /* Functions to abstract and display alternative content
+ */
+ function displayAltContent(obj) {
+ if (ua.ie && ua.win && obj.readyState != 4) {
+ // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
+ // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
+ var el = createElement("div");
+ obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
+ el.parentNode.replaceChild(abstractAltContent(obj), el);
+ obj.style.display = "none";
+ (function(){
+ if (obj.readyState == 4) {
+ obj.parentNode.removeChild(obj);
}
- if(oDesc && oDesc[propType]){
- return oDesc[propType];
+ else {
+ setTimeout(arguments.callee, 10);
}
- if(type == 'prop' && prop == 'value'){
- return function(value){
- var elem = this;
- return (desc.isVal) ?
- singleVal(elem, prop, value, false, (arguments.length === 0)) :
- olds[type](elem, prop, value)
- ;
- };
+ })();
+ }
+ else {
+ obj.parentNode.replaceChild(abstractAltContent(obj), obj);
+ }
+ }
+
+ function abstractAltContent(obj) {
+ var ac = createElement("div");
+ if (ua.win && ua.ie) {
+ ac.innerHTML = obj.innerHTML;
+ }
+ else {
+ var nestedObj = obj.getElementsByTagName(OBJECT)[0];
+ if (nestedObj) {
+ var c = nestedObj.childNodes;
+ if (c) {
+ var cl = c.length;
+ for (var i = 0; i < cl; i++) {
+ if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
+ ac.appendChild(c[i].cloneNode(true));
+ }
+ }
}
- if(type == 'prop' && propType == 'value' && desc.value.apply){
- return function(value){
- var sup = olds[type](this, prop);
- if(sup && sup.apply){
- sup = sup.apply(this, arguments);
- }
- return sup;
- };
- }
- return function(value){
- return olds[type](this, prop, value);
- };
- };
- extendedProps[nodeName][prop][type] = desc;
- if(desc.value === undefined){
- if(!desc.set){
- desc.set = desc.writeable ?
- getSup('set', desc, oldDesc) :
- (webshims.cfg.useStrict && prop == 'prop') ?
- function(){throw(prop +' is readonly on '+ nodeName);} :
- $.noop
- ;
- }
- if(!desc.get){
- desc.get = getSup('get', desc, oldDesc);
- }
-
}
-
- ['value', 'get', 'set'].forEach(function(descProp){
- if(desc[descProp]){
- desc['_sup'+descProp] = getSup(descProp, oldDesc);
- }
- });
- };
-
- });
+ }
+ return ac;
+ }
- //see also: https://github.com/lojjic/PIE/issues/40 | https://prototype.lighthouseapp.com/projects/8886/tickets/1107-ie8-fatal-crash-when-prototypejs-is-loaded-with-rounded-cornershtc
- var isExtendNativeSave = Modernizr.ES5;
- var extendNativeValue = (function(){
- var UNKNOWN = webshims.getPrototypeOf(document.createElement('foobar'));
- var has = Object.prototype.hasOwnProperty;
- return function(nodeName, prop, desc){
- var elem;
- var elemProto;
- if( isExtendNativeSave && (elem = document.createElement(nodeName)) && (elemProto = webshims.getPrototypeOf(elem)) && UNKNOWN !== elemProto && ( !elem[prop] || !has.call(elem, prop) ) ){
- var sup = elem[prop];
- desc._supvalue = function(){
- if(sup && sup.apply){
- return sup.apply(this, arguments);
+ /* Cross-browser dynamic SWF creation
+ */
+ function createSWF(attObj, parObj, id) {
+ var r, el = getElementById(id);
+ if (ua.wk && ua.wk < 312) { return r; }
+ if (el) {
+ if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
+ attObj.id = id;
+ }
+ if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
+ var att = "";
+ for (var i in attObj) {
+ if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
+ if (i.toLowerCase() == "data") {
+ parObj.movie = attObj[i];
+ }
+ else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
+ att += ' class="' + attObj[i] + '"';
+ }
+ else if (i.toLowerCase() != "classid") {
+ att += ' ' + i + '="' + attObj[i] + '"';
+ }
}
- return sup;
- };
- elemProto[prop] = desc.value;
- } else {
- desc._supvalue = function(){
- var data = elementData(this, 'propValue');
- if(data && data[prop] && data[prop].apply){
- return data[prop].apply(this, arguments);
+ }
+ var par = "";
+ for (var j in parObj) {
+ if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
+ par += '<param name="' + j + '" value="' + parObj[j] + '" />';
}
- return data && data[prop];
- };
- initProp.extendValue(nodeName, prop, desc.value);
+ }
+ el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
+ objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
+ r = getElementById(attObj.id);
}
- desc.value._supvalue = desc._supvalue;
- };
- })();
-
- var initProp = (function(){
-
- var initProps = {};
-
- webshims.addReady(function(context, contextElem){
- var nodeNameCache = {};
- var getElementsByName = function(name){
- if(!nodeNameCache[name]){
- nodeNameCache[name] = $(context.getElementsByTagName(name));
- if(contextElem[0] && $.nodeName(contextElem[0], name)){
- nodeNameCache[name] = nodeNameCache[name].add(contextElem);
+ else { // well-behaving browsers
+ var o = createElement(OBJECT);
+ o.setAttribute("type", FLASH_MIME_TYPE);
+ for (var m in attObj) {
+ if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
+ if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
+ o.setAttribute("class", attObj[m]);
+ }
+ else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
+ o.setAttribute(m, attObj[m]);
+ }
}
}
- };
-
-
- $.each(initProps, function(name, fns){
- getElementsByName(name);
- if(!fns || !fns.forEach){
- webshims.warn('Error: with '+ name +'-property. methods: '+ fns);
- return;
+ for (var n in parObj) {
+ if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
+ createObjParam(o, n, parObj[n]);
+ }
}
- fns.forEach(function(fn){
- nodeNameCache[name].each(fn);
- });
- });
- nodeNameCache = null;
- });
-
- var tempCache;
- var emptyQ = $([]);
- var createNodeNameInit = function(nodeName, fn){
- if(!initProps[nodeName]){
- initProps[nodeName] = [fn];
- } else {
- initProps[nodeName].push(fn);
+ el.parentNode.replaceChild(o, el);
+ r = o;
}
- if($.isDOMReady){
- (tempCache || $( document.getElementsByTagName(nodeName) )).each(fn);
- }
- };
-
- var elementExtends = {};
- return {
- createTmpCache: function(nodeName){
- if($.isDOMReady){
- tempCache = tempCache || $( document.getElementsByTagName(nodeName) );
- }
- return tempCache || emptyQ;
- },
- flushTmpCache: function(){
- tempCache = null;
- },
- content: function(nodeName, prop){
- createNodeNameInit(nodeName, function(){
- var val = $.attr(this, prop);
- if(val != null){
- $.attr(this, prop, val);
+ }
+ return r;
+ }
+
+ function createObjParam(el, pName, pValue) {
+ var p = createElement("param");
+ p.setAttribute("name", pName);
+ p.setAttribute("value", pValue);
+ el.appendChild(p);
+ }
+
+ /* Cross-browser SWF removal
+ - Especially needed to safely and completely remove a SWF in Internet Explorer
+ */
+ function removeSWF(id) {
+ var obj = getElementById(id);
+ if (obj && obj.nodeName == "OBJECT") {
+ if (ua.ie && ua.win) {
+ obj.style.display = "none";
+ (function(){
+ if (obj.readyState == 4) {
+ removeObjectInIE(id);
}
- });
- },
- createElement: function(nodeName, fn){
- createNodeNameInit(nodeName, fn);
- },
- extendValue: function(nodeName, prop, value){
- createNodeNameInit(nodeName, function(){
- $(this).each(function(){
- var data = elementData(this, 'propValue', {});
- data[prop] = this[prop];
- this[prop] = value;
- });
- });
+ else {
+ setTimeout(arguments.callee, 10);
+ }
+ })();
}
- };
- })();
-
- var createPropDefault = function(descs, removeType){
- if(descs.defaultValue === undefined){
- descs.defaultValue = '';
+ else {
+ obj.parentNode.removeChild(obj);
+ }
}
- if(!descs.removeAttr){
- descs.removeAttr = {
- value: function(){
- descs[removeType || 'prop'].set.call(this, descs.defaultValue);
- descs.removeAttr._supvalue.call(this);
+ }
+
+ function removeObjectInIE(id) {
+ var obj = getElementById(id);
+ if (obj) {
+ for (var i in obj) {
+ if (typeof obj[i] == "function") {
+ obj[i] = null;
}
- };
+ }
+ obj.parentNode.removeChild(obj);
}
- if(!descs.attr){
- descs.attr = {};
+ }
+
+ /* Functions to optimize JavaScript compression
+ */
+ function getElementById(id) {
+ var el = null;
+ try {
+ el = doc.getElementById(id);
}
- };
+ catch (e) {}
+ return el;
+ }
- $.extend(webshims, {
+ function createElement(el) {
+ return doc.createElement(el);
+ }
+
+ /* Updated attachEvent function for Internet Explorer
+ - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
+ */
+ function addListener(target, eventType, fn) {
+ target.attachEvent(eventType, fn);
+ listenersArr[listenersArr.length] = [target, eventType, fn];
+ }
+
+ /* Flash Player and SWF content version matching
+ */
+ function hasPlayerVersion(rv) {
+ var pv = ua.pv, v = rv.split(".");
+ v[0] = parseInt(v[0], 10);
+ v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
+ v[2] = parseInt(v[2], 10) || 0;
+ return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
+ }
+
+
+
+ function setVisibility(id, isVisible) {
+ if (!autoHideShow) { return; }
+ var elem;
+ var v = isVisible ? "visible" : "hidden";
+ if (isDomLoaded && (elem && getElementById(id))) {
+ getElementById(id).style.visibility = v;
+ }
+ }
- getID: (function(){
- var ID = new Date().getTime();
- return function(elem){
- elem = $(elem);
- var id = elem.attr('id');
- if(!id){
- ID++;
- id = 'ID-'+ ID;
- elem.attr('id', id);
+ /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
+ */
+ var cleanup = function() {
+ if (ua.ie && ua.win && window.attachEvent) {
+ window.attachEvent("onunload", function() {
+ // remove listeners to avoid memory leaks
+ var ll = listenersArr.length;
+ for (var i = 0; i < ll; i++) {
+ listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
}
- return id;
- };
- })(),
- extendUNDEFProp: function(obj, props){
- $.each(props, function(name, prop){
- if( !(name in obj) ){
- obj[name] = prop;
+ // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
+ var il = objIdArr.length;
+ for (var j = 0; j < il; j++) {
+ removeSWF(objIdArr[j]);
}
- });
- },
- //http://www.w3.org/TR/html5/common-dom-interfaces.html#reflect
- createPropDefault: createPropDefault,
- data: elementData,
- moveToFirstEvent: function(elem, eventType, bindType){
- var events = ($._data(elem, 'events') || {})[eventType];
- var fn;
-
- if(events && events.length > 1){
- fn = events.pop();
- if(!bindType){
- bindType = 'bind';
+ // cleanup library's main closures to avoid memory leaks
+ for (var k in ua) {
+ ua[k] = null;
}
- if(bindType == 'bind' && events.delegateCount){
- events.splice( events.delegateCount, 0, fn);
- } else {
- events.unshift( fn );
+ ua = null;
+ for (var l in swfmini) {
+ swfmini[l] = null;
}
-
-
+ swfmini = null;
+ });
+ }
+ }();
+
+ webshims.ready('DOM', callDomLoadFunctions);
+
+ return {
+ /* Public API
+ - Reference: http://code.google.com/p/swfobject/wiki/documentation
+ */
+ registerObject: function() {
+
+ },
+
+ getObjectById: function(objectIdStr) {
+ if (ua.w3) {
+ return getObjectById(objectIdStr);
}
- elem = null;
},
- addShadowDom: (function(){
- var resizeTimer;
- var lastHeight;
- var lastWidth;
-
- var docObserve = {
- init: false,
- runs: 0,
- test: function(){
- var height = docObserve.getHeight();
- var width = docObserve.getWidth();
-
- if(height != docObserve.height || width != docObserve.width){
- docObserve.height = height;
- docObserve.width = width;
- docObserve.handler({type: 'docresize'});
- docObserve.runs++;
- if(docObserve.runs < 9){
- setTimeout(docObserve.test, 90);
+
+ embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
+ var callbackObj = {success:false, id:replaceElemIdStr};
+ if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
+ setVisibility(replaceElemIdStr, false);
+ addDomLoadEvent(function() {
+ widthStr += ""; // auto-convert to string
+ heightStr += "";
+ var att = {};
+ if (attObj && typeof attObj === OBJECT) {
+ for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
+ att[i] = attObj[i];
}
- } else {
- docObserve.runs = 0;
}
- },
- handler: function(e){
- clearTimeout(resizeTimer);
- resizeTimer = setTimeout(function(){
- if(e.type == 'resize'){
- var width = $(window).width();
- var height = $(window).width();
- if(height == lastHeight && width == lastWidth){
- return;
- }
- lastHeight = height;
- lastWidth = width;
-
- docObserve.height = docObserve.getHeight();
- docObserve.width = docObserve.getWidth();
-
+ att.data = swfUrlStr;
+ att.width = widthStr;
+ att.height = heightStr;
+ var par = {};
+ if (parObj && typeof parObj === OBJECT) {
+ for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
+ par[j] = parObj[j];
}
- $(document).triggerHandler('updateshadowdom');
- }, (e.type == 'resize') ? 50 : 9);
- },
- _create: function(){
- $.each({ Height: "getHeight", Width: "getWidth" }, function(name, type){
- var body = document.body;
- var doc = document.documentElement;
- docObserve[type] = function(){
- return Math.max(
- body[ "scroll" + name ], doc[ "scroll" + name ],
- body[ "offset" + name ], doc[ "offset" + name ],
- doc[ "client" + name ]
- );
- };
- });
- },
- start: function(){
- if(!this.init && document.body){
- this.init = true;
- this._create();
- this.height = docObserve.getHeight();
- this.width = docObserve.getWidth();
- setInterval(this.test, 600);
- $(this.test);
- webshims.ready('WINDOWLOAD', this.test);
- $(window).bind('resize', this.handler);
- (function(){
- var oldAnimate = $.fn.animate;
- var animationTimer;
-
- $.fn.animate = function(){
- clearTimeout(animationTimer);
- animationTimer = setTimeout(function(){
- docObserve.test();
- }, 99);
-
- return oldAnimate.apply(this, arguments);
- };
- })();
}
- }
- };
-
-
- webshims.docObserve = function(){
- webshims.ready('DOM', function(){
- docObserve.start();
- });
- };
- return function(nativeElem, shadowElem, opts){
- opts = opts || {};
- if(nativeElem.jquery){
- nativeElem = nativeElem[0];
- }
- if(shadowElem.jquery){
- shadowElem = shadowElem[0];
- }
- var nativeData = $.data(nativeElem, dataID) || $.data(nativeElem, dataID, {});
- var shadowData = $.data(shadowElem, dataID) || $.data(shadowElem, dataID, {});
- var shadowFocusElementData = {};
- if(!opts.shadowFocusElement){
- opts.shadowFocusElement = shadowElem;
- } else if(opts.shadowFocusElement){
- if(opts.shadowFocusElement.jquery){
- opts.shadowFocusElement = opts.shadowFocusElement[0];
- }
- shadowFocusElementData = $.data(opts.shadowFocusElement, dataID) || $.data(opts.shadowFocusElement, dataID, shadowFocusElementData);
- }
-
- nativeData.hasShadow = shadowElem;
- shadowFocusElementData.nativeElement = shadowData.nativeElement = nativeElem;
- shadowFocusElementData.shadowData = shadowData.shadowData = nativeData.shadowData = {
- nativeElement: nativeElem,
- shadowElement: shadowElem,
- shadowFocusElement: opts.shadowFocusElement
- };
- if(opts.shadowChilds){
- opts.shadowChilds.each(function(){
- elementData(this, 'shadowData', shadowData.shadowData);
- });
- }
-
- if(opts.data){
- shadowFocusElementData.shadowData.data = shadowData.shadowData.data = nativeData.shadowData.data = opts.data;
- }
- opts = null;
- webshims.docObserve();
- };
- })(),
- propTypes: {
- standard: function(descs, name){
- createPropDefault(descs);
- if(descs.prop){return;}
- descs.prop = {
- set: function(val){
- descs.attr.set.call(this, ''+val);
- },
- get: function(){
- return descs.attr.get.call(this) || descs.defaultValue;
- }
- };
-
- },
- "boolean": function(descs, name){
-
- createPropDefault(descs);
- if(descs.prop){return;}
- descs.prop = {
- set: function(val){
- if(val){
- descs.attr.set.call(this, "");
- } else {
- descs.removeAttr.value.call(this);
- }
- },
- get: function(){
- return descs.attr.get.call(this) != null;
- }
- };
- },
- "src": (function(){
- var anchor = document.createElement('a');
- anchor.style.display = "none";
- return function(descs, name){
-
- createPropDefault(descs);
- if(descs.prop){return;}
- descs.prop = {
- set: function(val){
- descs.attr.set.call(this, val);
- },
- get: function(){
- var href = this.getAttribute(name);
- var ret;
- if(href == null){return '';}
-
- anchor.setAttribute('href', href+'' );
-
- if(!$.support.hrefNormalized){
- try {
- $(anchor).insertAfter(this);
- ret = anchor.getAttribute('href', 4);
- } catch(er){
- ret = anchor.getAttribute('href', 4);
- }
- $(anchor).detach();
+ if (flashvarsObj && typeof flashvarsObj === OBJECT) {
+ for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
+ if (typeof par.flashvars != UNDEF) {
+ par.flashvars += "&" + k + "=" + flashvarsObj[k];
}
- return ret || anchor.href;
- }
- };
- };
- })(),
- enumarated: function(descs, name){
-
- createPropDefault(descs);
- if(descs.prop){return;}
- descs.prop = {
- set: function(val){
- descs.attr.set.call(this, val);
- },
- get: function(){
- var val = (descs.attr.get.call(this) || '').toLowerCase();
- if(!val || descs.limitedTo.indexOf(val) == -1){
- val = descs.defaultValue;
+ else {
+ par.flashvars = k + "=" + flashvarsObj[k];
}
- return val;
}
- };
- }
-
-// ,unsignedLong: $.noop
-// ,"doubble": $.noop
-// ,"long": $.noop
-// ,tokenlist: $.noop
-// ,settableTokenlist: $.noop
- },
- reflectProperties: function(nodeNames, props){
- if(typeof props == 'string'){
- props = props.split(listReg);
- }
- props.forEach(function(prop){
- webshims.defineNodeNamesProperty(nodeNames, prop, {
- prop: {
- set: function(val){
- $.attr(this, prop, val);
- },
- get: function(){
- return $.attr(this, prop) || '';
+ }
+ if (hasPlayerVersion(swfVersionStr)) { // create SWF
+ var obj = createSWF(att, par, replaceElemIdStr);
+ if (att.id == replaceElemIdStr) {
+ setVisibility(replaceElemIdStr, true);
}
+ callbackObj.success = true;
+ callbackObj.ref = obj;
}
+ else { // show alternative content
+ setVisibility(replaceElemIdStr, true);
+ }
+ if (callbackFn) { callbackFn(callbackObj); }
});
- });
- },
- defineNodeNameProperty: function(nodeName, prop, descs){
- havePolyfill[prop] = true;
-
- if(descs.reflect){
- webshims.propTypes[descs.propType || 'standard'](descs, prop);
}
-
- ['prop', 'attr', 'removeAttr'].forEach(function(type){
- var desc = descs[type];
- if(desc){
- if(type === 'prop'){
- desc = $.extend({writeable: true}, desc);
- } else {
- desc = $.extend({}, desc, {writeable: true});
- }
-
- extendQ[type](nodeName, prop, desc);
- if(nodeName != '*' && webshims.cfg.extendNative && type == 'prop' && desc.value && $.isFunction(desc.value)){
- extendNativeValue(nodeName, prop, desc);
- }
- descs[type] = desc;
- }
- });
- if(descs.initAttr){
- initProp.content(nodeName, prop);
- }
- return descs;
+ else if (callbackFn) { callbackFn(callbackObj); }
},
- defineNodeNameProperties: function(name, descs, propType, _noTmpCache){
- var olddesc;
- for(var prop in descs){
- if(!_noTmpCache && descs[prop].initAttr){
- initProp.createTmpCache(name);
- }
- if(propType){
- if(descs[prop][propType]){
- //webshims.log('override: '+ name +'['+prop +'] for '+ propType);
- } else {
- descs[prop][propType] = {};
- ['value', 'set', 'get'].forEach(function(copyProp){
- if(copyProp in descs[prop]){
- descs[prop][propType][copyProp] = descs[prop][copyProp];
- delete descs[prop][copyProp];
- }
- });
- }
- }
- descs[prop] = webshims.defineNodeNameProperty(name, prop, descs[prop]);
- }
- if(!_noTmpCache){
- initProp.flushTmpCache();
- }
- return descs;
+ switchOffAutoHideShow: function() {
+ autoHideShow = false;
},
- createElement: function(nodeName, create, descs){
- var ret;
- if($.isFunction(create)){
- create = {
- after: create
- };
- }
- initProp.createTmpCache(nodeName);
- if(create.before){
- initProp.createElement(nodeName, create.before);
- }
- if(descs){
- ret = webshims.defineNodeNameProperties(nodeName, descs, false, true);
- }
- if(create.after){
- initProp.createElement(nodeName, create.after);
- }
- initProp.flushTmpCache();
- return ret;
+ ua: ua,
+
+ getFlashPlayerVersion: function() {
+ return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
},
- onNodeNamesPropertyModify: function(nodeNames, props, desc, only){
- if(typeof nodeNames == 'string'){
- nodeNames = nodeNames.split(listReg);
+
+ hasFlashPlayerVersion: hasPlayerVersion,
+
+ createSWF: function(attObj, parObj, replaceElemIdStr) {
+ if (ua.w3) {
+ return createSWF(attObj, parObj, replaceElemIdStr);
}
- if($.isFunction(desc)){
- desc = {set: desc};
+ else {
+ return undefined;
}
+ },
+
+ showExpressInstall: function() {
- nodeNames.forEach(function(name){
- if(!modifyProps[name]){
- modifyProps[name] = {};
- }
- if(typeof props == 'string'){
- props = props.split(listReg);
- }
- if(desc.initAttr){
- initProp.createTmpCache(name);
- }
- props.forEach(function(prop){
- if(!modifyProps[name][prop]){
- modifyProps[name][prop] = [];
- havePolyfill[prop] = true;
- }
- if(desc.set){
- if(only){
- desc.set.only = only;
- }
- modifyProps[name][prop].push(desc.set);
- }
-
- if(desc.initAttr){
- initProp.content(name, prop);
- }
- });
- initProp.flushTmpCache();
-
- });
},
- defineNodeNamesBooleanProperty: function(elementNames, prop, descs){
- if(!descs){
- descs = {};
+
+ removeSWF: function(objElemIdStr) {
+ if (ua.w3) {
+ removeSWF(objElemIdStr);
}
- if($.isFunction(descs)){
- descs.set = descs;
- }
- webshims.defineNodeNamesProperty(elementNames, prop, {
- attr: {
- set: function(val){
- this.setAttribute(prop, val);
- if(descs.set){
- descs.set.call(this, true);
- }
- },
- get: function(){
- var ret = this.getAttribute(prop);
- return (ret == null) ? undefined : prop;
- }
- },
- removeAttr: {
- value: function(){
- this.removeAttribute(prop);
- if(descs.set){
- descs.set.call(this, false);
- }
- }
- },
- reflect: true,
- propType: 'boolean',
- initAttr: descs.initAttr || false
- });
},
- contentAttr: function(elem, name, val){
- if(!elem.nodeName){return;}
- var attr;
- if(val === undefined){
- attr = (elem.attributes[name] || {});
- val = attr.specified ? attr.value : null;
- return (val == null) ? undefined : val;
- }
+
+ createCSS: function() {
- if(typeof val == 'boolean'){
- if(!val){
- elem.removeAttribute(name);
- } else {
- elem.setAttribute(name, name);
- }
- } else {
- elem.setAttribute(name, val);
- }
},
-// set current Lang:
-// - webshims.activeLang(lang:string);
-// get current lang
-// - webshims.activeLang();
-// get current lang
-// webshims.activeLang({
-// register: moduleName:string,
-// callback: callback:function
-// });
-// get/set including removeLang
-// - webshims.activeLang({
-// module: moduleName:string,
-// callback: callback:function,
-// langObj: languageObj:array/object
-// });
- activeLang: (function(){
- var callbacks = [];
- var registeredCallbacks = {};
- var currentLang;
- var shortLang;
- var notLocal = /:\/\/|^\.*\//;
- var loadRemoteLang = function(data, lang, options){
- var langSrc;
- if(lang && options && $.inArray(lang, options.availabeLangs || []) !== -1){
- data.loading = true;
- langSrc = options.langSrc;
- if(!notLocal.test(langSrc)){
- langSrc = webshims.cfg.basePath+langSrc;
- }
- webshims.loader.loadScript(langSrc+lang+'.js', function(){
- if(data.langObj[lang]){
- data.loading = false;
- callLang(data, true);
- } else {
- $(function(){
- if(data.langObj[lang]){
- callLang(data, true);
- }
- data.loading = false;
- });
- }
- });
- return true;
- }
- return false;
- };
- var callRegister = function(module){
- if(registeredCallbacks[module]){
- registeredCallbacks[module].forEach(function(data){
- data.callback();
- });
- }
- };
- var callLang = function(data, _noLoop){
- if(data.activeLang != currentLang && data.activeLang !== shortLang){
- var options = modules[data.module].options;
- if( data.langObj[currentLang] || (shortLang && data.langObj[shortLang]) ){
- data.activeLang = currentLang;
- data.callback(data.langObj[currentLang] || data.langObj[shortLang], currentLang);
- callRegister(data.module);
- } else if( !_noLoop &&
- !loadRemoteLang(data, currentLang, options) &&
- !loadRemoteLang(data, shortLang, options) &&
- data.langObj[''] && data.activeLang !== '' ) {
- data.activeLang = '';
- data.callback(data.langObj[''], currentLang);
- callRegister(data.module);
- }
- }
- };
+ addDomLoadEvent: addDomLoadEvent,
+
+ addLoadEvent: addLoadEvent,
+
+
+ // For internal usage only
+ expressInstallCallback: function() {
-
- var activeLang = function(lang){
-
- if(typeof lang == 'string' && lang !== currentLang){
- currentLang = lang;
- shortLang = currentLang.split('-')[0];
- if(currentLang == shortLang){
- shortLang = false;
- }
- $.each(callbacks, function(i, data){
- callLang(data);
- });
- } else if(typeof lang == 'object'){
-
- if(lang.register){
- if(!registeredCallbacks[lang.register]){
- registeredCallbacks[lang.register] = [];
- }
- registeredCallbacks[lang.register].push(lang);
- lang.callback();
- } else {
- if(!lang.activeLang){
- lang.activeLang = '';
- }
- callbacks.push(lang);
- callLang(lang);
- }
- }
- return currentLang;
- };
-
- return activeLang;
- })()
- });
-
- $.each({
- defineNodeNamesProperty: 'defineNodeNameProperty',
- defineNodeNamesProperties: 'defineNodeNameProperties',
- createElements: 'createElement'
- }, function(name, baseMethod){
- webshims[name] = function(names, a, b, c){
- if(typeof names == 'string'){
- names = names.split(listReg);
- }
- var retDesc = {};
- names.forEach(function(nodeName){
- retDesc[nodeName] = webshims[baseMethod](nodeName, a, b, c);
- });
- return retDesc;
- };
- });
-
- webshims.isReady('webshimLocalization', true);
-});
-//html5a11y
-(function($, document){
- //if we support basic styleing or do not support ARIA (assumed) abort
- if(!Modernizr.localstorage || ('hidden' in document.createElement('a'))){return;}
-
- var elemMappings = {
- article: "article",
- aside: "complementary",
- section: "region",
- nav: "navigation",
- address: "contentinfo"
- };
- var addRole = function(elem, role){
- var hasRole = elem.getAttribute('role');
- if (!hasRole) {
- elem.setAttribute('role', role);
}
};
-
- $.webshims.addReady(function(context, contextElem){
- $.each(elemMappings, function(name, role){
- var elems = $(name, context).add(contextElem.filter(name));
- for (var i = 0, len = elems.length; i < len; i++) {
- addRole(elems[i], role);
- }
- });
- if (context === document) {
- var header = document.getElementsByTagName('header')[0];
- var footers = document.getElementsByTagName('footer');
- var footerLen = footers.length;
- if (header && !$(header).closest('section, article')[0]) {
- addRole(header, 'banner');
- }
- if (!footerLen) {
- return;
- }
- var footer = footers[footerLen - 1];
- if (!$(footer).closest('section, article')[0]) {
- addRole(footer, 'contentinfo');
- }
- }
- });
-
-})(jQuery, document);
+}();
-jQuery.webshims.register('details', function($, webshims, window, doc, undefined, options){
- var isInterActiveSummary = function(summary){
- var details = $(summary).parent('details');
- if(details[0] && details.children(':first').get(0) === summary){
- return details;
- }
- };
-
- var bindDetailsSummary = function(summary, details){
- summary = $(summary);
- details = $(details);
- var oldSummary = $.data(details[0], 'summaryElement');
- $.data(summary[0], 'detailsElement', details);
- if(!oldSummary || summary[0] !== oldSummary[0]){
- if(oldSummary){
- if(oldSummary.hasClass('fallback-summary')){
- oldSummary.remove();
- } else {
- oldSummary
- .unbind('.summaryPolyfill')
- .removeData('detailsElement')
- .removeAttr('role')
- .removeAttr('tabindex')
- .removeAttr('aria-expanded')
- .removeClass('summary-button')
- .find('span.details-open-indicator')
- .remove()
- ;
- }
- }
- $.data(details[0], 'summaryElement', summary);
- details.prop('open', details.prop('open'));
- }
- };
- var getSummary = function(details){
- var summary = $.data(details, 'summaryElement');
- if(!summary){
- summary = $('> summary:first-child', details);
- if(!summary[0]){
- $(details).prependPolyfill('<summary class="fallback-summary">'+ options.text +'</summary>');
- summary = $.data(details, 'summaryElement');
- } else {
- bindDetailsSummary(summary, details);
- }
- }
- return summary;
- };
-
-// var isOriginalPrevented = function(e){
-// var src = e.originalEvent;
-// if(!src){return e.isDefaultPrevented();}
-//
-// return src.defaultPrevented || src.returnValue === false ||
-// src.getPreventDefault && src.getPreventDefault();
-// };
-
- webshims.createElement('summary', function(){
- var details = isInterActiveSummary(this);
- if(!details || $.data(this, 'detailsElement')){return;}
- var timer;
- var stopNativeClickTest;
- var tabindex = $.attr(this, 'tabIndex') || '0';
- bindDetailsSummary(this, details);
- $(this)
- .on({
- 'focus.summaryPolyfill': function(){
- $(this).addClass('summary-has-focus');
- },
- 'blur.summaryPolyfill': function(){
- $(this).removeClass('summary-has-focus');
- },
- 'mouseenter.summaryPolyfill': function(){
- $(this).addClass('summary-has-hover');
- },
- 'mouseleave.summaryPolyfill': function(){
- $(this).removeClass('summary-has-hover');
- },
- 'click.summaryPolyfill': function(e){
- var details = isInterActiveSummary(this);
- if(details){
- if(!stopNativeClickTest && e.originalEvent){
- stopNativeClickTest = true;
- e.stopImmediatePropagation();
- e.preventDefault();
- $(this).trigger('click');
- stopNativeClickTest = false;
- return false;
- } else {
- clearTimeout(timer);
-
- timer = setTimeout(function(){
- if(!e.isDefaultPrevented()){
- details.prop('open', !details.prop('open'));
- }
- }, 0);
- }
- }
- },
- 'keydown.summaryPolyfill': function(e){
- if( (e.keyCode == 13 || e.keyCode == 32) && !e.isDefaultPrevented()){
- stopNativeClickTest = true;
- e.preventDefault();
- $(this).trigger('click');
- stopNativeClickTest = false;
- }
- }
- })
- .attr({tabindex: tabindex, role: 'button'})
- .prepend('<span class="details-open-indicator" />')
- ;
- webshims.moveToFirstEvent(this, 'click');
- });
-
- var initDetails;
- webshims.defineNodeNamesBooleanProperty('details', 'open', function(val){
- var summary = $($.data(this, 'summaryElement'));
- if(!summary){return;}
- var action = (val) ? 'removeClass' : 'addClass';
- var details = $(this);
- if (!initDetails && options.animate){
- details.stop().css({width: '', height: ''});
- var start = {
- width: details.width(),
- height: details.height()
- };
- }
- summary.attr('aria-expanded', ''+val);
- details[action]('closed-details-summary').children().not(summary[0])[action]('closed-details-child');
- if(!initDetails && options.animate){
- var end = {
- width: details.width(),
- height: details.height()
- };
- details.css(start).animate(end, {
- complete: function(){
- $(this).css({width: '', height: ''});
- }
- });
- }
-
- });
- webshims.createElement('details', function(){
- initDetails = true;
- var summary = getSummary(this);
- $.prop(this, 'open', $.prop(this, 'open'));
- initDetails = false;
- });
-});
-
(function($, Modernizr, webshims){
"use strict";
var hasNative = Modernizr.audio && Modernizr.video;
var supportsLoop = false;
var bugs = webshims.bugs;
@@ -1114,11 +509,11 @@
webshims.reTest([swfType], hasNative);
}
});
};
var options = webshims.cfg.mediaelement;
- var swfType = options && options.player == 'jwplayer' ? 'mediaelement-swf' : 'mediaelement-jaris';
+ var swfType = 'mediaelement-jaris';
var hasSwf;
if(!options){
webshims.error("mediaelement wasn't implemented but loaded");
return;
}
@@ -1139,38 +534,48 @@
webshims.reTest('mediaelement-native-fix');
}
}
if(hasNative && !options.preferFlash){
+ var noSwitch = {
+ 1: 1,
+ 2: 1
+ };
var switchOptions = function(e){
+ var media;
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){
+ if(!options.preferFlash &&
+ ($(e.target).is('audio, video') || (parent && $('source:last', parent)[0] == e.target)) &&
+ (media = $(e.target).closest('audio, video')) && !noSwitch[media.prop('error')]
+ ){
+ $(function(){
+ if(hasSwf && !options.preferFlash){
loadSwf();
+ webshims.ready('WINDOWLOAD '+swfType, function(){
+ setTimeout(function(){
+ if(!options.preferFlash && webshims.mediaelement.createSWF && !media.is('.nonnative-api-active')){
+ options.preferFlash = true;
+ document.removeEventListener('error', switchOptions, true);
+ $('audio, video').each(function(){
+ webshims.mediaelement.selectSource(this);
+ });
+ webshims.info("switching mediaelements option to 'preferFlash', due to an error with native player: "+e.target.src+" Mediaerror: "+ media.prop('error'));
+ }
+ }, 9);
+ });
+ } else{
+ document.removeEventListener('error', switchOptions, true);
}
- 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').each(function(){
- webshims.mediaelement.selectSource(this);
- });
- 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){
+ var error = $.prop(this, 'error');
+ if(error && !noSwitch[error]){
switchOptions({target: this});
+ return false;
}
});
}
@@ -1201,10 +606,11 @@
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");
}
+ return false;
}
};
var detectTrackError = function(){
document.addEventListener('error', trackListener, true);
@@ -1224,11 +630,11 @@
})();
}
webshims.register('mediaelement-core', function($, webshims, window, document, undefined){
- hasSwf = swfobject.hasFlashPlayerVersion('9.0.115');
+ hasSwf = swfmini.hasFlashPlayerVersion('9.0.115');
$('html').addClass(hasSwf ? 'swf' : 'no-swf');
var mediaelement = webshims.mediaelement;
mediaelement.parseRtmp = function(data){
var src = data.src.split('://');
var paths = src[1].split('/');
@@ -1317,11 +723,11 @@
return function(){
if(loaded || !hasYt){return;}
loaded = true;
webshims.loader.loadScript("https://www.youtube.com/player_api");
$(function(){
- webshims.polyfill("mediaelement-yt");
+ webshims._polyfill(["mediaelement-yt"]);
});
};
})();
var loadThird = function(){
if(hasSwf){
@@ -1441,11 +847,11 @@
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', 'video/rtmp', 'audio/rtmp'];
+ mediaelement.swfMimeTypes = ['video/3gpp', 'video/x-msvideo', 'video/quicktime', 'video/x-m4v', 'video/mp4', 'video/m4p', 'video/x-flv', 'video/flv', 'audio/mpeg', 'audio/aac', 'audio/mp4', 'audio/x-m4a', 'audio/m4a', 'audio/mp3', 'audio/x-fla', 'audio/fla', 'youtube/flv', 'video/jarisplayer', 'jarisplayer/jarisplayer', 'video/youtube', 'video/rtmp', 'audio/rtmp'];
mediaelement.canThirdPlaySrces = function(mediaElem, srces){
var ret = '';
if(hasSwf || hasYt){
mediaElem = $(mediaElem);
@@ -1466,15 +872,16 @@
mediaelement.canNativePlaySrces = function(mediaElem, srces){
var ret = '';
if(hasNative){
mediaElem = $(mediaElem);
var nodeName = (mediaElem[0].nodeName || '').toLowerCase();
- if(!nativeCanPlayType[nodeName]){return ret;}
+ var nativeCanPlay = (nativeCanPlayType[nodeName] || {prop: {_supvalue: false}}).prop._supvalue || mediaElem[0].canPlayType;
+ if(!nativeCanPlay){return ret;}
srces = srces || mediaelement.srces(mediaElem);
$.each(srces, function(i, src){
- if(src.type && nativeCanPlayType[nodeName].prop._supvalue.call(mediaElem[0], src.type) ){
+ if(src.type && nativeCanPlay.call(mediaElem[0], src.type) ){
ret = src;
return false;
}
});
}
@@ -1485,11 +892,11 @@
if(!message){
message = "can't play sources";
}
$(elem).pause().data('mediaerror', message);
- webshims.warn('mediaelementError: '+ message);
+ webshims.error('mediaelementError: '+ message);
setTimeout(function(){
if($(elem).data('mediaerror')){
$(elem).trigger('mediaerror');
}
}, 1);
@@ -1559,134 +966,155 @@
data = data || webshims.data(elem, 'mediaelement');
stepSources(elem, data, options.preferFlash || undefined, _srces);
};
mediaelement.selectSource = selectSource;
+
$(document).on('ended', function(e){
var data = webshims.data(e.target, 'mediaelement');
if( supportsLoop && (!data || data.isActive == 'html5') && !$.prop(e.target, 'loop')){return;}
setTimeout(function(){
if( $.prop(e.target, 'paused') || !$.prop(e.target, 'loop') ){return;}
$(e.target).prop('currentTime', 0).play();
}, 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);
+ webshims.ready('dom-support', function(){
+ 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 = '';
+ });
+ nativeCanPlayType[nodeName] = webshims.defineNodeNameProperty(nodeName, 'canPlayType', {
+ prop: {
+ value: function(type){
+ var ret = '';
+ if(hasNative && nativeCanPlayType[nodeName].prop._supvalue){
+ ret = nativeCanPlayType[nodeName].prop._supvalue.call(this, type);
+ if(ret == 'no'){
+ ret = '';
+ }
}
- }
- if(!ret && hasSwf){
- type = $.trim((type || '').split(';')[0]);
- if(mediaelement.swfMimeTypes.indexOf(type) != -1){
- ret = 'maybe';
+ if(!ret && hasSwf){
+ type = $.trim((type || '').split(';')[0]);
+ if(mediaelement.swfMimeTypes.indexOf(type) != -1){
+ ret = 'maybe';
+ }
}
+ return ret;
}
- return ret;
}
+ });
+ });
+ webshims.onNodeNamesPropertyModify(['audio', 'video'], ['src', 'poster'], {
+ set: function(){
+ var elem = this;
+ var baseData = webshims.data(elem, 'mediaelementBase') || webshims.data(elem, 'mediaelementBase', {});
+ clearTimeout(baseData.loadTimer);
+ baseData.loadTimer = setTimeout(function(){
+ selectSource(elem);
+ elem = null;
+ }, 9);
}
});
});
- webshims.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){
- var media = $('video, audio', context)
- .add(insertedElement.filter('video, audio'))
- .each(function(){
- var data = webshims.data(this, 'mediaelement');
+ var testFixMedia = function(){
+ if(webshims.implement(this, 'mediaelement')){
+ 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');
+ }
+ };
- if(hasNative && $.prop(this, 'paused') && !$.prop(this, 'readyState') && $(this).is('audio[preload="none"][controls]:not([autoplay])') && (!data || data.isActive == 'html5')){
- //IE controls not visible bug
- $(this).prop('preload', 'metadata').mediaLoad();
- } else {
- selectSource(this, data);
- }
-
- if(hasNative){
-
- //FF progress bug
- (function(){
- 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);
+ $(this)
+ .on({
+ 'play loadstart progress': function(e){
+ if(e.type == 'progress'){
+ lastBuffered = getBufferedString();
}
- return bufferString;
- };
- var testBuffer = function(){
- var buffered = getBufferedString();
- if(buffered != lastBuffered){
- lastBuffered = buffered;
- $(elem).triggerHandler('progress');
+ clearTimeout(bufferTimer);
+ bufferTimer = setTimeout(testBuffer, 999);
+ },
+ 'emptied stalled mediaerror abort suspend': function(e){
+ if(e.type == 'emptied'){
+ lastBuffered = false;
}
- };
-
- $(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);
- }
- })
- ;
- })();
+ clearTimeout(bufferTimer);
+ }
+ })
+ ;
+ if('ActiveXObject' in window && $.prop(this, 'paused') && !$.prop(this, 'readyState') && $(this).is('audio[preload="none"][controls]:not([autoplay],.nonnative-api-active)')){
+ $(this).prop('preload', 'metadata').mediaLoad();
}
-
- })
- ;
- if(!loadTrackUi.loaded && $('track', media).length){
- loadTrackUi();
+ }
}
- media = null;
+
+ };
+ var handleMedia = false;
+
+
+ webshims.ready('dom-support', function(){
+ handleMedia = true;
+ webshims.addReady(function(context, insertedElement){
+ var media = $('video, audio', context)
+ .add(insertedElement.filter('video, audio'))
+ .each(testFixMedia)
+ ;
+ if(!loadTrackUi.loaded && $('track', media).length){
+ loadTrackUi();
+ }
+ media = null;
+ });
});
+
+ if(hasNative && !handleMedia){
+ webshims.addReady(function(context, insertedElement){
+ if(!handleMedia){
+ $('video, audio', context)
+ .add(insertedElement.filter('video, audio'))
+ .each(function(){
+ if(!mediaelement.canNativePlaySrces(this) || (!loadTrackUi.loaded && $('track', this).length)){
+ loadThird();
+ handleMedia = true;
+ return false;
+ }
+ })
+ ;
+ }
+ });
+ }
};
if(Modernizr.track && !bugs.track){
webshims.defineProperty(TextTrack.prototype, 'shimActiveCues', {
get: function(){
@@ -1702,6 +1130,824 @@
} else {
webshims.ready(swfType, initMediaElements);
}
webshims.ready('WINDOWLOAD mediaelement', loadTrackUi);
});
-})(jQuery, Modernizr, jQuery.webshims);
+})(jQuery, Modernizr, jQuery.webshims);
+jQuery.webshims.register('track', function($, webshims, window, document, undefined){
+ "use strict";
+ var mediaelement = webshims.mediaelement;
+ var id = new Date().getTime();
+ var ADDBACK = $.fn.addBack ? 'addBack' : 'andSelf';
+ //descriptions are not really shown, but they are inserted into the dom
+ var showTracks = {subtitles: 1, captions: 1, descriptions: 1};
+ var notImplemented = function(){
+ webshims.error('not implemented yet');
+ };
+ var dummyTrack = $('<track />');
+ var supportTrackMod = Modernizr.ES5 && Modernizr.objectAccessor;
+ var createEventTarget = function(obj){
+ var eventList = {};
+ obj.addEventListener = function(name, fn){
+ if(eventList[name]){
+ webshims.error('always use $.on to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
+ }
+ eventList[name] = fn;
+
+ };
+ obj.removeEventListener = function(name, fn){
+ if(eventList[name] && eventList[name] != fn){
+ webshims.error('always use $.on/$.off to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
+ }
+ if(eventList[name]){
+ delete eventList[name];
+ }
+ };
+ return obj;
+ };
+
+ var cueListProto = {
+ getCueById: function(id){
+ var cue = null;
+ for(var i = 0, len = this.length; i < len; i++){
+ if(this[i].id === id){
+ cue = this[i];
+ break;
+ }
+ }
+ return cue;
+ }
+ };
+ var numericModes = {
+ 0: 'disabled',
+ 1: 'hidden',
+ 2: 'showing'
+ };
+
+ var textTrackProto = {
+ shimActiveCues: null,
+ _shimActiveCues: null,
+ activeCues: null,
+ cues: null,
+ kind: 'subtitles',
+ label: '',
+ language: '',
+ mode: 'disabled',
+ readyState: 0,
+ oncuechange: null,
+ toString: function() {
+ return "[object TextTrack]";
+ },
+ addCue: function(cue){
+ if(!this.cues){
+ this.cues = mediaelement.createCueList();
+ } else {
+ var lastCue = this.cues[this.cues.length-1];
+ if(lastCue && lastCue.startTime > cue.startTime){
+ webshims.error("cue startTime higher than previous cue's startTime");
+ }
+ }
+ if(cue.track && cue.track.removeCue){
+ cue.track.removeCue(cue);
+ }
+ cue.track = this;
+ this.cues.push(cue);
+ },
+ //ToDo: make it more dynamic
+ removeCue: function(cue){
+ var cues = this.cues || [];
+ var i = 0;
+ var len = cues.length;
+ if(cue.track != this){
+ webshims.error("cue not part of track");
+ return;
+ }
+ for(; i < len; i++){
+ if(cues[i] === cue){
+ cues.splice(i, 1);
+ cue.track = null;
+ break;
+ }
+ }
+ if(cue.track){
+ webshims.error("cue not part of track");
+ return;
+ }
+ },
+ DISABLED: 'disabled',
+ OFF: 'disabled',
+ HIDDEN: 'hidden',
+ SHOWING: 'showing',
+ ERROR: 3,
+ LOADED: 2,
+ LOADING: 1,
+ NONE: 0
+ };
+ var copyProps = ['kind', 'label', 'srclang'];
+ var copyName = {srclang: 'language'};
+
+ var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
+
+ var updateMediaTrackList = function(baseData, trackList){
+ var removed = [];
+ var added = [];
+ var newTracks = [];
+ var i, len;
+ if(!baseData){
+ baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
+ }
+
+ if(!trackList){
+ baseData.blockTrackListUpdate = true;
+ trackList = $.prop(this, 'textTracks');
+ baseData.blockTrackListUpdate = false;
+ }
+
+ clearTimeout(baseData.updateTrackListTimer);
+
+ $('track', this).each(function(){
+ var track = $.prop(this, 'track');
+ newTracks.push(track);
+ if(trackList.indexOf(track) == -1){
+ added.push(track);
+ }
+ });
+
+ if(baseData.scriptedTextTracks){
+ for(i = 0, len = baseData.scriptedTextTracks.length; i < len; i++){
+ newTracks.push(baseData.scriptedTextTracks[i]);
+ if(trackList.indexOf(baseData.scriptedTextTracks[i]) == -1){
+ added.push(baseData.scriptedTextTracks[i]);
+ }
+ }
+ }
+
+ for(i = 0, len = trackList.length; i < len; i++){
+ if(newTracks.indexOf(trackList[i]) == -1){
+ removed.push(trackList[i]);
+ }
+ }
+
+ if(removed.length || added.length){
+ trackList.splice(0);
+
+ for(i = 0, len = newTracks.length; i < len; i++){
+ trackList.push(newTracks[i]);
+ }
+ for(i = 0, len = removed.length; i < len; i++){
+ $([trackList]).triggerHandler($.Event({type: 'removetrack', track: removed[i]}));
+ }
+ for(i = 0, len = added.length; i < len; i++){
+ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: added[i]}));
+ }
+ if(baseData.scriptedTextTracks || removed.length){
+ $(this).triggerHandler('updatetrackdisplay');
+ }
+ }
+ };
+
+ var refreshTrack = function(track, trackData){
+ if(!trackData){
+ trackData = webshims.data(track, 'trackData');
+ }
+ if(trackData && !trackData.isTriggering){
+ trackData.isTriggering = true;
+ setTimeout(function(){
+ if(!(trackData.track || {}).readyState){
+ $(track).triggerHandler('checktrackmode');
+ } else {
+ $(track).closest('audio, video').triggerHandler('updatetrackdisplay');
+ }
+ trackData.isTriggering = false;
+ }, 1);
+ }
+ };
+
+ var emptyDiv = $('<div />')[0];
+ window.TextTrackCue = function(startTime, endTime, text){
+ if(arguments.length != 3){
+ webshims.error("wrong arguments.length for TextTrackCue.constructor");
+ }
+
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.text = text;
+
+ this.id = "";
+ this.pauseOnExit = false;
+
+ createEventTarget(this);
+ };
+
+ window.TextTrackCue.prototype = {
+
+ onenter: null,
+ onexit: null,
+ pauseOnExit: false,
+ getCueAsHTML: function(){
+ var lastText = "";
+ var parsedText = "";
+ var fragment = document.createDocumentFragment();
+ var fn;
+ if(!owns(this, 'getCueAsHTML')){
+ fn = this.getCueAsHTML = function(){
+ var i, len;
+ if(lastText != this.text){
+ lastText = this.text;
+ parsedText = mediaelement.parseCueTextToHTML(lastText);
+ emptyDiv.innerHTML = parsedText;
+
+ for(i = 0, len = emptyDiv.childNodes.length; i < len; i++){
+ fragment.appendChild(emptyDiv.childNodes[i].cloneNode(true));
+ }
+ }
+ return fragment.cloneNode(true);
+ };
+
+ }
+ return fn ? fn.apply(this, arguments) : fragment.cloneNode(true);
+ },
+ track: null,
+
+
+ id: ''
+ //todo-->
+// ,
+// snapToLines: true,
+// line: 'auto',
+// size: 100,
+// position: 50,
+// vertical: '',
+// align: 'middle'
+ };
+
+
+
+
+
+ mediaelement.createCueList = function(){
+ return $.extend([], cueListProto);
+ };
+
+ mediaelement.parseCueTextToHTML = (function(){
+ var tagSplits = /(<\/?[^>]+>)/ig;
+ var allowedTags = /^(?:c|v|ruby|rt|b|i|u)/;
+ var regEnd = /\<\s*\//;
+ var addToTemplate = function(localName, attribute, tag, html){
+ var ret;
+ if(regEnd.test(html)){
+ ret = '</'+ localName +'>';
+ } else {
+ tag.splice(0, 1);
+ ret = '<'+ localName +' '+ attribute +'="'+ (tag.join(' ').replace(/\"/g, '"')) +'">';
+ }
+ return ret;
+ };
+ var replacer = function(html){
+ var tag = html.replace(/[<\/>]+/ig,"").split(/[\s\.]+/);
+ if(tag[0]){
+ tag[0] = tag[0].toLowerCase();
+ if(allowedTags.test(tag[0])){
+ if(tag[0] == 'c'){
+ html = addToTemplate('span', 'class', tag, html);
+ } else if(tag[0] == 'v'){
+ html = addToTemplate('q', 'title', tag, html);
+ }
+ } else {
+ html = "";
+ }
+ }
+ return html;
+ };
+
+ return function(cueText){
+ return cueText.replace(tagSplits, replacer);
+ };
+ })();
+
+ mediaelement.loadTextTrack = function(mediaelem, track, trackData, _default){
+ var loadEvents = 'play playing timeupdate updatetrackdisplay';
+ var obj = trackData.track;
+ var load = function(){
+ var src = $.prop(track, 'src');
+ var error;
+ var ajax;
+ if(obj.mode != 'disabled' && src && $.attr(track, 'src')){
+ $(mediaelem).unbind(loadEvents, load);
+ $(track).unbind('checktrackmode', load);
+ if(!obj.readyState){
+ error = function(){
+ obj.readyState = 3;
+ obj.cues = null;
+ obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = null;
+ $(track).triggerHandler('error');
+ };
+ obj.readyState = 1;
+ try {
+ obj.cues = mediaelement.createCueList();
+ obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = mediaelement.createCueList();
+ ajax = $.ajax({
+ dataType: 'text',
+ url: src,
+ success: function(text){
+ if(ajax.getResponseHeader('content-type') != 'text/vtt'){
+ webshims.error('set the mime-type of your WebVTT files to text/vtt. see: http://dev.w3.org/html5/webvtt/#text/vtt');
+ }
+ mediaelement.parseCaptions(text, obj, function(cues){
+ if(cues && 'length' in cues){
+ obj.readyState = 2;
+ $(track).triggerHandler('load');
+ $(mediaelem).triggerHandler('updatetrackdisplay');
+ } else {
+ error();
+ }
+ });
+
+ },
+ error: error
+ });
+ } catch(er){
+ error();
+ webshims.warn(er);
+ }
+ }
+ }
+ };
+ obj.readyState = 0;
+ obj.shimActiveCues = null;
+ obj._shimActiveCues = null;
+ obj.activeCues = null;
+ obj.cues = null;
+ $(mediaelem).unbind(loadEvents, load);
+ $(track).unbind('checktrackmode', load);
+ $(mediaelem).on(loadEvents, load);
+ $(track).on('checktrackmode', load);
+ if(_default){
+ obj.mode = showTracks[obj.kind] ? 'showing' : 'hidden';
+ load();
+ }
+ };
+
+ mediaelement.createTextTrack = function(mediaelem, track){
+ var obj, trackData;
+ if(track.nodeName){
+ trackData = webshims.data(track, 'trackData');
+
+ if(trackData){
+ refreshTrack(track, trackData);
+ obj = trackData.track;
+ }
+ }
+
+ if(!obj){
+ obj = createEventTarget(webshims.objectCreate(textTrackProto));
+
+ if(!supportTrackMod){
+ copyProps.forEach(function(copyProp){
+ var prop = $.prop(track, copyProp);
+ if(prop){
+ obj[copyName[copyProp] || copyProp] = prop;
+ }
+ });
+ }
+
+
+ if(track.nodeName){
+
+ if(supportTrackMod){
+ copyProps.forEach(function(copyProp){
+ webshims.defineProperty(obj, copyName[copyProp] || copyProp, {
+ get: function(){
+ return $.prop(track, copyProp);
+ }
+ });
+ });
+ }
+
+ trackData = webshims.data(track, 'trackData', {track: obj});
+ mediaelement.loadTextTrack(mediaelem, track, trackData, ($.prop(track, 'default') && $(track).siblings('track[default]')[ADDBACK]()[0] == track));
+ } else {
+ if(supportTrackMod){
+ copyProps.forEach(function(copyProp){
+ webshims.defineProperty(obj, copyName[copyProp] || copyProp, {
+ value: track[copyProp],
+ writeable: false
+ });
+ });
+ }
+ obj.cues = mediaelement.createCueList();
+ obj.activeCues = obj._shimActiveCues = obj.shimActiveCues = mediaelement.createCueList();
+ obj.mode = 'hidden';
+ obj.readyState = 2;
+ }
+ }
+ return obj;
+ };
+
+
+/*
+taken from:
+Captionator 0.5.1 [CaptionCrunch]
+Christopher Giffard, 2011
+Share and enjoy
+
+https://github.com/cgiffard/Captionator
+
+modified for webshims
+*/
+ mediaelement.parseCaptionChunk = (function(){
+ // Set up timestamp parsers
+ var WebVTTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s*(.*)/;
+ var GoogleTimestampParser = /^([\d\.]+)\s+\+([\d\.]+)\s*(.*)/;
+ var WebVTTDEFAULTSCueParser = /^(DEFAULTS|DEFAULT)\s+\-\-\>\s+(.*)/g;
+ var WebVTTSTYLECueParser = /^(STYLE|STYLES)\s+\-\-\>\s*\n([\s\S]*)/g;
+ var WebVTTCOMMENTCueParser = /^(COMMENT|COMMENTS)\s+\-\-\>\s+(.*)/g;
+
+ return function(subtitleElement,objectCount){
+ var cueDefaults = [];
+
+ var subtitleParts, timeIn, timeOut, html, timeData, subtitlePartIndex, cueSettings = "", id, specialCueData;
+ var timestampMatch, tmpCue;
+
+ // WebVTT Special Cue Logic
+ if ((specialCueData = WebVTTDEFAULTSCueParser.exec(subtitleElement))) {
+// cueDefaults = specialCueData.slice(2).join("");
+// cueDefaults = cueDefaults.split(/\s+/g).filter(function(def) { return def && !!def.length; });
+ return null;
+ } else if ((specialCueData = WebVTTSTYLECueParser.exec(subtitleElement))) {
+ return null;
+ } else if ((specialCueData = WebVTTCOMMENTCueParser.exec(subtitleElement))) {
+ return null; // At this stage, we don't want to do anything with these.
+ }
+
+ subtitleParts = subtitleElement.split(/\n/g);
+
+ // Trim off any blank lines (logically, should only be max. one, but loop to be sure)
+ while (!subtitleParts[0].replace(/\s+/ig,"").length && subtitleParts.length > 0) {
+ subtitleParts.shift();
+ }
+
+ if (subtitleParts[0].match(/^\s*[a-z0-9-\_]+\s*$/ig)) {
+ // The identifier becomes the cue ID (when *we* load the cues from file. Programatically created cues can have an ID of whatever.)
+ id = String(subtitleParts.shift().replace(/\s*/ig,""));
+ }
+
+ for (subtitlePartIndex = 0; subtitlePartIndex < subtitleParts.length; subtitlePartIndex ++) {
+ var timestamp = subtitleParts[subtitlePartIndex];
+
+ if ((timestampMatch = WebVTTTimestampParser.exec(timestamp))) {
+
+ // WebVTT
+
+ timeData = timestampMatch.slice(1);
+
+ timeIn = parseInt((timeData[0]||0) * 60 * 60,10) + // Hours
+ parseInt((timeData[1]||0) * 60,10) + // Minutes
+ parseInt((timeData[2]||0),10) + // Seconds
+ parseFloat("0." + (timeData[3]||0)); // MS
+
+ timeOut = parseInt((timeData[4]||0) * 60 * 60,10) + // Hours
+ parseInt((timeData[5]||0) * 60,10) + // Minutes
+ parseInt((timeData[6]||0),10) + // Seconds
+ parseFloat("0." + (timeData[7]||0)); // MS
+/*
+ if (timeData[8]) {
+ cueSettings = timeData[8];
+ }
+*/
+ }
+
+ // We've got the timestamp - return all the other unmatched lines as the raw subtitle data
+ subtitleParts = subtitleParts.slice(0,subtitlePartIndex).concat(subtitleParts.slice(subtitlePartIndex+1));
+ break;
+ }
+
+ if (!timeIn && !timeOut) {
+ // We didn't extract any time information. Assume the cue is invalid!
+ webshims.warn("couldn't extract time information: "+[timeIn, timeOut, subtitleParts.join("\n"), id].join(' ; '));
+ return null;
+ }
+/*
+ // Consolidate cue settings, convert defaults to object
+ var compositeCueSettings =
+ cueDefaults
+ .reduce(function(previous,current,index,array){
+ previous[current.split(":")[0]] = current.split(":")[1];
+ return previous;
+ },{});
+
+ // Loop through cue settings, replace defaults with cue specific settings if they exist
+ compositeCueSettings =
+ cueSettings
+ .split(/\s+/g)
+ .filter(function(set) { return set && !!set.length; })
+ // Convert array to a key/val object
+ .reduce(function(previous,current,index,array){
+ previous[current.split(":")[0]] = current.split(":")[1];
+ return previous;
+ },compositeCueSettings);
+
+ // Turn back into string like the TextTrackCue constructor expects
+ cueSettings = "";
+ for (var key in compositeCueSettings) {
+ if (compositeCueSettings.hasOwnProperty(key)) {
+ cueSettings += !!cueSettings.length ? " " : "";
+ cueSettings += key + ":" + compositeCueSettings[key];
+ }
+ }
+*/
+ // The remaining lines are the subtitle payload itself (after removing an ID if present, and the time);
+ html = subtitleParts.join("\n");
+ tmpCue = new TextTrackCue(timeIn, timeOut, html);
+ if(id){
+ tmpCue.id = id;
+ }
+ return tmpCue;
+ };
+ })();
+
+ mediaelement.parseCaptions = function(captionData, track, complete) {
+ var subtitles = mediaelement.createCueList();
+ var cue, lazyProcess, regWevVTT;
+ var startDate;
+ var isWEBVTT;
+ if (captionData) {
+
+ regWevVTT = /^WEBVTT(\s*FILE)?/ig;
+
+ lazyProcess = function(i, len){
+
+ for(; i < len; i++){
+ cue = captionData[i];
+ if(regWevVTT.test(cue)){
+ isWEBVTT = true;
+ } else if(cue.replace(/\s*/ig,"").length){
+ if(!isWEBVTT){
+ webshims.error('please use WebVTT format. This is the standard');
+ complete(null);
+ break;
+ }
+ cue = mediaelement.parseCaptionChunk(cue, i);
+ if(cue){
+ track.addCue(cue);
+ }
+ }
+ if(startDate < (new Date().getTime()) - 30){
+ i++;
+ setTimeout(function(){
+ startDate = new Date().getTime();
+ lazyProcess(i, len);
+ }, 90);
+
+ break;
+ }
+ }
+ if(i >= len){
+ if(!isWEBVTT){
+ webshims.error('please use WebVTT format. This is the standard');
+ }
+ complete(track.cues);
+ }
+ };
+
+ captionData = captionData.replace(/\r\n/g,"\n");
+
+ setTimeout(function(){
+ captionData = captionData.replace(/\r/g,"\n");
+ setTimeout(function(){
+ startDate = new Date().getTime();
+ captionData = captionData.split(/\n\n+/g);
+ lazyProcess(0, captionData.length);
+ }, 9);
+ }, 9);
+
+ } else {
+ webshims.error("Required parameter captionData not supplied.");
+ }
+ };
+
+
+ mediaelement.createTrackList = function(mediaelem, baseData){
+ baseData = baseData || webshims.data(mediaelem, 'mediaelementBase') || webshims.data(mediaelem, 'mediaelementBase', {});
+ if(!baseData.textTracks){
+ baseData.textTracks = [];
+ webshims.defineProperties(baseData.textTracks, {
+ onaddtrack: {value: null},
+ onremovetrack: {value: null}
+ });
+ createEventTarget(baseData.textTracks);
+ }
+ return baseData.textTracks;
+ };
+
+ if(!Modernizr.track){
+ webshims.defineNodeNamesBooleanProperty(['track'], 'default');
+ webshims.reflectProperties(['track'], ['srclang', 'label']);
+
+ webshims.defineNodeNameProperties('track', {
+ src: {
+ //attr: {},
+ reflect: true,
+ propType: 'src'
+ }
+ });
+ }
+
+ webshims.defineNodeNameProperties('track', {
+ kind: {
+ attr: Modernizr.track ? {
+ set: function(value){
+ var trackData = webshims.data(this, 'trackData');
+ this.setAttribute('data-kind', value);
+ if(trackData){
+ trackData.attrKind = value;
+ }
+ },
+ get: function(){
+ var trackData = webshims.data(this, 'trackData');
+ if(trackData && ('attrKind' in trackData)){
+ return trackData.attrKind;
+ }
+ return this.getAttribute('kind');
+ }
+ } : {},
+ reflect: true,
+ propType: 'enumarated',
+ defaultValue: 'subtitles',
+ limitedTo: ['subtitles', 'captions', 'descriptions', 'chapters', 'metadata']
+ }
+ });
+
+ $.each(copyProps, function(i, copyProp){
+ var name = copyName[copyProp] || copyProp;
+ webshims.onNodeNamesPropertyModify('track', copyProp, function(){
+ var trackData = webshims.data(this, 'trackData');
+ var track = this;
+ if(trackData){
+ if(copyProp == 'kind'){
+ refreshTrack(this, trackData);
+ }
+ if(!supportTrackMod){
+ trackData.track[name] = $.prop(this, copyProp);
+ }
+ clearTimeout(trackData.changedTrackPropTimer);
+ trackData.changedTrackPropTimer = setTimeout(function(){
+ $(track).trigger('updatesubtitlestate');
+ }, 1);
+ }
+ });
+ });
+
+
+ webshims.onNodeNamesPropertyModify('track', 'src', function(val){
+ if(val){
+ var data = webshims.data(this, 'trackData');
+ var media;
+ if(data){
+ media = $(this).closest('video, audio');
+ if(media[0]){
+ mediaelement.loadTextTrack(media, this, data);
+ }
+ }
+ }
+
+ });
+
+ //
+
+ webshims.defineNodeNamesProperties(['track'], {
+ ERROR: {
+ value: 3
+ },
+ LOADED: {
+ value: 2
+ },
+ LOADING: {
+ value: 1
+ },
+ NONE: {
+ value: 0
+ },
+ readyState: {
+ get: function(){
+ return ($.prop(this, 'track') || {readyState: 0}).readyState;
+ },
+ writeable: false
+ },
+ track: {
+ get: function(){
+ return mediaelement.createTextTrack($(this).closest('audio, video')[0], this);
+ },
+ writeable: false
+ }
+ }, 'prop');
+
+ webshims.defineNodeNamesProperties(['audio', 'video'], {
+ textTracks: {
+ get: function(){
+ var media = this;
+ var baseData = webshims.data(media, 'mediaelementBase') || webshims.data(media, 'mediaelementBase', {});
+ var tracks = mediaelement.createTrackList(media, baseData);
+ if(!baseData.blockTrackListUpdate){
+ updateMediaTrackList.call(media, baseData, tracks);
+ }
+ return tracks;
+ },
+ writeable: false
+ },
+ addTextTrack: {
+ value: function(kind, label, lang){
+ var textTrack = mediaelement.createTextTrack(this, {
+ kind: dummyTrack.prop('kind', kind || '').prop('kind'),
+ label: label || '',
+ srclang: lang || ''
+ });
+ var baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
+ if (!baseData.scriptedTextTracks) {
+ baseData.scriptedTextTracks = [];
+ }
+ baseData.scriptedTextTracks.push(textTrack);
+ updateMediaTrackList.call(this);
+ return textTrack;
+ }
+ }
+ }, 'prop');
+
+
+ $(document).on('emptied ended updatetracklist', function(e){
+ if($(e.target).is('audio, video')){
+ var baseData = webshims.data(e.target, 'mediaelementBase');
+ if(baseData){
+ clearTimeout(baseData.updateTrackListTimer);
+ baseData.updateTrackListTimer = setTimeout(function(){
+ updateMediaTrackList.call(e.target, baseData);
+ }, 0);
+ }
+ }
+ });
+
+ var getNativeReadyState = function(trackElem, textTrack){
+ return textTrack.readyState || trackElem.readyState;
+ };
+ var stopOriginalEvent = function(e){
+ if(e.originalEvent){
+ e.stopImmediatePropagation();
+ }
+ };
+ var startTrackImplementation = function(){
+ if(webshims.implement(this, 'track')){
+ var shimedTrack = $.prop(this, 'track');
+ var origTrack = this.track;
+ var kind;
+ var readyState;
+ if(origTrack){
+ kind = $.prop(this, 'kind');
+ readyState = getNativeReadyState(this, origTrack);
+ if (origTrack.mode || readyState) {
+ shimedTrack.mode = numericModes[origTrack.mode] || origTrack.mode;
+ }
+ //disable track from showing + remove UI
+ if(kind != 'descriptions'){
+ origTrack.mode = (typeof origTrack.mode == 'string') ? 'disabled' : 0;
+ this.kind = 'metadata';
+ $(this).attr({kind: kind});
+ }
+
+ }
+ $(this).on('load error', stopOriginalEvent);
+ }
+ };
+ webshims.addReady(function(context, insertedElement){
+ var insertedMedia = insertedElement.filter('video, audio, track').closest('audio, video');
+ $('video, audio', context)
+ .add(insertedMedia)
+ .each(function(){
+ updateMediaTrackList.call(this);
+ })
+ .each(function(){
+ if(Modernizr.track){
+ var shimedTextTracks = $.prop(this, 'textTracks');
+ var origTextTracks = this.textTracks;
+ if(shimedTextTracks.length != origTextTracks.length){
+ webshims.error("textTracks couldn't be copied");
+ }
+
+ $('track', this).each(startTrackImplementation);
+ }
+ })
+ ;
+ insertedMedia.each(function(){
+ var media = this;
+ var baseData = webshims.data(media, 'mediaelementBase');
+ if(baseData){
+ clearTimeout(baseData.updateTrackListTimer);
+ baseData.updateTrackListTimer = setTimeout(function(){
+ updateMediaTrackList.call(media, baseData);
+ }, 9);
+ }
+ });
+ });
+
+ if(Modernizr.track){
+ $('video, audio').trigger('trackapichange');
+ }
+});
\ No newline at end of file