/*! 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' + innerHTML + '').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 = ' -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 += ''; }); tag += ""; 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(/&/g, '%26').replace(/&/g, '%26').replace(/=/g, '%3D'); return url; } 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'}, ''), 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 ''; } 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 'Watch video!\n'.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 ? '

shift + slower / faster

' : ''; // TODO: add to player-layout.html root.appendChild(common.createElement('div', { className: 'fp-help' }, '\ \
\

spaceplay / pause

\

qunload | stop

\

ffullscreen

' + speedhelp + '\
\
\

volume

\

mmute

\
\
\

seek

\

 . seek to previous\

126 seek to 10%, 20% … 60%

\
\ ')); 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 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 = "

" + lines[++i] + "


"; while (typeof lines[++i] === 'string' && lines[i].trim() && i < lines.length) text += "

" + lines[i] + "


"; // 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 = /Android/.test(UA) && !/Firefox/.test(UA), IS_ANDROID_FIREFOX = /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: !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'}, '\
\ \ \

\
\ \
\
\
\
\
\
\ \
\
\
\
\
\
\ 00:00\ \ 00:00\
\

'.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, "

loading …

"); 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: " /app-editor/ewebeditor/js/flowplayer-6.0.5/flowplayer.swf", swfHls: "/app-editor/ewebeditor/js/flowplayer-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"},''),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 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 * @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 state to , // 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 * @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) });