diff --git a/ajax/libs/flowplayer/5.4.5/embed.min.js b/ajax/libs/flowplayer/5.4.5/embed.min.js new file mode 100644 index 000000000..e833b4903 --- /dev/null +++ b/ajax/libs/flowplayer/5.4.5/embed.min.js @@ -0,0 +1 @@ +!function(){function e(e,t,n){if(e)return n(e);if(window.fp5ecc[t])return window.fp5ecc[t].push(n);window.fp5ecc[t]=[n];var r=document.createElement("script");r.onload=r.onreadystatechange=function(){var e=r.readyState;if(void 0===e||/complete|loaded/.test(e))for(var n=window.fp5ecc[t],i=0;i=1&&Number(w[1])>=7,u,function(r){var o;!r&&m&&(o=jQuery.noConflict());var a=!r&&""!==p;e("undefined"!=typeof _gat,l,function(){e("undefined"!=typeof flowplayer,f,function(e){e||t(s),o=o||jQuery;var r=o(n),c=r.attr("src"),l=o(r.html().replace(/^[ \t\n\r]+/gm,"").replace(/[ \n\t\r]+$/gm,""));o(i).replaceWith(l),l.find(":not(video, source)").remove(),l.flowplayer({swf:d,e:1}),l.data("flowplayer").conf.embed={library:f,swf:d,script:c},a&&o.noConflict(!0)})})})}(); \ No newline at end of file diff --git a/ajax/libs/flowplayer/5.4.5/flowplayer.js b/ajax/libs/flowplayer/5.4.5/flowplayer.js new file mode 100644 index 000000000..97ae65781 --- /dev/null +++ b/ajax/libs/flowplayer/5.4.5/flowplayer.js @@ -0,0 +1,2581 @@ +/*! + + Flowplayer v5.4.5 (Tuesday, 17. December 2013 08:34AM) | flowplayer.org/license + +*/ +!function($) { + +/* + jQuery.browser for 1.9+ + + We all love feature detection but that's sometimes not enough. + + @author Tero Piirainen +*/ +!function($) { + + if (!$.browser) { + + var b = $.browser = {}, + 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"; + } + + } + +}(jQuery); +// auto-install (any video tag with parent .flowplayer) +$(function() { + if (typeof $.fn.flowplayer == 'function') { + $("video").parent(".flowplayer").flowplayer(); + } +}); + +var instances = [], + extensions = [], + UA = window.navigator.userAgent; + + +/* flowplayer() */ +window.flowplayer = function(fn) { + return $.isFunction(fn) ? extensions.push(fn) : + typeof fn == 'number' || fn === undefined ? instances[fn || 0] : + $(fn).data("flowplayer"); +}; + +$(window).on('beforeunload', function() { + $.each(instances, function(i, api) { + if (api.conf.splash) { + api.unload(); + } else { + api.bind("error", function () { + $(".flowplayer.is-error .fp-message").remove(); + }); + } + }); +}); + +var supportLocalStorage = false; +try { + if (typeof window.localStorage == "object") { + window.localStorage.flowplayerTestStorage = "test"; + supportLocalStorage = true; + } +} catch (ignored) {} + +$.extend(flowplayer, { + + version: '5.4.5', + + engine: {}, + + conf: {}, + + support: {}, + + defaults: { + + debug: false, + + // true = forced playback + disabled: false, + + // first engine to try + engine: 'html5', + + fullscreen: window == window.top, + + // keyboard shortcuts + keyboard: true, + + // default aspect ratio + ratio: 9 / 16, + + adaptiveRatio: false, + + // scale flash object to video's aspect ratio in normal mode? + flashfit: false, + + rtmp: 0, + + splash: false, + + live: false, + + swf: "//releases.flowplayer.org/5.4.5/flowplayer.swf", + + speeds: [0.25, 0.5, 1, 1.5, 2], + + tooltip: true, + + // 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: [] + + } + +}); + +// keep track of players +var playerCount = 1; + +// jQuery plugin +$.fn.flowplayer = function(opts, callback) { + + if (typeof opts == 'string') opts = { swf: opts } + if ($.isFunction(opts)) { callback = opts; opts = {} } + + return !opts && this.data("flowplayer") || this.each(function() { + + // private variables + var root = $(this).addClass("is-loading"), + conf = $.extend({}, flowplayer.defaults, flowplayer.conf, opts, root.data()), + videoTag = $("video", root).addClass("fp-engine").removeAttr("controls"), + urlResolver = videoTag.length ? new URLResolver(videoTag) : null, + storage = {}, + lastSeekPosition, + engine; + + if (conf.playlist.length) { // Create initial video tag if called without + var preload = videoTag.attr('preload'), placeHolder; + if (videoTag.length) videoTag.replaceWith(placeHolder = $('

')); + videoTag = $('

")[0]; + + for (var i = 0; i < vendors.length; i++) { + if (el.style[vendors[i] + 'AnimationName'] !== 'undefined') return true; + } + })(); + + + +}(); + + +/* The most minimal Flash embedding */ + +// movie required in opts +function embed(swf, flashvars) { + + var id = "obj" + ("" + Math.random()).slice(2, 15), + tag = '' : + ' data="' + swf + '" type="application/x-shockwave-flash">'; + + var opts = { + width: "100%", + height: "100%", + allowscriptaccess: "always", + wmode: "transparent", + quality: "high", + flashvars: "", + + // https://github.com/flowplayer/flowplayer/issues/13#issuecomment-9369919 + movie: swf + ($.browser.msie ? "?" + id : ""), + name: id + }; + + // flashvars + $.each(flashvars, function(key, value) { + opts.flashvars += key + "=" + value + "&"; + }); + + // parameters + $.each(opts, function(key, value) { + tag += ''; + }); + + tag += ""; + + return $(tag); +} + + +// Flash is buggy allover +if (window.attachEvent) { + window.attachEvent("onbeforeunload", function() { + __flash_savedUnloadHandler = __flash_unloadHandler = function() {}; + }); +} + + +flowplayer.engine.flash = function(player, root) { + + var conf = player.conf, + video = player.video, + callbackId, + objectTag, + api; + + var engine = { + + pick: function(sources) { + + if (flowplayer.support.flashVideo) { + + // always pick video/flash first + var flash = $.grep(sources, function(source) { return source.type == 'flash'; })[0]; + if (flash) return flash; + + for (var i = 0, source; i < sources.length; i++) { + source = sources[i]; + if (/mp4|flv/.test(source.type)) return source; + } + } + }, + + load: function(video) { + + function escapeURL(url) { + return url.replace(/&/g, '%26').replace(/&/g, '%26').replace(/=/g, '%3D'); + } + + var html5Tag = $("video", root), + url = escapeURL(video.src); + is_absolute = /^https?:/.test(url); + + // html5 tag not needed (pause needed for firefox) + try { + if (html5Tag.length > 0 && flowplayer.support.video) html5Tag[0].pause(); + } catch (e) { + // Omit errors on calling pause(), see https://github.com/flowplayer/flowplayer/issues/490 + } + var removeTag = function() { + html5Tag.remove(); + }; + var hasSupportedSource = function(sources) { + return $.grep(sources, function(src) { + return !!html5Tag[0].canPlayType('video/' + src.type); + }).length > 0; + }; + if (flowplayer.support.video && + html5Tag.prop('autoplay') && + hasSupportedSource(video.sources)) html5Tag.one('timeupdate', removeTag); + else removeTag(); + + // convert to absolute + if (!is_absolute && !conf.rtmp) url = $("").attr("src", url)[0].src; + + if (api) { + api.__play(url); + + } else { + + callbackId = "fp" + ("" + Math.random()).slice(3, 15); + + var opts = { + hostname: conf.embedded ? conf.hostname : location.hostname, + url: url, + callback: "jQuery."+ callbackId + }; + if (root.data("origin")) { + opts.origin = root.data("origin"); + } + + if (is_absolute) delete conf.rtmp; + + // optional conf + $.each(['key', 'autoplay', 'preload', 'rtmp', 'loop', 'debug', 'preload', 'splash', 'bufferTime'], function(i, key) { + if (conf[key]) opts[key] = conf[key]; + }); + + // issue #376 + if (opts.rtmp) { + opts.rtmp = escapeURL(opts.rtmp); + } + + objectTag = embed(conf.swf, opts); + + objectTag.prependTo(root); + + api = objectTag[0]; + + // throw error if no loading occurs + setTimeout(function() { + try { + if (!api.PercentLoaded()) { + return root.trigger("error", [player, { code: 7, url: conf.swf }]); + } + } catch (e) {} + }, 5000); + + // detect disabled flash + setTimeout(function() { + if (typeof api.PercentLoaded === 'undefined') { + root.trigger('flashdisabled', [player]); + } + }, 1000); + + // listen + $[callbackId] = function(type, arg) { + + if (conf.debug && type != "status") console.log("--", type, arg); + + var event = $.Event(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", 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 != 'buffered') { + // add some delay so that player is truly ready after an event + setTimeout(function() { player.trigger(event, arg); }, 1) + } + + }; + + } + + }, + + // not supported yet + speed: $.noop, + + + unload: function() { + api && api.__unload && api.__unload(); + delete $[callbackId]; + $("object", root).remove(); + api = 0; + } + + }; + + $.each("pause,resume,seek,volume".split(","), function(i, name) { + + engine[name] = function(arg) { + try { + if (player.ready) { + + if (name == 'seek' && player.video.time && !player.paused) { + player.trigger("beforeseek"); + } + + if (arg === undefined) { + api["__" + name](); + + } else { + api["__" + name](arg); + } + + } + } catch (e) { + if (typeof api["__" + name] === 'undefined') { //flash lost it's methods + return root.trigger('flashdisabled', [player]); + } + throw e; + } + }; + + }); + + var win = $(window); + + // handle Flash object aspect ratio + player.bind("ready fullscreen fullscreen-exit", function(e) { + var origH = root.height(), + origW = root.width(); + if (player.conf.flashfit || /full/.test(e.type)) { + + var fs = player.isFullscreen, + truefs = fs && FS_SUPPORT, + ie7 = !flowplayer.support.inlineBlock, + screenW = fs ? (truefs ? screen.width : win.width()) : origW, + screenH = fs ? (truefs ? screen.height : win.height()) : origH, + + // default values for fullscreen-exit without flashfit + hmargin = 0, + vmargin = 0, + objwidth = ie7 ? origW : '', + objheight = ie7 ? origH : '', + + aspectratio, dataratio; + + if (player.conf.flashfit || e.type === "fullscreen") { + aspectratio = player.video.width / player.video.height, + dataratio = player.video.height / player.video.width, + objheight = Math.max(dataratio * screenW), + objwidth = Math.max(aspectratio * screenH); + objheight = objheight > screenH ? objwidth * dataratio : objheight; + objheight = Math.min(Math.round(objheight), screenH); + objwidth = objwidth > screenW ? objheight * aspectratio : objwidth; + objwidth = Math.min(Math.round(objwidth), screenW); + vmargin = Math.max(Math.round((screenH + vmargin - objheight) / 2), 0); + hmargin = Math.max(Math.round((screenW + hmargin - objwidth) / 2), 0); + } + + $("object", root).css({ + width: objwidth, + height: objheight, + marginTop: vmargin, + marginLeft: hmargin + }); + } + }); + + return engine; + +}; + + +var VIDEO = $('

\ +
\ +
\ + \ + \ +

\ +

\ + \ +
\ +
\ +
\ +
\ +
\ + \ +
\ +
\ +
\ +
\ +
\ +
\ + 00:00\ + \ + 00:00\ +
\ +

\ +
'.replace(/class="/g, 'class="fp-') + ); + + function find(klass) { + return $(".fp-" + klass, root); + } + + // widgets + var progress = find("progress"), + buffer = find("buffer"), + elapsed = find("elapsed"), + remaining = find("remaining"), + waiting = find("waiting"), + ratio = find("ratio"), + speed = find("speed"), + durationEl = find("duration"), + origRatio = ratio.css("paddingTop"), + + // sliders + timeline = find("timeline").slider2(api.rtl), + timelineApi = timeline.data("api"), + + volume = find("volume"), + fullscreen = find("fullscreen"), + volumeSlider = find("volumeslider").slider2(api.rtl), + volumeApi = volumeSlider.data("api"), + noToggle = root.is(".fixed-controls, .no-toggle"); + + timelineApi.disableAnimation(root.hasClass('is-touch')); + + // aspect ratio + function setRatio(val) { + if ((root.css('width') === '0px' || root.css('height') === '0px') || val !== flowplayer.defaults.ratio) { + if (!parseInt(origRatio, 10)) ratio.css("paddingTop", val * 100 + "%"); + } + if (!support.inlineBlock) $("object", root).height(root.height()); + } + + function hover(flag) { + root.toggleClass("is-mouseover", flag).toggleClass("is-mouseout", !flag); + } + + // loading... + if (!support.animation) waiting.html("

loading …

"); + + setRatio(conf.ratio); + + // no fullscreen in IFRAME + try { + if (!conf.fullscreen) fullscreen.remove(); + + } catch (e) { + fullscreen.remove(); + } + + + api.bind("ready", function() { + + var duration = api.video.duration; + + timelineApi.disable(api.disabled || !duration); + + conf.adaptiveRatio && setRatio(api.video.height / api.video.width); + + // initial time & volume + durationEl.add(remaining).html(format(duration)); + + // do we need additional space for showing hour + ((duration >= 3600) && root.addClass('is-long')) || root.removeClass('is-long'); + volumeApi.slide(api.volumeLevel); + + + }).bind("unload", function() { + if (!origRatio) ratio.css("paddingTop", ""); + + // buffer + }).bind("buffer", function() { + var video = api.video, + max = video.buffer / video.duration; + + if (!video.seekable && support.seekable) timelineApi.max(max); + if (max < 1) buffer.css("width", (max * 100) + "%"); + else buffer.css({ width: '100%' }); + + }).bind("speed", function(e, api, val) { + speed.text(val + "x").addClass("fp-hilite"); + setTimeout(function() { speed.removeClass("fp-hilite") }, 1000); + + }).bind("buffered", function() { + buffer.css({ width: '100%' }); + timelineApi.max(1); + + // progress + }).bind("progress", function() { + + var time = api.video.time, + duration = api.video.duration; + + if (!timelineApi.dragging) { + timelineApi.slide(time / duration, api.seeking ? 0 : 250); + } + + elapsed.html(format(time)); + remaining.html("-" + format(duration - time)); + + }).bind("finish resume seek", function(e) { + root.toggleClass("is-finished", e.type == "finish"); + + }).bind("stop", function() { + elapsed.html(format(0)); + timelineApi.slide(0, 100); + + }).bind("finish", function() { + elapsed.html(format(api.video.duration)); + timelineApi.slide(1, 100); + root.removeClass("is-seeking"); + + // misc + }).bind("beforeseek", function() { + progress.stop(); + + }).bind("volume", function() { + volumeApi.slide(api.volumeLevel); + + + }).bind("disable", function() { + var flag = api.disabled; + timelineApi.disable(flag); + volumeApi.disable(flag); + root.toggleClass("is-disabled", api.disabled); + + }).bind("mute", function(e, api, flag) { + root.toggleClass("is-muted", flag); + + }).bind("error", function(e, api, error) { + root.removeClass("is-loading").addClass("is-error"); + + if (error) { + error.message = conf.errors[error.code]; + api.error = true; + + var el = $(".fp-message", root); + $("h2", el).text((api.engine || 'html5') + ": " + error.message); + $("p", el).text(error.url || api.video.url || api.video.src || conf.errorUrls[error.code]); + root.unbind("mouseenter click").removeClass("is-mouseover"); + } + + + // hover + }).bind("mouseenter mouseleave", function(e) { + if (noToggle) return; + + var is_over = e.type == "mouseenter", + lastMove; + + // is-mouseover/out + hover(is_over); + + if (is_over) { + + root.bind("pause.x mousemove.x volume.x", function() { + hover(true); + lastMove = new Date; + }); + + hovertimer = setInterval(function() { + if (new Date - lastMove > 5000) { + hover(false) + lastMove = new Date; + } + }, 100); + + } else { + root.unbind(".x"); + clearInterval(hovertimer); + } + + + // allow dragging over the player edge + }).bind("mouseleave", function() { + + if (timelineApi.dragging || volumeApi.dragging) { + root.addClass("is-mouseover").removeClass("is-mouseout"); + } + + // click + }).bind("click.player", function(e) { + if ($(e.target).is(".fp-ui, .fp-engine") || e.flash) { + e.preventDefault(); + return api.toggle(); + } + }).bind('contextmenu', function(ev) { + ev.preventDefault(); + var o = root.offset(), + w = $(window), + left = ev.clientX - o.left, + t = ev.clientY - o.top + w.scrollTop(); + var menu = root.find('.fp-context-menu').css({ + left: left + 'px', + top: t + 'px', + display: 'block' + }).on('click', function(ev) { + ev.stopPropagation(); + }); + $('html').on('click.outsidemenu', function(ev) { + menu.hide(); + $('html').off('click.outsidemenu'); + }); + }).bind('flashdisabled', function() { + root.addClass('is-flash-disabled').one('ready', function() { + root.removeClass('is-flash-disabled').find('.fp-flash-disabled').remove(); + }).append('
Adobe Flash is disabled for this page, click player area to enable.
'); + }); + + // poster -> background image + if (conf.poster) root.css("backgroundImage", "url(" + conf.poster + ")"); + + var bc = root.css("backgroundColor"), + has_bg = root.css("backgroundImage") != "none" || bc && bc != "rgba(0, 0, 0, 0)" && bc != "transparent"; + + // is-poster class + if (has_bg && !conf.splash && !conf.autoplay) { + + api.bind("ready stop", function() { + root.addClass("is-poster").one("progress", function() { + root.removeClass("is-poster"); + }); + }); + + } + + // default background color if not present + if (!has_bg && api.forcedSplash) { + root.css("backgroundColor", "#555"); + } + + $(".fp-toggle, .fp-play", root).click(api.toggle); + + /* controlbar elements */ + $.each(['mute', 'fullscreen', 'unload'], function(i, key) { + find(key).click(function() { + api[key](); + }); + }); + + timeline.bind("slide", function(e, val) { + api.seeking = true; + api.seek(val * api.video.duration); + }); + + volumeSlider.bind("slide", function(e, val) { + api.volume(val); + }); + + // times + find("time").click(function(e) { + $(this).toggleClass("is-inverted"); + }); + + hover(noToggle); + +}); + +var focused, + focusedRoot, + IS_HELP = "is-help"; + + // keyboard. single global listener +$(document).bind("keydown.fp", function(e) { + + var el = focused, + metaKeyPressed = e.ctrlKey || e.metaKey || e.altKey, + key = e.which, + conf = el && el.conf; + + if (!el || !conf.keyboard || el.disabled) return; + + // help dialog (shift key not truly required) + if ($.inArray(key, [63, 187, 191]) != -1) { + focusedRoot.toggleClass(IS_HELP); + return false; + } + + // close help / unload + if (key == 27 && focusedRoot.hasClass(IS_HELP)) { + focusedRoot.toggleClass(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: 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 + root.bind("mouseenter mouseleave", function(e) { + focused = !api.disabled && e.type == 'mouseenter' ? api : 0; + if (focused) focusedRoot = root; + }); + + // TODO: add to player-layout.html + root.append('\ +
\ + \ +
\ +

spaceplay / pause

\ +

qunload | stop

\ +

ffullscreen

\ +

shift + slower / faster (latest Chrome and Safari)

\ +
\ +
\ +

volume

\ +

mmute

\ +
\ +
\ +

seek

\ +

 . seek to previous\ +

126 seek to 10%, 20%, …60%

\ +
\ +
\ + '); + + if (api.conf.tooltip) { + $(".fp-ui", root).attr("title", "Hit ? for help").on("mouseout.tip", function() { + $(this).removeAttr("title").off("mouseout.tip"); + }); + } + + $(".fp-close", root).click(function() { + root.toggleClass(IS_HELP); + }); + +}); + +var VENDOR = $.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 +$(document).bind(FS_NATIVE_SUPPORT ? "fullscreenchange" : VENDOR + "fullscreenchange", function(e) { + var el = $(document.webkitCurrentFullScreenElement || document.mozFullScreenElement || document.fullscreenElement || e.target); + if (el.length && !FULL_PLAYER) { + FULL_PLAYER = el.trigger(FS_ENTER, [el]); + } else { + FULL_PLAYER.trigger(FS_EXIT, [FULL_PLAYER]); + FULL_PLAYER = null; + } + +}); + + +flowplayer(function(player, root) { + + if (!player.conf.fullscreen) return; + + var win = $(window), + fsResume = {index: 0, pos: 0, play: false}, + scrollTop; + + player.isFullscreen = false; + + player.fullscreen = function(flag) { + + if (player.disabled) return; + + if (flag === undefined) flag = !player.isFullscreen; + + if (flag) scrollTop = win.scrollTop(); + + if ((VENDOR == "webkit" || IS_SAFARI) && player.engine == "flash") { + // play current index on fullscreen toggle + fsResume.index = player.video.index; + if (player.conf.rtmp) + // avoid restart + $.extend(fsResume, {pos: player.video.time, play: player.playing}); + } + + if (FS_SUPPORT) { + + if (flag) { + if (FS_NATIVE_SUPPORT) { + root[0].requestFullscreen(); + } else { + root[0][VENDOR + 'RequestFullScreen'](Element.ALLOW_KEYBOARD_INPUT); + if (IS_SAFARI && !document.webkitCurrentFullScreenElement && !document.mozFullScreenElement) { // Element.ALLOW_KEYBOARD_INPUT not allowed + root[0][VENDOR + 'RequestFullScreen'](); + } + } + + } else { + if (FS_NATIVE_SUPPORT) { + document.exitFullscreen(); + } else { + document[VENDOR + 'CancelFullScreen'](); + } + } + + } else { + player.trigger(flag ? FS_ENTER : FS_EXIT, [player]); + } + + return player; + }; + + var lastClick; + + root.bind("mousedown.fs", function() { + if (+new Date - lastClick < 150 && player.ready) player.fullscreen(); + lastClick = +new Date; + }); + + player.bind(FS_ENTER, function(e) { + root.addClass("is-fullscreen"); + player.isFullscreen = true; + + }).bind(FS_EXIT, function(e) { + var oldOpacity; + if (!FS_SUPPORT && player.engine === "html5") { + oldOpacity = root.css('opacity') || ''; + root.css('opacity', 0); + } + root.removeClass("is-fullscreen"); + if (!FS_SUPPORT && player.engine === "html5") setTimeout(function() { root.css('opacity', oldOpacity); }); + player.isFullscreen = false; + win.scrollTop(scrollTop); + + }).bind("ready", function () { + if (fsResume.index > 0) { + player.play(fsResume.index); + // above loads "different" clip, resume position below + fsResume.index = 0; + } else if (fsResume.pos && !isNaN(fsResume.pos)) { + var fsreset = function () { + if (!fsResume.play) + player.pause(); + $.extend(fsResume, {pos: 0, play: false}); + }; + + if (player.conf.live) { + player.resume(); + fsreset(); + } else { + player.resume().seek(fsResume.pos, fsreset); + } + } + }); + +}); + + +flowplayer(function(player, root) { + + var conf = $.extend({ active: 'is-active', advance: true, query: ".fp-playlist a" }, player.conf), + klass = conf.active; + + // getters + function els() { + return $(conf.query, root); + } + + function active() { + return $(conf.query + "." + klass, root); + } + + + 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') player.load.apply(null, arguments); + player.unbind('resume.fromfirst'); // Don't start from beginning if clip explicitely chosen + player.video.index = i; + player.load(typeof player.conf.playlist[i] === 'string' ? + player.conf.playlist[i].toString() : + $.map(player.conf.playlist[i], function(item) { return $.extend({}, item); }) + ); + return player; + }; + + player.next = function(e) { + 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) { + 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; + }; + + $('.fp-next', root).click(player.next); + $('.fp-prev', root).click(player.prev); + + if (conf.advance) { + root.unbind("finish.pl").bind("finish.pl", function(e, player) { + + // next clip is found or loop + var next = player.video.index + 1; + if (next < player.conf.playlist.length || conf.loop) { + next = next === player.conf.playlist.length ? 0 : next; + root.removeClass('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 { + root.addClass("is-playing"); // show play button + + // 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; + }); + } + }); + } + + var playlistInitialized = false; + if (player.conf.playlist.length) { // playlist configured by javascript, generate playlist + playlistInitialized = true; + var plEl = root.find('.fp-playlist'); + if (!plEl.length) { + plEl = $('
'); + var cntrls = $('.fp-next,.fp-prev', root); + if (!cntrls.length) $('video', root).after(plEl); + else cntrls.eq(0).before(plEl); + } + plEl.empty(); + $.each(player.conf.playlist, function(i, item) { + var href; + if (typeof item === 'string') { + href = item; + } else { + for (var key in item[0]) { + if (item[0].hasOwnProperty(key)) { + href = item[0][key]; + break; + } + } + } + plEl.append($('').attr({ + href: href, + 'data-index': i + })); + }); + } + + if (els().length) { + if (!playlistInitialized) { + player.conf.playlist = []; + els().each(function() { + var src = $(this).attr('href'); + $(this).attr('data-index', player.conf.playlist.length); + player.conf.playlist.push(src); + }); + } + + /* click -> play */ + root.on("click", conf.query, function(e) { + e.preventDefault(); + var el = $(e.target).closest(conf.query); + var toPlay = Number(el.attr('data-index')); + if (toPlay != -1) { + player.play(toPlay); + } + }); + + // playlist wide cuepoint support + var has_cuepoints = els().filter("[data-cuepoints]").length; + + // highlight + player.bind("load", function(e, api, video) { + var prev = active().removeClass(klass), + prevIndex = prev.attr('data-index'), + index = video.index = player.video.index || 0, + el = $('a[data-index="' + index + '"]', root).addClass(klass), + is_last = index == player.conf.playlist.length - 1; + // index + root.removeClass("video" + prevIndex).addClass("video" + index).toggleClass("last-video", is_last); + + // video properties + video.index = api.video.index = index; + video.is_last = api.video.is_last = is_last; + + // cuepoints + if (has_cuepoints) player.cuepoints = el.data("cuepoints"); + + + // without namespace callback called only once. unknown rason. + }).bind("unload.pl", function() { + active().toggleClass(klass); + + }); + + } + + if (player.conf.playlist.length) { + // disable single clip looping + player.conf.loop = false; + } + + +}); + +var CUE_RE = / ?cue\d+ ?/; + +flowplayer(function(player, root) { + + var lastTime = 0; + + player.cuepoints = player.conf.cuepoints || []; + + function setClass(index) { + root[0].className = root[0].className.replace(CUE_RE, " "); + if (index >= 0) root.addClass("cue" + index); + } + + player.bind("progress", function(e, api, time) { + + // avoid throwing multiple times + if (lastTime && time - lastTime < 0.015) return lastTime = time; + lastTime = time; + + var cues = player.cuepoints || []; + + for (var i = 0, cue; i < cues.length; i++) { + + cue = cues[i]; + if (!isNaN(cue)) cue = { time: cue }; + if (cue.time < 0) cue.time = player.video.duration + cue.time; + cue.index = i; + + // progress_interval / 2 = 0.125 + if (Math.abs(cue.time - time) < 0.125 * player.currentSpeed) { + setClass(i); + root.trigger("cuepoint", [player, cue]); + } + + } + + // no CSS class name + }).bind("unload seek", setClass); + + if (player.conf.generate_cuepoints) { + + player.bind("load", function() { + + // clean up cuepoint elements of previous playlist items + $(".fp-cuepoint", root).remove(); + + }).bind("ready", function() { + + var cues = player.cuepoints || [], + duration = player.video.duration, + timeline = $(".fp-timeline", root).css("overflow", "visible"); + + $.each(cues, function(i, cue) { + + var time = cue.time || cue; + if (time < 0) time = duration + cue; + + var el = $("").addClass("fp-cuepoint fp-cuepoint" + i) + .css("left", (time / duration * 100) + "%"); + + el.appendTo(timeline).mousedown(function() { + player.seek(time); + + // preventDefault() doesn't work + return false; + }); + + }); + + }); + + } + +}); +flowplayer(function(player, root, engine) { + + var track = $("track", root), + conf = player.conf; + + if (flowplayer.support.subtitles) { + + player.subtitles = track.length && track[0].track; + + // use native when supported + if (conf.nativesubtitles && conf.engine == 'html5') return; + } + + // avoid duplicate loads + track.remove(); + + var TIMECODE_RE = /^(([0-9]{2}:)?[0-9]{2}:[0-9]{2}[,.]{1}[0-9]{3}) --\> (([0-9]{2}:)?[0-9]{2}:[0-9]{2}[,.]{1}[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(',','.')); + } + + player.subtitles = []; + + var url = track.attr("src"); + + if (!url) return; + setTimeout(function() { + $.get(url, function(txt) { + + 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 ($.trim(lines[++i]) && i < lines.length) text += "

" + lines[i] + "


"; + + // entry + entry = { + title: title, + startTime: seconds(timecode[1]), + endTime: seconds(timecode[2] || timecode[3]), + text: text + }; + + cue = { time: entry.startTime, subtitle: entry }; + + player.subtitles.push(entry); + player.cuepoints.push(cue); + player.cuepoints.push({ time: entry.endTime, subtitleEnd: title }); + + // initial cuepoint + if (entry.startTime === 0) { + player.trigger("cuepoint", cue); + } + + } + + } + + }).fail(function() { + player.trigger("error", {code: 8, url: url }); + return false; + }); + }); + var wrap = $("
").appendTo(root), + currentPoint; + + player.bind("cuepoint", function(e, api, cue) { + + if (cue.subtitle) { + currentPoint = cue.index; + wrap.html(cue.subtitle.text).addClass("fp-active"); + + } else if (cue.subtitleEnd) { + wrap.removeClass("fp-active"); + currentPoint = cue.index; + } + + }).bind("seek", function(e, api, time) { + // Clear future subtitles if seeking backwards + if (currentPoint && player.cuepoints[currentPoint] && player.cuepoints[currentPoint].time > time) { + wrap.removeClass('fp-active'); + currentPoint = null; + } + $.each(player.cuepoints || [], function(i, 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)) player.trigger("cuepoint", cue); + } // Also handle cuepoints that act as the removal trigger + else if (cue.subtitleEnd && time >= cue.time && cue.index == currentPoint + 1) player.trigger("cuepoint", cue); + }); + + }); + +}); + + + +flowplayer(function(player, root) { + + var id = player.conf.analytics, time = 0, last = 0; + + if (id) { + + // load Analytics script if needed + if (typeof _gat == 'undefined') $.getScript("//google-analytics.com/ga.js"); + + function track(e) { + + if (time && typeof _gat != 'undefined') { + var tracker = _gat._getTracker(id), + video = player.video; + + tracker._setAllowLinker(true); + + // http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html + tracker._trackEvent( + "Video / Seconds played", + player.engine + "/" + video.type, + root.attr("title") || video.src.split("/").slice(-1)[0].replace(TYPE_RE, ''), + Math.round(time / 1000) + ); + time = 0; + } + + } + + player.bind("load unload", track).bind("progress", function() { + + if (!player.seeking) { + time += last ? (+new Date - last) : 0; + last = +new Date; + } + + }).bind("pause", function() { + last = 0; + }); + + $(window).unload(track); + + } + +});var isIeMobile = /IEMobile/.test(UA); +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; + + // custom load for android + if (isAndroid) { + player.conf.videoTypePreference = "mp4"; // Android has problems with webm aspect ratio + 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; + }; + } + } + + // hide volume + if (!flowplayer.support.volume) { + root.addClass("no-volume no-mute"); + } + root.addClass("is-touch"); + root.find('.fp-timeline').data('api').disableAnimation(); + + // fake mouseover effect with click + var hasMoved = false; + root.bind('touchmove', function() { + hasMoved = true; + }).bind("touchend click", function(e) { + if (hasMoved) { //not intentional, most likely scrolling + hasMoved = false; + return; + } + + if (player.playing && !root.hasClass("is-mouseover")) { + root.addClass("is-mouseover").removeClass("is-mouseout"); + return false; + } + + if (player.paused && root.hasClass("is-mouseout") && !player.splash) { + player.toggle(); + } + + if (player.paused && isIeMobile) { // IE on WP7 need an additional api.play() call + $('video.fp-engine', root)[0].play(); + } + + }); + + // native fullscreen + if (player.conf.native_fullscreen && typeof $('", { "class": "fp-embed", title: 'Copy to your site'}).appendTo(ui), + target = $("
", { 'class': 'fp-embed-code'}) + .append("