UNPKG

flowplayer

Version:
1,350 lines (1,107 loc) 368 kB
/*! Flowplayer v7.0.4 (2017-04-28) | flowplayer.org/license */ /*! (C) WebReflection Mit Style License */ (function(e){function g(e,t,n,r){for(var i,s=n.slice(),o=w(t,e),u=0,a=s.length;u<a;u++){handler=s[u],typeof handler=="object"&&typeof handler.handleEvent=="function"?handler.handleEvent(o):handler.call(e,o);if(o.stoppedImmediatePropagation)break}return i=!o.stoppedPropagation,r&&i&&e.parentNode?e.parentNode.dispatchEvent(o):!o.defaultPrevented}function y(e,t){return{configurable:!0,get:e,set:t}}function b(e,t,n){var r=f(t||e,n);u(e,"textContent",y(function(){return r.get.call(this)},function(e){r.set.call(this,e)}))}function w(e,t){return e.currentTarget=t,e.eventPhase=e.target===e.currentTarget?2:3,e}function E(e,t){var n=e.length;while(n--&&e[n]!==t);return n}function S(){if(this.tagName==="BR")return"\n";var e=this.firstChild,t=[];while(e)e.nodeType!==8&&e.nodeType!==7&&t.push(e.textContent),e=e.nextSibling;return t.join("")}function x(e){return e.nodeType!==9&&document.documentElement.contains(e)}function T(e){!n&&d.test(document.readyState)&&(n=!n,document.detachEvent(r,T),e=document.createEvent("Event"),e.initEvent(i,!0,!0),document.dispatchEvent(e))}function N(e){var t;while(t=this.lastChild)this.removeChild(t);e!=null&&this.appendChild(document.createTextNode(e))}function C(t,n){return n||(n=e.event),n.target||(n.target=n.srcElement||n.fromElement||document),n.timeStamp||(n.timeStamp=(new Date).getTime()),n}if(document.createEvent)return;var t=!0,n=!1,r="onreadystatechange",i="DOMContentLoaded",s="__IE8__"+Math.random(),o=e.Object,u=o.defineProperty||function(e,t,n){e[t]=n.value},a=o.defineProperties||function(t,n){for(var r in n)if(l.call(n,r))try{u(t,r,n[r])}catch(i){e.console&&console.log(r+" failed on object:",t,i.message)}},f=o.getOwnPropertyDescriptor,l=o.prototype.hasOwnProperty,c=e.Element.prototype,h=e.Text.prototype,p=/^[a-z]+$/,d=/loaded|complete/,v={},m=document.createElement("div");b(e.HTMLCommentElement.prototype,c,"nodeValue"),b(e.HTMLScriptElement.prototype,null,"text"),b(h,null,"nodeValue"),b(e.HTMLTitleElement.prototype,null,"text"),u(e.HTMLStyleElement.prototype,"textContent",function(e){return y(function(){return e.get.call(this.styleSheet)},function(t){e.set.call(this.styleSheet,t)})}(f(e.CSSStyleSheet.prototype,"cssText"))),a(c,{textContent:{get:S,set:N},firstElementChild:{get:function(){for(var e=this.childNodes||[],t=0,n=e.length;t<n;t++)if(e[t].nodeType==1)return e[t]}},lastElementChild:{get:function(){for(var e=this.childNodes||[],t=e.length;t--;)if(e[t].nodeType==1)return e[t]}},previousElementSibling:{get:function(){var e=this.previousSibling;while(e&&e.nodeType!=1)e=e.previousSibling;return e}},nextElementSibling:{get:function(){var e=this.nextSibling;while(e&&e.nodeType!=1)e=e.nextSibling;return e}},childElementCount:{get:function(){for(var e=0,t=this.childNodes||[],n=t.length;n--;e+=t[n].nodeType==1);return e}},addEventListener:{value:function(e,t,n){var r=this,i="on"+e,o=r[s]||u(r,s,{value:{}})[s],a=o[i]||(o[i]={}),f=a.h||(a.h=[]),c;if(!l.call(a,"w")){a.w=function(e){return e[s]||g(r,C(r,e),f,!1)};if(!l.call(v,i))if(p.test(e))try{c=document.createEventObject(),c[s]=!0,r.nodeType!=9&&r.parentNode==null&&m.appendChild(r),r.fireEvent(i,c),v[i]=!0}catch(c){v[i]=!1;while(m.hasChildNodes())m.removeChild(m.firstChild)}else v[i]=!1;(a.n=v[i])&&r.attachEvent(i,a.w)}E(f,t)<0&&f[n?"unshift":"push"](t)}},dispatchEvent:{value:function(e){var t=this,n="on"+e.type,r=t[s],i=r&&r[n],o=!!i,u;return e.target||(e.target=t),o?i.n?t.fireEvent(n,e):g(t,e,i.h,!0):(u=t.parentNode)?u.dispatchEvent(e):!0,!e.defaultPrevented}},removeEventListener:{value:function(e,t,n){var r=this,i="on"+e,o=r[s],u=o&&o[i],a=u&&u.h,f=a?E(a,t):-1;-1<f&&a.splice(f,1)}}}),a(h,{addEventListener:{value:c.addEventListener},dispatchEvent:{value:c.dispatchEvent},removeEventListener:{value:c.removeEventListener}}),a(e.XMLHttpRequest.prototype,{addEventListener:{value:function(e,t,n){var r=this,i="on"+e,o=r[s]||u(r,s,{value:{}})[s],a=o[i]||(o[i]={}),f=a.h||(a.h=[]);E(f,t)<0&&(r[i]||(r[i]=function(){var t=document.createEvent("Event");t.initEvent(e,!0,!0),r.dispatchEvent(t)}),f[n?"unshift":"push"](t))}},dispatchEvent:{value:function(e){var t=this,n="on"+e.type,r=t[s],i=r&&r[n],o=!!i;return o&&(i.n?t.fireEvent(n,e):g(t,e,i.h,!0))}},removeEventListener:{value:c.removeEventListener}}),a(e.Event.prototype,{bubbles:{value:!0,writable:!0},cancelable:{value:!0,writable:!0},preventDefault:{value:function(){this.cancelable&&(this.defaultPrevented=!0,this.returnValue=!1)}},stopPropagation:{value:function(){this.stoppedPropagation=!0,this.cancelBubble=!0}},stopImmediatePropagation:{value:function(){this.stoppedImmediatePropagation=!0,this.stopPropagation()}},initEvent:{value:function(e,t,n){this.type=e,this.bubbles=!!t,this.cancelable=!!n,this.bubbles||this.stopPropagation()}}}),a(e.HTMLDocument.prototype,{textContent:{get:function(){return this.nodeType===11?S.call(this):null},set:function(e){this.nodeType===11&&N.call(this,e)}},addEventListener:{value:function(n,s,o){var u=this;c.addEventListener.call(u,n,s,o),t&&n===i&&!d.test(u.readyState)&&(t=!1,u.attachEvent(r,T),e==top&&function a(e){try{u.documentElement.doScroll("left"),T()}catch(t){setTimeout(a,50)}}())}},dispatchEvent:{value:c.dispatchEvent},removeEventListener:{value:c.removeEventListener},createEvent:{value:function(e){var t;if(e!=="Event")throw new Error("unsupported "+e);return t=document.createEventObject(),t.timeStamp=(new Date).getTime(),t}}}),a(e.Window.prototype,{getComputedStyle:{value:function(){function i(e){this._=e}function s(){}var e=/^(?:[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/,t=/^(top|right|bottom|left)$/,n=/\-([a-z])/g,r=function(e,t){return t.toUpperCase()};return i.prototype.getPropertyValue=function(i){var s=this._,o=s.style,u=s.currentStyle,a=s.runtimeStyle,f,l,c;return i=(i==="float"?"style-float":i).replace(n,r),f=u?u[i]:o[i],e.test(f)&&!t.test(i)&&(l=o.left,c=a&&a.left,c&&(a.left=u.left),o.left=i==="fontSize"?"1em":f,f=o.pixelLeft+"px",o.left=l,c&&(a.left=c)),f==null?f:f+""||"auto"},s.prototype.getPropertyValue=function(){return null},function(e,t){return t?new s(e):new i(e)}}()},addEventListener:{value:function(t,n,r){var i=e,o="on"+t,u;i[o]||(i[o]=function(e){return g(i,C(i,e),u,!1)}),u=i[o][s]||(i[o][s]=[]),E(u,n)<0&&u[r?"unshift":"push"](n)}},dispatchEvent:{value:function(t){var n=e["on"+t.type];return n?n.call(e,t)!==!1&&!t.defaultPrevented:!0}},removeEventListener:{value:function(t,n,r){var i="on"+t,u=(e[i]||o)[s],a=u?E(u,n):-1;-1<a&&u.splice(a,1)}}})})(this); (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.flowplayer = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ 'use strict'; var common = module.exports = {}, ClassList = _dereq_('class-list'), $ = window.jQuery, punycode = _dereq_('punycode'), computedStyle = _dereq_('computed-style'); common.noop = function() {}; common.identity = function(i) { return i; }; common.removeNode = function(el) { if (!el || !el.parentNode) return; el.parentNode.removeChild(el); }; common.find = function(query, ctx) { if ($) return $(query, ctx).toArray(); ctx = ctx || document; return Array.prototype.map.call(ctx.querySelectorAll(query), function(el) { return el; }); }; common.text = function(el, txt) { el[('innerText' in el) ? 'innerText' : 'textContent'] = txt; }; common.findDirect = function(query, ctx) { return common.find(query, ctx).filter(function(node) { return node.parentNode === ctx; }); }; common.hasClass = function(el, kls) { if (typeof el.className !== 'string') return false; return ClassList(el).contains(kls); }; common.isSameDomain = function(url) { var w = window.location, a = common.createElement('a', { href: url }); return w.hostname === a.hostname && w.protocol === a.protocol && w.port === a.port; }; common.css = function(el, property, value) { if (typeof property === 'object') { return Object.keys(property).forEach(function(key) { common.css(el, key, property[key]); }); } if (typeof value !== 'undefined') { if (value === '') return el ? el.style.removeProperty(property) : undefined; return el ? el.style.setProperty(property, value) : undefined; } return el ? computedStyle(el, property) : undefined; }; common.createElement = function(tag, attributes, innerHTML) { try { var el = document.createElement(tag); for (var key in attributes) { if (!attributes.hasOwnProperty(key)) continue; if (key === 'css') { common.css(el, attributes[key]); } else { common.attr(el, key, attributes[key]); } } el.innerHTML = innerHTML || ''; return el; } catch (e) { if (!$) throw e; return $('<' + tag + '>' + innerHTML + '</' + tag + '>').attr(attributes)[0]; } }; common.toggleClass = function(el, cls, flag) { if (!el) return; var classes = ClassList(el); if (typeof flag === 'undefined') classes.toggle(cls); else if (flag) classes.add(cls); else if (!flag) classes.remove(cls); }; common.addClass = function(el, cls) { return common.toggleClass(el, cls, true); }; common.removeClass = function(el, cls) { return common.toggleClass(el, cls, false); }; common.append = function(par, child) { par.appendChild(child); return par; }; common.appendTo = function(child, par) { common.append(par, child); return child; }; common.prepend = function(par, child) { par.insertBefore(child, par.firstChild); }; // Inserts `el` after `child` that is child of `par` common.insertAfter = function(par, child, el) { if (child == common.lastChild(par)) par.appendChild(el); var childIndex = Array.prototype.indexOf.call(par.children, child); par.insertBefore(el, par.children[childIndex + 1]); }; common.html = function(elms, val) { elms = elms.length ? elms : [elms]; elms.forEach(function(elm) { elm.innerHTML = val; }); }; common.attr = function(el, key, val) { if (key === 'class') key = 'className'; if (common.hasOwnOrPrototypeProperty(el, key)) { try { el[key] = val; } catch (e) { // Most likely IE not letting set property if ($) { $(el).attr(key, val); } else { throw e; } } } else { if (val === false) { el.removeAttribute(key); } else { el.setAttribute(key, val); } } return el; }; common.prop = function(el, key, val) { if (typeof val === 'undefined') { return el && el[key]; } el[key] = val; }; common.offset = function(el) { var ret = el.getBoundingClientRect(); if (el.offsetWidth / el.offsetHeight > el.clientWidth / el.clientHeight) { // https://github.com/flowplayer/flowplayer/issues/757 ret = { left: ret.left * 100, right: ret.right * 100, top: ret.top * 100, bottom: ret.bottom * 100, width: ret.width * 100, height: ret.height * 100 }; } return ret; }; common.width = function(el, val) { /*jshint -W093 */ if (val) return el.style.width = (''+val).replace(/px$/, '') + 'px'; var ret = common.offset(el).width; return typeof ret === 'undefined' ? el.offsetWidth : ret; }; common.height = function(el, val) { /*jshint -W093 */ if (val) return el.style.height = (''+val).replace(/px$/, '') + 'px'; var ret = common.offset(el).height; return typeof ret === 'undefined' ? el.offsetHeight : ret; }; common.lastChild = function(el) { return el.children[el.children.length - 1]; }; common.hasParent = function(el, parentSelector) { var parent = el.parentElement; while (parent) { if (common.matches(parent, parentSelector)) return true; parent = parent.parentElement; } return false; }; common.createAbsoluteUrl = function(url) { return common.createElement('a', {href: url}).href; // This won't work on IE7 }; common.xhrGet = function(url, successCb, errorCb) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (this.readyState !== 4) return; if (this.status >= 400) return errorCb(); successCb(this.responseText); }; xhr.open('get', url, true); xhr.send(); }; common.pick = function(obj, props) { var ret = {}; props.forEach(function(prop) { if (obj.hasOwnProperty(prop)) ret[prop] = obj[prop]; }); return ret; }; common.hostname = function(host) { return punycode.toUnicode(host || window.location.hostname); }; //Hacks common.browser = { webkit: 'WebkitAppearance' in document.documentElement.style }; common.getPrototype = function(el) { /* jshint proto:true */ if (!Object.getPrototypeOf) return el.__proto__; return Object.getPrototypeOf(el); }; common.hasOwnOrPrototypeProperty = function(obj, prop) { var o = obj; while (o) { if (Object.prototype.hasOwnProperty.call(o, prop)) return true; o = common.getPrototype(o); } return false; }; // Polyfill for Element.matches // adapted from https://developer.mozilla.org/en/docs/Web/API/Element/matches common.matches = function(elem, selector) { var proto = Element.prototype, fn = proto.matches || proto.matchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector || proto.oMatchesSelector || proto.webkitMatchesSelector || function (selector) { var element = this, matches = (element.document || element.ownerDocument).querySelectorAll(selector), i = 0; while (matches[i] && matches[i] !== element) { i++; } return matches[i] ? true : false; }; return fn.call(elem, selector); }; // Polyfill for CSSStyleDeclaration // from https://github.com/shawnbot/aight (function(CSSSDProto) { function getAttribute(property) { return property.replace(/-[a-z]/g, function(bit) { return bit[1].toUpperCase(); }); } // patch CSSStyleDeclaration.prototype using IE8's methods if (typeof CSSSDProto.setAttribute !== "undefined") { CSSSDProto.setProperty = function(property, value) { return this.setAttribute(getAttribute(property), String(value) /*, important */ ); }; CSSSDProto.getPropertyValue = function(property) { return this.getAttribute(getAttribute(property)) || null; }; CSSSDProto.removeProperty = function(property) { var value = this.getPropertyValue(property); this.removeAttribute(getAttribute(property)); return value; }; } })(window.CSSStyleDeclaration.prototype); },{"class-list":33,"computed-style":34,"punycode":41}],2:[function(_dereq_,module,exports){ 'use strict'; var common = _dereq_('../common'); // movie required in opts module.exports = function embed(swf, flashvars, wmode, bgColor) { wmode = wmode || "opaque"; var id = "obj" + ("" + Math.random()).slice(2, 15), tag = '<object class="fp-engine" id="' + id+ '" name="' + id + '" ', msie = navigator.userAgent.indexOf('MSIE') > -1; tag += msie ? 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">' : ' data="' + swf + '" type="application/x-shockwave-flash">'; var opts = { width: "100%", height: "100%", allowscriptaccess: "always", wmode: wmode, quality: "high", flashvars: "", // https://github.com/flowplayer/flowplayer/issues/13#issuecomment-9369919 movie: swf + (msie ? "?" + id : ""), name: id }; if (wmode !== 'transparent') opts.bgcolor = bgColor || '#333333'; // flashvars Object.keys(flashvars).forEach(function(key) { opts.flashvars += key + "=" + flashvars[key] + "&"; }); // parameters Object.keys(opts).forEach(function(key) { tag += '<param name="' + key + '" value="'+ opts[key] +'"/>'; }); tag += "</object>"; var el = common.createElement('div', {}, tag); return common.find('object', el); }; // Flash is buggy allover if (window.attachEvent) { window.attachEvent("onbeforeunload", function() { window.__flash_savedUnloadHandler = window.__flash_unloadHandler = function() {}; }); } },{"../common":1}],3:[function(_dereq_,module,exports){ 'use strict'; var flowplayer = _dereq_('../flowplayer'), common = _dereq_('../common'), embed = _dereq_('./embed'), extend = _dereq_('extend-object'), bean = _dereq_('bean'), engineImpl; engineImpl = function flashEngine(player, root) { var conf = player.conf, loadVideo, callbackId, api; var suspended, timeouts = []; 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; }, suspendEngine: function() { suspended = true; }, resumeEngine: function() { suspended = false; }, load: function(video) { loadVideo = video; timeouts.forEach(function(t) { clearTimeout(t); }); function escapeURL(url) { return url.replace(/&amp;/g, '%26').replace(/&/g, '%26').replace(/=/g, '%3D'); } var html5Tag = common.findDirect('video', root)[0] || common.find('.fp-player > video', root)[0], url = video.src, is_absolute = isAbsolute(url); var removeTag = function() { common.removeNode(html5Tag); }; var hasSupportedSource = function(sources) { return sources.some(function(src) { return !!html5Tag.canPlayType(src.type); }); }; if (flowplayer.support.video && common.prop(html5Tag, 'autoplay') && hasSupportedSource(video.sources)) bean.one(html5Tag, 'timeupdate', removeTag); else removeTag(); // convert to absolute var rtmp = video.rtmp || conf.rtmp; if (!is_absolute && !rtmp) url = common.createAbsoluteUrl(url); if (api && isHLS(video) && api.data !== common.createAbsoluteUrl(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; }); var hlsQualities = typeof video.hlsQualities !== 'undefined' ? video.hlsQualities : conf.hlsQualities; if (typeof hlsQualities !== 'undefined') opts.hlsQualities = hlsQualities ? encodeURIComponent(JSON.stringify(hlsQualities)) : hlsQualities; // 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); player.off('quality.flashengine').on('quality.flashengine', function(ev, _api, quality) { var hlsQualities = typeof player.video.hlsQualities !== 'undefined' ? player.video.hlsQualities : player.conf.hlsQualities; if (!hlsQualities) return; api.__quality(quality); }); // 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 // timeouts.push(setTimeout(function() { if (typeof api.PercentLoaded === 'undefined') { player.trigger('flashdisabled', [player]); } }, 15000)); timeouts.push(setTimeout(function() { if (typeof api.PercentLoaded === 'undefined') { player.trigger('flashdisabled', [player, false]); } }, 500)); player.off('resume.flashhack').on('resume.flashhack', function() { var timer = setTimeout(function() { var currentTime = api.__status().time; var timer2 = setTimeout(function() { if (player.playing && !player.loading && api.__status().time === currentTime) { player.trigger('flashdisabled', [player]); } }, 400); timeouts.push(timer2); player.one('seek.flashhack pause.flashhack load.flashack', function() { clearTimeout(timer2); }); }, 800); timeouts.push(timer); player.one('progress', function() { clearTimeout(timer); }); }); api.pollInterval = setInterval(function () { if (!api || suspended) return; var status = api.__status ? api.__status() : null; if (!status) return; if (player.conf.live || player.live || video.live) { video.seekOffset = status.seekOffset; video.duration = status.duration + status.seekOffset; } 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; case "metadata": var str = atob(arg); arg = { key: str.substr(10, 4), data: str.substr(21) } 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'); player.off('.flashhack'); clearInterval(api.pollInterval); timeouts.forEach(function(t) { clearTimeout(t); }); } }; ['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":28,"./embed":2,"bean":31,"extend-object":36}],4:[function(_dereq_,module,exports){ 'use strict'; var flowplayer = _dereq_('../flowplayer'), bean = _dereq_('bean'), 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, inline, subtitles) { if (typeof autoplay === 'undefined') autoplay = true; if (typeof preload === 'undefined') preload = 'none'; if (typeof useCache === 'undefined') useCache = true; if (typeof inline === 'undefined') inline = 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); var className = 'fp-engine '; if (subtitles && subtitles.length) className += 'native-subtitles'; el.className = className; if (flowplayer.support.autoplay) el.autoplay = autoplay ? 'autoplay' : false; if (flowplayer.support.dataload) el.preload = preload; if (inline) { el.setAttribute('webkit-playsinline', 'true'); el.setAttribute('playsinline', 'true'); } if (subtitles && subtitles.length) { var setMode = function(mode) { var tracks = el.textTracks; if (!tracks.length) return; tracks[0].mode = mode; }; if (subtitles.some(function(st) { return !common.isSameDomain(st.src); })) common.attr(el, 'crossorigin', 'anonymous'); if (typeof el.textTracks.addEventListener === 'function') el.textTracks.addEventListener('addtrack', function() { setMode('disabled'); setMode('showing'); }); subtitles.forEach(function(st) { el.appendChild(common.createElement('track', { kind: 'subtitles', srclang: st.srclang || 'en', label: st.label || 'en', src: st.src, 'default': st['default'] })); }); } 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, conf = player.conf, self, timer, lastBuffer, 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; 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 container = common.find('.fp-player', root)[0], reload = false, created = false; if (conf.splash && !api) { api = createVideoTag( video, undefined, undefined, undefined, !conf.disableInline, flowplayer.support.subtitles && conf.nativesubtitles && video.subtitles ); common.prepend(container, api); created = true; } else if (!api) { api = createVideoTag(video, !!video.autoplay || !!conf.autoplay, conf.clip.preload || true, false); common.prepend(container, api); created = true; } else { common.addClass(api, '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', false); player.off('.loophack'); if (video.loop || conf.loop) { if (/mpegurl/i.test(video.type)) { player.on('finish.loophack', function() { player.resume(); }); } else common.prop(api, 'loop', true); } 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) || self._listeners; if (reload || (created && !conf.splash)) api.load(); if (support.iOS.iPad && support.iOS.chrome) api.load(); if (api.paused && (video.autoplay || conf.autoplay || conf.splash)) 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(function (videoTag) { common.attr(videoTag, 'src', ''); common.removeNode(videoTag); }); 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); bean.off(api, '.dvrhack'); player.off('.loophack'); }); var eventListeners = {}; //Special event handling for HLS metadata events var listenMetadata = function(track) { if (track.kind !== 'metadata') return; track.mode = 'hidden'; track.addEventListener('cuechange', function() { player.trigger('metadata', [player, track.activeCues[0].value]); }, false); }; if (api && api.textTracks && api.textTracks.length) Array.prototype.forEach.call(api.textTracks, listenMetadata); if (api && api.textTracks && typeof api.textTracks.addEventListener === 'function') api.textTracks.addEventListener('addtrack', function(tev) { listenMetadata(tev.track); }, false); if (player.conf.dvr || player.dvr || video.dvr) { bean.on(api, 'progress.dvrhack', function() { if (!api.seekable.length) return; player.video.duration = api.seekable.end(null); player.video.seekOffset = api.seekable.start(null); player.trigger('dvrwindow', [player, { start: api.seekable.start(null), end: api.seekable.end(null) }]); if (api.currentTime >= api.seekable.start(null)) return; api.currentTime = api.seekable.start(null); }); } Object.keys(EVENTS).forEach(function(type) { var flow = EVENTS[type]; if (type === 'webkitendfullscreen' && player.conf.disableInline) flow = 'unload'; if (!flow) return; var l = function(e) { video = api.listeners[instanceId]; if (!e.target || !common.hasClass(e.target, 'fp-engine')) return; if (conf.debug && !/progress/.test(flow)) console.log(type, "->", flow, e); var triggerEvent = function() { player.trigger(flow, [player, arg]); }; // no events if player not ready if (!player.ready && !/ready|error/.test(flow) || !flow || !common.find('video', root).length) { if (flow === 'resume') player.one('ready', function() { setTimeout(function() { triggerEvent(); }) }); return; } var arg; if (flow === 'unload') { //Call player unload player.unload(); return; } switch (flow) { case "ready": arg = extend(video, { duration: api.duration < Number.MAX_VALUE ? api.duration : 0, width: api.videoWidth, height: api.videoHeight, url: api.currentSrc, src: api.currentSrc }); try { arg.seekable = /mpegurl/i.test(video ? (video.type || '') : '') && api.duration || api.seekable && api.seekable.end(null) || player.live; } 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 && arg.buffer !== lastBuffer) { player.trigger("buffer", [player, arg.buffer]); lastBuffer = arg.buffer; } else if (!arg.buffered && arg.buffer !== lastBuffer) { arg.buffered = true; player.trigger("buffer", [player, arg.buffer]).trigger("buffered", e); lastBuffer = arg.buffer; 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); common.toggleClass(root, 'is-live', false); }; 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; common.addClass(root, 'is-live'); // Make UI believe it's live triggerEvent(); } api.removeEventListener('timeupdate', timeUpdated); }; api.addEventListener('timeupdate', timeUpdated); return; } break; case "progress": case "seek": 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":28,"bean":31,"extend-object":36}],5:[function(_dereq_,module,exports){ 'use strict'; var flowplayer = _dereq_('../flowplayer') , common = _dereq_('../common') , bean = _dereq_('bean'); flowplayer(function(api, root) { api.on('ready', function() { var el = common.find('video.fp-engine', root)[0]; if (!el) return; el.setAttribute('x-webkit-airplay', 'allow'); if (!window.WebKitPlaybackTargetAvailabilityEvent) return; el.addEventListener('webkitplaybacktargetavailabilitychanged', function(ev) { if (ev.availability !== 'available') return; var btnContainer = common.find('.fp-header', root)[0]; common.find('.fp-airplay', btnContainer).forEach(common.removeNode); var trigger = common.createElement('a', { 'class': 'fp-airplay fp-icon', title: 'Play on AirPlay device'}) btnContainer.insertBefore(trigger, common.find('.fp-fullscreen', btnContainer)[0]); }); el.addEventListener('webkitcurrentplaybacktargetiswirelesschanged', function() { var trigger = common.find('.fp-airplay', root)[0]; if (!trigger) return; common.toggleClass(trigger, 'fp-active', el.webkitCurrentPlaybackTargetIsWireless); }); }); bean.on(root, 'click', '.fp-airplay', function(ev) { ev.preventDefault(); var video = common.find('video.fp-engine', root)[0]; video.webkitShowPlaybackTargetPicker(); }); }); },{"../common":1,"../flowplayer":28,"bean":31}],6:[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":28,"./resolve":19,"bean":31,"scriptjs":42}],7:[function(_dereq_,module,exports){ /* global chrome */ /* eslint-disable no-console */ 'use strict'; var flowplayer = _dereq_('../flowplayer') , common = _dereq_('../common') , bean = _dereq_('bean') , scriptjs = _dereq_('scriptjs'); flowplayer(function(api, root) { if (api.conf.chromecast === false) return; scriptjs('https://www.gstatic.com/cv/js/sender/v1/cast_sender.js'); window['__onGCastApiAvailable'] = function(loaded) { if (!loaded) return; initialize(); }; var conf = api.conf.chromecast || {} , session , timer , trigger; function initialize() { var applicationId, sessionRequest, apiConfig; applicationId = conf.applicationId || chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID; sessionRequest = new chrome.cast.SessionRequest(applicationId); apiConfig = new chrome.cast.ApiConfig( sessionRequest, sessionListener, receiverListener ); chrome.cast.initialize(apiConfig, onInitSuccess, onError); } function sessionListener() { console.log('sessionListener'); } function receiverListener(ev) { if (ev !== chrome.cast.ReceiverAvailability.AVAILABLE) return; createUIElements(); } function onInitSuccess() { /* noop */ } function onError() { console.log('onError'); } function createUIElements() { var btnContainer = common.find('.fp-header', root)[0]; common.find('.fp-chromecast', btnContainer).forEach(common.removeNode); common.find('.fp-chromecast-engine', root).forEach(common.removeNode); trigger = common.createElement('a', { 'class': 'fp-chromecast fp-icon', title: 'Play on Cast device'}) btnContainer.insertBefore(trigger, common.find('.