diff options
author | Heckyel <heckyel@openmailbox.org> | 2017-02-10 15:14:47 -0500 |
---|---|---|
committer | Heckyel <heckyel@openmailbox.org> | 2017-02-10 15:14:47 -0500 |
commit | cbc731c581070b61e8f13960f999d09684038822 (patch) | |
tree | cd90135bf306dd4df0117e12f7a02684b6ed1bdd /librevideojs/js/cliplibrejs.dev.js | |
parent | e707968dde70de7cedf7f0ada672f59bd8db902e (diff) | |
download | librevideojs-html5-player-cbc731c581070b61e8f13960f999d09684038822.tar.lz librevideojs-html5-player-cbc731c581070b61e8f13960f999d09684038822.tar.xz librevideojs-html5-player-cbc731c581070b61e8f13960f999d09684038822.zip |
new version compatible with hotkeys
Diffstat (limited to 'librevideojs/js/cliplibrejs.dev.js')
-rw-r--r-- | librevideojs/js/cliplibrejs.dev.js | 514 |
1 files changed, 511 insertions, 3 deletions
diff --git a/librevideojs/js/cliplibrejs.dev.js b/librevideojs/js/cliplibrejs.dev.js index d779226..1361b40 100644 --- a/librevideojs/js/cliplibrejs.dev.js +++ b/librevideojs/js/cliplibrejs.dev.js @@ -6,7 +6,7 @@ * @licstart The following is the entire license notice for the * JavaScript code in this page. * - * Copyleft 2016 Jesús Eduardo + * Copyleft 2016 Jesus Eduardo * * The JavaScript code in this page is free software: you can * redistribute it and/or modify it under the terms of the GNU @@ -66,7 +66,6 @@ var librevjs = function(id, options, ready){ if (ready) { librevjs.players[id].ready(ready); } - return librevjs.players[id]; // Otherwise get element for ID @@ -6305,5 +6304,514 @@ if (document.readyState === 'complete') { // You have to wait at least once in case this script is loaded after your video in the DOM (weird behavior only with minified version) librevjs.autoSetupTimeout(1); librevjs.plugin = function(name, init){ - librevjs.Player.prototype[name] = init; +librevjs.Player.prototype[name] = init; }; +/* Selector Quality +@base: https://github.com/dominic-p/videojs-resolution-selector +================================================================================ */ +(function(_V_) { + /*********************************************************************************** + * Define some helper functions + ***********************************************************************************/ + var methods = { + /** + * Utility function for merging 2 objects recursively. It treats + * arrays like plain objects and it relies on a for...in loop which will + * break if the Object prototype is messed with. + * + * @param (object) destination The object to modify and return + * @param (object) source The object to use to overwrite the first + * object + * + * @returns (object) The modified first object is returned + */ + extend : function(destination, source){ + for (var prop in source){ + // Sanity check + if (!source.hasOwnProperty(prop)){continue;} + + // Enable recursive (deep) object extension + if (typeof source[prop] == 'object' && null !== source[prop]) { + destination[prop] = methods.extend( destination[prop] || {}, source[prop] ); + } else { + destination[prop] = source[prop]; + } + } + return destination; + }, + + /** + * In a future version, this can be made more intelligent, + * but for now, we'll just add a "p" at the end if we are passed + * numbers. + * + * @param (string) res The resolution to make a label for + * + * @returns (string) The label text string + */ + res_label : function(res){ + return (/^\d+$/.test(res)) ? res + 'p' : res; + }, + matchResolution: function(resStack, res){ + }, + + /** + * returns a dummy object that implements the basic get/set + * functionality of the Cookies library. Used in the case where + * the Cookies library is not present + */ + buildCookiesDummy: function(){ + return{ + get: function(key){ + return ""; + }, + set: function(key, val){ + return false; + } + }; + } + }; + + /*********************************************************************************** + * Setup our resolution menu items + ***********************************************************************************/ + _V_.ResolutionMenuItem = _V_.MenuItem.extend({ + + /** @constructor */ + init : function(player, options){ + + // Modify options for parent MenuItem class's init. + options.label = methods.res_label(options.res); + options.selected = (options.res.toString() === player.getCurrentRes().toString()); + + // Call the parent constructor + _V_.MenuItem.call(this, player, options); + + // Store the resolution as a call property + this.resolution = options.res; + + // Register our click handler + this.on('click', this.onClick); + + // Toggle the selected class whenever the resolution changes + player.on('changeRes', _V_.bind(this, function(){ + if (this.resolution == player.getCurrentRes()){ + this.selected(true); + } else { + this.selected(false); + } + })); + } + }); + + // Handle clicks on the menu items + _V_.ResolutionMenuItem.prototype.onClick = function(){ + var player = this.player(), + video_el = player.el().firstChild, + current_time = player.currentTime(), + is_paused = player.paused(), + button_nodes = player.controlBar.resolutionSelector.el().firstChild.children, + button_node_count = button_nodes.length; + + // Do nothing if we aren't changing resolutions + if (player.getCurrentRes() == this.resolution){return;} + + // Make sure the loadedmetadata event will fire + if ('none' == video_el.preload) {video_el.preload = 'metadata';} + + // Change the source and make sure we don't start the video over + player.src( player.availableRes[this.resolution]).one('loadedmetadata', function() { + player.currentTime(current_time); + if (!is_paused) {player.play();} + }); + + // Save the newly selected resolution in our player options property + player.currentRes = this.resolution; + + // Update the button text + while (button_node_count > 0){ + button_node_count--; + if ('librevjs-current-res' == button_nodes[button_node_count].className){ + button_nodes[button_node_count].innerHTML = methods.res_label(this.resolution); + break; + } + } + + // Update the classes to reflect the currently selected resolution + player.trigger('changeRes'); + }; + + /*********************************************************************************** + * Setup our resolution menu title item + ***********************************************************************************/ + _V_.ResolutionTitleMenuItem = _V_.MenuItem.extend({ + + init : function(player, options){ + + // Call the parent constructor + _V_.MenuItem.call(this, player, options); + + // No click handler for the menu title + this.off('click'); + } + }); + + /*********************************************************************************** + * Define our resolution selector button + ***********************************************************************************/ + _V_.ResolutionSelector = _V_.MenuButton.extend({ + + /** @constructor */ + init : function(player, options) { + + // Add our list of available resolutions to the player object + player.availableRes = options.available_res; + + // Call the parent constructor + _V_.MenuButton.call(this, player, options); + } + }); + + // Create a menu item for each available resolution + _V_.ResolutionSelector.prototype.createItems = function(){ + + var player = this.player(), + items = [], + current_res; + + // Add the menu title item + items.push( new _V_.ResolutionTitleMenuItem(player,{ + el : _V_.Component.prototype.createEl('li',{ + className : 'librevjs-menu-title librevjs-res-menu-title', + innerHTML : 'Calidad' + }) + })); + + // Add an item for each available resolution + for (current_res in player.availableRes){ + // Don't add an item for the length attribute + if ('length' == current_res) {continue;} + items.push( new _V_.ResolutionMenuItem(player,{ + res : current_res + })); + } + + // Sort the available resolutions in descending order + items.sort(function(a,b){ + if (typeof a.resolution == 'undefined'){ + return -1; + } else { + return parseInt(b.resolution) - parseInt(a.resolution); + } + }); + return items; + }; + + /*********************************************************************************** + * Register the plugin with cliplibrejs, main plugin function + ***********************************************************************************/ + _V_.plugin('resolutionSelector', function(options){ + + // Only enable the plugin on HTML5 videos + if (!this.el().firstChild.canPlayType){return;} + + var player = this, + sources = player.options().sources, + i = sources.length, + j, + found_type, + + // Override default options with those provided + settings = methods.extend({ + + default_res : '', // (string) The resolution that should be selected by default ( '480' or '480,1080,240' ) + force_types : false // (array) List of media types. If passed, we need to have source for each type in each resolution or that resolution will not be an option + + }, options || {}), + + available_res = {length : 0}, + current_res, + resolutionSelector, + + // Split default resolutions if set and valid, otherwise default to an empty array + default_resolutions = (settings.default_res && typeof settings.default_res == 'string') ? settings.default_res.split( ',' ) : [], + cookieNamespace = 'cliplibrejs.resolutionSelector', + resCookieName = cookieNamespace + '.res', + cookieRef = (typeof(Cookies) === "function") ? Cookies : methods.buildCookiesDummy(); + + // Get all of the available resoloutions + while (i > 0){ + + i--; + + // Skip sources that don't have data-res attributes + if (!sources[i]['data-res']){continue;} + current_res = sources[i]['data-res']; + if (typeof available_res[current_res] !== 'object'){ + available_res[current_res] = []; + available_res.length++; + } + available_res[current_res].push( sources[i] ); + } + + // Check for forced types + if (settings.force_types){ + // Loop through all available resoultions + for (current_res in available_res){ + // Don't count the length property as a resolution + if ('length' == current_res){continue;} + i = settings.force_types.length; + // For each resolution loop through the required types + while (i > 0){ + + i--; + + j = available_res[current_res].length; + found_types = 0; + + // For each required type loop through the available sources to check if its there + while (j > 0){ + + j--; + + if (settings.force_types[i] === available_res[current_res][j].type){ + found_types++; + } + } // End loop through current resolution sources + + if (found_types < settings.force_types.length){ + delete available_res[current_res]; + available_res.length--; + break; + } + } // End loop through required types + } // End loop through resolutions + } + + // Make sure we have at least 2 available resolutions before we add the button + if (available_res.length < 2) {return;} + + var resCookie = cookieRef.get(resCookieName) + if (resCookie) { + // rebuild the default_resolutions stack with the cookie's resolution on top + default_resolutions = [resCookie].concat(default_resolutions); + } + + // Loop through the choosen default resolutions if there were any + for (i = 0; i < default_resolutions.length; i++){ + // Set the video to start out with the first available default res + if (available_res[default_resolutions[i]]){ + player.src(available_res[default_resolutions[i]]); + player.currentRes = default_resolutions[i]; + break; + } + } + + // Helper function to get the current resolution + player.getCurrentRes = function(){ + if (typeof player.currentRes !== 'undefined'){ + return player.currentRes; + } else { + try { + return res = player.options().sources[0]['data-res']; + } catch(e) { + return ''; + } + } + }; + + // Get the started resolution + current_res = player.getCurrentRes(); + + if (current_res) {current_res = methods.res_label(current_res);} + + // Add the resolution selector button + resolutionSelector = new _V_.ResolutionSelector(player,{ + el : _V_.Component.prototype.createEl( null,{ + className : 'librevjs-res-button librevjs-menu-button librevjs-control', + innerHTML : '<div class="librevjs-control-content"><span class="librevjs-current-res">' + (current_res || 'Quality') + '</span></div>', + role : 'button', + 'aria-live' : 'polite', // let the screen reader user know that the text of the button may change + tabIndex : 0 + }), + available_res : available_res + }); + + // Attach an event to remember previous res selection via cookie + this.on('changeRes', function(){ + cookieRef.set(resCookieName, player.getCurrentRes()); + }); + + // Attach an event to update player.src once on loadedmetadata + // if a resolution was previously set + this.one('loadedmetadata', function(){ + var resCookie = cookieRef.get(resCookieName); + + if (resCookie) { + player.src(player.availableRes[resCookie]); + player.currentRes = resCookie; + player.trigger( 'changeRes' ); + } + }); + + // Add the button to the control bar object and the DOM + player.controlBar.resolutionSelector = player.controlBar.addChild( resolutionSelector ); + }); +})(cliplibrejs); + +/* Hotkeys for LibreVideoJS +@base: https://github.com/ctd1500/videojs-hotkeys +================================================================================ */ +(function(window, cliplibrejs){ + 'use strict'; + + window['cliplibrejs_hotkeys'] = {version: "0.2.4"}; + var hotkeys = function(options){ + var player = this; + var def_options = { + volumeStep: 0.1, + seekStep: 5, + enableMute: true, + enableFullscreen: true, + enableNumbers: true, + }; + options = options || {}; + + // Set default player tabindex to handle keydown and doubleclick events + if (!player.el().hasAttribute('tabIndex')){ + player.el().setAttribute('tabIndex', '-1'); + } + + player.on('play', function(){ + // Fix allowing the YouTube plugin to have hotkey support. + var ifblocker = player.el().querySelector('.iframeblocker'); + if (ifblocker && + ifblocker.style.display == ""){ + ifblocker.style.display = "block"; + ifblocker.style.bottom = "39px"; + } + }); + + var keyDown = function keyDown(event){ + var ewhich = event.which; + var volumeStep = options.volumeStep || def_options.volumeStep; + var seekStep = options.seekStep || def_options.seekStep; + var enableMute = options.enableMute || def_options.enableMute; + var enableFull = options.enableFullscreen || def_options.enableFullscreen; + var enableNumbers = options.enableNumbers || def_options.enableNumbers; + + // When controls are disabled, hotkeys will be disabled as well + if (player.controls()){ + + // Don't catch keys if any control buttons are focused + var activeEl = document.activeElement; + if (activeEl == player.el() || + activeEl == player.el().querySelector('.librevjs-tech') || + activeEl == player.el().querySelector('.librevjs-control-bar') || + activeEl == player.el().querySelector('.iframeblocker')){ + + // Spacebar toggles play/pause + if (ewhich === 32){ + event.preventDefault(); + if (this.player_.paused()){ + this.player_.play(); + } else { + this.player_.pause(); + } + } + + // Seeking with the left/right arrow keys + else if (ewhich === 37){ // Left Arrow + event.preventDefault(); + var curTime = player.currentTime() - seekStep; + + // The flash player tech will allow you to seek into negative + // numbers and break the seekbar, so try to prevent that. + if (player.currentTime() <= seekStep){ + curTime = 0; + } + player.currentTime(curTime); + } else if (ewhich === 39){ // Right Arrow + event.preventDefault(); + player.currentTime(player.currentTime() + seekStep); + } + + // Volume control with the up/down arrow keys + else if (ewhich === 40){ // Down Arrow + event.preventDefault(); + player.volume(player.volume() - volumeStep); + } else if (ewhich === 38){ // Up Arrow + event.preventDefault(); + player.volume(player.volume() + volumeStep); + } + + // Toggle Mute with the M key + else if (ewhich === 77){ + if (enableMute) { + if (player.muted()){ + player.muted(false); + } else { + player.muted(true); + } + } + } + + // Toggle Fullscreen with the F key + else if (ewhich === 70){ + if (enableFull){ + if (this.player_.isFullScreen){ + this.player_.cancelFullScreen(); + } else{ + this.player_.requestFullScreen(); + } + } + } + + // Number keys from 0-9 skip to a percentage of the video. 0 is 0% and 9 is 90% + else if ((ewhich > 47 && ewhich < 59) || (ewhich > 95 && ewhich < 106)){ + if (enableNumbers){ + var sub = 48; + if (ewhich > 95){ + sub = 96; + } + var number = ewhich - sub; + event.preventDefault(); + player.currentTime(player.duration() * number * 0.1); + } + } + } + } + }; + + var doubleClick = function doubleClick(event){ + var enableFull = options.enableFullscreen || def_options.enableFullscreen; + + // When controls are disabled, hotkeys will be disabled as well + if (player.controls()){ + + // Don't catch clicks if any control buttons are focused + var activeEl = event.relatedTarget || event.toElement || document.activeElement; + if (activeEl == player.el() || + activeEl == player.el().querySelector('.librevjs-tech') || + activeEl == player.el().querySelector('.iframeblocker')){ + + if (enableFull){ + if (this.player_.isFullScreen){ + this.player_.cancelFullScreen(); + } else{ + this.player_.requestFullScreen(); + } + } + } + } + }; + + player.on('keydown', keyDown); + player.on('dblclick', doubleClick); + + return this; + }; + + cliplibrejs.plugin('hotkeys', hotkeys); + +})(window, window.cliplibrejs); |