/*! Flowplayer v5.4.6 (2014-05-12) | 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.6', 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.6/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("