Skip to content

Instantly share code, notes, and snippets.

@kcoder666
Last active September 17, 2016 11:04
Show Gist options
  • Save kcoder666/ab169d9fd4e7a112175a7e6fb9d239b9 to your computer and use it in GitHub Desktop.
Save kcoder666/ab169d9fd4e7a112175a7e6fb9d239b9 to your computer and use it in GitHub Desktop.
/*!
Flowplayer v6.0.5 (Wednesday, 13. January 2016 09:17AM) | flowplayer.org/license
*/
/*! (C) WebReflection Mit Style License */
(function(e){function g(e,t,n,r){for(var i,s=n.slice(),o=w(t,e),u=0,a=s.length;u<a;u++){handler=s[u],typeof handler=="object"&&typeof handler.handleEvent=="function"?handler.handleEvent(o):handler.call(e,o);if(o.stoppedImmediatePropagation)break}return i=!o.stoppedPropagation,r&&i&&e.parentNode?e.parentNode.dispatchEvent(o):!o.defaultPrevented}function y(e,t){return{configurable:!0,get:e,set:t}}function b(e,t,n){var r=f(t||e,n);u(e,"textContent",y(function(){return r.get.call(this)},function(e){r.set.call(this,e)}))}function w(e,t){return e.currentTarget=t,e.eventPhase=e.target===e.currentTarget?2:3,e}function E(e,t){var n=e.length;while(n--&&e[n]!==t);return n}function S(){if(this.tagName==="BR")return"\n";var e=this.firstChild,t=[];while(e)e.nodeType!==8&&e.nodeType!==7&&t.push(e.textContent),e=e.nextSibling;return t.join("")}function x(e){return e.nodeType!==9&&document.documentElement.contains(e)}function T(e){!n&&d.test(document.readyState)&&(n=!n,document.detachEvent(r,T),e=document.createEvent("Event"),e.initEvent(i,!0,!0),document.dispatchEvent(e))}function N(e){var t;while(t=this.lastChild)this.removeChild(t);e!=null&&this.appendChild(document.createTextNode(e))}function C(t,n){return n||(n=e.event),n.target||(n.target=n.srcElement||n.fromElement||document),n.timeStamp||(n.timeStamp=(new Date).getTime()),n}if(document.createEvent)return;var t=!0,n=!1,r="onreadystatechange",i="DOMContentLoaded",s="__IE8__"+Math.random(),o=e.Object,u=o.defineProperty||function(e,t,n){e[t]=n.value},a=o.defineProperties||function(t,n){for(var r in n)if(l.call(n,r))try{u(t,r,n[r])}catch(i){e.console&&console.log(r+" failed on object:",t,i.message)}},f=o.getOwnPropertyDescriptor,l=o.prototype.hasOwnProperty,c=e.Element.prototype,h=e.Text.prototype,p=/^[a-z]+$/,d=/loaded|complete/,v={},m=document.createElement("div");b(e.HTMLCommentElement.prototype,c,"nodeValue"),b(e.HTMLScriptElement.prototype,null,"text"),b(h,null,"nodeValue"),b(e.HTMLTitleElement.prototype,null,"text"),u(e.HTMLStyleElement.prototype,"textContent",function(e){return y(function(){return e.get.call(this.styleSheet)},function(t){e.set.call(this.styleSheet,t)})}(f(e.CSSStyleSheet.prototype,"cssText"))),a(c,{textContent:{get:S,set:N},firstElementChild:{get:function(){for(var e=this.childNodes||[],t=0,n=e.length;t<n;t++)if(e[t].nodeType==1)return e[t]}},lastElementChild:{get:function(){for(var e=this.childNodes||[],t=e.length;t--;)if(e[t].nodeType==1)return e[t]}},previousElementSibling:{get:function(){var e=this.previousSibling;while(e&&e.nodeType!=1)e=e.previousSibling;return e}},nextElementSibling:{get:function(){var e=this.nextSibling;while(e&&e.nodeType!=1)e=e.nextSibling;return e}},childElementCount:{get:function(){for(var e=0,t=this.childNodes||[],n=t.length;n--;e+=t[n].nodeType==1);return e}},addEventListener:{value:function(e,t,n){var r=this,i="on"+e,o=r[s]||u(r,s,{value:{}})[s],a=o[i]||(o[i]={}),f=a.h||(a.h=[]),c;if(!l.call(a,"w")){a.w=function(e){return e[s]||g(r,C(r,e),f,!1)};if(!l.call(v,i))if(p.test(e))try{c=document.createEventObject(),c[s]=!0,r.nodeType!=9&&r.parentNode==null&&m.appendChild(r),r.fireEvent(i,c),v[i]=!0}catch(c){v[i]=!1;while(m.hasChildNodes())m.removeChild(m.firstChild)}else v[i]=!1;(a.n=v[i])&&r.attachEvent(i,a.w)}E(f,t)<0&&f[n?"unshift":"push"](t)}},dispatchEvent:{value:function(e){var t=this,n="on"+e.type,r=t[s],i=r&&r[n],o=!!i,u;return e.target||(e.target=t),o?i.n?t.fireEvent(n,e):g(t,e,i.h,!0):(u=t.parentNode)?u.dispatchEvent(e):!0,!e.defaultPrevented}},removeEventListener:{value:function(e,t,n){var r=this,i="on"+e,o=r[s],u=o&&o[i],a=u&&u.h,f=a?E(a,t):-1;-1<f&&a.splice(f,1)}}}),a(h,{addEventListener:{value:c.addEventListener},dispatchEvent:{value:c.dispatchEvent},removeEventListener:{value:c.removeEventListener}}),a(e.XMLHttpRequest.prototype,{addEventListener:{value:function(e,t,n){var r=this,i="on"+e,o=r[s]||u(r,s,{value:{}})[s],a=o[i]||(o[i]={}),f=a.h||(a.h=[]);E(f,t)<0&&(r[i]||(r[i]=function(){var t=document.createEvent("Event");t.initEvent(e,!0,!0),r.dispatchEvent(t)}),f[n?"unshift":"push"](t))}},dispatchEvent:{value:function(e){var t=this,n="on"+e.type,r=t[s],i=r&&r[n],o=!!i;return o&&(i.n?t.fireEvent(n,e):g(t,e,i.h,!0))}},removeEventListener:{value:c.removeEventListener}}),a(e.Event.prototype,{bubbles:{value:!0,writable:!0},cancelable:{value:!0,writable:!0},preventDefault:{value:function(){this.cancelable&&(this.defaultPrevented=!0,this.returnValue=!1)}},stopPropagation:{value:function(){this.stoppedPropagation=!0,this.cancelBubble=!0}},stopImmediatePropagation:{value:function(){this.stoppedImmediatePropagation=!0,this.stopPropagation()}},initEvent:{value:function(e,t,n){this.type=e,this.bubbles=!!t,this.cancelable=!!n,this.bubbles||this.stopPropagation()}}}),a(e.HTMLDocument.prototype,{textContent:{get:function(){return this.nodeType===11?S.call(this):null},set:function(e){this.nodeType===11&&N.call(this,e)}},addEventListener:{value:function(n,s,o){var u=this;c.addEventListener.call(u,n,s,o),t&&n===i&&!d.test(u.readyState)&&(t=!1,u.attachEvent(r,T),e==top&&function a(e){try{u.documentElement.doScroll("left"),T()}catch(t){setTimeout(a,50)}}())}},dispatchEvent:{value:c.dispatchEvent},removeEventListener:{value:c.removeEventListener},createEvent:{value:function(e){var t;if(e!=="Event")throw new Error("unsupported "+e);return t=document.createEventObject(),t.timeStamp=(new Date).getTime(),t}}}),a(e.Window.prototype,{getComputedStyle:{value:function(){function i(e){this._=e}function s(){}var e=/^(?:[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/,t=/^(top|right|bottom|left)$/,n=/\-([a-z])/g,r=function(e,t){return t.toUpperCase()};return i.prototype.getPropertyValue=function(i){var s=this._,o=s.style,u=s.currentStyle,a=s.runtimeStyle,f,l,c;return i=(i==="float"?"style-float":i).replace(n,r),f=u?u[i]:o[i],e.test(f)&&!t.test(i)&&(l=o.left,c=a&&a.left,c&&(a.left=u.left),o.left=i==="fontSize"?"1em":f,f=o.pixelLeft+"px",o.left=l,c&&(a.left=c)),f==null?f:f+""||"auto"},s.prototype.getPropertyValue=function(){return null},function(e,t){return t?new s(e):new i(e)}}()},addEventListener:{value:function(t,n,r){var i=e,o="on"+t,u;i[o]||(i[o]=function(e){return g(i,C(i,e),u,!1)}),u=i[o][s]||(i[o][s]=[]),E(u,n)<0&&u[r?"unshift":"push"](n)}},dispatchEvent:{value:function(t){var n=e["on"+t.type];return n?n.call(e,t)!==!1&&!t.defaultPrevented:!0}},removeEventListener:{value:function(t,n,r){var i="on"+t,u=(e[i]||o)[s],a=u?E(u,n):-1;-1<a&&u.splice(a,1)}}})})(this);
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.flowplayer=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
'use strict';
var common = module.exports = {},
ClassList = _dereq_('class-list'),
$ = window.jQuery,
punycode = _dereq_('punycode'),
computedStyle = _dereq_('computed-style');
common.noop = function() {};
common.identity = function(i) { return i; };
common.removeNode = function(el) {
if (!el || !el.parentNode) return;
el.parentNode.removeChild(el);
};
common.find = function(query, ctx) {
if ($) return $(query, ctx).toArray();
ctx = ctx || document;
return Array.prototype.map.call(ctx.querySelectorAll(query), function(el) { return el; });
};
common.text = function(el, txt) {
el[('innerText' in el) ? 'innerText' : 'textContent'] = txt;
};
common.findDirect = function(query, ctx) {
return common.find(query, ctx).filter(function(node) {
return node.parentNode === ctx;
});
};
common.hasClass = function(el, kls) {
return ClassList(el).contains(kls);
};
common.isSameDomain = function(url) {
var w = window.location,
a = common.createElement('a', { href: url });
return w.hostname === a.hostname &&
w.protocol === a.protocol &&
w.port === a.port;
};
common.css = function(el, property, value) {
if (typeof property === 'object') {
return Object.keys(property).forEach(function(key) {
common.css(el, key, property[key]);
});
}
if (typeof value !== 'undefined') {
if (value === '') return el ? el.style.removeProperty(property) : undefined;
return el ? el.style.setProperty(property, value) : undefined;
}
return el ? computedStyle(el, property) : undefined;
};
common.createElement = function(tag, attributes, innerHTML) {
try {
var el = document.createElement(tag);
for (var key in attributes) {
if (!attributes.hasOwnProperty(key)) continue;
if (key === 'css') {
common.css(el, attributes[key]);
} else {
common.attr(el, key, attributes[key]);
}
}
el.innerHTML = innerHTML || '';
return el;
} catch (e) {
if (!$) throw e;
return $('<' + tag + '>' + innerHTML + '</' + tag + '>').attr(attributes)[0];
}
};
common.toggleClass = function(el, cls, flag) {
if (!el) return;
var classes = ClassList(el);
if (typeof flag === 'undefined') classes.toggle(cls);
else if (flag) classes.add(cls);
else if (!flag) classes.remove(cls);
};
common.addClass = function(el, cls) {
return common.toggleClass(el, cls, true);
};
common.removeClass = function(el, cls) {
return common.toggleClass(el, cls, false);
};
common.append = function(par, child) {
par.appendChild(child);
return par;
};
common.appendTo = function(child, par) {
common.append(par, child);
return child;
};
common.prepend = function(par, child) {
par.insertBefore(child, par.firstChild);
};
// Inserts `el` after `child` that is child of `par`
common.insertAfter = function(par, child, el) {
if (child == common.lastChild(par)) par.appendChild(el);
var childIndex = Array.prototype.indexOf.call(par.children, child);
par.insertBefore(el, par.children[childIndex + 1]);
};
common.html = function(elms, val) {
elms = elms.length ? elms : [elms];
elms.forEach(function(elm) {
elm.innerHTML = val;
});
};
common.attr = function(el, key, val) {
if (key === 'class') key = 'className';
if (common.hasOwnOrPrototypeProperty(el, key)) {
try {
el[key] = val;
} catch (e) { // Most likely IE not letting set property
if ($) {
$(el).attr(key, val);
} else {
throw e;
}
}
} else {
if (val === false) {
el.removeAttribute(key);
} else {
el.setAttribute(key, val);
}
}
return el;
};
common.prop = function(el, key, val) {
if (typeof val === 'undefined') {
return el && el[key];
}
el[key] = val;
};
common.offset = function(el) {
var ret = el.getBoundingClientRect();
if (el.offsetWidth / el.offsetHeight > el.clientWidth / el.clientHeight) { // https://github.com/flowplayer/flowplayer/issues/757
ret = {
left: ret.left * 100,
right: ret.right * 100,
top: ret.top * 100,
bottom: ret.bottom * 100,
width: ret.width * 100,
height: ret.height * 100
};
}
return ret;
};
common.width = function(el, val) {
/*jshint -W093 */
if (val) return el.style.width = (''+val).replace(/px$/, '') + 'px';
var ret = common.offset(el).width;
return typeof ret === 'undefined' ? el.offsetWidth : ret;
};
common.height = function(el, val) {
/*jshint -W093 */
if (val) return el.style.height = (''+val).replace(/px$/, '') + 'px';
var ret = common.offset(el).height;
return typeof ret === 'undefined' ? el.offsetHeight : ret;
};
common.lastChild = function(el) {
return el.children[el.children.length - 1];
};
common.hasParent = function(el, parentSelector) {
var parent = el.parentElement;
while (parent) {
if (common.matches(parent, parentSelector)) return true;
parent = parent.parentElement;
}
return false;
};
common.createAbsoluteUrl = function(url) {
return common.createElement('a', {href: url}).href; // This won't work on IE7
};
common.xhrGet = function(url, successCb, errorCb) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState !== 4) return;
if (this.status >= 400) return errorCb();
successCb(this.responseText);
};
xhr.open('get', url, true);
xhr.send();
};
common.pick = function(obj, props) {
var ret = {};
props.forEach(function(prop) {
if (obj.hasOwnProperty(prop)) ret[prop] = obj[prop];
});
return ret;
};
common.hostname = function(host) {
return punycode.toUnicode(host || window.location.hostname);
};
//Hacks
common.browser = {
webkit: 'WebkitAppearance' in document.documentElement.style
};
common.getPrototype = function(el) {
/* jshint proto:true */
if (!Object.getPrototypeOf) return el.__proto__;
return Object.getPrototypeOf(el);
};
common.hasOwnOrPrototypeProperty = function(obj, prop) {
var o = obj;
while (o) {
if (Object.prototype.hasOwnProperty.call(o, prop)) return true;
o = common.getPrototype(o);
}
return false;
};
// Polyfill for Element.matches
// adapted from https://developer.mozilla.org/en/docs/Web/API/Element/matches
common.matches = function(elem, selector) {
var proto = Element.prototype,
fn = proto.matches ||
proto.matchesSelector ||
proto.mozMatchesSelector ||
proto.msMatchesSelector ||
proto.oMatchesSelector ||
proto.webkitMatchesSelector ||
function (selector) {
var element = this,
matches = (element.document || element.ownerDocument).querySelectorAll(selector),
i = 0;
while (matches[i] && matches[i] !== element) {
i++;
}
return matches[i] ? true : false;
};
return fn.call(elem, selector);
};
// Polyfill for CSSStyleDeclaration
// from https://github.com/shawnbot/aight
(function(CSSSDProto) {
function getAttribute(property) {
return property.replace(/-[a-z]/g, function(bit) {
return bit[1].toUpperCase();
});
}
// patch CSSStyleDeclaration.prototype using IE8's methods
if (typeof CSSSDProto.setAttribute !== "undefined") {
CSSSDProto.setProperty = function(property, value) {
return this.setAttribute(getAttribute(property), String(value) /*, important */ );
};
CSSSDProto.getPropertyValue = function(property) {
return this.getAttribute(getAttribute(property)) || null;
};
CSSSDProto.removeProperty = function(property) {
var value = this.getPropertyValue(property);
this.removeAttribute(getAttribute(property));
return value;
};
}
})(window.CSSStyleDeclaration.prototype);
},{"class-list":22,"computed-style":24,"punycode":21}],2:[function(_dereq_,module,exports){
'use strict';
var common = _dereq_('../common');
// movie required in opts
module.exports = function embed(swf, flashvars, wmode, bgColor) {
wmode = wmode || "opaque";
var id = "obj" + ("" + Math.random()).slice(2, 15),
tag = '<object class="fp-engine" id="' + id+ '" name="' + id + '" ',
msie = navigator.userAgent.indexOf('MSIE') > -1;
tag += msie ? 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">' :
' data="' + swf + '" type="application/x-shockwave-flash">';
var opts = {
width: "100%",
height: "100%",
allowscriptaccess: "always",
wmode: wmode,
quality: "high",
flashvars: "",
// https://github.com/flowplayer/flowplayer/issues/13#issuecomment-9369919
movie: swf + (msie ? "?" + id : ""),
name: id
};
if (wmode !== 'transparent') opts.bgcolor = bgColor || '#333333';
// flashvars
Object.keys(flashvars).forEach(function(key) {
opts.flashvars += key + "=" + flashvars[key] + "&";
});
// parameters
Object.keys(opts).forEach(function(key) {
tag += '<param name="' + key + '" value="'+ opts[key] +'"/>';
});
tag += "</object>";
var el = common.createElement('div', {}, tag);
return common.find('object', el);
};
// Flash is buggy allover
if (window.attachEvent) {
window.attachEvent("onbeforeunload", function() {
window.__flash_savedUnloadHandler = window.__flash_unloadHandler = function() {};
});
}
},{"../common":1}],3:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
common = _dereq_('../common'),
embed = _dereq_('./embed'),
extend = _dereq_('extend-object'),
bean = _dereq_('bean'),
engineImpl;
engineImpl = function flashEngine(player, root) {
var conf = player.conf,
video = player.video,
loadVideo,
callbackId,
objectTag,
api;
var win = window;
var engine = {
engineName: engineImpl.engineName,
pick: function(sources) {
var source = extend({}, (function() {
if (flowplayer.support.flashVideo) {
var selectedSource;
for (var i = 0, source; i < sources.length; i++) {
source = sources[i];
if (/mp4|flv|flash/i.test(source.type)) selectedSource = source;
if (player.conf.swfHls && /mpegurl/i.test(source.type)) selectedSource = source;
if (selectedSource && !/mp4/i.test(selectedSource.type)) return selectedSource;
// Did not find any source or source was video/mp4, let's try find more
}
return selectedSource; // Accept the fact we don't have anything or just an MP4
}
})());
if (!source) return;
if (source.src && !isAbsolute(source.src) && !player.conf.rtmp && !source.rtmp) source.src = common.createAbsoluteUrl(source.src);
return source;
},
load: function(video) {
loadVideo = video;
function escapeURL(url) {
return url.replace(/&amp;/g, '%26').replace(/&/g, '%26').replace(/=/g, '%3D');
}
var html5Tag = common.findDirect('video', root)[0] || common.find('.fp-player > video', root)[0],
url = video.src,
is_absolute = isAbsolute(url);
var removeTag = function() {
common.removeNode(html5Tag);
};
var hasSupportedSource = function(sources) {
return sources.some(function(src) {
return !!html5Tag.canPlayType(src.type);
});
};
if (flowplayer.support.video &&
common.prop(html5Tag, 'autoplay') &&
hasSupportedSource(video.sources)) bean.one(html5Tag, 'timeupdate', removeTag);
else removeTag();
// convert to absolute
var rtmp = video.rtmp || conf.rtmp;
if (!is_absolute && !rtmp) url = common.createAbsoluteUrl(url);
if (api && isHLS(video) && api.data !== conf.swfHls) engine.unload();
if (api) {
['live', 'preload', 'loop'].forEach(function(prop) {
if (!video.hasOwnProperty(prop)) return;
api.__set(prop, video[prop]);
});
Object.keys(video.flashls || {}).forEach(function(key) {
api.__set('hls_' + key, video.flashls[key]);
});
var providerChangeNeeded = false;
if (!is_absolute && rtmp) api.__set('rtmp', rtmp.url || rtmp);
else {
var oldRtmp = api.__get('rtmp');
providerChangeNeeded = !!oldRtmp;
api.__set('rtmp', null);
}
api.__play(url, providerChangeNeeded || video.rtmp && video.rtmp !== conf.rtmp);
} else {
callbackId = "fpCallback" + ("" + Math.random()).slice(3, 15);
url = escapeURL(url);
var opts = {
hostname: conf.embedded ? common.hostname(conf.hostname) : common.hostname(location.hostname),
url: url,
callback: callbackId
};
if (root.getAttribute('data-origin')) {
opts.origin = root.getAttribute('data-origin');
}
// optional conf
['proxy', 'key', 'autoplay', 'preload', 'subscribe', 'live', 'loop', 'debug', 'splash', 'poster', 'rtmpt'].forEach(function(key) {
if (conf.hasOwnProperty(key)) opts[key] = conf[key];
if (video.hasOwnProperty(key)) opts[key] = video[key];
if ((conf.rtmp || {}).hasOwnProperty(key)) opts[key] = (conf.rtmp || {})[key];
if ((video.rtmp || {}).hasOwnProperty(key)) opts[key] = (video.rtmp || {})[key];
});
if (conf.rtmp) opts.rtmp = conf.rtmp.url || conf.rtmp;
if (video.rtmp) opts.rtmp = video.rtmp.url || video.rtmp;
Object.keys(video.flashls || {}).forEach(function(key) {
var val = video.flashls[key];
opts['hls_' + key] = val;
});
// bufferTime might be 0
if (conf.bufferTime !== undefined) opts.bufferTime = conf.bufferTime;
if (is_absolute) delete opts.rtmp;
// issues #376
if (opts.rtmp) {
opts.rtmp = escapeURL(opts.rtmp);
}
// issues #733, 906
var bgColor = conf.bgcolor || common.css(root, 'background-color') ||'', bg;
if (bgColor.indexOf('rgb') === 0) {
bg = toHex(bgColor);
} else if (bgColor.indexOf('#') === 0) {
bg = toLongHex(bgColor);
}
// issues #387
opts.initialVolume = player.volumeLevel;
var swfUrl = isHLS(video) ? conf.swfHls : conf.swf;
api = embed(swfUrl, opts, conf.wmode, bg)[0];
var container = common.find('.fp-player', root)[0];
common.prepend(container, api);
// throw error if no loading occurs
setTimeout(function() {
try {
if (!api.PercentLoaded()) {
return player.trigger("error", [player, { code: 7, url: conf.swf }]);
}
} catch (e) {}
}, 5000);
// detect disabled flash
setTimeout(function() {
if (typeof api.PercentLoaded === 'undefined') {
player.trigger('flashdisabled', [player]);
}
}, 1000);
player.off('resume.flashhack').on('resume.flashhack', function() {
var timer = setTimeout(function() {
if (player.playing) {
player.trigger('flashdisabled', [player]);
}
}, 1000);
player.one('progress', function() {
clearTimeout(timer);
});
});
api.pollInterval = setInterval(function () {
if (!api) return;
var status = api.__status ? api.__status() : null;
if (!status) return;
if (player.playing && status.time && status.time !== player.video.time) player.trigger("progress", [player, status.time]);
video.buffer = status.buffer / video.bytes * video.duration;
player.trigger("buffer", [player, video.buffer]);
if (!video.buffered && status.time > 0) {
video.buffered = true;
player.trigger("buffered", [player]);
}
}, 250);
// listen
window[callbackId] = function(type, arg) {
var video = loadVideo;
if (conf.debug) {
if (type.indexOf('debug') === 0 && arg && arg.length) {
console.log.apply(console, ['-- ' + type].concat(arg));
}
else console.log("--", type, arg);
}
var event = {
type: type
};
switch (type) {
// RTMP sends a lot of finish events in vain
// case "finish": if (conf.rtmp) return;
case "ready": arg = extend(video, arg); break;
case "click": event.flash = true; break;
case "keydown": event.which = arg; break;
case "seek": video.time = arg; break;
case "status":
player.trigger("progress", [player, arg.time]);
if (arg.buffer < video.bytes && !video.buffered) {
video.buffer = arg.buffer / video.bytes * video.duration;
player.trigger("buffer", video.buffer);
} else if (!video.buffered) {
video.buffered = true;
player.trigger("buffered");
}
break;
}
if (type === 'click' || type === 'keydown') {
event.target = root;
bean.fire(root, type, [event]);
}
else if (type != 'buffered' && type !== 'unload') {
// add some delay so that player is truly ready after an event
setTimeout(function() { player.trigger(event, [player, arg]); }, 1);
} else if (type === 'unload') {
player.trigger(event, [player, arg]);
}
};
}
},
// not supported yet
speed: common.noop,
unload: function() {
if (api && api.__unload) api.__unload();
try {
if (callbackId && window[callbackId])delete window[callbackId];
} catch (e) {}
common.find("object", root).forEach(common.removeNode);
api = 0;
player.off('.flashengine');
clearInterval(api.pollInterval);
}
};
['pause','resume','seek','volume'].forEach(function(name) {
engine[name] = function(arg) {
try {
if (player.ready) {
if (arg === undefined) {
api["__" + name]();
} else {
api["__" + name](arg);
}
}
} catch (e) {
if (typeof api["__" + name] === 'undefined') { //flash lost it's methods
return player.trigger('flashdisabled', [player]);
}
throw e;
}
};
});
function toHex(bg) {
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
bg = bg.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
if (!bg) return;
return '#' + hex(bg[1]) + hex(bg[2]) + hex(bg[3]);
}
function toLongHex(bg) {
if (bg.length === 7) return bg;
var a = bg.split('').slice(1);
return '#' + a.map(function(i) {
return i + i;
}).join('');
}
function isHLS(video) {
return /application\/x-mpegurl/i.test(video.type);
}
return engine;
};
engineImpl.engineName = 'flash';
engineImpl.canPlay = function(type, conf) {
return flowplayer.support.flashVideo && /video\/(mp4|flash|flv)/i.test(type) || flowplayer.support.flashVideo && conf.swfHls && /mpegurl/i.test(type);
};
flowplayer.engines.push(engineImpl);
function isAbsolute(url) {
return /^https?:/.test(url);
}
},{"../common":1,"../flowplayer":18,"./embed":2,"bean":20,"extend-object":26}],4:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
bean = _dereq_('bean'),
ClassList = _dereq_('class-list'),
extend = _dereq_('extend-object'),
common = _dereq_('../common');
var VIDEO = document.createElement('video');
// HTML5 --> Flowplayer event
var EVENTS = {
// fired
ended: 'finish',
pause: 'pause',
play: 'resume',
progress: 'buffer',
timeupdate: 'progress',
volumechange: 'volume',
ratechange: 'speed',
//seeking: 'beforeseek',
seeked: 'seek',
// abort: 'resume',
// not fired
loadeddata: 'ready',
// loadedmetadata: 0,
// canplay: 0,
// error events
// load: 0,
// emptied: 0,
// empty: 0,
error: 'error',
dataunavailable: 'error',
webkitendfullscreen: !flowplayer.support.inlineVideo && 'unload'
};
function round(val, per) {
per = per || 100;
return Math.round(val * per) / per;
}
function getType(type) {
return /mpegurl/i.test(type) ? "application/x-mpegurl" : type;
}
function canPlay(type) {
if (!/^(video|application)/i.test(type))
type = getType(type);
return !!VIDEO.canPlayType(type).replace("no", '');
}
function findFromSourcesByType(sources, type) {
var arr = sources.filter(function(s) {
return s.type === type;
});
return arr.length ? arr[0] : null;
}
var videoTagCache;
var createVideoTag = function(video, autoplay, preload, useCache) {
if (typeof autoplay === 'undefined') autoplay = true;
if (typeof preload === 'undefined') preload = 'none';
if (typeof useCache === 'undefined') useCache = true;
if (useCache && videoTagCache) {
videoTagCache.type = getType(video.type);
videoTagCache.src = video.src;
common.find('track', videoTagCache).forEach(common.removeNode);
videoTagCache.removeAttribute('crossorigin');
return videoTagCache;
}
var el = document.createElement('video');
el.src = video.src;
el.type = getType(video.type);
el.className = 'fp-engine';
el.autoplay = autoplay ? 'autoplay' : false;
el.preload = preload;
el.setAttribute('x-webkit-airplay', 'allow');
if (useCache) videoTagCache = el;
return el;
};
var engine;
engine = function(player, root) {
var api = common.findDirect('video', root)[0] || common.find('.fp-player > video', root)[0],
support = flowplayer.support,
track = common.find("track", api)[0],
conf = player.conf,
self,
timer,
volumeLevel;
/*jshint -W093 */
return self = {
engineName: engine.engineName,
pick: function(sources) {
var source = (function() {
if (support.video) {
if (conf.videoTypePreference) {
var mp4source = findFromSourcesByType(sources, conf.videoTypePreference);
if (mp4source) return mp4source;
}
for (var i = 0, source; i < sources.length; i++) {
if (canPlay(sources[i].type)) return sources[i];
}
}
})();
if (!source) return;
if (typeof source.src === 'string') source.src = common.createAbsoluteUrl(source.src);
return source;
},
load: function(video) {
var created = false, container = common.find('.fp-player', root)[0], reload = false;
if (conf.splash && !api) {
api = createVideoTag(video);
common.prepend(container, api);
created = true;
} else if (!api) {
api = createVideoTag(video, !!video.autoplay || !!conf.autoplay, conf.clip.preload || 'metadata', false);
common.prepend(container, api);
created = true;
} else {
ClassList(api).add('fp-engine');
common.find('source,track', api).forEach(common.removeNode);
if (!player.conf.nativesubtitles) common.attr(api, 'crossorigin', false);
reload = api.src === video.src;
}
if (!support.inlineVideo) {
common.css(api, {
position: 'absolute',
top: '-9999em'
});
}
//TODO subtitles support
// IE does not fire delegated timeupdate events
bean.off(api, 'timeupdate', common.noop);
bean.on(api, 'timeupdate', common.noop);
common.prop(api, 'loop', !!(video.loop || conf.loop));
if (typeof volumeLevel !== 'undefined') {
api.volume = volumeLevel;
}
if (player.video.src && video.src != player.video.src || video.index) common.attr(api, 'autoplay', 'autoplay');
api.src = video.src;
api.type = video.type;
self._listeners = listen(api, common.find("source", api).concat(api), video);
// iPad (+others?) demands load()
if (conf.clip.preload != 'none' && video.type != "mpegurl" || !support.zeropreload || !support.dataload) api.load();
if (created || reload) api.load();
if (api.paused && (video.autoplay || conf.autoplay)) api.play();
},
pause: function() {
api.pause();
},
resume: function() {
api.play();
},
speed: function(val) {
api.playbackRate = val;
},
seek: function(time) {
try {
var pausedState = player.paused;
api.currentTime = time;
if (pausedState) api.pause();
} catch (ignored) {}
},
volume: function(level) {
volumeLevel = level;
if (api) {
api.volume = level;
}
},
unload: function() {
common.find('video.fp-engine', root).forEach(common.removeNode);
if (!support.cachedVideoTag) videoTagCache = null;
timer = clearInterval(timer);
var instanceId = root.getAttribute('data-flowplayer-instance-id');
delete api.listeners[instanceId];
api = 0;
if (self._listeners) Object.keys(self._listeners).forEach(function(typ) {
self._listeners[typ].forEach(function(l) {
root.removeEventListener(typ, l, true);
});
});
}
};
function listen(api, sources, video) {
// listen only once
var instanceId = root.getAttribute('data-flowplayer-instance-id');
if (api.listeners && api.listeners.hasOwnProperty(instanceId)) {
api.listeners[instanceId] = video;
return;
}
(api.listeners || (api.listeners = {}))[instanceId] = video;
bean.on(sources, 'error', function(e) {
try {
if (canPlay(e.target.getAttribute('type'))) {
player.trigger("error", [player, { code: 4, video: extend(video, {src: api.src, url: api.src}) }]);
}
} catch (er) {
// Most likely: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
}
});
player.on('shutdown', function() {
bean.off(sources);
});
var eventListeners = {};
Object.keys(EVENTS).forEach(function(type) {
var flow = EVENTS[type];
if (!flow) return;
var l = function(e) {
video = api.listeners[instanceId];
if (!e.target || !ClassList(e.target).contains('fp-engine')) return;
if (conf.debug && !/progress/.test(flow)) console.log(type, "->", flow, e);
// no events if player not ready
if (!player.ready && !/ready|error/.test(flow) || !flow || !common.find('video', root).length) { return; }
var arg, vtype;
if (flow === 'unload') { //Call player unload
player.unload();
return;
}
var triggerEvent = function() {
player.trigger(flow, [player, arg]);
};
switch (flow) {
case "ready":
arg = extend(video, {
duration: api.duration,
width: api.videoWidth,
height: api.videoHeight,
url: api.currentSrc,
src: api.currentSrc
});
try {
arg.seekable = !player.live && /mpegurl/i.test(video ? (video.type || '') : '') && api.duration || api.seekable && api.seekable.end(null);
} catch (ignored) {}
// buffer
timer = timer || setInterval(function() {
try {
arg.buffer = api.buffered.end(null);
} catch (ignored) {}
if (arg.buffer) {
if (round(arg.buffer, 1000) < round(arg.duration, 1000) && !arg.buffered) {
player.trigger("buffer", e);
} else if (!arg.buffered) {
arg.buffered = true;
player.trigger("buffer", e).trigger("buffered", e);
clearInterval(timer);
timer = 0;
}
}
}, 250);
if (!player.live && !arg.duration && !support.hlsDuration && type === "loadeddata") {
var durationChanged = function() {
arg.duration = api.duration;
try {
arg.seekable = api.seekable && api.seekable.end(null);
} catch (ignored) {}
triggerEvent();
api.removeEventListener('durationchange', durationChanged);
ClassList(root).remove('is-live');
};
api.addEventListener('durationchange', durationChanged);
// Ugly hack to handle broken Android devices
var timeUpdated = function() {
if (!player.ready && !api.duration) { // No duration even though the video already plays
arg.duration = 0;
ClassList(root).add('is-live'); // Make UI believe it's live
triggerEvent();
}
api.removeEventListener('timeupdate', timeUpdated);
};
api.addEventListener('timeupdate', timeUpdated);
return;
}
break;
case "progress": case "seek":
var dur = player.video.duration;
if (api.currentTime > 0 || player.live) {
arg = Math.max(api.currentTime, 0);
} else if (flow == 'progress') {
return;
}
break;
case "speed":
arg = round(api.playbackRate);
break;
case "volume":
arg = round(api.volume);
break;
case "error":
try {
arg = (e.srcElement || e.originalTarget).error;
arg.video = extend(video, {src: api.src, url: api.src});
} catch (er) {
// Most likely https://bugzilla.mozilla.org/show_bug.cgi?id=208427
return;
}
}
triggerEvent();
};
root.addEventListener(type, l, true);
if (!eventListeners[type]) eventListeners[type] = [];
eventListeners[type].push(l);
});
return eventListeners;
}
};
engine.canPlay = function(type) {
return flowplayer.support.video && canPlay(type);
};
engine.engineName = 'html5';
flowplayer.engines.push(engine);
},{"../common":1,"../flowplayer":18,"bean":20,"class-list":22,"extend-object":26}],5:[function(_dereq_,module,exports){
'use strict';
/* global _gat */
var flowplayer = _dereq_('../flowplayer'),
TYPE_RE = _dereq_('./resolve').TYPE_RE,
scriptjs = _dereq_('scriptjs'),
bean = _dereq_('bean');
flowplayer(function(player, root) {
var id = player.conf.analytics, time = 0, last = 0, timer;
if (id) {
// load Analytics script if needed
if (typeof _gat == 'undefined') scriptjs("//google-analytics.com/ga.js");
var getTracker = function() {
var tracker = _gat._getTracker(id);
tracker._setAllowLinker(true);
return tracker;
};
var track = function track(e, api, video) {
video = video || player.video;
if (time && typeof _gat != 'undefined') {
var tracker = getTracker();
// http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html
tracker._trackEvent(
"Video / Seconds played",
player.engine.engineName + "/" + video.type,
video.title || root.getAttribute("title") || video.src.split("/").slice(-1)[0].replace(TYPE_RE, ''),
Math.round(time / 1000)
);
time = 0;
if (timer) {
clearTimeout(timer);
timer = null;
}
}
};
player.bind("load unload", track).bind("progress", function() {
if (!player.seeking) {
time += last ? (+new Date() - last) : 0;
last = +new Date();
}
if (!timer) {
timer = setTimeout(function() {
timer = null;
var tracker = getTracker();
tracker._trackEvent('Flowplayer heartbeat', 'Heartbeat', '', 0, true);
}, 10*60*1000); // heartbeat every 10 minutes
}
}).bind("pause", function() {
last = 0;
});
player.bind('shutdown', function() {
bean.off(window, 'unload', track);
});
bean.on(window, 'unload', track);
}
});
},{"../flowplayer":18,"./resolve":13,"bean":20,"scriptjs":29}],6:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
ClassList = _dereq_('class-list'),
common = _dereq_('../common'),
bean = _dereq_('bean');
flowplayer(function(player, root) {
var CUE_RE = / ?cue\d+ ?/;
var lastTime = 0, cuepointsDisabled = false;
function setClass(index) {
root.className = root.className.replace(CUE_RE, " ");
if (index >= 0) ClassList(root).add('cue' + index);
}
var segments = {}, lastFiredSegment = -0.125;
var fire = function(cue) {
var idx = player.cuepoints.indexOf(cue);
if (!isNaN(cue)) cue = { time: cue };
cue.index = idx;
setClass(idx);
player.trigger('cuepoint', [player, cue]);
};
player.on("progress", function(e, api, time) {
if (cuepointsDisabled) return;
var segment = segmentForCue(time);
while (lastFiredSegment < segment) {
lastFiredSegment += 0.125;
if (!segments[lastFiredSegment]) continue;
segments[lastFiredSegment].forEach(fire);
}
}).on("unload", setClass)
.on('beforeseek', function(ev) {
setTimeout(function() {
if (!ev.defaultPrevented) cuepointsDisabled = true;
});
}).on("seek", function(ev, api, time) {
setClass();
lastFiredSegment = segmentForCue(time || 0) - 0.125;
cuepointsDisabled = false;
if (!time && segments[0]) segments[0].forEach(fire);
}).on('ready', function(e, api, video) {
lastFiredSegment = -0.125;
var cues = video.cuepoints || player.conf.cuepoints || [];
player.setCuepoints(cues);
}).on('finish', function() {
lastFiredSegment = -0.125;
});
if (player.conf.generate_cuepoints) {
player.bind("load", function() {
// clean up cuepoint elements of previous playlist items
common.find('.fp-cuepoint', root).forEach(common.removeNode);
});
}
/**
* API
*/
player.setCuepoints = function(cues) {
player.cuepoints = [];
segments = {};
cues.forEach(player.addCuepoint);
return player;
};
player.addCuepoint = function(cue) {
if (!player.cuepoints) player.cuepoints = [];
var segment = segmentForCue(cue);
if (!segments[segment]) segments[segment] = [];
segments[segment].push(cue);
player.cuepoints.push(cue);
if (player.conf.generate_cuepoints && cue.visible !== false) {
var duration = player.video.duration,
timeline = common.find('.fp-timeline', root)[0];
common.css(timeline, "overflow", "visible");
var time = cue.time || cue;
if (time < 0) time = duration + time;
var el = common.createElement('a', {className: 'fp-cuepoint fp-cuepoint' + (player.cuepoints.length - 1)});
common.css(el, "left", (time / duration * 100) + "%");
timeline.appendChild(el);
bean.on(el, 'mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
player.seek(time);
});
}
return player;
};
player.removeCuepoint = function(cue) {
var idx = player.cuepoints.indexOf(cue),
segment = segmentForCue(cue);
if (idx === -1) return;
player.cuepoints = player.cuepoints.slice(0, idx).concat(player.cuepoints.slice(idx+1));
var sIdx = segments[segment].indexOf(cue);
if (sIdx === -1) return;
segments[segment] = segments[segment].slice(0, sIdx).concat(segments[segment].slice(sIdx+1));
return player;
};
function segmentForCue(cue) {
var time = cue && !isNaN(cue.time) ? cue.time : cue;
if (time < 0) time = player.video.duration + time;
return Math.round(time/0.125)*0.125;
}
});
},{"../common":1,"../flowplayer":18,"bean":20,"class-list":22}],7:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
bean = _dereq_('bean'),
common = _dereq_('../common'),
isObject = _dereq_('is-object'),
extend = _dereq_('extend-object'),
ClassList = _dereq_('class-list');
flowplayer(function(player, root) {
// no embedding
if (player.conf.embed === false) return;
var conf = player.conf,
ui = common.find('.fp-ui', root)[0],
trigger = common.createElement('a', { "class": "fp-embed", title: 'Copy to your site'}),
target = common.createElement('div',{ 'class': 'fp-embed-code'}, '<label>Paste this HTML code on your site to embed.</label><textarea></textarea>'),
area = common.find("textarea", target)[0];
ui.appendChild(trigger);
ui.appendChild(target);
player.embedCode = function() {
var embedConf = player.conf.embed || {},
video = player.video;
if (embedConf.iframe) {
var src = player.conf.embed.iframe,
width = embedConf.width || video.width || common.width(root),
height = embedConf.height || video.height || common.height(root);
return '<iframe src="' + player.conf.embed.iframe + '" allowfullscreen style="width:' + width + ';height:' + height + ';border:none;"></iframe>';
}
var props = ['ratio', 'rtmp', 'live', 'bufferTime', 'origin', 'analytics', 'key', 'subscribe', 'swf', 'swfHls', 'embed', 'adaptiveRatio', 'logo'];
if (embedConf.playlist) props.push('playlist');
var c = common.pick(player.conf, props);
if (c.logo) c.logo = common.createElement('img', {src: c.logo}).src;
if (!embedConf.playlist || !player.conf.playlist.length) c.clip = extend({}, player.conf.clip, common.pick(player.video, ['sources']));
var script = "var w=window,d=document,e;w._fpes||(w._fpes=[],w.addEventListener(\"load\",function(){var s=d.createElement(\"script\");s.src=\"//embed.flowplayer.org/6.0.5/embed.min.js\",d.body.appendChild(s)})),e=[].slice.call(d.getElementsByTagName(\"script\"),-1)[0].parentNode,w._fpes.push({e:e,l:\"$library\",c:$conf});\n".replace('$conf', JSON.stringify(c)).replace('$library', embedConf.library || '');
return '<a href="$href">Watch video!\n<script>$script</script></a>'.replace('$href', player.conf.origin || window.location.href).replace('$script', script);
};
fptip(root, ".fp-embed", "is-embedding");
bean.on(root, 'click', '.fp-embed-code textarea', function() {
area.select();
});
bean.on(root, 'click', '.fp-embed', function() {
area.textContent = player.embedCode().replace(/(\r\n|\n|\r)/gm,"");
area.focus();
area.select();
});
});
var fptip = function(root, trigger, active) {
function close() {
rootClasses.remove(active);
bean.off(document, '.st');
}
var rootClasses = ClassList(root);
bean.on(root, 'click', trigger || 'a', function(e) {
e.preventDefault();
rootClasses.toggle(active);
if (rootClasses.contains(active)) {
bean.on(document, 'keydown.st', function(e) {
if (e.which == 27) close();
});
bean.on(document, 'click.st', function(e) {
if (!common.hasParent(e.target, '.' + active)) close();
});
}
});
};
},{"../common":1,"../flowplayer":18,"bean":20,"class-list":22,"extend-object":26,"is-object":28}],8:[function(_dereq_,module,exports){
'use strict';
/* global jQuery */
/**
* Mimimal jQuery-like event emitter implementation
*/
module.exports = function(obj, elem) {
if (!elem) elem = document.createElement('div'); //In this case we always want to trigger (Custom)Events on dom element
var handlers = {}, eventArguments = {};
var listenEvent = function(type, hndlr, disposable) {
var actualEvent = type.split('.')[0]; //Strip namespace
var internalHandler = function(ev) {
if (disposable) {
elem.removeEventListener(actualEvent, internalHandler);
handlers[type].splice(handlers[type].indexOf(internalHandler), 1);
}
var args = [ev].concat(eventArguments[ev.timeStamp + ev.type] || []);
if (hndlr) hndlr.apply(undefined, args);
};
elem.addEventListener(actualEvent, internalHandler);
//Store handlers for unbinding
if (!handlers[type]) handlers[type] = [];
handlers[type].push(internalHandler);
};
obj.on = obj.bind = function(typ, hndlr) {
var types = typ.split(' ');
types.forEach(function(type) {
listenEvent(type, hndlr);
});
return obj; //for chaining
};
obj.one = function(typ, hndlr) {
var types = typ.split(' ');
types.forEach(function(type) {
listenEvent(type, hndlr, true);
});
return obj;
};
// Function to check if all items in toBeContained array are in the containing array
var containsAll = function(containing, toBeContained) {
return toBeContained.filter(function(i) {
return containing.indexOf(i) === -1;
}).length === 0;
};
obj.off = obj.unbind = function(typ) {
var types = typ.split(' ');
types.forEach(function(type) {
var typeNameSpaces = type.split('.').slice(1),
actualType = type.split('.')[0];
Object.keys(handlers).filter(function(t) {
var handlerNamespaces = t.split('.').slice(1);
return (!actualType || t.indexOf(actualType) === 0) && containsAll(handlerNamespaces, typeNameSpaces);
}).forEach(function(t) {
var registererHandlers = handlers[t],
actualEvent = t.split('.')[0];
registererHandlers.forEach(function(hndlr) {
elem.removeEventListener(actualEvent, hndlr);
registererHandlers.splice(registererHandlers.indexOf(hndlr), 1);
});
});
});
return obj;
};
obj.trigger = function(typ, args, returnEvent) {
if (!typ) return;
args = (args || []).length ? args || [] : [args];
var event = document.createEvent('Event'), typStr;
typStr = typ.type || typ;
event.initEvent(typStr, false, true);
if (Object.defineProperty) event.preventDefault = function() {
Object.defineProperty(this, 'defaultPrevented', { get: function() { return true; } });
};
eventArguments[event.timeStamp + event.type] = args;
elem.dispatchEvent(event);
return returnEvent ? event : obj;
};
};
module.exports.EVENTS = [
'beforeseek',
'disable',
'error',
'finish',
'fullscreen',
'fullscreen-exit',
'load',
'mute',
'pause',
'progress',
'ready',
'resume',
'seek',
'speed',
'stop',
'unload',
'volume',
'boot',
'shutdown'
];
},{}],9:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
bean = _dereq_('bean'),
ClassList = _dereq_('class-list'),
extend = _dereq_('extend-object'),
common = _dereq_('../common'),
VENDOR = flowplayer.support.browser.mozilla ? "moz": "webkit",
FS_ENTER = "fullscreen",
FS_EXIT = "fullscreen-exit",
FULL_PLAYER,
FS_SUPPORT = flowplayer.support.fullscreen,
FS_NATIVE_SUPPORT = typeof document.exitFullscreen == 'function',
ua = navigator.userAgent.toLowerCase(),
IS_SAFARI = /(safari)[ \/]([\w.]+)/.exec(ua) && !/(chrome)[ \/]([\w.]+)/.exec(ua);
// esc button
bean.on(document, "fullscreenchange.ffscr webkitfullscreenchange.ffscr mozfullscreenchange.ffscr MSFullscreenChange.ffscr", function(e) {
var el = document.webkitCurrentFullScreenElement || document.mozFullScreenElement || document.fullscreenElement || document.msFullscreenElement || e.target;
if (!FULL_PLAYER && (!el.parentNode || !el.parentNode.getAttribute('data-flowplayer-instance-id'))) return;
var player = FULL_PLAYER || flowplayer(el.parentNode);
if (el && !FULL_PLAYER) {
FULL_PLAYER = player.trigger(FS_ENTER, [el]);
} else {
FULL_PLAYER.trigger(FS_EXIT, [FULL_PLAYER]);
FULL_PLAYER = null;
}
});
flowplayer(function(player, root) {
var wrapper = common.createElement('div', {className: 'fp-player'});
Array.prototype.map.call(root.children, common.identity).forEach(function(el) {
if (common.matches(el, '.fp-ratio,script')) return;
wrapper.appendChild(el);
});
root.appendChild(wrapper);
if (!player.conf.fullscreen) return;
var win = window,
scrollY,
scrollX,
rootClasses = ClassList(root);
player.isFullscreen = false;
player.fullscreen = function(flag) {
if (player.disabled) return;
if (flag === undefined) flag = !player.isFullscreen;
if (flag) {
scrollY = win.scrollY;
scrollX = win.scrollX;
}
if (FS_SUPPORT) {
if (flag) {
['requestFullScreen', 'webkitRequestFullScreen', 'mozRequestFullScreen', 'msRequestFullscreen'].forEach(function(fName) {
if (typeof wrapper[fName] === 'function') {
wrapper[fName](Element.ALLOW_KEYBOARD_INPUT);
if (IS_SAFARI && !document.webkitCurrentFullScreenElement && !document.mozFullScreenElement) { // Element.ALLOW_KEYBOARD_INPUT not allowed
wrapper[fName]();
}
return false;
}
});
} else {
['exitFullscreen', 'webkitCancelFullScreen', 'mozCancelFullScreen', 'msExitFullscreen'].forEach(function(fName) {
if (typeof document[fName] === 'function') {
document[fName]();
return false;
}
});
}
} else {
player.trigger(flag ? FS_ENTER : FS_EXIT, [player]);
}
return player;
};
var lastClick;
player.on("mousedown.fs", function() {
if (+new Date() - lastClick < 150 && player.ready) player.fullscreen();
lastClick = +new Date();
});
player.on(FS_ENTER, function(e) {
rootClasses.add("is-fullscreen");
if (!FS_SUPPORT) common.css(root, 'position', 'fixed');
player.isFullscreen = true;
}).on(FS_EXIT, function(e) {
var oldOpacity;
if (!FS_SUPPORT && player.engine === "html5") {
oldOpacity = root.css('opacity') || '';
common.css(root, 'opacity', 0);
}
if (!FS_SUPPORT) common.css(root, 'position', '');
rootClasses.remove("is-fullscreen");
if (!FS_SUPPORT && player.engine === "html5") setTimeout(function() { root.css('opacity', oldOpacity); });
player.isFullscreen = false;
win.scrollTo(scrollX, scrollY);
}).on('unload', function() {
if (player.isFullscreen) player.fullscreen();
});
player.on('shutdown', function() {
FULL_PLAYER = null;
});
});
},{"../common":1,"../flowplayer":18,"bean":20,"class-list":22,"extend-object":26}],10:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
bean = _dereq_('bean'),
focused,
focusedRoot,
IS_HELP = "is-help",
common = _dereq_('../common'),
ClassList = _dereq_('class-list');
// keyboard. single global listener
bean.on(document, "keydown.fp", function(e) {
var el = focused,
metaKeyPressed = e.ctrlKey || e.metaKey || e.altKey,
key = e.which,
conf = el && el.conf,
focusedRootClasses = focusedRoot && ClassList(focusedRoot);
if (!el || !conf.keyboard || el.disabled) return;
// help dialog (shift key not truly required)
if ([63, 187, 191].indexOf(key) != -1) {
focusedRootClasses.toggle(IS_HELP);
return false;
}
// close help / unload
if (key == 27 && focusedRootClasses.contains(IS_HELP)) {
focusedRootClasses.toggle(IS_HELP);
return false;
}
if (!metaKeyPressed && el.ready) {
e.preventDefault();
// slow motion / fast forward
if (e.shiftKey) {
if (key == 39) el.speed(true);
else if (key == 37) el.speed(false);
return;
}
// 1, 2, 3, 4 ..
if (key < 58 && key > 47) return el.seekTo(key - 48);
switch (key) {
case 38: case 75: el.volume(el.volumeLevel + 0.15); break; // volume up
case 40: case 74: el.volume(el.volumeLevel - 0.15); break; // volume down
case 39: case 76: el.seeking = true; el.seek(true); break; // forward
case 37: case 72: el.seeking = true; el.seek(false); break; // backward
case 190: el.seekTo(); break; // to last seek position
case 32: el.toggle(); break; // spacebar
case 70: if(conf.fullscreen) el.fullscreen(); break; // toggle fullscreen
case 77: el.mute(); break; // mute
case 81: el.unload(); break; // unload/stop
}
}
});
flowplayer(function(api, root) {
// no keyboard configured
if (!api.conf.keyboard) return;
// hover
bean.on(root, "mouseenter mouseleave", function(e) {
focused = !api.disabled && e.type == 'mouseover' ? api : 0;
if (focused) focusedRoot = root;
});
var speedhelp = flowplayer.support.video && api.conf.engine !== "flash" &&
!!document.createElement('video').playbackRate ?
'<p><em>shift</em> + <em>&#8592;</em><em>&#8594;</em>slower / faster</p>' : '';
// TODO: add to player-layout.html
root.appendChild(common.createElement('div', { className: 'fp-help' }, '\
<a class="fp-close"></a>\
<div class="fp-help-section fp-help-basics">\
<p><em>space</em>play / pause</p>\
<p><em>q</em>unload | stop</p>\
<p><em>f</em>fullscreen</p>' + speedhelp + '\
</div>\
<div class="fp-help-section">\
<p><em>&#8593;</em><em>&#8595;</em>volume</p>\
<p><em>m</em>mute</p>\
</div>\
<div class="fp-help-section">\
<p><em>&#8592;</em><em>&#8594;</em>seek</p>\
<p><em>&nbsp;. </em>seek to previous\
</p><p><em>1</em><em>2</em>&hellip; <em>6</em> seek to 10%, 20% &hellip; 60% </p>\
</div>\
'));
if (api.conf.tooltip) {
var ui = common.find('.fp-ui', root)[0];
ui.setAttribute('title', 'Hit ? for help');
bean.one(root, "mouseout.tip", '.fp-ui', function() {
ui.removeAttribute('title');
});
}
bean.on(root, 'click', '.fp-close', function() {
ClassList(root).toggle(IS_HELP);
});
api.bind('shutdown', function() {
if (focusedRoot == root) focusedRoot = null;
});
});
},{"../common":1,"../flowplayer":18,"bean":20,"class-list":22}],11:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
isIeMobile = /IEMobile/.test(window.navigator.userAgent),
ClassList = _dereq_('class-list'),
common = _dereq_('../common'),
bean = _dereq_('bean'),
format = _dereq_('./ui').format,
UA = window.navigator.userAgent;
if (flowplayer.support.touch || isIeMobile) {
flowplayer(function(player, root) {
var isAndroid = /Android/.test(UA) && !/Firefox/.test(UA) && !/Opera/.test(UA),
isSilk = /Silk/.test(UA),
androidVer = isAndroid ? parseFloat(/Android\ (\d\.\d)/.exec(UA)[1], 10) : 0,
rootClasses = ClassList(root);
// custom load for android
if (isAndroid && !isIeMobile) {
if (!/Chrome/.test(UA) && androidVer < 4) {
var originalLoad = player.load;
player.load = function(video, callback) {
var ret = originalLoad.apply(player, arguments);
player.trigger('ready', [player, player.video]);
return ret;
};
}
var timer, currentTime = 0;
var resumeTimer = function(api) {
timer = setInterval(function() {
api.video.time = ++currentTime;
api.trigger('progress', [api, currentTime]);
}, 1000);
};
player.bind('ready pause unload', function() {
if (timer) {
clearInterval(timer);
timer = null;
}
});
player.bind('ready', function() {
currentTime = 0;
});
player.bind('resume', function(ev, api) {
if (!api.live) return;
if (currentTime) { return resumeTimer(api); }
player.one('progress', function(ev, api, t) {
if (t === 0) { // https://github.com/flowplayer/flowplayer/issues/727
resumeTimer(api);
}
});
});
}
// hide volume
if (!flowplayer.support.volume) {
rootClasses.add("no-volume");
rootClasses.add("no-mute");
}
rootClasses.add("is-touch");
if (player.sliders && player.sliders.timeline) player.sliders.timeline.disableAnimation();
if (!flowplayer.support.inlineVideo || player.conf.native_fullscreen) player.conf.nativesubtitles = true;
// fake mouseover effect with click
var hasMoved = false;
bean.on(root, 'touchmove', function() {
hasMoved = true;
});
bean.on(root, 'touchend click', function(e) {
if (hasMoved) { //not intentional, most likely scrolling
hasMoved = false;
return;
}
if (player.playing && !rootClasses.contains("is-mouseover")) {
rootClasses.add("is-mouseover");
rootClasses.remove("is-mouseout");
e.preventDefault();
e.stopPropagation();
return;
}
if (!player.playing && !player.splash && rootClasses.contains('is-mouseout') && !rootClasses.contains('is-mouseover')) {
setTimeout(function() {
if (!player.playing && !player.splash) {
player.resume();
}
}, 400);
}
});
// native fullscreen
if (player.conf.native_fullscreen && typeof document.createElement('video').webkitEnterFullScreen === 'function') {
player.fullscreen = function() {
var video = common.find('video.fp-engine', root)[0];
video.webkitEnterFullScreen();
bean.one(video, 'webkitendfullscreen', function() {
common.prop(video, 'controls', true);
common.prop(video, 'controls', false);
});
};
}
// Android browser gives video.duration == 1 until second 'timeupdate' event
if (isAndroid || isSilk) player.bind("ready", function() {
var video = common.find('video.fp-engine', root)[0];
bean.one(video, 'canplay', function() {
video.play();
});
video.play();
player.bind("progress.dur", function() {
var duration = video.duration;
if (duration !== 1) {
player.video.duration = duration;
common.find(".fp-duration", root)[0].innerHTML = format(duration);
player.unbind("progress.dur");
}
});
});
});
}
},{"../common":1,"../flowplayer":18,"./ui":17,"bean":20,"class-list":22}],12:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
extend = _dereq_('extend-object'),
bean = _dereq_('bean'),
ClassList = _dereq_('class-list'),
common = _dereq_('../common'),
Resolve = _dereq_('./resolve'),
resolver = new Resolve(),
$ = window.jQuery,
externalRe = /^#/;
flowplayer(function(player, root) {
var conf = extend({ active: 'is-active', advance: true, query: ".fp-playlist a" }, player.conf),
klass = conf.active, rootClasses = ClassList(root);
// getters
function els() {
return common.find(conf.query, queryRoot());
}
function queryRoot() {
if (externalRe.test(conf.query)) return;
return root;
}
function active() {
return common.find(conf.query + "." + klass, queryRoot());
}
player.play = function(i) {
if (i === undefined) return player.resume();
if (typeof i === 'number' && !player.conf.playlist[i]) return player;
else if (typeof i != 'number') return player.load.apply(null, arguments);
var arg = extend({index: i}, player.conf.playlist[i]);
if (i === player.video.index) return player.load(arg, function() { player.resume(); });
player.off('resume.fromfirst'); // Don't start from beginning if clip explicitely chosen
player.load(arg, function() {
player.video.index = i;
});
return player;
};
player.next = function(e) {
if (e) e.preventDefault();
var current = player.video.index;
if (current != -1) {
current = current === player.conf.playlist.length - 1 ? 0 : current + 1;
player.play(current);
}
return player;
};
player.prev = function(e) {
if (e) e.preventDefault();
var current = player.video.index;
if (current != -1) {
current = current === 0 ? player.conf.playlist.length - 1 : current - 1;
player.play(current);
}
return player;
};
player.setPlaylist = function(items) {
player.conf.playlist = items;
delete player.video.index;
generatePlaylist();
return player;
};
player.addPlaylistItem = function(item) {
return player.setPlaylist(player.conf.playlist.concat([item]));
};
player.removePlaylistItem = function(idx) {
var pl = player.conf.playlist;
return player.setPlaylist(pl.slice(0, idx).concat(pl.slice(idx+1)));
};
bean.on(root, 'click', '.fp-next', player.next);
bean.on(root, 'click', '.fp-prev', player.prev);
if (conf.advance) {
player.off("finish.pl").on("finish.pl", function(e, player) {
// clip looping
if (player.video.loop) return player.seek(0, function() { player.resume(); });
// next clip is found or loop
var next = player.video.index >= 0 ? player.video.index + 1 : undefined;
if (next < player.conf.playlist.length || conf.loop) {
next = next === player.conf.playlist.length ? 0 : next;
rootClasses.remove('is-finished');
setTimeout(function() { // Let other finish callbacks fire first
player.play(next);
});
// stop to last clip, play button starts from 1:st clip
} else {
// If we have multiple items in playlist, start from first
if (player.conf.playlist.length > 1) player.one("resume.fromfirst", function() {
player.play(0);
return false;
});
}
});
}
function generatePlaylist() {
var plEl = common.find('.fp-playlist', root)[0];
if (!plEl) {
plEl = common.createElement('div', {className: 'fp-playlist'});
var cntrls = common.find('.fp-next,.fp-prev', root);
if (!cntrls.length) common.insertAfter(root, common.find('video', root)[0], plEl);
else cntrls[0].parentElement.insertBefore(plEl, cntrls[0]);
}
plEl.innerHTML = '';
if (player.conf.playlist[0].length) { // FP5 style playlist
player.conf.playlist = player.conf.playlist.map(function(itm) {
if (typeof itm === 'string') {
var type = itm.split(Resolve.TYPE_RE)[1];
return {
sources: [{
type: type.toLowerCase() === 'm3u8' ? 'application/x-mpegurl' : 'video/' + type,
src: itm
}]
};
}
return {
sources: itm.map(function(src) {
var s = {};
Object.keys(src).forEach(function(k) {
s.type = /mpegurl/i.test(k) ? 'application/x-mpegurl' : 'video/' + k;
s.src = src[k];
});
return s;
})
};
});
}
player.conf.playlist.forEach(function(item, i) {
var href = item.sources[0].src;
plEl.appendChild(common.createElement('a', {
href: href,
'data-index': i
}));
});
}
var playlistInitialized = false;
if (player.conf.playlist.length) { // playlist configured by javascript, generate playlist
playlistInitialized = true;
generatePlaylist();
if (!player.conf.clip || !player.conf.clip.sources.length) {
player.conf.clip = player.conf.playlist[player.conf.startIndex || 0];
}
}
if (els().length && !playlistInitialized) { //generate playlist from existing elements
player.conf.playlist = [];
delete player.conf.startIndex;
els().forEach(function(el) {
var src = el.href;
el.setAttribute('data-index', player.conf.playlist.length);
var itm = resolver.resolve(src, player.conf.clip.sources);
if ($) {
extend(itm, $(el).data());
}
player.conf.playlist.push(itm);
});
}
/* click -> play */
bean.on(externalRe.test(conf.query) ? document : root, "click", conf.query, function(e) {
e.preventDefault();
var el = e.currentTarget;
var toPlay = Number(el.getAttribute('data-index'));
if (toPlay != -1) {
player.play(toPlay);
}
});
// highlight
function videoIndex(video) {
if (typeof video.index !== 'undefined') return video.index;
if (typeof player.video.index !== 'undefined') return player.video.index;
return player.conf.startIndex || 0;
}
player.on("load", function(e, api, video) {
if (!player.conf.playlist.length) return;
var prev = active()[0],
prevIndex = prev && prev.getAttribute('data-index'),
index = video.index = videoIndex(video),
el = common.find(conf.query +'[data-index="' + index + '"]', queryRoot())[0],
is_last = index == player.conf.playlist.length - 1;
if (prev) ClassList(prev).remove(klass);
if (el) ClassList(el).add(klass);
// index
rootClasses.remove("video" + prevIndex);
rootClasses.add("video" + index);
common.toggleClass(root, "last-video", is_last);
// video properties
video.index = api.video.index = index;
video.is_last = api.video.is_last = is_last;
// without namespace callback called only once. unknown rason.
}).on("unload.pl", function() {
if (!player.conf.playlist.length) return;
active().forEach(function(el) {
ClassList(el).toggle(klass);
});
player.conf.playlist.forEach(function(itm, i) {
rootClasses.remove('video' + i);
});
});
if (player.conf.playlist.length) {
// disable single clip looping
player.conf.loop = false;
}
});
},{"../common":1,"../flowplayer":18,"./resolve":13,"bean":20,"class-list":22,"extend-object":26}],13:[function(_dereq_,module,exports){
'use strict';
var TYPE_RE = /\.(\w{3,4})(\?.*)?$/i,
extend = _dereq_('extend-object');
function parseSource(el) {
var src = el.attr("src"),
type = el.attr("type") || "",
suffix = src.split(TYPE_RE)[1];
type = type.toLowerCase();
return extend(el.data(), { src: src, suffix: suffix || type, type: type || suffix });
}
function getType(typ) {
if (/mpegurl/i.test(typ)) return 'application/x-mpegurl';
return 'video/' + typ;
}
/* Resolves video object from initial configuration and from load() method */
module.exports = function URLResolver() {
var self = this;
self.sourcesFromVideoTag = function(videoTag, $) {
/* global $ */
var sources = [];
// initial sources
$("source", videoTag).each(function() {
sources.push(parseSource($(this)));
});
if (!sources.length && videoTag.length) sources.push(parseSource(videoTag));
return sources;
};
self.resolve = function(video, sources) {
if (!video) return { sources: sources };
if (typeof video == 'string') {
video = { src: video, sources: [] };
video.sources = (sources || []).map(function(source) {
var suffix = source.src.split(TYPE_RE)[1];
return {type: source.type, src: video.src.replace(TYPE_RE, '.' + suffix + "$2")};
});
}
if (video instanceof Array) {
video = {
sources: video.map(function(src) {
if (src.type && src.src) return src;
return Object.keys(src).reduce(function(m, typ) {
return extend(m, {
type: getType(typ),
src: src[typ]
});
}, {});
})
};
}
return video;
};
};
module.exports.TYPE_RE = TYPE_RE;
},{"extend-object":26}],14:[function(_dereq_,module,exports){
'use strict';
// skip IE policies
// document.ondragstart = function () { return false; };
//
var ClassList = _dereq_('class-list'),
bean = _dereq_('bean'),
common = _dereq_('../common');
// execute function every <delay> ms
var throttle = function(fn, delay) {
var locked;
return function () {
if (!locked) {
fn.apply(this, arguments);
locked = 1;
setTimeout(function () { locked = 0; }, delay);
}
};
};
var slider = function(root, rtl) {
var IS_IPAD = /iPad/.test(navigator.userAgent) && !/CriOS/.test(navigator.userAgent);
var progress = common.lastChild(root),
rootClasses = ClassList(root),
progressClasses = ClassList(progress),
disabled,
offset,
width,
height,
vertical,
size,
maxValue,
max,
skipAnimation = false,
/* private */
calc = function() {
offset = common.offset(root);
width = common.width(root);
height = common.height(root);
/* exit from fullscreen can mess this up.*/
// vertical = height > width;
size = vertical ? height : width;
max = toDelta(maxValue);
},
fire = function(value) {
if (!disabled && value != api.value && (!maxValue || value < maxValue)) {
bean.fire(root, 'slide', [ value ]);
api.value = value;
}
},
mousemove = function(e) {
var pageX = e.pageX || e.clientX;
if (!pageX && e.originalEvent && e.originalEvent.touches && e.originalEvent.touches.length) {
pageX = e.originalEvent.touches[0].pageX;
}
var delta = vertical ? e.pageY - offset.top : pageX - offset.left;
delta = Math.max(0, Math.min(max || size, delta));
var value = delta / size;
if (vertical) value = 1 - value;
if (rtl) value = 1 - value;
return move(value, 0, true);
},
move = function(value, speed) {
if (speed === undefined) { speed = 0; }
if (value > 1) value = 1;
var to = (Math.round(value * 1000) / 10) + "%";
if (!maxValue || value <= maxValue) {
progressClasses.remove('animated');
if (skipAnimation) {
progressClasses.remove('animated');
} else {
progressClasses.add('animated');
common.css(progress, 'transition-duration', (speed || 0) + 'ms');
}
common.css(progress, 'width', to);
}
return value;
},
toDelta = function(value) {
return Math.max(0, Math.min(size, vertical ? (1 - value) * height : value * width));
},
/* public */
api = {
max: function(value) {
maxValue = value;
},
disable: function(flag) {
disabled = flag;
},
slide: function(value, speed, fireEvent) {
calc();
if (fireEvent) fire(value);
move(value, speed);
},
// Should animation be handled via css
disableAnimation: function(value, alsoCssAnimations) {
skipAnimation = value !== false;
common.toggleClass(root, 'no-animation', !!alsoCssAnimations);
}
};
calc();
// bound dragging into document
bean.on(root, 'mousedown.sld touchstart', function(e) {
e.preventDefault();
if (!disabled) {
// begin --> recalculate. allows dynamic resizing of the slider
var delayedFire = throttle(fire, 100);
calc();
api.dragging = true;
rootClasses.add('is-dragging');
fire(mousemove(e));
bean.on(document, 'mousemove.sld touchmove.sld', function(e) {
e.preventDefault();
delayedFire(mousemove(e));
});
bean.one(document, 'mouseup touchend', function() {
api.dragging = false;
rootClasses.remove('is-dragging');
bean.off(document, 'mousemove.sld touchmove.sld');
});
}
});
return api;
};
module.exports = slider;
},{"../common":1,"bean":20,"class-list":22}],15:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
common = _dereq_('../common'),
bean = _dereq_('bean'),
ClassList = _dereq_('class-list');
flowplayer.defaults.subtitleParser = function(txt) {
var TIMECODE_RE = /^(([0-9]{2}:){1,2}[0-9]{2}[,.][0-9]{3}) --\> (([0-9]{2}:){1,2}[0-9]{2}[,.][0-9]{3})(.*)/;
function seconds(timecode) {
var els = timecode.split(':');
if (els.length == 2) els.unshift(0);
return els[0] * 60 * 60 + els[1] * 60 + parseFloat(els[2].replace(',','.'));
}
var entries = [];
for (var i = 0, lines = txt.split("\n"), len = lines.length, entry = {}, title, timecode, text, cue; i < len; i++) {
timecode = TIMECODE_RE.exec(lines[i]);
if (timecode) {
// title
title = lines[i - 1];
// text
text = "<p>" + lines[++i] + "</p><br/>";
while (typeof lines[++i] === 'string' && lines[i].trim() && i < lines.length) text += "<p>" + lines[i] + "</p><br/>";
// entry
entry = {
title: title,
startTime: seconds(timecode[1]),
endTime: seconds(timecode[3]),
text: text
};
entries.push(entry);
}
}
return entries;
};
flowplayer(function(p, root) {
var wrapClasses, currentPoint, wrap,
rootClasses = ClassList(root),
subtitleControl;
var createSubtitleControl = function() {
subtitleControl = common.createElement('a', {className: 'fp-menu'});
var menu = common.createElement('ul', {className: 'fp-dropdown fp-dropup'});
menu.appendChild(common.createElement('li', {'data-subtitle-index': -1}, 'No subtitles'));
(p.video.subtitles || []).forEach(function(st, i) {
var srcLang = st.srclang || 'en',
label = st.label || 'Default (' + srcLang + ')';
var item = common.createElement('li', {'data-subtitle-index': i}, label);
menu.appendChild(item);
});
subtitleControl.appendChild(menu);
common.find('.fp-controls', root)[0].appendChild(subtitleControl);
return subtitleControl;
};
bean.on(root, 'click', '.fp-menu', function(ev) {
ClassList(subtitleControl).toggle('dropdown-open');
});
bean.on(root, 'click', '.fp-menu li[data-subtitle-index]', function(ev) {
var idx = ev.target.getAttribute('data-subtitle-index');
if (idx === '-1') return p.disableSubtitles();
p.loadSubtitles(idx);
});
var createUIElements = function() {
var playerEl = common.find('.fp-player', root)[0];
wrap = common.find('.fp-subtitle', root)[0];
wrap = wrap || common.appendTo(common.createElement('div', {'class': 'fp-subtitle'}), playerEl);
Array.prototype.forEach.call(wrap.children, common.removeNode);
wrapClasses = ClassList(wrap);
common.find('.fp-menu', root).forEach(common.removeNode);
createSubtitleControl();
};
p.on('ready', function(ev, player, video) {
var conf = player.conf;
if (flowplayer.support.subtitles && conf.nativesubtitles && player.engine.engineName == 'html5') {
var setMode = function(mode) {
var tracks = common.find('video', root)[0].textTracks;
if (!tracks.length) return;
tracks[0].mode = mode;
};
if (!video.subtitles || !video.subtitles.length) return;
var videoTag = common.find('video.fp-engine', root)[0];
if (video.subtitles.some(function(st) { return !common.isSameDomain(st.src); })) common.attr(videoTag, 'crossorigin', 'anonymous');
videoTag.textTracks.addEventListener('addtrack', function() {
setMode('disabled');
setMode('showing');
});
video.subtitles.forEach(function(st) {
videoTag.appendChild(common.createElement('track', {
kind: 'subtitles',
srclang: st.srclang || 'en',
label: st.label || 'en',
src: st.src,
'default': st['default']
}));
});
return;
}
player.subtitles = [];
createUIElements();
rootClasses.remove('has-menu');
p.disableSubtitles();
if (!video.subtitles || !video.subtitles.length) return;
rootClasses.add('has-menu');
var defaultSubtitle = video.subtitles.filter(function(one) {
return one['default'];
})[0];
if (defaultSubtitle) player.loadSubtitles(video.subtitles.indexOf(defaultSubtitle));
});
p.bind("cuepoint", function(e, api, cue) {
if (cue.subtitle) {
currentPoint = cue.index;
common.html(wrap, cue.subtitle.text);
wrapClasses.add('fp-active');
} else if (cue.subtitleEnd) {
wrapClasses.remove('fp-active');
currentPoint = cue.index;
}
});
p.bind("seek", function(e, api, time) {
// Clear future subtitles if seeking backwards
if (currentPoint && p.cuepoints[currentPoint] && p.cuepoints[currentPoint].time > time) {
wrapClasses.remove('fp-active');
currentPoint = null;
}
(p.cuepoints || []).forEach(function(cue) {
var entry = cue.subtitle;
//Trigger cuepoint if start time before seek position and end time nonexistent or in the future
if (entry && currentPoint != cue.index) {
if (time >= cue.time && (!entry.endTime || time <= entry.endTime)) p.trigger("cuepoint", [p, cue]);
} // Also handle cuepoints that act as the removal trigger
else if (cue.subtitleEnd && time >= cue.time && cue.index == currentPoint + 1) p.trigger("cuepoint", [p, cue]);
});
});
var setActiveSubtitleClass = function(idx) {
common.toggleClass(common.find('li.active', root)[0], 'active');
common.toggleClass(common.find('li[data-subtitle-index="' + idx + '"]', root)[0], 'active');
};
p.disableSubtitles = function() {
p.subtitles = [];
(p.cuepoints || []).forEach(function(c) {
if (c.subtitle || c.subtitleEnd) p.removeCuepoint(c);
});
if (wrap) Array.prototype.forEach.call(wrap.children, common.removeNode);
setActiveSubtitleClass(-1);
return p;
};
p.loadSubtitles = function(i) {
//First remove possible old subtitles
p.disableSubtitles();
var st = p.video.subtitles[i];
var url = st.src;
if (!url) return;
setActiveSubtitleClass(i);
common.xhrGet(url, function(txt) {
var entries = p.conf.subtitleParser(txt);
entries.forEach(function(entry) {
var cue = { time: entry.startTime, subtitle: entry, visible: false };
p.subtitles.push(entry);
p.addCuepoint(cue);
p.addCuepoint({ time: entry.endTime, subtitleEnd: entry.title, visible: false });
// initial cuepoint
if (entry.startTime === 0 && !p.video.time) {
p.trigger("cuepoint", [p, cue]);
}
});
}, function() {
p.trigger("error", {code: 8, url: url });
return false;
});
return p;
};
});
},{"../common":1,"../flowplayer":18,"bean":20,"class-list":22}],16:[function(_dereq_,module,exports){
'use strict';
/* global ActiveXObject */
var flowplayer = _dereq_('../flowplayer'),
extend = _dereq_('extend-object');
(function() {
var parseIpadVersion = function(UA) {
var e = /Version\/(\d\.\d)/.exec(UA);
if (e && e.length > 1) {
return parseFloat(e[1], 10);
}
return 0;
};
var createVideoTag = function() {
var videoTag = document.createElement('video');
videoTag.loop = true;
videoTag.autoplay = true;
videoTag.preload = true;
return videoTag;
};
var b = {},
ua = navigator.userAgent.toLowerCase(),
match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(safari)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
if (match[1]) {
b[match[1]] = true;
b.version = match[2] || "0";
}
var video = createVideoTag(),
UA = navigator.userAgent,
IS_IE = b.msie || /Trident\/7/.test(UA),
IS_IPAD = /iPad|MeeGo/.test(UA) && !/CriOS/.test(UA),
IS_IPAD_CHROME = /iPad/.test(UA) && /CriOS/.test(UA),
IS_IPHONE = /iP(hone|od)/i.test(UA) && !/iPad/.test(UA) && !/IEMobile/i.test(UA),
IS_ANDROID = false, // /Android/.test(UA) && !/Firefox/.test(UA),
IS_ANDROID_FIREFOX = false, // /Android/.test(UA) && /Firefox/.test(UA),
IS_SILK = /Silk/.test(UA),
IS_WP = /IEMobile/.test(UA),
WP_VER = IS_WP ? parseFloat(/Windows\ Phone\ (\d+\.\d+)/.exec(UA)[1], 10) : 0,
IE_MOBILE_VER = IS_WP ? parseFloat(/IEMobile\/(\d+\.\d+)/.exec(UA)[1], 10) : 0,
IPAD_VER = IS_IPAD ? parseIpadVersion(UA) : 0,
ANDROID_VER = IS_ANDROID ? parseFloat(/Android\ (\d\.\d)/.exec(UA)[1], 10) : 0,
s = extend(flowplayer.support, {
browser: b,
subtitles: !!video.addTextTrack,
fullscreen: typeof document.webkitCancelFullScreen == 'function' && !/Mac OS X 10_5.+Version\/5\.0\.\d Safari/.test(UA) ||
document.mozFullScreenEnabled ||
typeof document.exitFullscreen == 'function' ||
typeof document.msExitFullscreen == 'function',
inlineBlock: !(IS_IE && b.version < 8),
touch: ('ontouchstart' in window),
dataload: true, // !IS_IPAD && !IS_IPHONE && !IS_WP,
zeropreload: !IS_IE && !IS_ANDROID, // IE supports only preload=metadata
volume: !IS_IPAD && !IS_ANDROID && !IS_IPHONE && !IS_SILK && !IS_IPAD_CHROME,
cachedVideoTag: !IS_IPAD && !IS_IPHONE && !IS_IPAD_CHROME && !IS_WP,
firstframe: !IS_IPHONE && !IS_IPAD && !IS_ANDROID && !IS_SILK && !IS_IPAD_CHROME && !IS_WP && !IS_ANDROID_FIREFOX,
inlineVideo: !IS_IPHONE && (!IS_WP || (WP_VER >= 8.1 && IE_MOBILE_VER >= 11)) && (!IS_ANDROID || ANDROID_VER >= 3),
hlsDuration: !IS_ANDROID && (!b.safari || IS_IPAD || IS_IPHONE || IS_IPAD_CHROME),
seekable: !IS_IPAD && !IS_IPAD_CHROME
});
// flashVideo
try {
var plugin = navigator.plugins["Shockwave Flash"],
ver = IS_IE ? new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable('$version') : plugin.description;
if (!IS_IE && !plugin[0].enabledPlugin) s.flashVideo = false;
else {
ver = ver.split(/\D+/);
if (ver.length && !ver[0]) ver = ver.slice(1);
s.flashVideo = ver[0] > 9 || ver[0] == 9 && ver[3] >= 115;
}
} catch (ignored) {}
try {
s.video = !!video.canPlayType;
if (s.video) video.canPlayType('video/mp4');
} catch (e) {
s.video = false;
}
// animation
s.animation = (function() {
var vendors = ['','Webkit','Moz','O','ms','Khtml'], el = document.createElement('p');
for (var i = 0; i < vendors.length; i++) {
if (typeof el.style[vendors[i] + 'AnimationName'] !== 'undefined') return true;
}
})();
})();
},{"../flowplayer":18,"extend-object":26}],17:[function(_dereq_,module,exports){
'use strict';
var flowplayer = _dereq_('../flowplayer'),
common = _dereq_('../common'),
ClassList = _dereq_('class-list'),
bean = _dereq_('bean'),
slider = _dereq_('./slider');
function zeropad(val) {
val = parseInt(val, 10);
return val >= 10 ? val : "0" + val;
}
// display seconds in hh:mm:ss format
function format(sec) {
sec = sec || 0;
var h = Math.floor(sec / 3600),
min = Math.floor(sec / 60);
sec = sec - (min * 60);
if (h >= 1) {
min -= h * 60;
return h + ":" + zeropad(min) + ":" + zeropad(sec);
}
return zeropad(min) + ":" + zeropad(sec);
}
flowplayer(function(api, root) {
var conf = api.conf,
support = flowplayer.support,
hovertimer,
rootClasses = ClassList(root);
common.find('.fp-ratio,.fp-ui', root).forEach(common.removeNode);
rootClasses.add('flowplayer');
root.appendChild(common.createElement('div', {className: 'fp-ratio'}));
var ui = common.createElement('div', {className: 'fp-ui'}, '\
<div class="waiting"><em></em><em></em><em></em></div>\
<a class="fullscreen"></a>\
<a class="unload"></a>\
<p class="speed"></p>\
<div class="controls">\
<a class="play"></a>\
<div class="timeline">\
<div class="buffer"></div>\
<div class="progress"></div>\
</div>\
<div class="timeline-tooltip fp-tooltip"></div>\
<div class="volume">\
<a class="mute"></a>\
<div class="volumeslider">\
<div class="volumelevel"></div>\
</div>\
</div>\
</div>\
<div class="time">\
<em class="elapsed">00:00</em>\
<em class="remaining"></em>\
<em class="duration">00:00</em>\
</div>\
<div class="message"><h2></h2><p></p></div>'.replace(/class="/g, 'class="fp-'));
root.appendChild(ui);
function find(klass) {
return common.find(".fp-" + klass, root)[0];
}
// widgets
var progress = find("progress"),
buffer = find("buffer"),
elapsed = find("elapsed"),
remaining = find("remaining"),
waiting = find("waiting"),
ratio = find("ratio"),
speed = find("speed"),
speedClasses = ClassList(speed),
durationEl = find("duration"),
controls = find('controls'),
timelineTooltip = find('timeline-tooltip'),
origRatio = common.css(ratio, 'padding-top'),
// sliders
timeline = find("timeline"),
timelineApi = slider(timeline, api.rtl),
volume = find("volume"),
fullscreen = find("fullscreen"),
volumeSlider = find("volumeslider"),
volumeApi = slider(volumeSlider, api.rtl),
noToggle = rootClasses.contains('fixed-controls') || rootClasses.contains('no-toggle');
timelineApi.disableAnimation(rootClasses.contains('is-touch'));
api.sliders = api.sliders || {};
api.sliders.timeline = timelineApi;
api.sliders.volume = volumeApi;
// aspect ratio
function setRatio(val) {
common.css(ratio, 'padding-top', val * 100 + "%");
if (!support.inlineBlock) common.height(common.find('object', root)[0], common.height(root));
}
function hover(flag) {
if (flag) {
rootClasses.add('is-mouseover');
rootClasses.remove('is-mouseout');
} else {
rootClasses.add('is-mouseout');
rootClasses.remove('is-mouseover');
}
}
// loading...
if (!support.animation) common.html(waiting, "<p>loading &hellip;</p>");
if (conf.ratio) setRatio(conf.ratio);
// no fullscreen in IFRAME
try {
if (!conf.fullscreen) common.removeNode(fullscreen);
} catch (e) {
common.removeNode(fullscreen);
}
api.on("ready", function(ev, api, video) {
var duration = api.video.duration;
timelineApi.disable(api.disabled || !duration);
if (conf.adaptiveRatio && !isNaN(video.height / video.width)) setRatio(video.height / video.width, true);
// initial time & volume
common.html([durationEl, remaining], format(duration));
// do we need additional space for showing hour
common.toggleClass(root, 'is-long', duration >= 3600);
volumeApi.slide(api.volumeLevel);
if (api.engine.engineName === 'flash') timelineApi.disableAnimation(true, true);
else timelineApi.disableAnimation(false);
common.find('.fp-title', ui).forEach(common.removeNode);
if (video.title) {
common.prepend(ui, common.createElement('div', {
className: 'fp-title'
}, video.title));
}
}).on("unload", function() {
if (!origRatio && !conf.splash) common.css(ratio, "paddingTop", "");
timelineApi.slide(0);
// buffer
}).on("buffer", function() {
var video = api.video,
max = video.buffer / video.duration;
if (!video.seekable && support.seekable) timelineApi.max(max);
if (max < 1) common.css(buffer, "width", (max * 100) + "%");
else common.css(buffer, 'width', '100%');
}).on("speed", function(e, api, val) {
common.text(speed, val + "x");
speedClasses.add('fp-hilite');
setTimeout(function() { speedClasses.remove('fp-hilite'); }, 1000);
}).on("buffered", function() {
common.css(buffer, 'width', '100%');
timelineApi.max(1);
// progress
}).on("progress", function() {
var time = api.video.time,
duration = api.video.duration;
if (!timelineApi.dragging) {
timelineApi.slide(time / duration, api.seeking ? 0 : 250);
}
common.html(elapsed, format(time));
common.html(remaining, '-' + format(duration - time));
}).on("finish resume seek", function(e) {
common.toggleClass(root, "is-finished", e.type == "finish");
}).on("stop", function() {
common.html(elapsed, format(0));
timelineApi.slide(0, 100);
}).on("finish", function() {
common.html(elapsed, format(api.video.duration));
timelineApi.slide(1, 100);
rootClasses.remove('is-seeking');
// misc
}).on("beforeseek", function() {
//TODO FIXME
//progress.stop();
}).on("volume", function() {
volumeApi.slide(api.volumeLevel);
}).on("disable", function() {
var flag = api.disabled;
timelineApi.disable(flag);
volumeApi.disable(flag);
common.toggleClass(root, 'is-disabled', api.disabled);
}).on("mute", function(e, api, flag) {
common.toggleClass(root, 'is-muted', flag);
}).on("error", function(e, api, error) {
common.removeClass(root, 'is-loading');
common.removeClass(root, 'is-seeking');
common.addClass(root, 'is-error');
if (error) {
error.message = conf.errors[error.code];
api.error = true;
var el = common.find('.fp-message', root)[0],
video = error.video || api.video;
common.find('h2', el)[0].innerHTML = (api.engine && api.engine.engineName || 'html5') + ": " + error.message;
common.find('p', el)[0].innerHTML = error.url || video.url || video.src || conf.errorUrls[error.code];
api.off("mouseenter click");
rootClasses.remove('is-mouseover');
}
// hover
});
//Interaction events
bean.on(root, "mouseenter mouseleave", function(e) {
if (noToggle) return;
var is_over = e.type == "mouseover",
lastMove;
// is-mouseover/out
hover(is_over);
if (is_over) {
var reg = function() {
hover(true);
lastMove = new Date();
};
api.on("pause.x volume.x", reg);
bean.on(root, 'mousemove.x', reg);
hovertimer = setInterval(function() {
if (new Date() - lastMove > conf.mouseoutTimeout) {
hover(false);
lastMove = new Date();
}
}, 100);
} else {
bean.off(root, 'mousemove.x');
api.off("pause.x volume.x");
clearInterval(hovertimer);
}
// allow dragging over the player edge
});
bean.on(root, "mouseleave", function() {
if (timelineApi.dragging || volumeApi.dragging) {
rootClasses.add('is-mouseover');
rootClasses.remove('is-mouseout');
}
// click
});
bean.on(root, "click.player", function(e) {
if (api.disabled) return;
var kls = ClassList(e.target);
if (kls.contains('fp-ui') || kls.contains('fp-engine') || e.flash) {
if (e.preventDefault) e.preventDefault();
return api.toggle();
}
});
bean.on(root, 'mousemove', '.fp-timeline', function(ev) {
var x = ev.pageX || ev.clientX,
delta = x - common.offset(timeline).left,
percentage = delta / common.width(timeline),
seconds = percentage * api.video.duration;
if (percentage < 0) return;
common.html(timelineTooltip, format(seconds));
common.css(timelineTooltip, 'left', (x - common.offset(controls).left - common.width(timelineTooltip) / 2) + 'px');
});
bean.on(root, 'contextmenu', function(ev) {
var o = common.offset(common.find('.fp-player', root)[0]),
w = window,
left = ev.clientX - (o.left + w.scrollX),
t = ev.clientY - (o.top + w.scrollY);
if (rootClasses.contains('is-flash-disabled')) return;
var menu = common.find('.fp-context-menu', root)[0];
if (!menu) return;
ev.preventDefault();
common.css(menu,
{left: left + 'px',
top: t + 'px',
display: 'block'
});
bean.on(root, 'click', '.fp-context-menu', function(ev) {
ev.stopPropagation();
});
bean.on(document, 'click.outsidemenu', function(ev) {
common.css(menu, 'display', 'none');
bean.off(document, 'click.outsidemenu');
});
});
api.on('flashdisabled', function() {
rootClasses.add('is-flash-disabled');
api.one('ready progress', function() {
rootClasses.remove('is-flash-disabled');
common.find('.fp-flash-disabled', root).forEach(common.removeNode);
});
root.appendChild(common.createElement('div', {className: "fp-flash-disabled"}, 'Adobe Flash is disabled for this page, click player area to enable'));
});
// poster -> background image
if (conf.poster) common.css(root, 'background-image', "url(" + conf.poster + ")");
var bc = common.css(root, 'background-color'),
has_bg = common.css(root, 'background-image') != "none" || bc && bc != "rgba(0, 0, 0, 0)" && bc != "transparent";
// is-poster class
if (has_bg && !conf.splash) {
if (!conf.poster) conf.poster = true;
api.on("ready stop", function() {
rootClasses.add("is-poster");
api.poster = true;
api.one("progress", function() {
rootClasses.remove("is-poster");
api.poster = false;
});
});
}
if (typeof conf.splash === 'string') {
common.css(root, 'background-image', "url('" + conf.splash + "')");
}
// default background color if not present
if (!has_bg && api.forcedSplash) {
common.css(root, "background-color", "#555");
}
bean.on(root, 'click', '.fp-toggle, .fp-play', function() {
if (api.disabled) return;
api.toggle();
});
/* controlbar elements */
bean.on(root, 'click', '.fp-mute', function() { api.mute(); });
bean.on(root, 'click', '.fp-fullscreen', function() { api.fullscreen(); });
bean.on(root, 'click', '.fp-unload', function() { api.unload(); });
bean.on(timeline, 'slide', function(val) {
api.seeking = true;
api.seek(val * api.video.duration);
});
bean.on(volumeSlider, 'slide', function(val) {
api.volume(val);
});
// times
var time = find('time');
bean.on(root, 'click', '.fp-time', function() {
ClassList(time).toggle('is-inverted');
});
hover(noToggle);
api.on('shutdown', function() {
bean.off(timeline);
bean.off(volumeSlider);
});
});
module.exports.format = format;
},{"../common":1,"../flowplayer":18,"./slider":14,"bean":20,"class-list":22}],18:[function(_dereq_,module,exports){
'use strict';
var extend = _dereq_('extend-object'),
isFunction = _dereq_('is-function'),
ClassList = _dereq_('class-list'),
bean = _dereq_('bean'),
common = _dereq_('./common'),
events = _dereq_('./ext/events');
var instances = [],
extensions = [],
UA = window.navigator.userAgent;
var oldHandler = window.onbeforeunload;
window.onbeforeunload = function(ev) {
instances.forEach(function(api) {
if (api.conf.splash) {
api.unload();
} else {
api.bind("error", function () {
common.find('.flowplayer.is-error .fp-message').forEach(common.removeNode);
});
}
});
if (oldHandler) return oldHandler(ev);
};
var supportLocalStorage = false;
try {
if (typeof window.localStorage == "object") {
window.localStorage.flowplayerTestStorage = "test";
supportLocalStorage = true;
}
} catch (ignored) {}
var isSafari = /Safari/.exec(navigator.userAgent) && !/Chrome/.exec(navigator.userAgent),
m = /(\d+\.\d+) Safari/.exec(navigator.userAgent),
safariVersion = m ? Number(m[1]) : 100;
/* flowplayer() */
var flowplayer = module.exports = function(fn, opts, callback) {
if (isFunction(fn)) return extensions.push(fn);
if (typeof fn == 'number' || typeof fn === 'undefined') return instances[fn || 0];
if (fn.nodeType) { // Is an element
if (fn.getAttribute('data-flowplayer-instance-id') !== null) { // Already flowplayer instance
return instances[fn.getAttribute('data-flowplayer-instance-id')];
}
if (!opts) return; // Can't initialize without data
return initializePlayer(fn, opts, callback);
}
if (fn.jquery) return flowplayer(fn[0], opts, callback);
if (typeof fn === 'string') {
var el = common.find(fn)[0];
return el && flowplayer(el, opts, callback);
}
};
extend(flowplayer, {
version: '6.0.5',
engines: [],
conf: {},
set: function(key, value) {
if (typeof key === 'string') flowplayer.conf[key] = value;
else extend(flowplayer.conf, key);
},
support: {},
defaults: {
debug: supportLocalStorage ? !!localStorage.flowplayerDebug : false,
// true = forced playback
disabled: false,
fullscreen: window == window.top,
// keyboard shortcuts
keyboard: true,
// default aspect ratio
ratio: 9 / 16,
adaptiveRatio: false,
rtmp: 0,
proxy: 'best',
splash: false,
live: false,
swf: "//releases.flowplayer.org/6.0.5/flowplayer.swf",
swfHls: "//releases.flowplayer.org/6.0.5/flowplayerhls.swf",
speeds: [0.25, 0.5, 1, 1.5, 2],
tooltip: true,
mouseoutTimeout: 5000,
// initial volume level
volume: !supportLocalStorage ? 1 : localStorage.muted == "true" ? 0 : !isNaN(localStorage.volume) ? localStorage.volume || 1 : 1,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#error-codes
errors: [
// video exceptions
'',
'Video loading aborted',
'Network error',
'Video not properly encoded',
'Video file not found',
// player exceptions
'Unsupported video',
'Skin not found',
'SWF file not found',
'Subtitles not found',
'Invalid RTMP URL',
'Unsupported video format. Try installing Adobe Flash.'
],
errorUrls: ['','','','','','','','','','',
'http://get.adobe.com/flashplayer/'
],
playlist: [],
hlsFix: isSafari && safariVersion < 8
},
// Expose utilities for plugins
bean: bean,
common: common,
extend: extend
});
// keep track of players
var playerCount = 0;
var URLResolver = _dereq_('./ext/resolve');
if (typeof window.jQuery !== 'undefined') {
var $ = window.jQuery;
// auto-install (any video tag with parent .flowplayer)
$(function() {
if (typeof $.fn.flowplayer == 'function') {
$('.flowplayer:has(video,script[type="application/json"])').flowplayer();
}
});
// jQuery plugin
var videoTagConfig = function(videoTag) {
if (!videoTag.length) return {};
var clip = videoTag.data() || {}, conf = {};
$.each(['autoplay', 'loop', 'preload', 'poster'], function(i, key) {
var val = videoTag.attr(key);
if (val !== undefined && ['autoplay', 'poster'].indexOf(key) !== -1) conf[key] = val ? val : true;
else if (val !== undefined) clip[key] = val ? val : true;
});
clip.subtitles = videoTag.find('track').map(function() {
var tr = $(this);
return {
src: tr.attr('src'),
kind: tr.attr('kind'),
label: tr.attr('label'),
srclang: tr.attr('srclang'),
'default': tr.prop('default')
};
}).get();
clip.sources = (new URLResolver()).sourcesFromVideoTag(videoTag, $);
return extend(conf, {clip: clip});
};
$.fn.flowplayer = function(opts, callback) {
return this.each(function() {
if (typeof opts == 'string') opts = { swf: opts };
if (isFunction(opts)) { callback = opts; opts = {}; }
var root = $(this),
scriptConf = root.find('script[type="application/json"]'),
confObject = scriptConf.length ? JSON.parse(scriptConf.text()) : videoTagConfig(root.find('video')),
conf = $.extend({}, opts || {}, confObject, root.data());
var api = initializePlayer(this, conf, callback);
events.EVENTS.forEach(function(evName) {
api.on(evName + '.jquery', function(ev) {
root.trigger.call(root, ev.type, ev.detail && ev.detail.args);
});
});
root.data('flowplayer', api);
});
};
}
function initializePlayer(element, opts, callback) {
if (opts && opts.embed) opts.embed = extend({}, flowplayer.defaults.embed, opts.embed);
var root = element,
rootClasses = ClassList(root),
conf = extend({}, flowplayer.defaults, flowplayer.conf, opts),
storage = {},
lastSeekPosition,
engine,
url,
urlResolver = new URLResolver();
rootClasses.add('is-loading');
try {
storage = supportLocalStorage ? window.localStorage : storage;
} catch(e) {}
var isRTL = (root.currentStyle && root.currentStyle.direction === 'rtl') ||
(window.getComputedStyle && window.getComputedStyle(root, null) !== null && window.getComputedStyle(root, null).getPropertyValue('direction') === 'rtl');
if (isRTL) rootClasses.add('is-rtl');
/*** API ***/
var api = {
// properties
conf: conf,
currentSpeed: 1,
volumeLevel: conf.muted ? 0 : typeof conf.volume === "undefined" ? storage.volume * 1 : conf.volume,
video: {},
// states
disabled: false,
finished: false,
loading: false,
muted: storage.muted == "true" || conf.muted,
paused: false,
playing: false,
ready: false,
splash: false,
rtl: isRTL,
// methods
load: function(video, callback) {
if (api.error || api.loading) return;
api.video = {};
api.finished = false;
video = video || conf.clip;
// resolve URL
video = extend({}, urlResolver.resolve(video, conf.clip.sources));
if (api.playing || api.engine) video.autoplay = true;
var engineImpl = selectEngine(video);
if (!engineImpl) return api.trigger("error", [api, { code: flowplayer.support.flashVideo ? 5 : 10 }]);
if (!engineImpl.engineName) throw new Error('engineName property of factory should be exposed');
if (!api.engine || engineImpl.engineName !== api.engine.engineName) {
api.ready = false;
if (api.engine) {
api.engine.unload();
api.conf.autoplay = true;
}
engine = api.engine = engineImpl(api, root);
api.one('ready', function() {
engine.volume(api.volumeLevel);
});
}
extend(video, engine.pick(video.sources.filter(function(source) { // Filter out sources explicitely configured for some other engine
if (!source.engine) return true;
return source.engine === engine.engineName;
})));
if (video.src) {
var e = api.trigger('load', [api, video, engine], true);
if (!e.defaultPrevented) {
engine.load(video);
// callback
if (isFunction(video)) callback = video;
if (callback) api.one("ready", callback);
} else {
api.loading = false;
}
}
return api;
},
pause: function(fn) {
if (api.ready && !api.seeking && !api.loading) {
engine.pause();
api.one("pause", fn);
}
return api;
},
resume: function() {
if (api.ready && api.paused) {
engine.resume();
// Firefox (+others?) does not fire "resume" after finish
if (api.finished) {
api.trigger("resume", [api]);
api.finished = false;
}
}
return api;
},
toggle: function() {
return api.ready ? api.paused ? api.resume() : api.pause() : api.load();
},
/*
seek(1.4) -> 1.4s time
seek(true) -> 10% forward
seek(false) -> 10% backward
*/
seek: function(time, callback) {
if (api.ready && !api.live) {
if (typeof time == "boolean") {
var delta = api.video.duration * 0.1;
time = api.video.time + (time ? delta : -delta);
}
time = lastSeekPosition = Math.min(Math.max(time, 0), api.video.duration - 0.1).toFixed(1);
var ev = api.trigger('beforeseek', [api, time], true);
if (!ev.defaultPrevented) {
engine.seek(time);
if (isFunction(callback)) api.one("seek", callback);
} else {
api.seeking = false;
common.toggleClass(root, 'is-seeking', api.seeking); // remove loading indicator
}
}
return api;
},
/*
seekTo(1) -> 10%
seekTo(2) -> 20%
seekTo(3) -> 30%
...
seekTo() -> last position
*/
seekTo: function(position, fn) {
var time = position === undefined ? lastSeekPosition : api.video.duration * 0.1 * position;
return api.seek(time, fn);
},
mute: function(flag, skipStore) {
if (flag === undefined) flag = !api.muted;
if (!skipStore) {
storage.muted = api.muted = flag;
storage.volume = !isNaN(storage.volume) ? storage.volume : conf.volume; // make sure storage has volume
}
api.volume(flag ? 0 : storage.volume, true);
api.trigger("mute", [api, flag]);
return api;
},
volume: function(level, skipStore) {
if (api.ready) {
level = Math.min(Math.max(level, 0), 1);
if (!skipStore) storage.volume = level;
engine.volume(level);
}
return api;
},
speed: function(val, callback) {
if (api.ready) {
// increase / decrease
if (typeof val == "boolean") {
val = conf.speeds[conf.speeds.indexOf(api.currentSpeed) + (val ? 1 : -1)] || api.currentSpeed;
}
engine.speed(val);
if (callback) root.one("speed", callback);
}
return api;
},
stop: function() {
if (api.ready) {
api.pause();
api.seek(0, function() {
api.trigger("stop", [api]);
});
}
return api;
},
unload: function() {
if (!rootClasses.contains("is-embedding")) {
if (conf.splash) {
api.trigger("unload", [api]);
if (engine) {
engine.unload();
api.engine = engine = 0;
}
} else {
api.stop();
}
}
return api;
},
shutdown: function() {
api.unload();
api.trigger('shutdown', [api]);
bean.off(root);
delete instances[root.getAttribute('data-flowplayer-instance-id')];
root.removeAttribute('data-flowplayer-instance-id');
},
disable: function(flag) {
if (flag === undefined) flag = !api.disabled;
if (flag != api.disabled) {
api.disabled = flag;
api.trigger("disable", flag);
}
return api;
}
};
api.conf = extend(api.conf, conf);
/* event binding / unbinding */
events(api);
var selectEngine = function(clip) {
var engine;
var engines = flowplayer.engines;
if (conf.engine) {
var eng = engines.filter(function(e) { return e.engineName === conf.engine; })[0];
if (eng && clip.sources.some(function(source) {
if (source.engine && source.engine !== eng.engineName) return false;
return eng.canPlay(source.type, api.conf);
})) return eng;
}
if (conf.enginePreference) engines = flowplayer.engines.filter(function(one) { return conf.enginePreference.indexOf(one.engineName) > -1; }).sort(function(a, b) {
return conf.enginePreference.indexOf(a.engineName) - conf.enginePreference.indexOf(b.engineName);
});
clip.sources.some(function(source) {
var eng = engines.filter(function(engine) {
if (source.engine && source.engine !== engine.engineName) return false;
return engine.canPlay(source.type, api.conf);
}).shift();
if (eng) engine = eng;
return !!eng;
});
return engine;
};
/*** Behaviour ***/
if (!root.getAttribute('data-flowplayer-instance-id')) { // Only bind once
root.setAttribute('data-flowplayer-instance-id', playerCount++);
api.on('boot', function() {
// splash
if (conf.splash || rootClasses.contains("is-splash") || !flowplayer.support.firstframe) {
api.forcedSplash = !conf.splash && !rootClasses.contains("is-splash");
api.splash = conf.autoplay = true;
if (!conf.splash) conf.splash = true;
rootClasses.add("is-splash");
}
if (conf.splash) common.find('video', root).forEach(common.removeNode);
if (conf.live || rootClasses.contains('is-live')) {
api.live = conf.live = true;
rootClasses.add('is-live');
}
// extensions
extensions.forEach(function(e) {
e(api, root);
});
// instances
instances.push(api);
// start
if (conf.splash) api.unload(); else api.load();
// disabled
if (conf.disabled) api.disable();
// initial callback
api.one("ready", callback);
}).on("load", function(e, api, video) {
// unload others
if (conf.splash) {
common.find('.flowplayer.is-ready,.flowplayer.is-loading').forEach(function(el) {
var playerId = el.getAttribute('data-flowplayer-instance-id');
if (playerId === root.getAttribute('data-flowplayer-instance-id')) return;
var a = instances[Number(playerId)];
if (a && a.conf.splash) a.unload();
});
}
// loading
rootClasses.add("is-loading");
api.loading = true;
if (typeof video.live !== 'undefined') {
common.toggleClass(root, 'is-live', video.live);
api.live = video.live;
}
}).on("ready", function(e, api, video) {
video.time = 0;
api.video = video;
rootClasses.remove("is-loading");
api.loading = false;
// saved state
if (api.muted) api.mute(true, true);
else api.volume(api.volumeLevel);
// see https://github.com/flowplayer/flowplayer/issues/479
var hlsFix = api.conf.hlsFix && /mpegurl/i.exec(video.type);
common.toggleClass(root, 'hls-fix', !!hlsFix);
}).on("unload", function(e) {
rootClasses.remove("is-loading");
api.loading = false;
}).on("ready unload", function(e) {
var is_ready = e.type == "ready";
common.toggleClass(root, 'is-splash', !is_ready);
common.toggleClass(root, 'is-ready', is_ready);
api.ready = is_ready;
api.splash = !is_ready;
}).on("progress", function(e, api, time) {
api.video.time = time;
}).on("speed", function(e, api, val) {
api.currentSpeed = val;
}).on("volume", function(e, api, level) {
api.volumeLevel = Math.round(level * 100) / 100;
if (!api.muted) storage.volume = level;
else if (level) api.mute(false);
}).on("beforeseek seek", function(e) {
api.seeking = e.type == "beforeseek";
common.toggleClass(root, 'is-seeking', api.seeking);
}).on("ready pause resume unload finish stop", function(e, _api, video) {
// PAUSED: pause / finish
api.paused = /pause|finish|unload|stop/.test(e.type);
api.paused = api.paused || e.type === 'ready' && !conf.autoplay && !api.playing;
// the opposite
api.playing = !api.paused;
// CSS classes
common.toggleClass(root, 'is-paused', api.paused);
common.toggleClass(root, 'is-playing', api.playing);
// sanity check
if (!api.load.ed) api.pause();
}).on("finish", function(e) {
api.finished = true;
}).on("error", function() {
});
}
// boot
api.trigger('boot', [api, root]);
return api;
}
},{"./common":1,"./ext/events":8,"./ext/resolve":13,"bean":20,"class-list":22,"extend-object":26,"is-function":27}],19:[function(_dereq_,module,exports){
//Flowplayer with extensions
_dereq_('es5-shim');
var flowplayer = module.exports = _dereq_('./flowplayer');
//
//Support needed before engines
_dereq_('./ext/support');
//Engines
_dereq_('./engine/embed');
_dereq_('./engine/html5');
_dereq_('./engine/flash');
//Extensions
//require('./ext/slider'); //TODO enable
_dereq_('./ext/ui');
_dereq_('./ext/keyboard');
_dereq_('./ext/playlist');
_dereq_('./ext/cuepoint');
_dereq_('./ext/subtitle');
_dereq_('./ext/analytics');
_dereq_('./ext/embed');
//Have to add fullscreen last
_dereq_('./ext/fullscreen');
_dereq_('./ext/mobile');
flowplayer(function(e,o){function a(e){var o=document.createElement("a");return o.href=e,t.hostname(o.hostname)}var n=function(e,o){var a=e.className.split(" ");-1===a.indexOf(o)&&(e.className+=" "+o)},r=function(e){return"none"!==window.getComputedStyle(e).display},l=e.conf,t=flowplayer.common,i=t.createElement,d=l.swf.indexOf("flowplayer.org")&&l.e&&o.getAttribute("data-origin"),p=d?a(d):t.hostname(),s=(document,l.key);"file:"==location.protocol&&(p="localhost"),e.load.ed=1,l.hostname=p,l.origin=d||location.href,d&&n(o,"is-embedded"),"string"==typeof s&&(s=s.split(/,\s*/));var f=function(e,a){var n=i("a",{href:a,className:"fp-brand"});n.innerHTML=e,t.find(".fp-controls",o)[0].appendChild(n)};if(s&&"function"==typeof key_check&&key_check(s,p)){if(l.logo){var c=t.find(".fp-player",o)[0],h=i("a",{className:"fp-logo"});d&&(h.href=d),l.embed&&l.embed.popup&&(h.target="_blank");var y=i("img",{src:l.logo});h.appendChild(y),(c||o).appendChild(h)}l.brand&&d||l.brand&&l.brand.showOnOrigin?f(l.brand.text||l.brand,d||location.href):t.addClass(o,"no-brand")}else{f("flowplayer","http://flowplayer.org");var h=i("a",{href:"http://flowplayer.org"});o.appendChild(h);var u=i("div",{className:"fp-context-menu"},'<ul><li class="copyright">&copy; 2015</li><li><a href="http://flowplayer.org">About Flowplayer</a></li><li><a href="http://flowplayer.org/license">GPL based license</a></li></ul>'),g=window.location.href.indexOf("localhost"),c=t.find(".fp-player",o)[0];7!==g&&(c||o).appendChild(u),e.on("pause resume finish unload ready",function(e,a){t.removeClass(o,"no-brand");var n=-1;if(a.video.src)for(var l=[["org","flowplayer","drive"],["org","flowplayer","my"],["org","flowplayer","cdn"]],i=0;i<l.length&&(n=a.video.src.indexOf("://"+l[i].reverse().join(".")),-1===n);i++);if((4===n||5===n)&&t.addClass(o,"no-brand"),/pause|resume/.test(e.type)&&"flash"!=a.engine.engineName&&4!=n&&5!=n){var d={display:"block",position:"absolute",left:"16px",bottom:"46px",zIndex:99999,width:"100px",height:"20px",backgroundImage:"url("+[".png","logo","/",".net",".cloudfront","d32wqyuo10o653","//"].reverse().join("")+")"};for(var p in d)d.hasOwnProperty(p)&&(h.style[p]=d[p]);a.load.ed=r(h)&&(7===g||u.parentNode==o||u.parentNode==c)&&!t.hasClass(o,"no-brand"),a.load.ed||a.pause()}else h.style.display="none"})}});
},{"./engine/embed":2,"./engine/flash":3,"./engine/html5":4,"./ext/analytics":5,"./ext/cuepoint":6,"./ext/embed":7,"./ext/fullscreen":9,"./ext/keyboard":10,"./ext/mobile":11,"./ext/playlist":12,"./ext/subtitle":15,"./ext/support":16,"./ext/ui":17,"./flowplayer":18,"es5-shim":25}],20:[function(_dereq_,module,exports){
/*!
* Bean - copyright (c) Jacob Thornton 2011-2012
* https://github.com/fat/bean
* MIT license
*/
(function (name, context, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof define == 'function' && define.amd) define(definition)
else context[name] = definition()
})('bean', this, function (name, context) {
name = name || 'bean'
context = context || this
var win = window
, old = context[name]
, namespaceRegex = /[^\.]*(?=\..*)\.|.*/
, nameRegex = /\..*/
, addEvent = 'addEventListener'
, removeEvent = 'removeEventListener'
, doc = document || {}
, root = doc.documentElement || {}
, W3C_MODEL = root[addEvent]
, eventSupport = W3C_MODEL ? addEvent : 'attachEvent'
, ONE = {} // singleton for quick matching making add() do one()
, slice = Array.prototype.slice
, str2arr = function (s, d) { return s.split(d || ' ') }
, isString = function (o) { return typeof o == 'string' }
, isFunction = function (o) { return typeof o == 'function' }
// events that we consider to be 'native', anything not in this list will
// be treated as a custom event
, standardNativeEvents =
'click dblclick mouseup mousedown contextmenu ' + // mouse buttons
'mousewheel mousemultiwheel DOMMouseScroll ' + // mouse wheel
'mouseover mouseout mousemove selectstart selectend ' + // mouse movement
'keydown keypress keyup ' + // keyboard
'orientationchange ' + // mobile
'focus blur change reset select submit ' + // form elements
'load unload beforeunload resize move DOMContentLoaded ' + // window
'readystatechange message ' + // window
'error abort scroll ' // misc
// element.fireEvent('onXYZ'... is not forgiving if we try to fire an event
// that doesn't actually exist, so make sure we only do these on newer browsers
, w3cNativeEvents =
'show ' + // mouse buttons
'input invalid ' + // form elements
'touchstart touchmove touchend touchcancel ' + // touch
'gesturestart gesturechange gestureend ' + // gesture
'textinput ' + // TextEvent
'readystatechange pageshow pagehide popstate ' + // window
'hashchange offline online ' + // window
'afterprint beforeprint ' + // printing
'dragstart dragenter dragover dragleave drag drop dragend ' + // dnd
'loadstart progress suspend emptied stalled loadmetadata ' + // media
'loadeddata canplay canplaythrough playing waiting seeking ' + // media
'seeked ended durationchange timeupdate play pause ratechange ' + // media
'volumechange cuechange ' + // media
'checking noupdate downloading cached updateready obsolete ' // appcache
// convert to a hash for quick lookups
, nativeEvents = (function (hash, events, i) {
for (i = 0; i < events.length; i++) events[i] && (hash[events[i]] = 1)
return hash
}({}, str2arr(standardNativeEvents + (W3C_MODEL ? w3cNativeEvents : ''))))
// custom events are events that we *fake*, they are not provided natively but
// we can use native events to generate them
, customEvents = (function () {
var isAncestor = 'compareDocumentPosition' in root
? function (element, container) {
return container.compareDocumentPosition && (container.compareDocumentPosition(element) & 16) === 16
}
: 'contains' in root
? function (element, container) {
container = container.nodeType === 9 || container === window ? root : container
return container !== element && container.contains(element)
}
: function (element, container) {
while (element = element.parentNode) if (element === container) return 1
return 0
}
, check = function (event) {
var related = event.relatedTarget
return !related
? related == null
: (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString())
&& !isAncestor(related, this))
}
return {
mouseenter: { base: 'mouseover', condition: check }
, mouseleave: { base: 'mouseout', condition: check }
, mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' }
}
}())
// we provide a consistent Event object across browsers by taking the actual DOM
// event object and generating a new one from its properties.
, Event = (function () {
// a whitelist of properties (for different event types) tells us what to check for and copy
var commonProps = str2arr('altKey attrChange attrName bubbles cancelable ctrlKey currentTarget ' +
'detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey ' +
'srcElement target timeStamp type view which propertyName')
, mouseProps = commonProps.concat(str2arr('button buttons clientX clientY dataTransfer ' +
'fromElement offsetX offsetY pageX pageY screenX screenY toElement'))
, mouseWheelProps = mouseProps.concat(str2arr('wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ ' +
'axis')) // 'axis' is FF specific
, keyProps = commonProps.concat(str2arr('char charCode key keyCode keyIdentifier ' +
'keyLocation location'))
, textProps = commonProps.concat(str2arr('data'))
, touchProps = commonProps.concat(str2arr('touches targetTouches changedTouches scale rotation'))
, messageProps = commonProps.concat(str2arr('data origin source'))
, stateProps = commonProps.concat(str2arr('state'))
, overOutRegex = /over|out/
// some event types need special handling and some need special properties, do that all here
, typeFixers = [
{ // key events
reg: /key/i
, fix: function (event, newEvent) {
newEvent.keyCode = event.keyCode || event.which
return keyProps
}
}
, { // mouse events
reg: /click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i
, fix: function (event, newEvent, type) {
newEvent.rightClick = event.which === 3 || event.button === 2
newEvent.pos = { x: 0, y: 0 }
if (event.pageX || event.pageY) {
newEvent.clientX = event.pageX
newEvent.clientY = event.pageY
} else if (event.clientX || event.clientY) {
newEvent.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft
newEvent.clientY = event.clientY + doc.body.scrollTop + root.scrollTop
}
if (overOutRegex.test(type)) {
newEvent.relatedTarget = event.relatedTarget
|| event[(type == 'mouseover' ? 'from' : 'to') + 'Element']
}
return mouseProps
}
}
, { // mouse wheel events
reg: /mouse.*(wheel|scroll)/i
, fix: function () { return mouseWheelProps }
}
, { // TextEvent
reg: /^text/i
, fix: function () { return textProps }
}
, { // touch and gesture events
reg: /^touch|^gesture/i
, fix: function () { return touchProps }
}
, { // message events
reg: /^message$/i
, fix: function () { return messageProps }
}
, { // popstate events
reg: /^popstate$/i
, fix: function () { return stateProps }
}
, { // everything else
reg: /.*/
, fix: function () { return commonProps }
}
]
, typeFixerMap = {} // used to map event types to fixer functions (above), a basic cache mechanism
, Event = function (event, element, isNative) {
if (!arguments.length) return
event = event || ((element.ownerDocument || element.document || element).parentWindow || win).event
this.originalEvent = event
this.isNative = isNative
this.isBean = true
if (!event) return
var type = event.type
, target = event.target || event.srcElement
, i, l, p, props, fixer
this.target = target && target.nodeType === 3 ? target.parentNode : target
if (isNative) { // we only need basic augmentation on custom events, the rest expensive & pointless
fixer = typeFixerMap[type]
if (!fixer) { // haven't encountered this event type before, map a fixer function for it
for (i = 0, l = typeFixers.length; i < l; i++) {
if (typeFixers[i].reg.test(type)) { // guaranteed to match at least one, last is .*
typeFixerMap[type] = fixer = typeFixers[i].fix
break
}
}
}
props = fixer(event, this, type)
for (i = props.length; i--;) {
if (!((p = props[i]) in this) && p in event) this[p] = event[p]
}
}
}
// preventDefault() and stopPropagation() are a consistent interface to those functions
// on the DOM, stop() is an alias for both of them together
Event.prototype.preventDefault = function () {
if (this.originalEvent.preventDefault) this.originalEvent.preventDefault()
else this.originalEvent.returnValue = false
}
Event.prototype.stopPropagation = function () {
if (this.originalEvent.stopPropagation) this.originalEvent.stopPropagation()
else this.originalEvent.cancelBubble = true
}
Event.prototype.stop = function () {
this.preventDefault()
this.stopPropagation()
this.stopped = true
}
// stopImmediatePropagation() has to be handled internally because we manage the event list for
// each element
// note that originalElement may be a Bean#Event object in some situations
Event.prototype.stopImmediatePropagation = function () {
if (this.originalEvent.stopImmediatePropagation) this.originalEvent.stopImmediatePropagation()
this.isImmediatePropagationStopped = function () { return true }
}
Event.prototype.isImmediatePropagationStopped = function () {
return this.originalEvent.isImmediatePropagationStopped && this.originalEvent.isImmediatePropagationStopped()
}
Event.prototype.clone = function (currentTarget) {
//TODO: this is ripe for optimisation, new events are *expensive*
// improving this will speed up delegated events
var ne = new Event(this, this.element, this.isNative)
ne.currentTarget = currentTarget
return ne
}
return Event
}())
// if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both
, targetElement = function (element, isNative) {
return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element
}
/**
* Bean maintains an internal registry for event listeners. We don't touch elements, objects
* or functions to identify them, instead we store everything in the registry.
* Each event listener has a RegEntry object, we have one 'registry' for the whole instance.
*/
, RegEntry = (function () {
// each handler is wrapped so we can handle delegation and custom events
var wrappedHandler = function (element, fn, condition, args) {
var call = function (event, eargs) {
return fn.apply(element, args ? slice.call(eargs, event ? 0 : 1).concat(args) : eargs)
}
, findTarget = function (event, eventElement) {
return fn.__beanDel ? fn.__beanDel.ft(event.target, element) : eventElement
}
, handler = condition
? function (event) {
var target = findTarget(event, this) // deleated event
if (condition.apply(target, arguments)) {
if (event) event.currentTarget = target
return call(event, arguments)
}
}
: function (event) {
if (fn.__beanDel) event = event.clone(findTarget(event)) // delegated event, fix the fix
return call(event, arguments)
}
handler.__beanDel = fn.__beanDel
return handler
}
, RegEntry = function (element, type, handler, original, namespaces, args, root) {
var customType = customEvents[type]
, isNative
if (type == 'unload') {
// self clean-up
handler = once(removeListener, element, type, handler, original)
}
if (customType) {
if (customType.condition) {
handler = wrappedHandler(element, handler, customType.condition, args)
}
type = customType.base || type
}
this.isNative = isNative = nativeEvents[type] && !!element[eventSupport]
this.customType = !W3C_MODEL && !isNative && type
this.element = element
this.type = type
this.original = original
this.namespaces = namespaces
this.eventType = W3C_MODEL || isNative ? type : 'propertychange'
this.target = targetElement(element, isNative)
this[eventSupport] = !!this.target[eventSupport]
this.root = root
this.handler = wrappedHandler(element, handler, null, args)
}
// given a list of namespaces, is our entry in any of them?
RegEntry.prototype.inNamespaces = function (checkNamespaces) {
var i, j, c = 0
if (!checkNamespaces) return true
if (!this.namespaces) return false
for (i = checkNamespaces.length; i--;) {
for (j = this.namespaces.length; j--;) {
if (checkNamespaces[i] == this.namespaces[j]) c++
}
}
return checkNamespaces.length === c
}
// match by element, original fn (opt), handler fn (opt)
RegEntry.prototype.matches = function (checkElement, checkOriginal, checkHandler) {
return this.element === checkElement &&
(!checkOriginal || this.original === checkOriginal) &&
(!checkHandler || this.handler === checkHandler)
}
return RegEntry
}())
, registry = (function () {
// our map stores arrays by event type, just because it's better than storing
// everything in a single array.
// uses '$' as a prefix for the keys for safety and 'r' as a special prefix for
// rootListeners so we can look them up fast
var map = {}
// generic functional search of our registry for matching listeners,
// `fn` returns false to break out of the loop
, forAll = function (element, type, original, handler, root, fn) {
var pfx = root ? 'r' : '$'
if (!type || type == '*') {
// search the whole registry
for (var t in map) {
if (t.charAt(0) == pfx) {
forAll(element, t.substr(1), original, handler, root, fn)
}
}
} else {
var i = 0, l, list = map[pfx + type], all = element == '*'
if (!list) return
for (l = list.length; i < l; i++) {
if ((all || list[i].matches(element, original, handler)) && !fn(list[i], list, i, type)) return
}
}
}
, has = function (element, type, original, root) {
// we're not using forAll here simply because it's a bit slower and this
// needs to be fast
var i, list = map[(root ? 'r' : '$') + type]
if (list) {
for (i = list.length; i--;) {
if (!list[i].root && list[i].matches(element, original, null)) return true
}
}
return false
}
, get = function (element, type, original, root) {
var entries = []
forAll(element, type, original, null, root, function (entry) {
return entries.push(entry)
})
return entries
}
, put = function (entry) {
var has = !entry.root && !this.has(entry.element, entry.type, null, false)
, key = (entry.root ? 'r' : '$') + entry.type
;(map[key] || (map[key] = [])).push(entry)
return has
}
, del = function (entry) {
forAll(entry.element, entry.type, null, entry.handler, entry.root, function (entry, list, i) {
list.splice(i, 1)
entry.removed = true
if (list.length === 0) delete map[(entry.root ? 'r' : '$') + entry.type]
return false
})
}
// dump all entries, used for onunload
, entries = function () {
var t, entries = []
for (t in map) {
if (t.charAt(0) == '$') entries = entries.concat(map[t])
}
return entries
}
return { has: has, get: get, put: put, del: del, entries: entries }
}())
// we need a selector engine for delegated events, use querySelectorAll if it exists
// but for older browsers we need Qwery, Sizzle or similar
, selectorEngine
, setSelectorEngine = function (e) {
if (!arguments.length) {
selectorEngine = doc.querySelectorAll
? function (s, r) {
return r.querySelectorAll(s)
}
: function () {
throw new Error('Bean: No selector engine installed') // eeek
}
} else {
selectorEngine = e
}
}
// we attach this listener to each DOM event that we need to listen to, only once
// per event type per DOM element
, rootListener = function (event, type) {
if (!W3C_MODEL && type && event && event.propertyName != '_on' + type) return
var listeners = registry.get(this, type || event.type, null, false)
, l = listeners.length
, i = 0
event = new Event(event, this, true)
if (type) event.type = type
// iterate through all handlers registered for this type, calling them unless they have
// been removed by a previous handler or stopImmediatePropagation() has been called
for (; i < l && !event.isImmediatePropagationStopped(); i++) {
if (!listeners[i].removed) listeners[i].handler.call(this, event)
}
}
// add and remove listeners to DOM elements
, listener = W3C_MODEL
? function (element, type, add) {
// new browsers
element[add ? addEvent : removeEvent](type, rootListener, false)
}
: function (element, type, add, custom) {
// IE8 and below, use attachEvent/detachEvent and we have to piggy-back propertychange events
// to simulate event bubbling etc.
var entry
if (add) {
registry.put(entry = new RegEntry(
element
, custom || type
, function (event) { // handler
rootListener.call(element, event, custom)
}
, rootListener
, null
, null
, true // is root
))
if (custom && element['_on' + custom] == null) element['_on' + custom] = 0
entry.target.attachEvent('on' + entry.eventType, entry.handler)
} else {
entry = registry.get(element, custom || type, rootListener, true)[0]
if (entry) {
entry.target.detachEvent('on' + entry.eventType, entry.handler)
registry.del(entry)
}
}
}
, once = function (rm, element, type, fn, originalFn) {
// wrap the handler in a handler that does a remove as well
return function () {
fn.apply(this, arguments)
rm(element, type, originalFn)
}
}
, removeListener = function (element, orgType, handler, namespaces) {
var type = orgType && orgType.replace(nameRegex, '')
, handlers = registry.get(element, type, null, false)
, removed = {}
, i, l
for (i = 0, l = handlers.length; i < l; i++) {
if ((!handler || handlers[i].original === handler) && handlers[i].inNamespaces(namespaces)) {
// TODO: this is problematic, we have a registry.get() and registry.del() that
// both do registry searches so we waste cycles doing this. Needs to be rolled into
// a single registry.forAll(fn) that removes while finding, but the catch is that
// we'll be splicing the arrays that we're iterating over. Needs extra tests to
// make sure we don't screw it up. @rvagg
registry.del(handlers[i])
if (!removed[handlers[i].eventType] && handlers[i][eventSupport])
removed[handlers[i].eventType] = { t: handlers[i].eventType, c: handlers[i].type }
}
}
// check each type/element for removed listeners and remove the rootListener where it's no longer needed
for (i in removed) {
if (!registry.has(element, removed[i].t, null, false)) {
// last listener of this type, remove the rootListener
listener(element, removed[i].t, false, removed[i].c)
}
}
}
// set up a delegate helper using the given selector, wrap the handler function
, delegate = function (selector, fn) {
//TODO: findTarget (therefore $) is called twice, once for match and once for
// setting e.currentTarget, fix this so it's only needed once
var findTarget = function (target, root) {
var i, array = isString(selector) ? selectorEngine(selector, root) : selector
for (; target && target !== root; target = target.parentNode) {
for (i = array.length; i--;) {
if (array[i] === target) return target
}
}
}
, handler = function (e) {
var match = findTarget(e.target, this)
if (match) fn.apply(match, arguments)
}
// __beanDel isn't pleasant but it's a private function, not exposed outside of Bean
handler.__beanDel = {
ft : findTarget // attach it here for customEvents to use too
, selector : selector
}
return handler
}
, fireListener = W3C_MODEL ? function (isNative, type, element) {
// modern browsers, do a proper dispatchEvent()
var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents')
evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1)
element.dispatchEvent(evt)
} : function (isNative, type, element) {
// old browser use onpropertychange, just increment a custom property to trigger the event
element = targetElement(element, isNative)
isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++
}
/**
* Public API: off(), on(), add(), (remove()), one(), fire(), clone()
*/
/**
* off(element[, eventType(s)[, handler ]])
*/
, off = function (element, typeSpec, fn) {
var isTypeStr = isString(typeSpec)
, k, type, namespaces, i
if (isTypeStr && typeSpec.indexOf(' ') > 0) {
// off(el, 't1 t2 t3', fn) or off(el, 't1 t2 t3')
typeSpec = str2arr(typeSpec)
for (i = typeSpec.length; i--;)
off(element, typeSpec[i], fn)
return element
}
type = isTypeStr && typeSpec.replace(nameRegex, '')
if (type && customEvents[type]) type = customEvents[type].base
if (!typeSpec || isTypeStr) {
// off(el) or off(el, t1.ns) or off(el, .ns) or off(el, .ns1.ns2.ns3)
if (namespaces = isTypeStr && typeSpec.replace(namespaceRegex, '')) namespaces = str2arr(namespaces, '.')
removeListener(element, type, fn, namespaces)
} else if (isFunction(typeSpec)) {
// off(el, fn)
removeListener(element, null, typeSpec)
} else {
// off(el, { t1: fn1, t2, fn2 })
for (k in typeSpec) {
if (typeSpec.hasOwnProperty(k)) off(element, k, typeSpec[k])
}
}
return element
}
/**
* on(element, eventType(s)[, selector], handler[, args ])
*/
, on = function(element, events, selector, fn) {
var originalFn, type, types, i, args, entry, first
//TODO: the undefined check means you can't pass an 'args' argument, fix this perhaps?
if (selector === undefined && typeof events == 'object') {
//TODO: this can't handle delegated events
for (type in events) {
if (events.hasOwnProperty(type)) {
on.call(this, element, type, events[type])
}
}
return
}
if (!isFunction(selector)) {
// delegated event
originalFn = fn
args = slice.call(arguments, 4)
fn = delegate(selector, originalFn, selectorEngine)
} else {
args = slice.call(arguments, 3)
fn = originalFn = selector
}
types = str2arr(events)
// special case for one(), wrap in a self-removing handler
if (this === ONE) {
fn = once(off, element, events, fn, originalFn)
}
for (i = types.length; i--;) {
// add new handler to the registry and check if it's the first for this element/type
first = registry.put(entry = new RegEntry(
element
, types[i].replace(nameRegex, '') // event type
, fn
, originalFn
, str2arr(types[i].replace(namespaceRegex, ''), '.') // namespaces
, args
, false // not root
))
if (entry[eventSupport] && first) {
// first event of this type on this element, add root listener
listener(element, entry.eventType, true, entry.customType)
}
}
return element
}
/**
* add(element[, selector], eventType(s), handler[, args ])
*
* Deprecated: kept (for now) for backward-compatibility
*/
, add = function (element, events, fn, delfn) {
return on.apply(
null
, !isString(fn)
? slice.call(arguments)
: [ element, fn, events, delfn ].concat(arguments.length > 3 ? slice.call(arguments, 5) : [])
)
}
/**
* one(element, eventType(s)[, selector], handler[, args ])
*/
, one = function () {
return on.apply(ONE, arguments)
}
/**
* fire(element, eventType(s)[, args ])
*
* The optional 'args' argument must be an array, if no 'args' argument is provided
* then we can use the browser's DOM event system, otherwise we trigger handlers manually
*/
, fire = function (element, type, args) {
var types = str2arr(type)
, i, j, l, names, handlers
for (i = types.length; i--;) {
type = types[i].replace(nameRegex, '')
if (names = types[i].replace(namespaceRegex, '')) names = str2arr(names, '.')
if (!names && !args && element[eventSupport]) {
fireListener(nativeEvents[type], type, element)
} else {
// non-native event, either because of a namespace, arguments or a non DOM element
// iterate over all listeners and manually 'fire'
handlers = registry.get(element, type, null, false)
args = [false].concat(args)
for (j = 0, l = handlers.length; j < l; j++) {
if (handlers[j].inNamespaces(names)) {
handlers[j].handler.apply(element, args)
}
}
}
}
return element
}
/**
* clone(dstElement, srcElement[, eventType ])
*
* TODO: perhaps for consistency we should allow the same flexibility in type specifiers?
*/
, clone = function (element, from, type) {
var handlers = registry.get(from, type, null, false)
, l = handlers.length
, i = 0
, args, beanDel
for (; i < l; i++) {
if (handlers[i].original) {
args = [ element, handlers[i].type ]
if (beanDel = handlers[i].handler.__beanDel) args.push(beanDel.selector)
args.push(handlers[i].original)
on.apply(null, args)
}
}
return element
}
, bean = {
'on' : on
, 'add' : add
, 'one' : one
, 'off' : off
, 'remove' : off
, 'clone' : clone
, 'fire' : fire
, 'Event' : Event
, 'setSelectorEngine' : setSelectorEngine
, 'noConflict' : function () {
context[name] = old
return this
}
}
// for IE, clean up on unload to avoid leaks
if (win.attachEvent) {
var cleanup = function () {
var i, entries = registry.entries()
for (i in entries) {
if (entries[i].type && entries[i].type !== 'unload') off(entries[i].element, entries[i].type)
}
win.detachEvent('onunload', cleanup)
win.CollectGarbage && win.CollectGarbage()
}
win.attachEvent('onunload', cleanup)
}
// initialize selector engine to internal default (qSA or throw Error)
setSelectorEngine()
return bean
});
},{}],21:[function(_dereq_,module,exports){
(function (global){
/*! http://mths.be/punycode v1.2.4 by @mathias */
;(function(root) {
/** Detect free variables */
var freeExports = typeof exports == 'object' && exports;
var freeModule = typeof module == 'object' && module &&
module.exports == freeExports && module;
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
}
/**
* The `punycode` object.
* @name punycode
* @type Object
*/
var punycode,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36,
tMin = 1,
tMax = 26,
skew = 38,
damp = 700,
initialBias = 72,
initialN = 128, // 0x80
delimiter = '-', // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/,
regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
/** Error messages */
errors = {
'overflow': 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
},
/** Convenience shortcuts */
baseMinusTMin = base - tMin,
floor = Math.floor,
stringFromCharCode = String.fromCharCode,
/** Temporary variable */
key;
/*--------------------------------------------------------------------------*/
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
throw RangeError(errors[type]);
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, fn) {
var length = array.length;
while (length--) {
array[length] = fn(array[length]);
}
return array;
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings.
* @private
* @param {String} domain The domain name.
* @param {Function} callback The function that gets called for every
* character.
* @returns {Array} A new string of characters returned by the callback
* function.
*/
function mapDomain(string, fn) {
return map(string.split(regexSeparators), fn).join('.');
}
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see <http://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
var output = [],
counter = 0,
length = string.length,
value,
extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
// high surrogate, and there is a next character
extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
/**
* Creates a string based on an array of numeric code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of numeric code points.
* @returns {String} The new Unicode string (UCS-2).
*/
function ucs2encode(array) {
return map(array, function(value) {
var output = '';
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
return output;
}).join('');
}
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic numeric code point value.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
return codePoint - 22;
}
if (codePoint - 65 < 26) {
return codePoint - 65;
}
if (codePoint - 97 < 26) {
return codePoint - 97;
}
return base;
}
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if `flag` is non-zero and `digit` has no uppercase form.
*/
function digitToBasic(digit, flag) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* http://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII-only symbols.
* @returns {String} The resulting string of Unicode symbols.
*/
function decode(input) {
// Don't use UCS-2
var output = [],
inputLength = input.length,
out,
i = 0,
n = initialN,
bias = initialBias,
basic,
j,
index,
oldi,
w,
k,
digit,
t,
/** Cached calculation results */
baseMinusT;
// Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
// if it's not a basic code point
if (input.charCodeAt(j) >= 0x80) {
error('not-basic');
}
output.push(input.charCodeAt(j));
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
if (index >= inputLength) {
error('invalid-input');
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error('overflow');
}
i += digit * w;
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error('overflow');
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if (floor(i / out) > maxInt - n) {
error('overflow');
}
n += floor(i / out);
i %= out;
// Insert `n` at position `i` of the output
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
/**
* Converts a string of Unicode symbols to a Punycode string of ASCII-only
* symbols.
* @memberOf punycode
* @param {String} input The string of Unicode symbols.
* @returns {String} The resulting Punycode string of ASCII-only symbols.
*/
function encode(input) {
var n,
delta,
handledCPCount,
basicLength,
bias,
j,
m,
q,
k,
t,
currentValue,
output = [],
/** `inputLength` will hold the number of code points in `input`. */
inputLength,
/** Cached calculation results */
handledCPCountPlusOne,
baseMinusT,
qMinusT;
// Convert the input in UCS-2 to Unicode
input = ucs2decode(input);
// Cache the length
inputLength = input.length;
// Initialize the state
n = initialN;
delta = 0;
bias = initialBias;
// Handle the basic code points
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 0x80) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length;
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if (basicLength) {
output.push(delimiter);
}
// Main encoding loop:
while (handledCPCount < inputLength) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
}
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error('overflow');
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error('overflow');
}
if (currentValue == n) {
// Represent delta as a generalized variable-length integer
for (q = delta, k = base; /* no condition */; k += base) {
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
);
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join('');
}
/**
* Converts a Punycode string representing a domain name to Unicode. Only the
* Punycoded parts of the domain name will be converted, i.e. it doesn't
* matter if you call it on a string that has already been converted to
* Unicode.
* @memberOf punycode
* @param {String} domain The Punycode domain name to convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
function toUnicode(domain) {
return mapDomain(domain, function(string) {
return regexPunycode.test(string)
? decode(string.slice(4).toLowerCase())
: string;
});
}
/**
* Converts a Unicode string representing a domain name to Punycode. Only the
* non-ASCII parts of the domain name will be converted, i.e. it doesn't
* matter if you call it with a domain that's already in ASCII.
* @memberOf punycode
* @param {String} domain The domain name to convert, as a Unicode string.
* @returns {String} The Punycode representation of the given domain name.
*/
function toASCII(domain) {
return mapDomain(domain, function(string) {
return regexNonASCII.test(string)
? 'xn--' + encode(string)
: string;
});
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
'version': '1.2.4',
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see <http://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode
* @type Object
*/
'ucs2': {
'decode': ucs2decode,
'encode': ucs2encode
},
'decode': decode,
'encode': encode,
'toASCII': toASCII,
'toUnicode': toUnicode
};
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define.amd == 'object' &&
define.amd
) {
define('punycode', function() {
return punycode;
});
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) { // in Node.js or RingoJS v0.8.0+
freeModule.exports = punycode;
} else { // in Narwhal or RingoJS v0.7.0-
for (key in punycode) {
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
}
}
} else { // in Rhino or a web browser
root.punycode = punycode;
}
}(this));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],22:[function(_dereq_,module,exports){
// contains, add, remove, toggle
var indexof = _dereq_('indexof')
module.exports = ClassList
function ClassList(elem) {
var cl = elem.classList
if (cl) {
return cl
}
var classList = {
add: add
, remove: remove
, contains: contains
, toggle: toggle
, toString: $toString
, length: 0
, item: item
}
return classList
function add(token) {
var list = getTokens()
if (indexof(list, token) > -1) {
return
}
list.push(token)
setTokens(list)
}
function remove(token) {
var list = getTokens()
, index = indexof(list, token)
if (index === -1) {
return
}
list.splice(index, 1)
setTokens(list)
}
function contains(token) {
return indexof(getTokens(), token) > -1
}
function toggle(token) {
if (contains(token)) {
remove(token)
return false
} else {
add(token)
return true
}
}
function $toString() {
return elem.className
}
function item(index) {
var tokens = getTokens()
return tokens[index] || null
}
function getTokens() {
var className = elem.className
return filter(className.split(" "), isTruthy)
}
function setTokens(list) {
var length = list.length
elem.className = list.join(" ")
classList.length = length
for (var i = 0; i < list.length; i++) {
classList[i] = list[i]
}
delete list[length]
}
}
function filter (arr, fn) {
var ret = []
for (var i = 0; i < arr.length; i++) {
if (fn(arr[i])) ret.push(arr[i])
}
return ret
}
function isTruthy(value) {
return !!value
}
},{"indexof":23}],23:[function(_dereq_,module,exports){
var indexOf = [].indexOf;
module.exports = function(arr, obj){
if (indexOf) return arr.indexOf(obj);
for (var i = 0; i < arr.length; ++i) {
if (arr[i] === obj) return i;
}
return -1;
};
},{}],24:[function(_dereq_,module,exports){
// DEV: We don't use var but favor parameters since these play nicer with minification
function computedStyle(el, prop, getComputedStyle, style) {
getComputedStyle = window.getComputedStyle;
style =
// If we have getComputedStyle
getComputedStyle ?
// Query it
// TODO: From CSS-Query notes, we might need (node, null) for FF
getComputedStyle(el) :
// Otherwise, we are in IE and use currentStyle
el.currentStyle;
if (style) {
return style
[
// Switch to camelCase for CSSOM
// DEV: Grabbed from jQuery
// https://github.com/jquery/jquery/blob/1.9-stable/src/css.js#L191-L194
// https://github.com/jquery/jquery/blob/1.9-stable/src/core.js#L593-L597
prop.replace(/-(\w)/gi, function (word, letter) {
return letter.toUpperCase();
})
];
}
}
module.exports = computedStyle;
},{}],25:[function(_dereq_,module,exports){
/*!
* https://github.com/es-shims/es5-shim
* @license es5-shim Copyright 2009-2015 by contributors, MIT License
* see https://github.com/es-shims/es5-shim/blob/master/LICENSE
*/
// vim: ts=4 sts=4 sw=4 expandtab
// Add semicolon to prevent IIFE from being passed as argument to concatenated code.
;
// UMD (Universal Module Definition)
// see https://github.com/umdjs/umd/blob/master/templates/returnExports.js
(function (root, factory) {
'use strict';
/* global define, exports, module */
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.returnExports = factory();
}
}(this, function () {
/**
* Brings an environment as close to ECMAScript 5 compliance
* as is possible with the facilities of erstwhile engines.
*
* Annotated ES5: http://es5.github.com/ (specific links below)
* ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
* Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
*/
// Shortcut to an often accessed properties, in order to avoid multiple
// dereference that costs universally. This also holds a reference to known-good
// functions.
var $Array = Array;
var ArrayPrototype = $Array.prototype;
var $Object = Object;
var ObjectPrototype = $Object.prototype;
var FunctionPrototype = Function.prototype;
var $String = String;
var StringPrototype = $String.prototype;
var $Number = Number;
var NumberPrototype = $Number.prototype;
var array_slice = ArrayPrototype.slice;
var array_splice = ArrayPrototype.splice;
var array_push = ArrayPrototype.push;
var array_unshift = ArrayPrototype.unshift;
var array_concat = ArrayPrototype.concat;
var call = FunctionPrototype.call;
var apply = FunctionPrototype.apply;
var max = Math.max;
var min = Math.min;
// Having a toString local variable name breaks in Opera so use to_string.
var to_string = ObjectPrototype.toString;
var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, tryFunctionObject = function tryFunctionObject(value) { try { fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]'; isCallable = function isCallable(value) { if (typeof value !== 'function') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };
var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; };
var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; };
/* inlined from http://npmjs.com/define-properties */
var supportsDescriptors = $Object.defineProperty && (function () {
try {
var obj = {};
$Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
for (var _ in obj) { return false; }
return obj.x === obj;
} catch (e) { /* this is ES3 */
return false;
}
}());
var defineProperties = (function (has) {
// Define configurable, writable, and non-enumerable props
// if they don't exist.
var defineProperty;
if (supportsDescriptors) {
defineProperty = function (object, name, method, forceAssign) {
if (!forceAssign && (name in object)) { return; }
$Object.defineProperty(object, name, {
configurable: true,
enumerable: false,
writable: true,
value: method
});
};
} else {
defineProperty = function (object, name, method, forceAssign) {
if (!forceAssign && (name in object)) { return; }
object[name] = method;
};
}
return function defineProperties(object, map, forceAssign) {
for (var name in map) {
if (has.call(map, name)) {
defineProperty(object, name, map[name], forceAssign);
}
}
};
}(ObjectPrototype.hasOwnProperty));
//
// Util
// ======
//
/* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */
var isPrimitive = function isPrimitive(input) {
var type = typeof input;
return input === null || (type !== 'object' && type !== 'function');
};
var isActualNaN = $Number.isNaN || function (x) { return x !== x; };
var ES = {
// ES5 9.4
// http://es5.github.com/#x9.4
// http://jsperf.com/to-integer
/* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */
ToInteger: function ToInteger(num) {
var n = +num;
if (isActualNaN(n)) {
n = 0;
} else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
return n;
},
/* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */
ToPrimitive: function ToPrimitive(input) {
var val, valueOf, toStr;
if (isPrimitive(input)) {
return input;
}
valueOf = input.valueOf;
if (isCallable(valueOf)) {
val = valueOf.call(input);
if (isPrimitive(val)) {
return val;
}
}
toStr = input.toString;
if (isCallable(toStr)) {
val = toStr.call(input);
if (isPrimitive(val)) {
return val;
}
}
throw new TypeError();
},
// ES5 9.9
// http://es5.github.com/#x9.9
/* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
ToObject: function (o) {
if (o == null) { // this matches both null and undefined
throw new TypeError("can't convert " + o + ' to object');
}
return $Object(o);
},
/* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */
ToUint32: function ToUint32(x) {
return x >>> 0;
}
};
//
// Function
// ========
//
// ES-5 15.3.4.5
// http://es5.github.com/#x15.3.4.5
var Empty = function Empty() {};
defineProperties(FunctionPrototype, {
bind: function bind(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 (!isCallable(target)) {
throw new TypeError('Function.prototype.bind called on incompatible ' + target);
}
// 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 = array_slice.call(arguments, 1); // for normal call
// 4. Let F be a new native ECMAScript object.
// 11. Set the [[Prototype]] internal property of F to the standard
// built-in Function prototype object as specified in 15.3.3.1.
// 12. Set the [[Call]] internal property of F as described in
// 15.3.4.5.1.
// 13. Set the [[Construct]] internal property of F as described in
// 15.3.4.5.2.
// 14. Set the [[HasInstance]] internal property of F as described in
// 15.3.4.5.3.
var bound;
var binder = 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.
// 5. Return the result of calling the [[Construct]] internal
// method of target providing args as the arguments.
var result = target.apply(
this,
array_concat.call(args, array_slice.call(arguments))
);
if ($Object(result) === result) {
return result;
}
return this;
} 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,
array_concat.call(args, array_slice.call(arguments))
);
}
};
// 15. If the [[Class]] internal property of Target is "Function", then
// a. Let L be the length property of Target minus the length of A.
// b. Set the length own property of F to either 0 or L, whichever is
// larger.
// 16. Else set the length own property of F to 0.
var boundLength = max(0, target.length - args.length);
// 17. Set the attributes of the length own property of F to the values
// specified in 15.3.5.1.
var boundArgs = [];
for (var i = 0; i < boundLength; i++) {
array_push.call(boundArgs, '$' + i);
}
// XXX Build a dynamic function with desired amount of arguments is the only
// way to set the length property of a function.
// In environments where Content Security Policies enabled (Chrome extensions,
// for ex.) all use of eval or Function costructor throws an exception.
// However in all of these environments Function.prototype.bind exists
// and so this code will never be executed.
bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
if (target.prototype) {
Empty.prototype = target.prototype;
bound.prototype = new Empty();
// Clean up dangling references.
Empty.prototype = null;
}
// TODO
// 18. Set the [[Extensible]] internal property of F to true.
// TODO
// 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
// 20. Call the [[DefineOwnProperty]] internal method of F with
// arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
// thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
// false.
// 21. Call the [[DefineOwnProperty]] internal method of F with
// arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
// [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
// and false.
// TODO
// NOTE Function objects created using Function.prototype.bind do not
// have a prototype property or the [[Code]], [[FormalParameters]], and
// [[Scope]] internal properties.
// XXX can't delete prototype in pure-js.
// 22. Return F.
return bound;
}
});
// _Please note: Shortcuts are defined after `Function.prototype.bind` as we
// use it in defining shortcuts.
var owns = call.bind(ObjectPrototype.hasOwnProperty);
var toStr = call.bind(ObjectPrototype.toString);
var arraySlice = call.bind(array_slice);
var arraySliceApply = apply.bind(array_slice);
var strSlice = call.bind(StringPrototype.slice);
var strSplit = call.bind(StringPrototype.split);
var strIndexOf = call.bind(StringPrototype.indexOf);
var push = call.bind(array_push);
var isEnum = call.bind(ObjectPrototype.propertyIsEnumerable);
var arraySort = call.bind(ArrayPrototype.sort);
//
// Array
// =====
//
var isArray = $Array.isArray || function isArray(obj) {
return toStr(obj) === '[object Array]';
};
// ES5 15.4.4.12
// http://es5.github.com/#x15.4.4.13
// Return len+argCount.
// [bugfix, ielt8]
// IE < 8 bug: [].unshift(0) === undefined but should be "1"
var hasUnshiftReturnValueBug = [].unshift(0) !== 1;
defineProperties(ArrayPrototype, {
unshift: function () {
array_unshift.apply(this, arguments);
return this.length;
}
}, hasUnshiftReturnValueBug);
// ES5 15.4.3.2
// http://es5.github.com/#x15.4.3.2
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
defineProperties($Array, { isArray: isArray });
// 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
// http://es5.github.com/#x15.4.4.18
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
// Check failure of by-index access of string characters (IE < 9)
// and failure of `0 in boxedString` (Rhino)
var boxedString = $Object('a');
var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
var properlyBoxesContext = function properlyBoxed(method) {
// Check node 0.6.21 bug where third parameter is not boxed
var properlyBoxesNonStrict = true;
var properlyBoxesStrict = true;
if (method) {
method.call('foo', function (_, __, context) {
if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
});
method.call([1], function () {
'use strict';
properlyBoxesStrict = typeof this === 'string';
}, 'x');
}
return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
};
defineProperties(ArrayPrototype, {
forEach: function forEach(callbackfn/*, thisArg*/) {
var object = ES.ToObject(this);
var self = splitString && isString(this) ? strSplit(this, '') : object;
var i = -1;
var length = ES.ToUint32(self.length);
var T;
if (arguments.length > 1) {
T = arguments[1];
}
// If no callback function or if callback is not a callable function
if (!isCallable(callbackfn)) {
throw new TypeError('Array.prototype.forEach callback must be a function');
}
while (++i < length) {
if (i in self) {
// Invoke the callback function with call, passing arguments:
// context, property value, property key, thisArg object
if (typeof T === 'undefined') {
callbackfn(self[i], i, object);
} else {
callbackfn.call(T, self[i], i, object);
}
}
}
}
}, !properlyBoxesContext(ArrayPrototype.forEach));
// ES5 15.4.4.19
// http://es5.github.com/#x15.4.4.19
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
defineProperties(ArrayPrototype, {
map: function map(callbackfn/*, thisArg*/) {
var object = ES.ToObject(this);
var self = splitString && isString(this) ? strSplit(this, '') : object;
var length = ES.ToUint32(self.length);
var result = $Array(length);
var T;
if (arguments.length > 1) {
T = arguments[1];
}
// If no callback function or if callback is not a callable function
if (!isCallable(callbackfn)) {
throw new TypeError('Array.prototype.map callback must be a function');
}
for (var i = 0; i < length; i++) {
if (i in self) {
if (typeof T === 'undefined') {
result[i] = callbackfn(self[i], i, object);
} else {
result[i] = callbackfn.call(T, self[i], i, object);
}
}
}
return result;
}
}, !properlyBoxesContext(ArrayPrototype.map));
// ES5 15.4.4.20
// http://es5.github.com/#x15.4.4.20
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
defineProperties(ArrayPrototype, {
filter: function filter(callbackfn/*, thisArg*/) {
var object = ES.ToObject(this);
var self = splitString && isString(this) ? strSplit(this, '') : object;
var length = ES.ToUint32(self.length);
var result = [];
var value;
var T;
if (arguments.length > 1) {
T = arguments[1];
}
// If no callback function or if callback is not a callable function
if (!isCallable(callbackfn)) {
throw new TypeError('Array.prototype.filter callback must be a function');
}
for (var i = 0; i < length; i++) {
if (i in self) {
value = self[i];
if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {
push(result, value);
}
}
}
return result;
}
}, !properlyBoxesContext(ArrayPrototype.filter));
// ES5 15.4.4.16
// http://es5.github.com/#x15.4.4.16
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
defineProperties(ArrayPrototype, {
every: function every(callbackfn/*, thisArg*/) {
var object = ES.ToObject(this);
var self = splitString && isString(this) ? strSplit(this, '') : object;
var length = ES.ToUint32(self.length);
var T;
if (arguments.length > 1) {
T = arguments[1];
}
// If no callback function or if callback is not a callable function
if (!isCallable(callbackfn)) {
throw new TypeError('Array.prototype.every callback must be a function');
}
for (var i = 0; i < length; i++) {
if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
return false;
}
}
return true;
}
}, !properlyBoxesContext(ArrayPrototype.every));
// ES5 15.4.4.17
// http://es5.github.com/#x15.4.4.17
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
defineProperties(ArrayPrototype, {
some: function some(callbackfn/*, thisArg */) {
var object = ES.ToObject(this);
var self = splitString && isString(this) ? strSplit(this, '') : object;
var length = ES.ToUint32(self.length);
var T;
if (arguments.length > 1) {
T = arguments[1];
}
// If no callback function or if callback is not a callable function
if (!isCallable(callbackfn)) {
throw new TypeError('Array.prototype.some callback must be a function');
}
for (var i = 0; i < length; i++) {
if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
return true;
}
}
return false;
}
}, !properlyBoxesContext(ArrayPrototype.some));
// ES5 15.4.4.21
// http://es5.github.com/#x15.4.4.21
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
var reduceCoercesToObject = false;
if (ArrayPrototype.reduce) {
reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';
}
defineProperties(ArrayPrototype, {
reduce: function reduce(callbackfn/*, initialValue*/) {
var object = ES.ToObject(this);
var self = splitString && isString(this) ? strSplit(this, '') : object;
var length = ES.ToUint32(self.length);
// If no callback function or if callback is not a callable function
if (!isCallable(callbackfn)) {
throw new TypeError('Array.prototype.reduce callback must be a function');
}
// no value to return if no initial value and an empty array
if (length === 0 && arguments.length === 1) {
throw new TypeError('reduce of empty array with no initial value');
}
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('reduce of empty array with no initial value');
}
} while (true);
}
for (; i < length; i++) {
if (i in self) {
result = callbackfn(result, self[i], i, object);
}
}
return result;
}
}, !reduceCoercesToObject);
// ES5 15.4.4.22
// http://es5.github.com/#x15.4.4.22
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
var reduceRightCoercesToObject = false;
if (ArrayPrototype.reduceRight) {
reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';
}
defineProperties(ArrayPrototype, {
reduceRight: function reduceRight(callbackfn/*, initial*/) {
var object = ES.ToObject(this);
var self = splitString && isString(this) ? strSplit(this, '') : object;
var length = ES.ToUint32(self.length);
// If no callback function or if callback is not a callable function
if (!isCallable(callbackfn)) {
throw new TypeError('Array.prototype.reduceRight callback must be a function');
}
// no value to return if no initial value, empty array
if (length === 0 && arguments.length === 1) {
throw new TypeError('reduceRight of empty array with no initial value');
}
var result;
var 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('reduceRight of empty array with no initial value');
}
} while (true);
}
if (i < 0) {
return result;
}
do {
if (i in self) {
result = callbackfn(result, self[i], i, object);
}
} while (i--);
return result;
}
}, !reduceRightCoercesToObject);
// ES5 15.4.4.14
// http://es5.github.com/#x15.4.4.14
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
var hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
defineProperties(ArrayPrototype, {
indexOf: function indexOf(searchElement/*, fromIndex */) {
var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
var length = ES.ToUint32(self.length);
if (length === 0) {
return -1;
}
var i = 0;
if (arguments.length > 1) {
i = ES.ToInteger(arguments[1]);
}
// handle negative indices
i = i >= 0 ? i : max(0, length + i);
for (; i < length; i++) {
if (i in self && self[i] === searchElement) {
return i;
}
}
return -1;
}
}, hasFirefox2IndexOfBug);
// ES5 15.4.4.15
// http://es5.github.com/#x15.4.4.15
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
var hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
defineProperties(ArrayPrototype, {
lastIndexOf: function lastIndexOf(searchElement/*, fromIndex */) {
var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
var length = ES.ToUint32(self.length);
if (length === 0) {
return -1;
}
var i = length - 1;
if (arguments.length > 1) {
i = min(i, ES.ToInteger(arguments[1]));
}
// handle negative indices
i = i >= 0 ? i : length - Math.abs(i);
for (; i >= 0; i--) {
if (i in self && searchElement === self[i]) {
return i;
}
}
return -1;
}
}, hasFirefox2LastIndexOfBug);
// ES5 15.4.4.12
// http://es5.github.com/#x15.4.4.12
var spliceNoopReturnsEmptyArray = (function () {
var a = [1, 2];
var result = a.splice();
return a.length === 2 && isArray(result) && result.length === 0;
}());
defineProperties(ArrayPrototype, {
// Safari 5.0 bug where .splice() returns undefined
splice: function splice(start, deleteCount) {
if (arguments.length === 0) {
return [];
} else {
return array_splice.apply(this, arguments);
}
}
}, !spliceNoopReturnsEmptyArray);
var spliceWorksWithEmptyObject = (function () {
var obj = {};
ArrayPrototype.splice.call(obj, 0, 0, 1);
return obj.length === 1;
}());
defineProperties(ArrayPrototype, {
splice: function splice(start, deleteCount) {
if (arguments.length === 0) { return []; }
var args = arguments;
this.length = max(ES.ToInteger(this.length), 0);
if (arguments.length > 0 && typeof deleteCount !== 'number') {
args = arraySlice(arguments);
if (args.length < 2) {
push(args, this.length - start);
} else {
args[1] = ES.ToInteger(deleteCount);
}
}
return array_splice.apply(this, args);
}
}, !spliceWorksWithEmptyObject);
var spliceWorksWithLargeSparseArrays = (function () {
// Per https://github.com/es-shims/es5-shim/issues/295
// Safari 7/8 breaks with sparse arrays of size 1e5 or greater
var arr = new $Array(1e5);
// note: the index MUST be 8 or larger or the test will false pass
arr[8] = 'x';
arr.splice(1, 1);
// note: this test must be defined *after* the indexOf shim
// per https://github.com/es-shims/es5-shim/issues/313
return arr.indexOf('x') === 7;
}());
var spliceWorksWithSmallSparseArrays = (function () {
// Per https://github.com/es-shims/es5-shim/issues/295
// Opera 12.15 breaks on this, no idea why.
var n = 256;
var arr = [];
arr[n] = 'a';
arr.splice(n + 1, 0, 'b');
return arr[n] === 'a';
}());
defineProperties(ArrayPrototype, {
splice: function splice(start, deleteCount) {
var O = ES.ToObject(this);
var A = [];
var len = ES.ToUint32(O.length);
var relativeStart = ES.ToInteger(start);
var actualStart = relativeStart < 0 ? max((len + relativeStart), 0) : min(relativeStart, len);
var actualDeleteCount = min(max(ES.ToInteger(deleteCount), 0), len - actualStart);
var k = 0;
var from;
while (k < actualDeleteCount) {
from = $String(actualStart + k);
if (owns(O, from)) {
A[k] = O[from];
}
k += 1;
}
var items = arraySlice(arguments, 2);
var itemCount = items.length;
var to;
if (itemCount < actualDeleteCount) {
k = actualStart;
while (k < (len - actualDeleteCount)) {
from = $String(k + actualDeleteCount);
to = $String(k + itemCount);
if (owns(O, from)) {
O[to] = O[from];
} else {
delete O[to];
}
k += 1;
}
k = len;
while (k > (len - actualDeleteCount + itemCount)) {
delete O[k - 1];
k -= 1;
}
} else if (itemCount > actualDeleteCount) {
k = len - actualDeleteCount;
while (k > actualStart) {
from = $String(k + actualDeleteCount - 1);
to = $String(k + itemCount - 1);
if (owns(O, from)) {
O[to] = O[from];
} else {
delete O[to];
}
k -= 1;
}
}
k = actualStart;
for (var i = 0; i < items.length; ++i) {
O[k] = items[i];
k += 1;
}
O.length = len - actualDeleteCount + itemCount;
return A;
}
}, !spliceWorksWithLargeSparseArrays || !spliceWorksWithSmallSparseArrays);
var originalJoin = ArrayPrototype.join;
var hasStringJoinBug;
try {
hasStringJoinBug = Array.prototype.join.call('123', ',') !== '1,2,3';
} catch (e) {
hasStringJoinBug = true;
}
if (hasStringJoinBug) {
defineProperties(ArrayPrototype, {
join: function join(separator) {
var sep = typeof separator === 'undefined' ? ',' : separator;
return originalJoin.call(isString(this) ? strSplit(this, '') : this, sep);
}
}, hasStringJoinBug);
}
var hasJoinUndefinedBug = [1, 2].join(undefined) !== '1,2';
if (hasJoinUndefinedBug) {
defineProperties(ArrayPrototype, {
join: function join(separator) {
var sep = typeof separator === 'undefined' ? ',' : separator;
return originalJoin.call(this, sep);
}
}, hasJoinUndefinedBug);
}
var pushShim = function push(item) {
var O = ES.ToObject(this);
var n = ES.ToUint32(O.length);
var i = 0;
while (i < arguments.length) {
O[n + i] = arguments[i];
i += 1;
}
O.length = n + i;
return n + i;
};
var pushIsNotGeneric = (function () {
var obj = {};
var result = Array.prototype.push.call(obj, undefined);
return result !== 1 || obj.length !== 1 || typeof obj[0] !== 'undefined' || !owns(obj, 0);
}());
defineProperties(ArrayPrototype, {
push: function push(item) {
if (isArray(this)) {
return array_push.apply(this, arguments);
}
return pushShim.apply(this, arguments);
}
}, pushIsNotGeneric);
// This fixes a very weird bug in Opera 10.6 when pushing `undefined
var pushUndefinedIsWeird = (function () {
var arr = [];
var result = arr.push(undefined);
return result !== 1 || arr.length !== 1 || typeof arr[0] !== 'undefined' || !owns(arr, 0);
}());
defineProperties(ArrayPrototype, { push: pushShim }, pushUndefinedIsWeird);
// ES5 15.2.3.14
// http://es5.github.io/#x15.4.4.10
// Fix boxed string bug
defineProperties(ArrayPrototype, {
slice: function (start, end) {
var arr = isString(this) ? strSplit(this, '') : this;
return arraySliceApply(arr, arguments);
}
}, splitString);
var sortIgnoresNonFunctions = (function () {
try {
[1, 2].sort(null);
[1, 2].sort({});
return true;
} catch (e) { /**/ }
return false;
}());
var sortThrowsOnRegex = (function () {
// this is a problem in Firefox 4, in which `typeof /a/ === 'function'`
try {
[1, 2].sort(/a/);
return false;
} catch (e) { /**/ }
return true;
}());
var sortIgnoresUndefined = (function () {
// applies in IE 8, for one.
try {
[1, 2].sort(undefined);
return true;
} catch (e) { /**/ }
return false;
}());
defineProperties(ArrayPrototype, {
sort: function sort(compareFn) {
if (typeof compareFn === 'undefined') {
return arraySort(this);
}
if (!isCallable(compareFn)) {
throw new TypeError('Array.prototype.sort callback must be a function');
}
return arraySort(this, compareFn);
}
}, sortIgnoresNonFunctions || !sortIgnoresUndefined || !sortThrowsOnRegex);
//
// Object
// ======
//
// ES5 15.2.3.14
// http://es5.github.com/#x15.2.3.14
// http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
var hasDontEnumBug = !({ 'toString': null }).propertyIsEnumerable('toString');
var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');
var hasStringEnumBug = !owns('x', '0');
var equalsConstructorPrototype = function (o) {
var ctor = o.constructor;
return ctor && ctor.prototype === o;
};
var blacklistedKeys = {
$window: true,
$console: true,
$parent: true,
$self: true,
$frame: true,
$frames: true,
$frameElement: true,
$webkitIndexedDB: true,
$webkitStorageInfo: true,
$external: true
};
var hasAutomationEqualityBug = (function () {
/* globals window */
if (typeof window === 'undefined') { return false; }
for (var k in window) {
try {
if (!blacklistedKeys['$' + k] && owns(window, k) && window[k] !== null && typeof window[k] === 'object') {
equalsConstructorPrototype(window[k]);
}
} catch (e) {
return true;
}
}
return false;
}());
var equalsConstructorPrototypeIfNotBuggy = function (object) {
if (typeof window === 'undefined' || !hasAutomationEqualityBug) { return equalsConstructorPrototype(object); }
try {
return equalsConstructorPrototype(object);
} catch (e) {
return false;
}
};
var dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
];
var dontEnumsLength = dontEnums.length;
// taken directly from https://github.com/ljharb/is-arguments/blob/master/index.js
// can be replaced with require('is-arguments') if we ever use a build process instead
var isStandardArguments = function isArguments(value) {
return toStr(value) === '[object Arguments]';
};
var isLegacyArguments = function isArguments(value) {
return value !== null &&
typeof value === 'object' &&
typeof value.length === 'number' &&
value.length >= 0 &&
!isArray(value) &&
isCallable(value.callee);
};
var isArguments = isStandardArguments(arguments) ? isStandardArguments : isLegacyArguments;
defineProperties($Object, {
keys: function keys(object) {
var isFn = isCallable(object);
var isArgs = isArguments(object);
var isObject = object !== null && typeof object === 'object';
var isStr = isObject && isString(object);
if (!isObject && !isFn && !isArgs) {
throw new TypeError('Object.keys called on a non-object');
}
var theKeys = [];
var skipProto = hasProtoEnumBug && isFn;
if ((isStr && hasStringEnumBug) || isArgs) {
for (var i = 0; i < object.length; ++i) {
push(theKeys, $String(i));
}
}
if (!isArgs) {
for (var name in object) {
if (!(skipProto && name === 'prototype') && owns(object, name)) {
push(theKeys, $String(name));
}
}
}
if (hasDontEnumBug) {
var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
for (var j = 0; j < dontEnumsLength; j++) {
var dontEnum = dontEnums[j];
if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
push(theKeys, dontEnum);
}
}
}
return theKeys;
}
});
var keysWorksWithArguments = $Object.keys && (function () {
// Safari 5.0 bug
return $Object.keys(arguments).length === 2;
}(1, 2));
var keysHasArgumentsLengthBug = $Object.keys && (function () {
var argKeys = $Object.keys(arguments);
return arguments.length !== 1 || argKeys.length !== 1 || argKeys[0] !== 1;
}(1));
var originalKeys = $Object.keys;
defineProperties($Object, {
keys: function keys(object) {
if (isArguments(object)) {
return originalKeys(arraySlice(object));
} else {
return originalKeys(object);
}
}
}, !keysWorksWithArguments || keysHasArgumentsLengthBug);
//
// Date
// ====
//
// ES5 15.9.5.43
// http://es5.github.com/#x15.9.5.43
// This function returns a String value represent the instance in time
// represented by this Date object. The format of the String is the Date Time
// string format defined in 15.9.1.15. All fields are present in the String.
// The time zone is always UTC, denoted by the suffix Z. If the time value of
// this object is not a finite Number a RangeError exception is thrown.
var negativeDate = -62198755200000;
var negativeYearString = '-000001';
var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;
var hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';
defineProperties(Date.prototype, {
toISOString: function toISOString() {
var result, length, value, year, month;
if (!isFinite(this)) {
throw new RangeError('Date.prototype.toISOString called on non-finite value.');
}
year = this.getUTCFullYear();
month = this.getUTCMonth();
// see https://github.com/es-shims/es5-shim/issues/111
year += Math.floor(month / 12);
month = (month % 12 + 12) % 12;
// the date time string format is specified in 15.9.1.15.
result = [month + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
year = (
(year < 0 ? '-' : (year > 9999 ? '+' : '')) +
strSlice('00000' + Math.abs(year), (0 <= year && year <= 9999) ? -4 : -6)
);
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 (
year + '-' + arraySlice(result, 0, 2).join('-') +
'T' + arraySlice(result, 2).join(':') + '.' +
strSlice('000' + this.getUTCMilliseconds(), -3) + 'Z'
);
}
}, hasNegativeDateBug || hasSafari51DateBug);
// ES5 15.9.5.44
// http://es5.github.com/#x15.9.5.44
// This function provides a String representation of a Date object for use by
// JSON.stringify (15.12.3).
var dateToJSONIsSupported = (function () {
try {
return Date.prototype.toJSON &&
new Date(NaN).toJSON() === null &&
new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
Date.prototype.toJSON.call({ // generic
toISOString: function () { return true; }
});
} catch (e) {
return false;
}
}());
if (!dateToJSONIsSupported) {
Date.prototype.toJSON = function toJSON(key) {
// 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 ES.ToPrimitive(O, hint Number).
var O = $Object(this);
var tv = ES.ToPrimitive(O);
// 3. If tv is a Number and is not finite, return null.
if (typeof tv === 'number' && !isFinite(tv)) {
return null;
}
// 4. Let toISO be the result of calling the [[Get]] internal method of
// O with argument "toISOString".
var toISO = O.toISOString;
// 5. If IsCallable(toISO) is false, throw a TypeError exception.
if (!isCallable(toISO)) {
throw new TypeError('toISOString property is not callable');
}
// 6. Return the result of calling the [[Call]] internal method of
// toISO with O as the this value and an empty argument list.
return toISO.call(O);
// 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.
};
}
// ES5 15.9.4.2
// http://es5.github.com/#x15.9.4.2
// based on work shared by Daniel Friesen (dantman)
// http://gist.github.com/303249
var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;
var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z')) || !isNaN(Date.parse('2012-12-31T23:59:60.000Z'));
var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));
if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
// XXX global assignment won't work in embeddings that use
// an alternate object for the context.
/* global Date: true */
/* eslint-disable no-undef */
var maxSafeUnsigned32Bit = Math.pow(2, 31) - 1;
var hasSafariSignedIntBug = isActualNaN(new Date(1970, 0, 1, 0, 0, 0, maxSafeUnsigned32Bit + 1).getTime());
Date = (function (NativeDate) {
/* eslint-enable no-undef */
// Date.length === 7
var DateShim = function Date(Y, M, D, h, m, s, ms) {
var length = arguments.length;
var date;
if (this instanceof NativeDate) {
var seconds = s;
var millis = ms;
if (hasSafariSignedIntBug && length >= 7 && ms > maxSafeUnsigned32Bit) {
// work around a Safari 8/9 bug where it treats the seconds as signed
var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit;
var sToShift = Math.floor(msToShift / 1e3);
seconds += sToShift;
millis -= sToShift * 1e3;
}
date = length === 1 && $String(Y) === Y ? // isString(Y)
// We explicitly pass it through parse:
new NativeDate(DateShim.parse(Y)) :
// We have to manually make calls depending on argument
// length here
length >= 7 ? new NativeDate(Y, M, D, h, m, seconds, millis) :
length >= 6 ? new NativeDate(Y, M, D, h, m, seconds) :
length >= 5 ? new NativeDate(Y, M, D, h, m) :
length >= 4 ? new NativeDate(Y, M, D, h) :
length >= 3 ? new NativeDate(Y, M, D) :
length >= 2 ? new NativeDate(Y, M) :
length >= 1 ? new NativeDate(Y) :
new NativeDate();
} else {
date = NativeDate.apply(this, arguments);
}
if (!isPrimitive(date)) {
// Prevent mixups with unfixed Date object
defineProperties(date, { constructor: DateShim }, true);
}
return date;
};
// 15.9.1.15 Date Time String Format.
var isoDateExpression = new RegExp('^' +
'(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign +
// 6-digit extended year
'(?:-(\\d{2})' + // optional month capture
'(?:-(\\d{2})' + // optional day capture
'(?:' + // capture hours:minutes:seconds.milliseconds
'T(\\d{2})' + // hours capture
':(\\d{2})' + // minutes capture
'(?:' + // optional :seconds.milliseconds
':(\\d{2})' + // seconds capture
'(?:(\\.\\d{1,}))?' + // milliseconds capture
')?' +
'(' + // capture UTC offset component
'Z|' + // UTC capture
'(?:' + // offset specifier +/-hours:minutes
'([-+])' + // sign capture
'(\\d{2})' + // hours offset capture
':(\\d{2})' + // minutes offset capture
')' +
')?)?)?)?' +
'$');
var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
var dayFromMonth = function dayFromMonth(year, month) {
var t = month > 1 ? 1 : 0;
return (
months[month] +
Math.floor((year - 1969 + t) / 4) -
Math.floor((year - 1901 + t) / 100) +
Math.floor((year - 1601 + t) / 400) +
365 * (year - 1970)
);
};
var toUTC = function toUTC(t) {
var s = 0;
var ms = t;
if (hasSafariSignedIntBug && ms > maxSafeUnsigned32Bit) {
// work around a Safari 8/9 bug where it treats the seconds as signed
var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit;
var sToShift = Math.floor(msToShift / 1e3);
s += sToShift;
ms -= sToShift * 1e3;
}
return $Number(new NativeDate(1970, 0, 1, 0, 0, s, ms));
};
// Copy any custom methods a 3rd party library may have added
for (var key in NativeDate) {
if (owns(NativeDate, key)) {
DateShim[key] = NativeDate[key];
}
}
// Copy "native" methods explicitly; they may be non-enumerable
defineProperties(DateShim, {
now: NativeDate.now,
UTC: NativeDate.UTC
}, true);
DateShim.prototype = NativeDate.prototype;
defineProperties(DateShim.prototype, {
constructor: DateShim
}, true);
// Upgrade Date.parse to handle simplified ISO 8601 strings
var parseShim = function parse(string) {
var match = isoDateExpression.exec(string);
if (match) {
// parse months, days, hours, minutes, seconds, and milliseconds
// provide default values if necessary
// parse the UTC offset component
var year = $Number(match[1]),
month = $Number(match[2] || 1) - 1,
day = $Number(match[3] || 1) - 1,
hour = $Number(match[4] || 0),
minute = $Number(match[5] || 0),
second = $Number(match[6] || 0),
millisecond = Math.floor($Number(match[7] || 0) * 1000),
// When time zone is missed, local offset should be used
// (ES 5.1 bug)
// see https://bugs.ecmascript.org/show_bug.cgi?id=112
isLocalTime = Boolean(match[4] && !match[8]),
signOffset = match[9] === '-' ? 1 : -1,
hourOffset = $Number(match[10] || 0),
minuteOffset = $Number(match[11] || 0),
result;
var hasMinutesOrSecondsOrMilliseconds = minute > 0 || second > 0 || millisecond > 0;
if (
hour < (hasMinutesOrSecondsOrMilliseconds ? 24 : 25) &&
minute < 60 && second < 60 && millisecond < 1000 &&
month > -1 && month < 12 && hourOffset < 24 &&
minuteOffset < 60 && // detect invalid offsets
day > -1 &&
day < (dayFromMonth(year, month + 1) - dayFromMonth(year, month))
) {
result = (
(dayFromMonth(year, month) + day) * 24 +
hour +
hourOffset * signOffset
) * 60;
result = (
(result + minute + minuteOffset * signOffset) * 60 +
second
) * 1000 + millisecond;
if (isLocalTime) {
result = toUTC(result);
}
if (-8.64e15 <= result && result <= 8.64e15) {
return result;
}
}
return NaN;
}
return NativeDate.parse.apply(this, arguments);
};
defineProperties(DateShim, { parse: parseShim });
return DateShim;
}(Date));
/* global Date: false */
}
// ES5 15.9.4.4
// http://es5.github.com/#x15.9.4.4
if (!Date.now) {
Date.now = function now() {
return new Date().getTime();
};
}
//
// Number
// ======
//
// ES5.1 15.7.4.5
// http://es5.github.com/#x15.7.4.5
var hasToFixedBugs = NumberPrototype.toFixed && (
(0.00008).toFixed(3) !== '0.000' ||
(0.9).toFixed(0) !== '1' ||
(1.255).toFixed(2) !== '1.25' ||
(1000000000000000128).toFixed(0) !== '1000000000000000128'
);
var toFixedHelpers = {
base: 1e7,
size: 6,
data: [0, 0, 0, 0, 0, 0],
multiply: function multiply(n, c) {
var i = -1;
var c2 = c;
while (++i < toFixedHelpers.size) {
c2 += n * toFixedHelpers.data[i];
toFixedHelpers.data[i] = c2 % toFixedHelpers.base;
c2 = Math.floor(c2 / toFixedHelpers.base);
}
},
divide: function divide(n) {
var i = toFixedHelpers.size, c = 0;
while (--i >= 0) {
c += toFixedHelpers.data[i];
toFixedHelpers.data[i] = Math.floor(c / n);
c = (c % n) * toFixedHelpers.base;
}
},
numToString: function numToString() {
var i = toFixedHelpers.size;
var s = '';
while (--i >= 0) {
if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) {
var t = $String(toFixedHelpers.data[i]);
if (s === '') {
s = t;
} else {
s += strSlice('0000000', 0, 7 - t.length) + t;
}
}
}
return s;
},
pow: function pow(x, n, acc) {
return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
},
log: function log(x) {
var n = 0;
var x2 = x;
while (x2 >= 4096) {
n += 12;
x2 /= 4096;
}
while (x2 >= 2) {
n += 1;
x2 /= 2;
}
return n;
}
};
var toFixedShim = function toFixed(fractionDigits) {
var f, x, s, m, e, z, j, k;
// Test for NaN and round fractionDigits down
f = $Number(fractionDigits);
f = isActualNaN(f) ? 0 : Math.floor(f);
if (f < 0 || f > 20) {
throw new RangeError('Number.toFixed called with invalid number of decimals');
}
x = $Number(this);
if (isActualNaN(x)) {
return 'NaN';
}
// If it is too big or small, return the string value of the number
if (x <= -1e21 || x >= 1e21) {
return $String(x);
}
s = '';
if (x < 0) {
s = '-';
x = -x;
}
m = '0';
if (x > 1e-21) {
// 1e-21 < x < 1e21
// -70 < log2(x) < 70
e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
z *= 0x10000000000000; // Math.pow(2, 52);
e = 52 - e;
// -18 < e < 122
// x = z / 2 ^ e
if (e > 0) {
toFixedHelpers.multiply(0, z);
j = f;
while (j >= 7) {
toFixedHelpers.multiply(1e7, 0);
j -= 7;
}
toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
j = e - 1;
while (j >= 23) {
toFixedHelpers.divide(1 << 23);
j -= 23;
}
toFixedHelpers.divide(1 << j);
toFixedHelpers.multiply(1, 1);
toFixedHelpers.divide(2);
m = toFixedHelpers.numToString();
} else {
toFixedHelpers.multiply(0, z);
toFixedHelpers.multiply(1 << (-e), 0);
m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f);
}
}
if (f > 0) {
k = m.length;
if (k <= f) {
m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m;
} else {
m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f);
}
} else {
m = s + m;
}
return m;
};
defineProperties(NumberPrototype, { toFixed: toFixedShim }, hasToFixedBugs);
var hasToPrecisionUndefinedBug = (function () {
try {
return 1.0.toPrecision(undefined) === '1';
} catch (e) {
return true;
}
}());
var originalToPrecision = NumberPrototype.toPrecision;
defineProperties(NumberPrototype, {
toPrecision: function toPrecision(precision) {
return typeof precision === 'undefined' ? originalToPrecision.call(this) : originalToPrecision.call(this, precision);
}
}, hasToPrecisionUndefinedBug);
//
// String
// ======
//
// ES5 15.5.4.14
// http://es5.github.com/#x15.5.4.14
// [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
// Many browsers do not split properly with regular expressions or they
// do not perform the split correctly under obscure conditions.
// See http://blog.stevenlevithan.com/archives/cross-browser-split
// I've tested in many browsers and this seems to cover the deviant ones:
// 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
// '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
// 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
// [undefined, "t", undefined, "e", ...]
// ''.split(/.?/) should be [], not [""]
// '.'.split(/()()/) should be ["."], not ["", "", "."]
if (
'ab'.split(/(?:ab)*/).length !== 2 ||
'.'.split(/(.?)(.?)/).length !== 4 ||
'tesst'.split(/(s)*/)[1] === 't' ||
'test'.split(/(?:)/, -1).length !== 4 ||
''.split(/.?/).length ||
'.'.split(/()()/).length > 1
) {
(function () {
var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group
var maxSafe32BitInt = Math.pow(2, 32) - 1;
StringPrototype.split = function (separator, limit) {
var string = String(this);
if (typeof separator === 'undefined' && limit === 0) {
return [];
}
// If `separator` is not a regex, use native split
if (!isRegex(separator)) {
return strSplit(this, separator, limit);
}
var output = [];
var flags = (separator.ignoreCase ? 'i' : '') +
(separator.multiline ? 'm' : '') +
(separator.unicode ? 'u' : '') + // in ES6
(separator.sticky ? 'y' : ''), // Firefox 3+ and ES6
lastLastIndex = 0,
// Make `global` and avoid `lastIndex` issues by working with a copy
separator2, match, lastIndex, lastLength;
var separatorCopy = new RegExp(separator.source, flags + 'g');
if (!compliantExecNpcg) {
// Doesn't need flags gy, but they don't hurt
separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
}
/* Values for `limit`, per the spec:
* If undefined: 4294967295 // maxSafe32BitInt
* If 0, Infinity, or NaN: 0
* If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
* If negative number: 4294967296 - Math.floor(Math.abs(limit))
* If other: Type-convert, then use the above rules
*/
var splitLimit = typeof limit === 'undefined' ? maxSafe32BitInt : ES.ToUint32(limit);
match = separatorCopy.exec(string);
while (match) {
// `separatorCopy.lastIndex` is not reliable cross-browser
lastIndex = match.index + match[0].length;
if (lastIndex > lastLastIndex) {
push(output, strSlice(string, lastLastIndex, match.index));
// Fix browsers whose `exec` methods don't consistently return `undefined` for
// nonparticipating capturing groups
if (!compliantExecNpcg && match.length > 1) {
/* eslint-disable no-loop-func */
match[0].replace(separator2, function () {
for (var i = 1; i < arguments.length - 2; i++) {
if (typeof arguments[i] === 'undefined') {
match[i] = void 0;
}
}
});
/* eslint-enable no-loop-func */
}
if (match.length > 1 && match.index < string.length) {
array_push.apply(output, arraySlice(match, 1));
}
lastLength = match[0].length;
lastLastIndex = lastIndex;
if (output.length >= splitLimit) {
break;
}
}
if (separatorCopy.lastIndex === match.index) {
separatorCopy.lastIndex++; // Avoid an infinite loop
}
match = separatorCopy.exec(string);
}
if (lastLastIndex === string.length) {
if (lastLength || !separatorCopy.test('')) {
push(output, '');
}
} else {
push(output, strSlice(string, lastLastIndex));
}
return output.length > splitLimit ? strSlice(output, 0, splitLimit) : output;
};
}());
// [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) -> []
} else if ('0'.split(void 0, 0).length) {
StringPrototype.split = function split(separator, limit) {
if (typeof separator === 'undefined' && limit === 0) { return []; }
return strSplit(this, separator, limit);
};
}
var str_replace = StringPrototype.replace;
var replaceReportsGroupsCorrectly = (function () {
var groups = [];
'x'.replace(/x(.)?/g, function (match, group) {
push(groups, group);
});
return groups.length === 1 && typeof groups[0] === 'undefined';
}());
if (!replaceReportsGroupsCorrectly) {
StringPrototype.replace = function replace(searchValue, replaceValue) {
var isFn = isCallable(replaceValue);
var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
if (!isFn || !hasCapturingGroups) {
return str_replace.call(this, searchValue, replaceValue);
} else {
var wrappedReplaceValue = function (match) {
var length = arguments.length;
var originalLastIndex = searchValue.lastIndex;
searchValue.lastIndex = 0;
var args = searchValue.exec(match) || [];
searchValue.lastIndex = originalLastIndex;
push(args, arguments[length - 2], arguments[length - 1]);
return replaceValue.apply(this, args);
};
return str_replace.call(this, searchValue, wrappedReplaceValue);
}
};
}
// ECMA-262, 3rd B.2.3
// Not an ECMAScript standard, 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
var string_substr = StringPrototype.substr;
var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';
defineProperties(StringPrototype, {
substr: function substr(start, length) {
var normalizedStart = start;
if (start < 0) {
normalizedStart = max(this.length + start, 0);
}
return string_substr.call(this, normalizedStart, length);
}
}, hasNegativeSubstrBug);
// ES5 15.5.4.20
// whitespace from: http://es5.github.io/#x15.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';
var zeroWidth = '\u200b';
var wsRegexChars = '[' + ws + ']';
var trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');
var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');
var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());
defineProperties(StringPrototype, {
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
// http://perfectionkills.com/whitespace-deviations/
trim: function trim() {
if (typeof this === 'undefined' || this === null) {
throw new TypeError("can't convert " + this + ' to object');
}
return $String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');
}
}, hasTrimWhitespaceBug);
var hasLastIndexBug = StringPrototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1;
defineProperties(StringPrototype, {
lastIndexOf: function lastIndexOf(searchString) {
if (typeof this === 'undefined' || this === null) {
throw new TypeError("can't convert " + this + ' to object');
}
var S = $String(this);
var searchStr = $String(searchString);
var numPos = arguments.length > 1 ? $Number(arguments[1]) : NaN;
var pos = isActualNaN(numPos) ? Infinity : ES.ToInteger(numPos);
var start = min(max(pos, 0), S.length);
var searchLen = searchStr.length;
var k = start + searchLen;
while (k > 0) {
k = max(0, k - searchLen);
var index = strIndexOf(strSlice(S, k, start + searchLen), searchStr);
if (index !== -1) {
return k + index;
}
}
return -1;
}
}, hasLastIndexBug);
var originalLastIndexOf = StringPrototype.lastIndexOf;
defineProperties(StringPrototype, {
lastIndexOf: function lastIndexOf(searchString) {
return originalLastIndexOf.apply(this, arguments);
}
}, StringPrototype.lastIndexOf.length !== 1);
// ES-5 15.1.2.2
/* eslint-disable radix */
if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
/* eslint-enable radix */
/* global parseInt: true */
parseInt = (function (origParseInt) {
var hexRegex = /^[\-+]?0[xX]/;
return function parseInt(str, radix) {
var string = $String(str).trim();
var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10);
return origParseInt(string, defaultedRadix);
};
}(parseInt));
}
if (String(new RangeError('test')) !== 'RangeError: test') {
var errorToStringShim = function toString() {
if (typeof this === 'undefined' || this === null) {
throw new TypeError("can't convert " + this + ' to object');
}
var name = this.name;
if (typeof name === 'undefined') {
name = 'Error';
} else if (typeof name !== 'string') {
name = $String(name);
}
var msg = this.message;
if (typeof msg === 'undefined') {
msg = '';
} else if (typeof msg !== 'string') {
msg = $String(msg);
}
if (!name) {
return msg;
}
if (!msg) {
return name;
}
return name + ': ' + msg;
};
// can't use defineProperties here because of toString enumeration issue in IE <= 8
Error.prototype.toString = errorToStringShim;
}
if (supportsDescriptors) {
var ensureNonEnumerable = function (obj, prop) {
if (isEnum(obj, prop)) {
var desc = Object.getOwnPropertyDescriptor(obj, prop);
desc.enumerable = false;
Object.defineProperty(obj, prop, desc);
}
};
ensureNonEnumerable(Error.prototype, 'message');
if (Error.prototype.message !== '') {
Error.prototype.message = '';
}
ensureNonEnumerable(Error.prototype, 'name');
}
if (String(/a/mig) !== '/a/gim') {
var regexToString = function toString() {
var str = '/' + this.source + '/';
if (this.global) {
str += 'g';
}
if (this.ignoreCase) {
str += 'i';
}
if (this.multiline) {
str += 'm';
}
return str;
};
// can't use defineProperties here because of toString enumeration issue in IE <= 8
RegExp.prototype.toString = regexToString;
}
}));
},{}],26:[function(_dereq_,module,exports){
var arr = [];
var each = arr.forEach;
var slice = arr.slice;
module.exports = function(obj) {
each.call(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
obj[prop] = source[prop];
}
}
});
return obj;
};
},{}],27:[function(_dereq_,module,exports){
module.exports = isFunction
var toString = Object.prototype.toString
function isFunction (fn) {
var string = toString.call(fn)
return string === '[object Function]' ||
(typeof fn === 'function' && string !== '[object RegExp]') ||
(typeof window !== 'undefined' &&
// IE8 and below
(fn === window.setTimeout ||
fn === window.alert ||
fn === window.confirm ||
fn === window.prompt))
};
},{}],28:[function(_dereq_,module,exports){
"use strict";
module.exports = function isObject(x) {
return typeof x === "object" && x !== null;
};
},{}],29:[function(_dereq_,module,exports){
/*!
* $script.js JS loader & dependency manager
* https://github.com/ded/script.js
* (c) Dustin Diaz 2014 | License MIT
*/
(function (name, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof define == 'function' && define.amd) define(definition)
else this[name] = definition()
})('$script', function () {
var doc = document
, head = doc.getElementsByTagName('head')[0]
, s = 'string'
, f = false
, push = 'push'
, readyState = 'readyState'
, onreadystatechange = 'onreadystatechange'
, list = {}
, ids = {}
, delay = {}
, scripts = {}
, scriptpath
, urlArgs
function every(ar, fn) {
for (var i = 0, j = ar.length; i < j; ++i) if (!fn(ar[i])) return f
return 1
}
function each(ar, fn) {
every(ar, function (el) {
return !fn(el)
})
}
function $script(paths, idOrDone, optDone) {
paths = paths[push] ? paths : [paths]
var idOrDoneIsDone = idOrDone && idOrDone.call
, done = idOrDoneIsDone ? idOrDone : optDone
, id = idOrDoneIsDone ? paths.join('') : idOrDone
, queue = paths.length
function loopFn(item) {
return item.call ? item() : list[item]
}
function callback() {
if (!--queue) {
list[id] = 1
done && done()
for (var dset in delay) {
every(dset.split('|'), loopFn) && !each(delay[dset], loopFn) && (delay[dset] = [])
}
}
}
setTimeout(function () {
each(paths, function loading(path, force) {
if (path === null) return callback()
if (!force && !/^https?:\/\//.test(path) && scriptpath) {
path = (path.indexOf('.js') === -1) ? scriptpath + path + '.js' : scriptpath + path;
}
if (scripts[path]) {
if (id) ids[id] = 1
return (scripts[path] == 2) ? callback() : setTimeout(function () { loading(path, true) }, 0)
}
scripts[path] = 1
if (id) ids[id] = 1
create(path, callback)
})
}, 0)
return $script
}
function create(path, fn) {
var el = doc.createElement('script'), loaded
el.onload = el.onerror = el[onreadystatechange] = function () {
if ((el[readyState] && !(/^c|loade/.test(el[readyState]))) || loaded) return;
el.onload = el[onreadystatechange] = null
loaded = 1
scripts[path] = 2
fn()
}
el.async = 1
el.src = urlArgs ? path + (path.indexOf('?') === -1 ? '?' : '&') + urlArgs : path;
head.insertBefore(el, head.lastChild)
}
$script.get = create
$script.order = function (scripts, id, done) {
(function callback(s) {
s = scripts.shift()
!scripts.length ? $script(s, id, done) : $script(s, callback)
}())
}
$script.path = function (p) {
scriptpath = p
}
$script.urlArgs = function (str) {
urlArgs = str;
}
$script.ready = function (deps, ready, req) {
deps = deps[push] ? deps : [deps]
var missing = [];
!each(deps, function (dep) {
list[dep] || missing[push](dep);
}) && every(deps, function (dep) {return list[dep]}) ?
ready() : !function (key) {
delay[key] = delay[key] || []
delay[key][push](ready)
req && req(missing)
}(deps.join('|'))
return $script
}
$script.done = function (idOrDone) {
$script([null], idOrDone)
}
return $script
});
},{}]},{},[19])(19)
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment