mirror of
https://github.com/videojs/video.js.git
synced 2025-01-10 23:30:03 +02:00
Clean up and documentation of src/js/video.js and DOM functions
Preparing to export utility functions on the videojs object closes #2182 Change el() to getEl() for consistency Cleaned up DOM functions library Clean up and document videojs object API Fixed mergeOptions to modify the first object instead of a copy More cleanup of the main video.js file and documentation Fixed issues with mergeOptions Cleaned up the addLanguage function Removed unnecessary underscores in private module vars
This commit is contained in:
parent
5d550ffada
commit
1bfe0b4fed
@ -32,6 +32,7 @@ CHANGELOG
|
|||||||
* @heff added support for fluid widths, aspect ratios, and metadata defaults ([view](https://github.com/videojs/video.js/pull/1952))
|
* @heff added support for fluid widths, aspect ratios, and metadata defaults ([view](https://github.com/videojs/video.js/pull/1952))
|
||||||
* @heff reorganized all utility functions in the codebase ([view](https://github.com/videojs/video.js/pull/2139))
|
* @heff reorganized all utility functions in the codebase ([view](https://github.com/videojs/video.js/pull/2139))
|
||||||
* @eXon made additional tech 2.0 improvements listed in #2126 ([view](https://github.com/videojs/video.js/pull/2166))
|
* @eXon made additional tech 2.0 improvements listed in #2126 ([view](https://github.com/videojs/video.js/pull/2166))
|
||||||
|
* @heff Cleaned up and documented src/js/video.js and DOM functions ([view](https://github.com/videojs/video.js/pull/2182))
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
"style": "./dist/video-js.css",
|
"style": "./dist/video-js.css",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"global": "^4.3.0",
|
"global": "^4.3.0",
|
||||||
"lodash.clonedeep": "^3.0.0",
|
|
||||||
"lodash.isplainobject": "^3.0.2",
|
"lodash.isplainobject": "^3.0.2",
|
||||||
"lodash.merge": "^3.2.1",
|
"lodash.merge": "^3.2.1",
|
||||||
"object.assign": "^2.0.1",
|
"object.assign": "^2.0.1",
|
||||||
|
@ -13,6 +13,7 @@ import toTitleCase from './utils/to-title-case.js';
|
|||||||
import assign from 'object.assign';
|
import assign from 'object.assign';
|
||||||
import mergeOptions from './utils/merge-options.js';
|
import mergeOptions from './utils/merge-options.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base UI Component class
|
* Base UI Component class
|
||||||
*
|
*
|
||||||
@ -52,8 +53,8 @@ class Component {
|
|||||||
this.player_ = player;
|
this.player_ = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a copy of prototype.options_ to protect against overriding global defaults
|
// Make a copy of prototype.options_ to protect against overriding defaults
|
||||||
this.options_ = assign({}, this.options_);
|
this.options_ = mergeOptions({}, this.options_);
|
||||||
|
|
||||||
// Updated options with supplied options
|
// Updated options with supplied options
|
||||||
options = this.options(options);
|
options = this.options(options);
|
||||||
@ -130,7 +131,7 @@ class Component {
|
|||||||
this.el_.parentNode.removeChild(this.el_);
|
this.el_.parentNode.removeChild(this.el_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dom.removeData(this.el_);
|
Dom.removeElData(this.el_);
|
||||||
this.el_ = null;
|
this.el_ = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,7 +742,7 @@ class Component {
|
|||||||
* @return {Component}
|
* @return {Component}
|
||||||
*/
|
*/
|
||||||
hasClass(classToCheck) {
|
hasClass(classToCheck) {
|
||||||
return Dom.hasClass(this.el_, classToCheck);
|
return Dom.hasElClass(this.el_, classToCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -751,7 +752,7 @@ class Component {
|
|||||||
* @return {Component}
|
* @return {Component}
|
||||||
*/
|
*/
|
||||||
addClass(classToAdd) {
|
addClass(classToAdd) {
|
||||||
Dom.addClass(this.el_, classToAdd);
|
Dom.addElClass(this.el_, classToAdd);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,7 +763,7 @@ class Component {
|
|||||||
* @return {Component}
|
* @return {Component}
|
||||||
*/
|
*/
|
||||||
removeClass(classToRemove) {
|
removeClass(classToRemove) {
|
||||||
Dom.removeClass(this.el_, classToRemove);
|
Dom.removeElClass(this.el_, classToRemove);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,19 +919,6 @@ class Component {
|
|||||||
// If component has display:none, offset will return 0
|
// If component has display:none, offset will return 0
|
||||||
// TODO: handle display:none and no dimension style using px
|
// TODO: handle display:none and no dimension style using px
|
||||||
return parseInt(this.el_['offset' + toTitleCase(widthOrHeight)], 10);
|
return parseInt(this.el_['offset' + toTitleCase(widthOrHeight)], 10);
|
||||||
|
|
||||||
// ComputedStyle version.
|
|
||||||
// Only difference is if the element is hidden it will return
|
|
||||||
// the percent value (e.g. '100%'')
|
|
||||||
// instead of zero like offsetWidth returns.
|
|
||||||
// var val = Dom.getComputedStyleValue(this.el_, widthOrHeight);
|
|
||||||
// var pxIndex = val.indexOf('px');
|
|
||||||
|
|
||||||
// if (pxIndex !== -1) {
|
|
||||||
// return val.slice(0, pxIndex);
|
|
||||||
// } else {
|
|
||||||
// return val;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,9 +68,9 @@ class MuteToggle extends Button {
|
|||||||
|
|
||||||
/* TODO improve muted icon classes */
|
/* TODO improve muted icon classes */
|
||||||
for (var i = 0; i < 4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
Dom.removeClass(this.el_, `vjs-vol-${i}`);
|
Dom.removeElClass(this.el_, `vjs-vol-${i}`);
|
||||||
}
|
}
|
||||||
Dom.addClass(this.el_, `vjs-vol-${level}`);
|
Dom.addElClass(this.el_, `vjs-vol-${level}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
|
// Subclasses Component
|
||||||
import Component from './component.js';
|
import Component from './component.js';
|
||||||
|
|
||||||
|
import document from 'global/document';
|
||||||
|
import window from 'global/window';
|
||||||
import * as Events from './utils/events.js';
|
import * as Events from './utils/events.js';
|
||||||
import * as Dom from './utils/dom.js';
|
import * as Dom from './utils/dom.js';
|
||||||
import * as Fn from './utils/fn.js';
|
import * as Fn from './utils/fn.js';
|
||||||
@ -10,23 +14,22 @@ import { createTimeRange } from './utils/time-ranges.js';
|
|||||||
import { bufferedPercent } from './utils/buffer.js';
|
import { bufferedPercent } from './utils/buffer.js';
|
||||||
import FullscreenApi from './fullscreen-api.js';
|
import FullscreenApi from './fullscreen-api.js';
|
||||||
import MediaError from './media-error.js';
|
import MediaError from './media-error.js';
|
||||||
import Options from './options.js';
|
import globalOptions from './global-options.js';
|
||||||
import safeParseTuple from 'safe-json-parse/tuple';
|
import safeParseTuple from 'safe-json-parse/tuple';
|
||||||
import window from 'global/window';
|
|
||||||
import document from 'global/document';
|
|
||||||
import assign from 'object.assign';
|
import assign from 'object.assign';
|
||||||
import mergeOptions from './utils/merge-options.js';
|
import mergeOptions from './utils/merge-options.js';
|
||||||
|
|
||||||
// Include required child components
|
// Include required child components (importing also registers them)
|
||||||
import MediaLoader from './tech/loader.js';
|
import MediaLoader from './tech/loader.js';
|
||||||
import Poster from './poster-image.js';
|
import PosterImage from './poster-image.js';
|
||||||
import TextTrackDisplay from './tracks/text-track-display.js';
|
import TextTrackDisplay from './tracks/text-track-display.js';
|
||||||
import LoadingSpinner from './loading-spinner.js';
|
import LoadingSpinner from './loading-spinner.js';
|
||||||
import BigPlayButton from './big-play-button.js';
|
import BigPlayButton from './big-play-button.js';
|
||||||
import controlBar from './control-bar/control-bar.js';
|
import ControlBar from './control-bar/control-bar.js';
|
||||||
import ErrorDisplay from './error-display.js';
|
import ErrorDisplay from './error-display.js';
|
||||||
import TextTrackSettings from './tracks/text-track-settings.js';
|
import TextTrackSettings from './tracks/text-track-settings.js';
|
||||||
// Require html5 for disposing the original video tag
|
|
||||||
|
// Require html5 tech, at least for disposing the original video tag
|
||||||
import Html5 from './tech/html5.js';
|
import Html5 from './tech/html5.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,13 +102,13 @@ class Player extends Component {
|
|||||||
this.tag = tag; // Store the original tag used to set options
|
this.tag = tag; // Store the original tag used to set options
|
||||||
|
|
||||||
// Store the tag attributes used to restore html5 element
|
// Store the tag attributes used to restore html5 element
|
||||||
this.tagAttributes = tag && Dom.getElementAttributes(tag);
|
this.tagAttributes = tag && Dom.getElAttributes(tag);
|
||||||
|
|
||||||
// Update Current Language
|
// Update Current Language
|
||||||
this.language_ = options['language'] || Options['language'];
|
this.language_ = options['language'] || globalOptions['language'];
|
||||||
|
|
||||||
// Update Supported Languages
|
// Update Supported Languages
|
||||||
this.languages_ = options['languages'] || Options['languages'];
|
this.languages_ = options['languages'] || globalOptions['languages'];
|
||||||
|
|
||||||
// Cache for video property values.
|
// Cache for video property values.
|
||||||
this.cache_ = {};
|
this.cache_ = {};
|
||||||
@ -211,7 +214,7 @@ class Player extends Component {
|
|||||||
|
|
||||||
// Copy over all the attributes from the tag, including ID and class
|
// Copy over all the attributes from the tag, including ID and class
|
||||||
// ID will now reference player box, not the video tag
|
// ID will now reference player box, not the video tag
|
||||||
const attrs = Dom.getElementAttributes(tag);
|
const attrs = Dom.getElAttributes(tag);
|
||||||
|
|
||||||
Object.getOwnPropertyNames(attrs).forEach(function(attr){
|
Object.getOwnPropertyNames(attrs).forEach(function(attr){
|
||||||
// workaround so we don't totally break IE7
|
// workaround so we don't totally break IE7
|
||||||
@ -246,7 +249,7 @@ class Player extends Component {
|
|||||||
this.fluid(this.options_['fluid']);
|
this.fluid(this.options_['fluid']);
|
||||||
this.aspectRatio(this.options_['aspectRatio']);
|
this.aspectRatio(this.options_['aspectRatio']);
|
||||||
|
|
||||||
// insertFirst seems to cause the networkState to flicker from 3 to 2, so
|
// insertElFirst seems to cause the networkState to flicker from 3 to 2, so
|
||||||
// keep track of the original for later so we can know if the source originally failed
|
// keep track of the original for later so we can know if the source originally failed
|
||||||
tag.initNetworkState_ = tag.networkState;
|
tag.initNetworkState_ = tag.networkState;
|
||||||
|
|
||||||
@ -254,7 +257,7 @@ class Player extends Component {
|
|||||||
if (tag.parentNode) {
|
if (tag.parentNode) {
|
||||||
tag.parentNode.insertBefore(el, tag);
|
tag.parentNode.insertBefore(el, tag);
|
||||||
}
|
}
|
||||||
Dom.insertFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup.
|
Dom.insertElFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup.
|
||||||
|
|
||||||
this.el_ = el;
|
this.el_ = el;
|
||||||
|
|
||||||
@ -479,7 +482,7 @@ class Player extends Component {
|
|||||||
// Add the tech element in the DOM if it was not already there
|
// Add the tech element in the DOM if it was not already there
|
||||||
// Make sure to not insert the original video element if using Html5
|
// Make sure to not insert the original video element if using Html5
|
||||||
if (this.tech.el().parentNode !== this.el() && (techName !== 'Html5' || !this.tag)) {
|
if (this.tech.el().parentNode !== this.el() && (techName !== 'Html5' || !this.tag)) {
|
||||||
Dom.insertFirst(this.tech.el(), this.el());
|
Dom.insertElFirst(this.tech.el(), this.el());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rid of the original video tag reference after the first tech is loaded
|
// Get rid of the original video tag reference after the first tech is loaded
|
||||||
@ -1376,7 +1379,7 @@ class Player extends Component {
|
|||||||
document.documentElement.style.overflow = 'hidden';
|
document.documentElement.style.overflow = 'hidden';
|
||||||
|
|
||||||
// Apply fullscreen styles
|
// Apply fullscreen styles
|
||||||
Dom.addClass(document.body, 'vjs-full-window');
|
Dom.addElClass(document.body, 'vjs-full-window');
|
||||||
|
|
||||||
this.trigger('enterFullWindow');
|
this.trigger('enterFullWindow');
|
||||||
}
|
}
|
||||||
@ -1399,7 +1402,7 @@ class Player extends Component {
|
|||||||
document.documentElement.style.overflow = this.docOrigOverflow;
|
document.documentElement.style.overflow = this.docOrigOverflow;
|
||||||
|
|
||||||
// Remove fullscreen styles
|
// Remove fullscreen styles
|
||||||
Dom.removeClass(document.body, 'vjs-full-window');
|
Dom.removeElClass(document.body, 'vjs-full-window');
|
||||||
|
|
||||||
// Resize the box, controller, and poster to original sizes
|
// Resize the box, controller, and poster to original sizes
|
||||||
// this.positionAll();
|
// this.positionAll();
|
||||||
@ -2116,7 +2119,7 @@ class Player extends Component {
|
|||||||
'tracks': []
|
'tracks': []
|
||||||
};
|
};
|
||||||
|
|
||||||
const tagOptions = Dom.getElementAttributes(tag);
|
const tagOptions = Dom.getElAttributes(tag);
|
||||||
const dataSetup = tagOptions['data-setup'];
|
const dataSetup = tagOptions['data-setup'];
|
||||||
|
|
||||||
// Check if data-setup attr exists.
|
// Check if data-setup attr exists.
|
||||||
@ -2141,9 +2144,9 @@ class Player extends Component {
|
|||||||
// Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
|
// Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
|
||||||
const childName = child.nodeName.toLowerCase();
|
const childName = child.nodeName.toLowerCase();
|
||||||
if (childName === 'source') {
|
if (childName === 'source') {
|
||||||
baseOptions['sources'].push(Dom.getElementAttributes(child));
|
baseOptions['sources'].push(Dom.getElAttributes(child));
|
||||||
} else if (childName === 'track') {
|
} else if (childName === 'track') {
|
||||||
baseOptions['tracks'].push(Dom.getElementAttributes(child));
|
baseOptions['tracks'].push(Dom.getElAttributes(child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2168,7 +2171,7 @@ Player.players = {};
|
|||||||
* @type {Object}
|
* @type {Object}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
Player.prototype.options_ = Options;
|
Player.prototype.options_ = globalOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired when the player has initial duration and dimension information
|
* Fired when the player has initial duration and dimension information
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Player from './player';
|
import Player from './player.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the method for registering a video.js plugin
|
* The method for registering a video.js plugin
|
||||||
*
|
*
|
||||||
* @param {String} name The name of the plugin
|
* @param {String} name The name of the plugin
|
||||||
* @param {Function} init The function that is run when the player inits
|
* @param {Function} init The function that is run when the player inits
|
||||||
|
@ -160,7 +160,7 @@ class Slider extends Component {
|
|||||||
|
|
||||||
calculateDistance(event){
|
calculateDistance(event){
|
||||||
let el = this.el_;
|
let el = this.el_;
|
||||||
let box = Dom.findPosition(el);
|
let box = Dom.findElPosition(el);
|
||||||
let boxW = el.offsetWidth;
|
let boxW = el.offsetWidth;
|
||||||
let boxH = el.offsetHeight;
|
let boxH = el.offsetHeight;
|
||||||
let handle = this.handle;
|
let handle = this.handle;
|
||||||
|
@ -267,7 +267,7 @@ Flash.formats = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Flash.onReady = function(currSwf){
|
Flash.onReady = function(currSwf){
|
||||||
let el = Dom.el(currSwf);
|
let el = Dom.getEl(currSwf);
|
||||||
let tech = el && el.tech;
|
let tech = el && el.tech;
|
||||||
|
|
||||||
// if there is no el then the tech has been disposed
|
// if there is no el then the tech has been disposed
|
||||||
@ -300,13 +300,13 @@ Flash.checkReady = function(tech){
|
|||||||
|
|
||||||
// Trigger events from the swf on the player
|
// Trigger events from the swf on the player
|
||||||
Flash.onEvent = function(swfID, eventName){
|
Flash.onEvent = function(swfID, eventName){
|
||||||
let tech = Dom.el(swfID).tech;
|
let tech = Dom.getEl(swfID).tech;
|
||||||
tech.trigger(eventName);
|
tech.trigger(eventName);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Log errors from the swf
|
// Log errors from the swf
|
||||||
Flash.onError = function(swfID, err){
|
Flash.onError = function(swfID, err){
|
||||||
const tech = Dom.el(swfID).tech;
|
const tech = Dom.getEl(swfID).tech;
|
||||||
const msg = 'FLASH: '+err;
|
const msg = 'FLASH: '+err;
|
||||||
|
|
||||||
if (err === 'srcnotfound') {
|
if (err === 'srcnotfound') {
|
||||||
|
@ -101,13 +101,13 @@ class Html5 extends Tech {
|
|||||||
el = document.createElement('video');
|
el = document.createElement('video');
|
||||||
|
|
||||||
// determine if native controls should be used
|
// determine if native controls should be used
|
||||||
let tagAttributes = this.options_.tag && Dom.getElementAttributes(this.options_.tag);
|
let tagAttributes = this.options_.tag && Dom.getElAttributes(this.options_.tag);
|
||||||
let attributes = mergeOptions({}, tagAttributes);
|
let attributes = mergeOptions({}, tagAttributes);
|
||||||
if (!browser.TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) {
|
if (!browser.TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) {
|
||||||
delete attributes.controls;
|
delete attributes.controls;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dom.setElementAttributes(el,
|
Dom.setElAttributes(el,
|
||||||
assign(attributes, {
|
assign(attributes, {
|
||||||
id: this.options_.techId,
|
id: this.options_.techId,
|
||||||
class: 'vjs-tech'
|
class: 'vjs-tech'
|
||||||
@ -139,7 +139,7 @@ class Html5 extends Tech {
|
|||||||
if (typeof this.options_[attr] !== 'undefined') {
|
if (typeof this.options_[attr] !== 'undefined') {
|
||||||
overwriteAttrs[attr] = this.options_[attr];
|
overwriteAttrs[attr] = this.options_[attr];
|
||||||
}
|
}
|
||||||
Dom.setElementAttributes(el, overwriteAttrs);
|
Dom.setElAttributes(el, overwriteAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return el;
|
return el;
|
||||||
|
@ -8,24 +8,22 @@ import roundFloat from './round-float.js';
|
|||||||
* Also allows for CSS (jQuery) ID syntax. But nothing other than IDs.
|
* Also allows for CSS (jQuery) ID syntax. But nothing other than IDs.
|
||||||
* @param {String} id Element ID
|
* @param {String} id Element ID
|
||||||
* @return {Element} Element with supplied ID
|
* @return {Element} Element with supplied ID
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
export const el = function(id){
|
export function getEl(id){
|
||||||
if (id.indexOf('#') === 0) {
|
if (id.indexOf('#') === 0) {
|
||||||
id = id.slice(1);
|
id = id.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return document.getElementById(id);
|
return document.getElementById(id);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an element and applies properties.
|
* Creates an element and applies properties.
|
||||||
* @param {String=} tagName Name of tag to be created.
|
* @param {String=} tagName Name of tag to be created.
|
||||||
* @param {Object=} properties Element properties to be applied.
|
* @param {Object=} properties Element properties to be applied.
|
||||||
* @return {Element}
|
* @return {Element}
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
export const createEl = function(tagName='div', properties={}){
|
export function createEl(tagName='div', properties={}){
|
||||||
let el = document.createElement(tagName);
|
let el = document.createElement(tagName);
|
||||||
|
|
||||||
Object.getOwnPropertyNames(properties).forEach(function(propName){
|
Object.getOwnPropertyNames(properties).forEach(function(propName){
|
||||||
@ -47,7 +45,7 @@ export const createEl = function(tagName='div', properties={}){
|
|||||||
});
|
});
|
||||||
|
|
||||||
return el;
|
return el;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert an element as the first child node of another
|
* Insert an element as the first child node of another
|
||||||
@ -55,13 +53,13 @@ export const createEl = function(tagName='div', properties={}){
|
|||||||
* @param {[type]} parent Element to insert child into
|
* @param {[type]} parent Element to insert child into
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export const insertFirst = function(child, parent){
|
export function insertElFirst(child, parent){
|
||||||
if (parent.firstChild) {
|
if (parent.firstChild) {
|
||||||
parent.insertBefore(child, parent.firstChild);
|
parent.insertBefore(child, parent.firstChild);
|
||||||
} else {
|
} else {
|
||||||
parent.appendChild(child);
|
parent.appendChild(child);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element Data Store. Allows for binding data to an element without putting it directly on the element.
|
* Element Data Store. Allows for binding data to an element without putting it directly on the element.
|
||||||
@ -70,7 +68,7 @@ export const insertFirst = function(child, parent){
|
|||||||
* @type {Object}
|
* @type {Object}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export const cache = {};
|
const elData = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique attribute name to store an element's guid in
|
* Unique attribute name to store an element's guid in
|
||||||
@ -78,24 +76,26 @@ export const cache = {};
|
|||||||
* @constant
|
* @constant
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export const expando = 'vdata' + (new Date()).getTime();
|
const elIdAttr = 'vdata' + (new Date()).getTime();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cache object where data for an element is stored
|
* Returns the cache object where data for an element is stored
|
||||||
* @param {Element} el Element to store data for.
|
* @param {Element} el Element to store data for.
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
export const getData = function(el){
|
export function getElData(el) {
|
||||||
var id = el[expando];
|
let id = el[elIdAttr];
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
id = el[expando] = Guid.newGUID();
|
id = el[elIdAttr] = Guid.newGUID();
|
||||||
}
|
}
|
||||||
if (!cache[id]) {
|
|
||||||
cache[id] = {};
|
if (!elData[id]) {
|
||||||
|
elData[id] = {};
|
||||||
}
|
}
|
||||||
return cache[id];
|
|
||||||
};
|
return elData[id];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not an element has cached data
|
* Returns whether or not an element has cached data
|
||||||
@ -103,73 +103,71 @@ export const getData = function(el){
|
|||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export const hasData = function(el){
|
export function hasElData(el) {
|
||||||
const id = el[expando];
|
const id = el[elIdAttr];
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!Object.getOwnPropertyNames(cache[id]).length;
|
return !!Object.getOwnPropertyNames(elData[id]).length;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete data for the element from the cache and the guid attr from getElementById
|
* Delete data for the element from the cache and the guid attr from getElementById
|
||||||
* @param {Element} el Remove data for an element
|
* @param {Element} el Remove data for an element
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export const removeData = function(el){
|
export function removeElData(el) {
|
||||||
var id = el[expando];
|
let id = el[elIdAttr];
|
||||||
if (!id) { return; }
|
|
||||||
// Remove all stored data
|
|
||||||
// Changed to = null
|
|
||||||
// http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
|
|
||||||
// cache[id] = null;
|
|
||||||
delete cache[id];
|
|
||||||
|
|
||||||
// Remove the expando property from the DOM node
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all stored data
|
||||||
|
delete elData[id];
|
||||||
|
|
||||||
|
// Remove the elIdAttr property from the DOM node
|
||||||
try {
|
try {
|
||||||
delete el[expando];
|
delete el[elIdAttr];
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (el.removeAttribute) {
|
if (el.removeAttribute) {
|
||||||
el.removeAttribute(expando);
|
el.removeAttribute(elIdAttr);
|
||||||
} else {
|
} else {
|
||||||
// IE doesn't appear to support removeAttribute on the document element
|
// IE doesn't appear to support removeAttribute on the document element
|
||||||
el[expando] = null;
|
el[elIdAttr] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if an element has a CSS class
|
* Check if an element has a CSS class
|
||||||
* @param {Element} element Element to check
|
* @param {Element} element Element to check
|
||||||
* @param {String} classToCheck Classname to check
|
* @param {String} classToCheck Classname to check
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
export const hasClass = function(element, classToCheck){
|
export function hasElClass(element, classToCheck) {
|
||||||
return ((' ' + element.className + ' ').indexOf(' ' + classToCheck + ' ') !== -1);
|
return ((' ' + element.className + ' ').indexOf(' ' + classToCheck + ' ') !== -1);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a CSS class name to an element
|
* Add a CSS class name to an element
|
||||||
* @param {Element} element Element to add class name to
|
* @param {Element} element Element to add class name to
|
||||||
* @param {String} classToAdd Classname to add
|
* @param {String} classToAdd Classname to add
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
export const addClass = function(element, classToAdd){
|
export function addElClass(element, classToAdd) {
|
||||||
if (!hasClass(element, classToAdd)) {
|
if (!hasElClass(element, classToAdd)) {
|
||||||
element.className = element.className === '' ? classToAdd : element.className + ' ' + classToAdd;
|
element.className = element.className === '' ? classToAdd : element.className + ' ' + classToAdd;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a CSS class name from an element
|
* Remove a CSS class name from an element
|
||||||
* @param {Element} element Element to remove from class name
|
* @param {Element} element Element to remove from class name
|
||||||
* @param {String} classToAdd Classname to remove
|
* @param {String} classToAdd Classname to remove
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
export const removeClass = function(element, classToRemove){
|
export function removeElClass(element, classToRemove) {
|
||||||
if (!hasClass(element, classToRemove)) {return;}
|
if (!hasElClass(element, classToRemove)) {return;}
|
||||||
|
|
||||||
let classNames = element.className.split(' ');
|
let classNames = element.className.split(' ');
|
||||||
|
|
||||||
@ -181,7 +179,7 @@ export const removeClass = function(element, classToRemove){
|
|||||||
}
|
}
|
||||||
|
|
||||||
element.className = classNames.join(' ');
|
element.className = classNames.join(' ');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply attributes to an HTML element.
|
* Apply attributes to an HTML element.
|
||||||
@ -189,7 +187,7 @@ export const removeClass = function(element, classToRemove){
|
|||||||
* @param {Object=} attributes Element attributes to be applied.
|
* @param {Object=} attributes Element attributes to be applied.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export const setElementAttributes = function(el, attributes){
|
export function setElAttributes(el, attributes) {
|
||||||
Object.getOwnPropertyNames(attributes).forEach(function(attrName){
|
Object.getOwnPropertyNames(attributes).forEach(function(attrName){
|
||||||
let attrValue = attributes[attrName];
|
let attrValue = attributes[attrName];
|
||||||
|
|
||||||
@ -199,7 +197,7 @@ export const setElementAttributes = function(el, attributes){
|
|||||||
el.setAttribute(attrName, (attrValue === true ? '' : attrValue));
|
el.setAttribute(attrName, (attrValue === true ? '' : attrValue));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an element's attribute values, as defined on the HTML tag
|
* Get an element's attribute values, as defined on the HTML tag
|
||||||
@ -210,7 +208,7 @@ export const setElementAttributes = function(el, attributes){
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export const getElementAttributes = function(tag){
|
export function getElAttributes(tag) {
|
||||||
var obj, knownBooleans, attrs, attrName, attrVal;
|
var obj, knownBooleans, attrs, attrName, attrVal;
|
||||||
|
|
||||||
obj = {};
|
obj = {};
|
||||||
@ -241,40 +239,26 @@ export const getElementAttributes = function(tag){
|
|||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the computed style value for an element
|
|
||||||
* From http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element/
|
|
||||||
* @param {Element} el Element to get style value for
|
|
||||||
* @param {String} strCssRule Style name
|
|
||||||
* @return {String} Style value
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
export const getComputedDimension = function(el, strCssRule){
|
|
||||||
var strValue = '';
|
|
||||||
if(document.defaultView && document.defaultView.getComputedStyle){
|
|
||||||
strValue = document.defaultView.getComputedStyle(el, '').getPropertyValue(strCssRule);
|
|
||||||
|
|
||||||
} else if(el.currentStyle){
|
|
||||||
// IE8 Width/Height support
|
|
||||||
let upperCasedRule = strCssRule.substr(0,1).toUpperCase() + strCssRule.substr(1);
|
|
||||||
strValue = el[`client${upperCasedRule}`] + 'px';
|
|
||||||
}
|
|
||||||
return strValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Attempt to block the ability to select text while dragging controls
|
// Attempt to block the ability to select text while dragging controls
|
||||||
export const blockTextSelection = function(){
|
export function blockTextSelection() {
|
||||||
document.body.focus();
|
document.body.focus();
|
||||||
document.onselectstart = function () { return false; };
|
document.onselectstart = function() {
|
||||||
};
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Turn off text selection blocking
|
// Turn off text selection blocking
|
||||||
export const unblockTextSelection = function(){ document.onselectstart = function () { return true; }; };
|
export function unblockTextSelection() {
|
||||||
|
document.onselectstart = function() {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Offset Left
|
// Offset Left
|
||||||
// getBoundingClientRect technique from John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
|
// getBoundingClientRect technique from John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
|
||||||
export const findPosition = function(el) {
|
export function findElPosition(el) {
|
||||||
let box;
|
let box;
|
||||||
|
|
||||||
if (el.getBoundingClientRect && el.parentNode) {
|
if (el.getBoundingClientRect && el.parentNode) {
|
||||||
@ -304,4 +288,4 @@ export const findPosition = function(el) {
|
|||||||
left: roundFloat(left),
|
left: roundFloat(left),
|
||||||
top: roundFloat(top)
|
top: roundFloat(top)
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
@ -24,7 +24,7 @@ export function on(elem, type, fn){
|
|||||||
return _handleMultipleEvents(on, elem, type, fn);
|
return _handleMultipleEvents(on, elem, type, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = Dom.getData(elem);
|
let data = Dom.getElData(elem);
|
||||||
|
|
||||||
// We need a place to store all our handler data
|
// We need a place to store all our handler data
|
||||||
if (!data.handlers) data.handlers = {};
|
if (!data.handlers) data.handlers = {};
|
||||||
@ -76,10 +76,10 @@ export function on(elem, type, fn){
|
|||||||
* @param {Function} fn Specific listener to remove. Don't include to remove listeners for an event type.
|
* @param {Function} fn Specific listener to remove. Don't include to remove listeners for an event type.
|
||||||
*/
|
*/
|
||||||
export function off(elem, type, fn) {
|
export function off(elem, type, fn) {
|
||||||
// Don't want to add a cache object through getData if not needed
|
// Don't want to add a cache object through getElData if not needed
|
||||||
if (!Dom.hasData(elem)) return;
|
if (!Dom.hasElData(elem)) return;
|
||||||
|
|
||||||
let data = Dom.getData(elem);
|
let data = Dom.getElData(elem);
|
||||||
|
|
||||||
// If no events exist, nothing to unbind
|
// If no events exist, nothing to unbind
|
||||||
if (!data.handlers) { return; }
|
if (!data.handlers) { return; }
|
||||||
@ -131,8 +131,8 @@ export function off(elem, type, fn) {
|
|||||||
export function trigger(elem, event) {
|
export function trigger(elem, event) {
|
||||||
// Fetches element data and a reference to the parent (for bubbling).
|
// Fetches element data and a reference to the parent (for bubbling).
|
||||||
// Don't want to add a data object to cache for every parent,
|
// Don't want to add a data object to cache for every parent,
|
||||||
// so checking hasData first.
|
// so checking hasElData first.
|
||||||
var elemData = (Dom.hasData(elem)) ? Dom.getData(elem) : {};
|
var elemData = (Dom.hasElData(elem)) ? Dom.getElData(elem) : {};
|
||||||
var parent = elem.parentNode || elem.ownerDocument;
|
var parent = elem.parentNode || elem.ownerDocument;
|
||||||
// type = event.type || event,
|
// type = event.type || event,
|
||||||
// handler;
|
// handler;
|
||||||
@ -156,7 +156,7 @@ export function trigger(elem, event) {
|
|||||||
|
|
||||||
// If at the top of the DOM, triggers the default action unless disabled.
|
// If at the top of the DOM, triggers the default action unless disabled.
|
||||||
} else if (!parent && !event.defaultPrevented) {
|
} else if (!parent && !event.defaultPrevented) {
|
||||||
var targetData = Dom.getData(event.target);
|
var targetData = Dom.getElData(event.target);
|
||||||
|
|
||||||
// Checks if the target has a default action for this event.
|
// Checks if the target has a default action for this event.
|
||||||
if (event.target[event.type]) {
|
if (event.target[event.type]) {
|
||||||
@ -309,7 +309,7 @@ export function fixEvent(event) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function _cleanUpEvents(elem, type) {
|
function _cleanUpEvents(elem, type) {
|
||||||
var data = Dom.getData(elem);
|
var data = Dom.getElData(elem);
|
||||||
|
|
||||||
// Remove the events of a particular type if there are none left
|
// Remove the events of a particular type if there are none left
|
||||||
if (data.handlers[type].length === 0) {
|
if (data.handlers[type].length === 0) {
|
||||||
@ -330,15 +330,11 @@ function _cleanUpEvents(elem, type) {
|
|||||||
delete data.handlers;
|
delete data.handlers;
|
||||||
delete data.dispatcher;
|
delete data.dispatcher;
|
||||||
delete data.disabled;
|
delete data.disabled;
|
||||||
|
|
||||||
// data.handlers = null;
|
|
||||||
// data.dispatcher = null;
|
|
||||||
// data.disabled = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally remove the expando if there is no data left
|
// Finally remove the element data if there is no data left
|
||||||
if (Object.getOwnPropertyNames(data).length <= 0) {
|
if (Object.getOwnPropertyNames(data).length === 0) {
|
||||||
Dom.removeData(elem);
|
Dom.removeElData(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,33 +1,39 @@
|
|||||||
import merge from 'lodash.merge';
|
import merge from 'lodash.merge';
|
||||||
import isPlainObject from 'lodash.isplainobject';
|
import isPlainObject from 'lodash.isplainobject';
|
||||||
import cloneDeep from 'lodash.clonedeep';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge two options objects, recursively merging any plain object properties as
|
* Merge two options objects, recursively merging **only** plain object
|
||||||
* well. Previously `deepMerge`
|
* properties. Previously `deepMerge`.
|
||||||
*
|
*
|
||||||
* @param {Object} obj1 Object to override values in
|
* @param {Object} object The destination object
|
||||||
* @param {Object} obj2 Overriding object
|
* @param {...Object} source One or more objects to merge into the first
|
||||||
* @return {Object} New object -- obj1 and obj2 will be untouched
|
*
|
||||||
|
* @returns {Object} The updated first object
|
||||||
*/
|
*/
|
||||||
export default function mergeOptions(obj1){
|
export default function mergeOptions(object={}) {
|
||||||
// Copy to ensure we're not modifying the defaults somewhere
|
|
||||||
obj1 = cloneDeep(obj1, function(value) {
|
|
||||||
if (!isPlainObject(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Allow for infinite additional object args to merge
|
// Allow for infinite additional object args to merge
|
||||||
Array.prototype.slice.call(arguments, 1).forEach(function(argObj){
|
Array.prototype.slice.call(arguments, 1).forEach(function(source){
|
||||||
|
|
||||||
// Recursively merge only plain objects
|
// Recursively merge only plain objects
|
||||||
// All other values will be directly copied
|
// All other values will be directly copied
|
||||||
merge(obj1, argObj, function(a, b) {
|
merge(object, source, function(a, b) {
|
||||||
if (!isPlainObject(a) || !isPlainObject(b)) {
|
|
||||||
|
// If we're not working with a plain object, copy the value as is
|
||||||
|
if (!isPlainObject(b)) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the new value is a plain object but the first object value is not
|
||||||
|
// we need to create a new object for the first object to merge with.
|
||||||
|
// This makes it consistent with how merge() works by default
|
||||||
|
// and also protects from later changes the to first object affecting
|
||||||
|
// the second object's values.
|
||||||
|
if (!isPlainObject(a)) {
|
||||||
|
return mergeOptions({}, b);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return obj1;
|
return object;
|
||||||
}
|
}
|
||||||
|
287
src/js/video.js
287
src/js/video.js
@ -1,26 +1,22 @@
|
|||||||
import document from 'global/document';
|
import document from 'global/document';
|
||||||
import assign from 'object.assign';
|
|
||||||
import MediaLoader from './tech/loader.js';
|
|
||||||
import Html5 from './tech/html5.js';
|
|
||||||
import Flash from './tech/flash.js';
|
|
||||||
import PosterImage from './poster-image.js';
|
|
||||||
import TextTrackDisplay from './tracks/text-track-display.js';
|
|
||||||
import LoadingSpinner from './loading-spinner.js';
|
|
||||||
import BigPlayButton from './big-play-button.js';
|
|
||||||
import ControlBar from './control-bar/control-bar.js';
|
|
||||||
import ErrorDisplay from './error-display.js';
|
|
||||||
import * as setup from './setup';
|
import * as setup from './setup';
|
||||||
import Component from './component';
|
import Component from './component';
|
||||||
import Options from './options';
|
import globalOptions from './global-options.js';
|
||||||
import * as Dom from './utils/dom.js';
|
|
||||||
import log from './utils/log.js';
|
|
||||||
import * as browser from './utils/browser.js';
|
|
||||||
import Player from './player';
|
import Player from './player';
|
||||||
import extendsFn from './extends.js';
|
|
||||||
import plugin from './plugins.js';
|
import plugin from './plugins.js';
|
||||||
import options from './options.js';
|
|
||||||
import mergeOptions from '../../src/js/utils/merge-options.js';
|
import mergeOptions from '../../src/js/utils/merge-options.js';
|
||||||
|
|
||||||
|
import assign from 'object.assign';
|
||||||
|
import log from './utils/log.js';
|
||||||
|
import * as Dom from './utils/dom.js';
|
||||||
|
import * as browser from './utils/browser.js';
|
||||||
|
import extendsFn from './extends.js';
|
||||||
|
import merge from 'lodash.merge';
|
||||||
|
|
||||||
|
// Include the built-in techs
|
||||||
|
import Html5 from './tech/html5.js';
|
||||||
|
import Flash from './tech/flash.js';
|
||||||
|
|
||||||
// HTML5 Element Shim for IE8
|
// HTML5 Element Shim for IE8
|
||||||
if (typeof HTMLVideoElement === 'undefined') {
|
if (typeof HTMLVideoElement === 'undefined') {
|
||||||
document.createElement('video');
|
document.createElement('video');
|
||||||
@ -32,11 +28,9 @@ if (typeof HTMLVideoElement === 'undefined') {
|
|||||||
* Doubles as the main function for users to create a player instance and also
|
* Doubles as the main function for users to create a player instance and also
|
||||||
* the main library object.
|
* the main library object.
|
||||||
*
|
*
|
||||||
* **ALIASES** videojs, _V_ (deprecated)
|
* The `videojs` function can be used to initialize or retrieve a player.
|
||||||
*
|
*
|
||||||
* The `vjs` function can be used to initialize or retrieve a player.
|
* var myPlayer = videojs('my_video_id');
|
||||||
*
|
|
||||||
* var myPlayer = vjs('my_video_id');
|
|
||||||
*
|
*
|
||||||
* @param {String|Element} id Video element or video element ID
|
* @param {String|Element} id Video element or video element ID
|
||||||
* @param {Object=} options Optional options object for config/settings
|
* @param {Object=} options Optional options object for config/settings
|
||||||
@ -72,7 +66,7 @@ var videojs = function(id, options, ready){
|
|||||||
|
|
||||||
// Otherwise get element for ID
|
// Otherwise get element for ID
|
||||||
} else {
|
} else {
|
||||||
tag = Dom.el(id);
|
tag = Dom.getEl(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID is a media element
|
// ID is a media element
|
||||||
@ -90,64 +84,235 @@ var videojs = function(id, options, ready){
|
|||||||
return tag['player'] || new Player(tag, options, ready);
|
return tag['player'] || new Player(tag, options, ready);
|
||||||
};
|
};
|
||||||
|
|
||||||
// CDN Version. Used to target right flash swf.
|
|
||||||
videojs.CDN_VERSION = '__VERSION_NO_PATCH__';
|
|
||||||
videojs.ACCESS_PROTOCOL = ('https:' === document.location.protocol ? 'https://' : 'http://');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Full player version
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
videojs['VERSION'] = '__VERSION__';
|
|
||||||
|
|
||||||
// Set CDN Version of swf
|
|
||||||
// The added (+) blocks the replace from changing this _VERSION_NO_PATCH_ string
|
|
||||||
if (videojs.CDN_VERSION !== '__VERSION_'+'NO_PATCH__') {
|
|
||||||
Options['flash']['swf'] = `${videojs.ACCESS_PROTOCOL}vjs.zencdn.net/${videojs.CDN_VERSION}/video-js.swf`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run Auto-load players
|
// Run Auto-load players
|
||||||
// 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)
|
// 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)
|
||||||
setup.autoSetupTimeout(1, videojs);
|
setup.autoSetupTimeout(1, videojs);
|
||||||
|
|
||||||
videojs.getComponent = Component.getComponent;
|
/**
|
||||||
videojs.registerComponent = Component.registerComponent;
|
* Current software version (semver)
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
videojs['VERSION'] = '__VERSION__';
|
||||||
|
|
||||||
// APIs that will be removed with 5.0, but need them to get tests passing
|
/**
|
||||||
// in ES6 transition
|
* Get the global options object
|
||||||
videojs.TOUCH_ENABLED = browser.TOUCH_ENABLED;
|
*
|
||||||
|
* @returns {Object} The global options object
|
||||||
|
*/
|
||||||
|
videojs.getGlobalOptions = () => globalOptions;
|
||||||
|
|
||||||
// Probably want to keep this one for 5.0?
|
/**
|
||||||
videojs.players = Player.players;
|
* Set options that will apply to every player
|
||||||
|
*
|
||||||
videojs.extends = extendsFn;
|
* videojs.setGlobalOptions({
|
||||||
|
* autoplay: true
|
||||||
videojs.mergeOptions = mergeOptions;
|
* });
|
||||||
|
* // -> all players will autoplay by default
|
||||||
videojs.getGlobalOptions = () => options;
|
*
|
||||||
|
* NOTE: This will do a deep merge with the new options,
|
||||||
|
* not overwrite the entire global options object.
|
||||||
|
*
|
||||||
|
* @returns {Object} The updated global options object
|
||||||
|
*/
|
||||||
videojs.setGlobalOptions = function(newOptions) {
|
videojs.setGlobalOptions = function(newOptions) {
|
||||||
mergeOptions(options, newOptions);
|
return mergeOptions(globalOptions, newOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set CDN Version of swf
|
||||||
|
const MINOR_VERSION = '__VERSION_NO_PATCH__';
|
||||||
|
const ACCESS_PROTOCOL = ('https:' === document.location.protocol ? 'https://' : 'http://');
|
||||||
|
|
||||||
|
// The added (+) blocks the replace from changing this _VERSION_NO_PATCH_ string
|
||||||
|
if (MINOR_VERSION !== '__VERSION_'+'NO_PATCH__') {
|
||||||
|
globalOptions['flash']['swf'] = `${ACCESS_PROTOCOL}vjs.zencdn.net/${MINOR_VERSION}/video-js.swf`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an object with the currently created players, keyed by player ID
|
||||||
|
*
|
||||||
|
* @returns {Object} The created players
|
||||||
|
*/
|
||||||
|
videojs.getPlayers = function() {
|
||||||
|
return Player.players;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a component class object by name
|
||||||
|
*
|
||||||
|
* var VjsButton = videojs.getComponent('Button');
|
||||||
|
*
|
||||||
|
* // Create a new instance of the component
|
||||||
|
* var myButton = new VjsButton(myPlayer);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
videojs.getComponent = Component.getComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a component so it can referred to by name
|
||||||
|
*
|
||||||
|
* Used when adding to other
|
||||||
|
* components, either through addChild
|
||||||
|
* `component.addChild('myComponent')`
|
||||||
|
* or through default children options
|
||||||
|
* `{ children: ['myComponent'] }`.
|
||||||
|
*
|
||||||
|
* // Get a component to subclass
|
||||||
|
* var VjsButton = videojs.getComponent('Button');
|
||||||
|
*
|
||||||
|
* // Subclass the component (see 'extends' doc for more info)
|
||||||
|
* var MySpecialButton = videojs.extends(VjsButton, {});
|
||||||
|
*
|
||||||
|
* // Register the new component
|
||||||
|
* VjsButton.registerComponent('MySepcialButton', MySepcialButton);
|
||||||
|
*
|
||||||
|
* // (optionally) add the new component as a default player child
|
||||||
|
* myPlayer.addChild('MySepcialButton');
|
||||||
|
*
|
||||||
|
* NOTE: You could also just initialize the component before adding.
|
||||||
|
* `component.addChild(new MyComponent());`
|
||||||
|
*
|
||||||
|
* @param {String} The class name of the component
|
||||||
|
* @param {Component} The component class
|
||||||
|
* @returns {Component} The newly registered component
|
||||||
|
*/
|
||||||
|
videojs.registerComponent = Component.registerComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A suite of browser and device tests
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
videojs.browser = browser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclass an existing class
|
||||||
|
* Mimics ES6 subclassing with the `extends` keyword
|
||||||
|
*
|
||||||
|
* // Create a basic javascript 'class'
|
||||||
|
* function MyClass(name){
|
||||||
|
* // Set a property at initialization
|
||||||
|
* this.myName = name;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Create an instance method
|
||||||
|
* MyClass.prototype.sayMyName = function(){
|
||||||
|
* alert(this.myName);
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* // Subclass the exisitng class and change the name
|
||||||
|
* // when initializing
|
||||||
|
* var MySubClass = videojs.extends(MyClass, {
|
||||||
|
* constructor: function(name) {
|
||||||
|
* // Call the super class constructor for the subclass
|
||||||
|
* MyClass.call(this, name)
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // Create an instance of the new sub class
|
||||||
|
* var myInstance = new MySubClass('John');
|
||||||
|
* myInstance.sayMyName(); // -> should alert "John"
|
||||||
|
*
|
||||||
|
* @param {Function} The Class to subclass
|
||||||
|
* @param {Object} An object including instace methods for the new class
|
||||||
|
* Optionally including a `constructor` function
|
||||||
|
*
|
||||||
|
* @returns {Function} The newly created subclass
|
||||||
|
*/
|
||||||
|
videojs.extends = extendsFn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge two options objects recursively
|
||||||
|
* Performs a deep merge like lodash.merge but **only merges plain objects**
|
||||||
|
* (not arrays, elements, anything else)
|
||||||
|
* Other values will be copied directly from the second object.
|
||||||
|
*
|
||||||
|
* var defaultOptions = {
|
||||||
|
* foo: true,
|
||||||
|
* bar: {
|
||||||
|
* a: true,
|
||||||
|
* b: [1,2,3]
|
||||||
|
* }
|
||||||
|
* };
|
||||||
|
* var newOptions = {
|
||||||
|
* foo: false,
|
||||||
|
* bar: {
|
||||||
|
* b: [4,5,6]
|
||||||
|
* }
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* var result = videojs.mergeOptions(defaultOptions, newOptions);
|
||||||
|
* // result.foo = false;
|
||||||
|
* // result.bar.a = true;
|
||||||
|
* // result.bar.b = [4,5,6];
|
||||||
|
*
|
||||||
|
* @param {Object} The options object whose values will be overriden
|
||||||
|
* @param {Object} The options object with values to override the first
|
||||||
|
* @param {Object} Any number of additional options objects
|
||||||
|
*
|
||||||
|
* @returns {Object} a new object with the merged values
|
||||||
|
*/
|
||||||
|
videojs.mergeOptions = mergeOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Video.js player plugin
|
||||||
|
*
|
||||||
|
* Plugins are only initialized when options for the plugin are included
|
||||||
|
* in the player options, or the plugin function on the player instance is
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* **See the plugin guide in the docs for a more detailed example**
|
||||||
|
*
|
||||||
|
* // Make a plugin that alerts when the player plays
|
||||||
|
* videojs.plugin('myPlugin', function(myPluginOptions) {
|
||||||
|
* myPluginOptions = myPluginOptions || {};
|
||||||
|
*
|
||||||
|
* var player = this;
|
||||||
|
* var alertText = myPluginOptions.text || 'Player is playing!'
|
||||||
|
*
|
||||||
|
* player.on('play', function(){
|
||||||
|
* alert(alertText);
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // USAGE EXAMPLES
|
||||||
|
*
|
||||||
|
* // EXAMPLE 1: New player with plugin options, call plugin immediately
|
||||||
|
* var player1 = videojs('idOne', {
|
||||||
|
* myPlugin: {
|
||||||
|
* text: 'Custom text!'
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* // Click play
|
||||||
|
* // --> Should alert 'Custom text!'
|
||||||
|
*
|
||||||
|
* // EXAMPLE 3: New player, initialize plugin later
|
||||||
|
* var player3 = videojs('idThree');
|
||||||
|
* // Click play
|
||||||
|
* // --> NO ALERT
|
||||||
|
* // Click pause
|
||||||
|
* // Initialize plugin using the plugin function on the player instance
|
||||||
|
* player3.myPlugin({
|
||||||
|
* text: 'Plugin added later!'
|
||||||
|
* });
|
||||||
|
* // Click play
|
||||||
|
* // --> Should alert 'Plugin added later!'
|
||||||
|
*
|
||||||
|
* @param {String} The plugin name
|
||||||
|
* @param {Function} The plugin function that will be called with options
|
||||||
|
*/
|
||||||
videojs.plugin = plugin;
|
videojs.plugin = plugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility function for adding languages to the default options. Useful for
|
* Adding languages so that they're available to all players.
|
||||||
* amending multiple language support at runtime.
|
|
||||||
*
|
*
|
||||||
* Example: videojs.addLanguage('es', {'Hello':'Hola'});
|
* videojs.addLanguage('es', { 'Hello': 'Hola' });
|
||||||
*
|
*
|
||||||
* @param {String} code The language code or dictionary property
|
* @param {String} code The language code or dictionary property
|
||||||
* @param {Object} data The data values to be translated
|
* @param {Object} data The data values to be translated
|
||||||
* @return {Object} The resulting global languages dictionary object
|
*
|
||||||
|
* @return {Object} The resulting language dictionary object
|
||||||
*/
|
*/
|
||||||
videojs.addLanguage = function(code, data){
|
videojs.addLanguage = function(code, data){
|
||||||
if(Options['languages'][code] !== undefined) {
|
return merge(globalOptions.languages, { [code]: data })[code];
|
||||||
Options['languages'][code] = mergeOptions(Options['languages'][code], data);
|
|
||||||
} else {
|
|
||||||
Options['languages'][code] = data;
|
|
||||||
}
|
|
||||||
return Options['languages'];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// REMOVING: We probably should add this to the migration plugin
|
// REMOVING: We probably should add this to the migration plugin
|
||||||
|
@ -153,7 +153,7 @@ test('should export ready api call to public', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should export useful components to the public', function () {
|
test('should export useful components to the public', function () {
|
||||||
ok(videojs.TOUCH_ENABLED !== undefined, 'Touch detection should be public');
|
ok(videojs.browser.TOUCH_ENABLED !== undefined, 'Touch detection should be public');
|
||||||
ok(videojs.getComponent('ControlBar'), 'ControlBar should be public');
|
ok(videojs.getComponent('ControlBar'), 'ControlBar should be public');
|
||||||
ok(videojs.getComponent('Button'), 'Button should be public');
|
ok(videojs.getComponent('Button'), 'Button should be public');
|
||||||
ok(videojs.getComponent('PlayToggle'), 'PlayToggle should be public');
|
ok(videojs.getComponent('PlayToggle'), 'PlayToggle should be public');
|
||||||
@ -213,7 +213,7 @@ test('should be able to initialize player twice on the same tag using string ref
|
|||||||
player.dispose();
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('videojs.players should be available after minification', function() {
|
test('videojs.getPlayers() should be available after minification', function() {
|
||||||
var videoTag = testHelperMakeTag();
|
var videoTag = testHelperMakeTag();
|
||||||
var id = videoTag.id;
|
var id = videoTag.id;
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ test('videojs.players should be available after minification', function() {
|
|||||||
fixture.appendChild(videoTag);
|
fixture.appendChild(videoTag);
|
||||||
|
|
||||||
var player = videojs(id);
|
var player = videojs(id);
|
||||||
ok(videojs.players[id] === player, 'videojs.players is available');
|
ok(videojs.getPlayers()[id] === player, 'videojs.getPlayers() is available');
|
||||||
|
|
||||||
player.dispose();
|
player.dispose();
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ import * as Dom from '../../src/js/utils/dom.js';
|
|||||||
import * as Events from '../../src/js/utils/events.js';
|
import * as Events from '../../src/js/utils/events.js';
|
||||||
import * as browser from '../../src/js/utils/browser.js';
|
import * as browser from '../../src/js/utils/browser.js';
|
||||||
import document from 'global/document';
|
import document from 'global/document';
|
||||||
|
import TestHelpers from './test-helpers.js';
|
||||||
|
|
||||||
q.module('Component', {
|
q.module('Component', {
|
||||||
'setup': function() {
|
'setup': function() {
|
||||||
@ -97,14 +98,14 @@ test('should do a deep merge of child options', function(){
|
|||||||
var mergedOptions = comp.options();
|
var mergedOptions = comp.options();
|
||||||
var children = mergedOptions['example'];
|
var children = mergedOptions['example'];
|
||||||
|
|
||||||
ok(children['childOne']['foo'] === 'baz', 'value three levels deep overridden');
|
strictEqual(children['childOne']['foo'], 'baz', 'value three levels deep overridden');
|
||||||
ok(children['childOne']['asdf'] === 'fdsa', 'value three levels deep maintained');
|
strictEqual(children['childOne']['asdf'], 'fdsa', 'value three levels deep maintained');
|
||||||
ok(children['childOne']['abc'] === '123', 'value three levels deep added');
|
strictEqual(children['childOne']['abc'], '123', 'value three levels deep added');
|
||||||
ok(children['childTwo'], 'object two levels deep maintained');
|
ok(children['childTwo'], 'object two levels deep maintained');
|
||||||
ok(children['childThree'] === false, 'object two levels deep removed');
|
strictEqual(children['childThree'], false, 'object two levels deep removed');
|
||||||
ok(children['childFour'], 'object two levels deep added');
|
ok(children['childFour'], 'object two levels deep added');
|
||||||
|
|
||||||
ok(Component.prototype.options_['example']['childOne']['foo'] === 'bar', 'prototype options were not overridden');
|
strictEqual(Component.prototype.options_['example']['childOne']['foo'], 'bar', 'prototype options were not overridden');
|
||||||
|
|
||||||
// Reset default component options to none
|
// Reset default component options to none
|
||||||
Component.prototype.options_ = null;
|
Component.prototype.options_ = null;
|
||||||
@ -165,8 +166,8 @@ test('should dispose of component and children', function(){
|
|||||||
|
|
||||||
// Add a listener
|
// Add a listener
|
||||||
comp.on('click', function(){ return true; });
|
comp.on('click', function(){ return true; });
|
||||||
var data = Dom.getData(comp.el());
|
var el = comp.el();
|
||||||
var id = comp.el()[Dom.expando];
|
var data = Dom.getElData(el);
|
||||||
|
|
||||||
var hasDisposed = false;
|
var hasDisposed = false;
|
||||||
var bubbles = null;
|
var bubbles = null;
|
||||||
@ -183,8 +184,8 @@ test('should dispose of component and children', function(){
|
|||||||
ok(!comp.el(), 'component element was deleted');
|
ok(!comp.el(), 'component element was deleted');
|
||||||
ok(!child.children(), 'child children were deleted');
|
ok(!child.children(), 'child children were deleted');
|
||||||
ok(!child.el(), 'child element was deleted');
|
ok(!child.el(), 'child element was deleted');
|
||||||
ok(!Dom.cache[id], 'listener cache nulled');
|
ok(!Dom.hasElData(el), 'listener data nulled');
|
||||||
ok(!Object.getOwnPropertyNames(data).length, 'original listener cache object was emptied');
|
ok(!Object.getOwnPropertyNames(data).length, 'original listener data object was emptied');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should add and remove event listeners to element', function(){
|
test('should add and remove event listeners to element', function(){
|
||||||
@ -428,7 +429,7 @@ test('should change the width and height of a component', function(){
|
|||||||
comp.height('123px');
|
comp.height('123px');
|
||||||
|
|
||||||
ok(comp.width() === 500, 'percent values working');
|
ok(comp.width() === 500, 'percent values working');
|
||||||
var compStyle = Dom.getComputedDimension(el, 'width');
|
var compStyle = TestHelpers.getComputedStyle(el, 'width');
|
||||||
ok(compStyle === comp.width() + 'px', 'matches computed style');
|
ok(compStyle === comp.width() + 'px', 'matches computed style');
|
||||||
ok(comp.height() === 123, 'px values working');
|
ok(comp.height() === 123, 'px values working');
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Player from '../../src/js/player.js';
|
import Player from '../../src/js/player.js';
|
||||||
import videojs from '../../src/js/video.js';
|
import videojs from '../../src/js/video.js';
|
||||||
import Options from '../../src/js/options.js';
|
import globalOptions from '../../src/js/global-options.js';
|
||||||
import * as Dom from '../../src/js/utils/dom.js';
|
import * as Dom from '../../src/js/utils/dom.js';
|
||||||
import * as browser from '../../src/js/utils/browser.js';
|
import * as browser from '../../src/js/utils/browser.js';
|
||||||
import log from '../../src/js/utils/log.js';
|
import log from '../../src/js/utils/log.js';
|
||||||
@ -66,7 +66,7 @@ test('should accept options from multiple sources and override in correct order'
|
|||||||
// version of the key for all version.
|
// version of the key for all version.
|
||||||
|
|
||||||
// Set a global option
|
// Set a global option
|
||||||
Options['attr'] = 1;
|
globalOptions['attr'] = 1;
|
||||||
|
|
||||||
var tag0 = TestHelpers.makeTag();
|
var tag0 = TestHelpers.makeTag();
|
||||||
var player0 = new Player(tag0);
|
var player0 = new Player(tag0);
|
||||||
@ -92,7 +92,7 @@ test('should accept options from multiple sources and override in correct order'
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should get tag, source, and track settings', function(){
|
test('should get tag, source, and track settings', function(){
|
||||||
// Partially tested in lib->getElementAttributes
|
// Partially tested in lib->getElAttributes
|
||||||
|
|
||||||
var fixture = document.getElementById('qunit-fixture');
|
var fixture = document.getElementById('qunit-fixture');
|
||||||
|
|
||||||
@ -752,14 +752,14 @@ test('should be scrubbing while seeking', function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should throw on startup no techs are specified', function() {
|
test('should throw on startup no techs are specified', function() {
|
||||||
const techOrder = Options.techOrder;
|
const techOrder = globalOptions.techOrder;
|
||||||
|
|
||||||
Options.techOrder = null;
|
globalOptions.techOrder = null;
|
||||||
q.throws(function() {
|
q.throws(function() {
|
||||||
videojs(TestHelpers.makeTag());
|
videojs(TestHelpers.makeTag());
|
||||||
}, 'a falsey techOrder should throw');
|
}, 'a falsey techOrder should throw');
|
||||||
|
|
||||||
Options.techOrder = techOrder;
|
globalOptions.techOrder = techOrder;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should have a sensible toJSON that is equivalent to player.options', function() {
|
test('should have a sensible toJSON that is equivalent to player.options', function() {
|
||||||
|
@ -26,16 +26,20 @@ var TestHelpers = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getComputedStyle: function(el, rule){
|
getComputedStyle: function(el, rule){
|
||||||
var val;
|
if (document.defaultView && document.defaultView.getComputedStyle) {
|
||||||
|
return document.defaultView.getComputedStyle(el, null).getPropertyValue(rule);
|
||||||
if(window.getComputedStyle){
|
|
||||||
val = window.getComputedStyle(el, null).getPropertyValue(rule);
|
|
||||||
// IE8
|
|
||||||
} else if(el.currentStyle){
|
|
||||||
val = el.currentStyle[rule];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
// IE8
|
||||||
|
if (el.currentStyle) {
|
||||||
|
if (rule === 'width' || rule === 'height') {
|
||||||
|
// return clientWidth or clientHeight instead for better accuracy
|
||||||
|
rule = 'client' + rule.substr(0, 1).toUpperCase() + rule.substr(1);
|
||||||
|
return el[rule] + 'px';
|
||||||
|
} else {
|
||||||
|
return el.currentStyle[rule];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import document from 'global/document';
|
import document from 'global/document';
|
||||||
import * as Dom from '../../../src/js/utils/dom.js';
|
import * as Dom from '../../../src/js/utils/dom.js';
|
||||||
|
import TestHelpers from '../test-helpers.js';
|
||||||
|
|
||||||
test('should return the element with the ID', function(){
|
test('should return the element with the ID', function(){
|
||||||
var el1 = document.createElement('div');
|
var el1 = document.createElement('div');
|
||||||
@ -12,8 +13,8 @@ test('should return the element with the ID', function(){
|
|||||||
el1.id = 'test_id1';
|
el1.id = 'test_id1';
|
||||||
el2.id = 'test_id2';
|
el2.id = 'test_id2';
|
||||||
|
|
||||||
ok(Dom.el('test_id1') === el1, 'found element for ID');
|
ok(Dom.getEl('test_id1') === el1, 'found element for ID');
|
||||||
ok(Dom.el('#test_id2') === el2, 'found element for CSS ID');
|
ok(Dom.getEl('#test_id2') === el2, 'found element for CSS ID');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should create an element', function(){
|
test('should create an element', function(){
|
||||||
@ -30,49 +31,47 @@ test('should insert an element first in another', function(){
|
|||||||
var el2 = document.createElement('div');
|
var el2 = document.createElement('div');
|
||||||
var parent = document.createElement('div');
|
var parent = document.createElement('div');
|
||||||
|
|
||||||
Dom.insertFirst(el1, parent);
|
Dom.insertElFirst(el1, parent);
|
||||||
ok(parent.firstChild === el1, 'inserts first into empty parent');
|
ok(parent.firstChild === el1, 'inserts first into empty parent');
|
||||||
|
|
||||||
Dom.insertFirst(el2, parent);
|
Dom.insertElFirst(el2, parent);
|
||||||
ok(parent.firstChild === el2, 'inserts first into parent with child');
|
ok(parent.firstChild === el2, 'inserts first into parent with child');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should get and remove data from an element', function(){
|
test('should get and remove data from an element', function(){
|
||||||
var el = document.createElement('div');
|
var el = document.createElement('div');
|
||||||
var data = Dom.getData(el);
|
var data = Dom.getElData(el);
|
||||||
var id = el[Dom.expando];
|
|
||||||
|
|
||||||
ok(typeof data === 'object', 'data object created');
|
ok(typeof data === 'object', 'data object created');
|
||||||
|
|
||||||
// Add data
|
// Add data
|
||||||
var testData = { asdf: 'fdsa' };
|
var testData = { asdf: 'fdsa' };
|
||||||
data.test = testData;
|
data.test = testData;
|
||||||
ok(Dom.getData(el).test === testData, 'data added');
|
ok(Dom.getElData(el).test === testData, 'data added');
|
||||||
|
|
||||||
// Remove all data
|
// Remove all data
|
||||||
Dom.removeData(el);
|
Dom.removeElData(el);
|
||||||
|
|
||||||
ok(!Dom.cache[id], 'cached item nulled');
|
ok(!Dom.hasElData(el), 'cached item emptied');
|
||||||
ok(el[Dom.expando] === null || el[Dom.expando] === undefined, 'element data id removed');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should add and remove a class name on an element', function(){
|
test('should add and remove a class name on an element', function(){
|
||||||
var el = document.createElement('div');
|
var el = document.createElement('div');
|
||||||
Dom.addClass(el, 'test-class');
|
Dom.addElClass(el, 'test-class');
|
||||||
ok(el.className === 'test-class', 'class added');
|
ok(el.className === 'test-class', 'class added');
|
||||||
Dom.addClass(el, 'test-class');
|
Dom.addElClass(el, 'test-class');
|
||||||
ok(el.className === 'test-class', 'same class not duplicated');
|
ok(el.className === 'test-class', 'same class not duplicated');
|
||||||
Dom.addClass(el, 'test-class2');
|
Dom.addElClass(el, 'test-class2');
|
||||||
ok(el.className === 'test-class test-class2', 'added second class');
|
ok(el.className === 'test-class test-class2', 'added second class');
|
||||||
Dom.removeClass(el, 'test-class');
|
Dom.removeElClass(el, 'test-class');
|
||||||
ok(el.className === 'test-class2', 'removed first class');
|
ok(el.className === 'test-class2', 'removed first class');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should read class names on an element', function(){
|
test('should read class names on an element', function(){
|
||||||
var el = document.createElement('div');
|
var el = document.createElement('div');
|
||||||
Dom.addClass(el, 'test-class1');
|
Dom.addElClass(el, 'test-class1');
|
||||||
ok(Dom.hasClass(el, 'test-class1') === true, 'class detected');
|
ok(Dom.hasElClass(el, 'test-class1') === true, 'class detected');
|
||||||
ok(Dom.hasClass(el, 'test-class') === false, 'substring correctly not detected');
|
ok(Dom.hasElClass(el, 'test-class') === false, 'substring correctly not detected');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should set element attributes from object', function(){
|
test('should set element attributes from object', function(){
|
||||||
@ -81,7 +80,7 @@ test('should set element attributes from object', function(){
|
|||||||
el = document.createElement('div');
|
el = document.createElement('div');
|
||||||
el.id = 'el1';
|
el.id = 'el1';
|
||||||
|
|
||||||
Dom.setElementAttributes(el, { controls: true, 'data-test': 'asdf' });
|
Dom.setElAttributes(el, { controls: true, 'data-test': 'asdf' });
|
||||||
|
|
||||||
equal(el.getAttribute('id'), 'el1');
|
equal(el.getAttribute('id'), 'el1');
|
||||||
equal(el.getAttribute('controls'), '');
|
equal(el.getAttribute('controls'), '');
|
||||||
@ -100,10 +99,10 @@ test('should read tag attributes from elements, including HTML5 in all browsers'
|
|||||||
|
|
||||||
document.getElementById('qunit-fixture').innerHTML += tags;
|
document.getElementById('qunit-fixture').innerHTML += tags;
|
||||||
|
|
||||||
var vid1Vals = Dom.getElementAttributes(document.getElementById('vid1'));
|
var vid1Vals = Dom.getElAttributes(document.getElementById('vid1'));
|
||||||
var vid2Vals = Dom.getElementAttributes(document.getElementById('vid2'));
|
var vid2Vals = Dom.getElAttributes(document.getElementById('vid2'));
|
||||||
var sourceVals = Dom.getElementAttributes(document.getElementById('source'));
|
var sourceVals = Dom.getElAttributes(document.getElementById('source'));
|
||||||
var trackVals = Dom.getElementAttributes(document.getElementById('track'));
|
var trackVals = Dom.getElAttributes(document.getElementById('track'));
|
||||||
|
|
||||||
// was using deepEqual, but ie8 would send all properties as attributes
|
// was using deepEqual, but ie8 would send all properties as attributes
|
||||||
|
|
||||||
@ -139,29 +138,9 @@ test('should read tag attributes from elements, including HTML5 in all browsers'
|
|||||||
equal(trackVals['title'], 'test');
|
equal(trackVals['title'], 'test');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should get the right style values for an element', function(){
|
test('Dom.findElPosition should find top and left position', function() {
|
||||||
var el = document.createElement('div');
|
|
||||||
var container = document.createElement('div');
|
|
||||||
var fixture = document.getElementById('qunit-fixture');
|
|
||||||
|
|
||||||
container.appendChild(el);
|
|
||||||
fixture.appendChild(container);
|
|
||||||
|
|
||||||
container.style.width = '1000px';
|
|
||||||
container.style.height = '1000px';
|
|
||||||
|
|
||||||
el.style.height = '100%';
|
|
||||||
el.style.width = '123px';
|
|
||||||
|
|
||||||
// integer px values may get translated int very-close floats in Chrome/OS X
|
|
||||||
// so round the dimensions to ignore this
|
|
||||||
equal(Math.round(parseFloat(Dom.getComputedDimension(el, 'height'))), 1000, 'the computed height is equal');
|
|
||||||
equal(Math.round(parseFloat(Dom.getComputedDimension(el, 'width'))), 123, 'the computed width is equal');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Dom.findPosition should find top and left position', function() {
|
|
||||||
const d = document.createElement('div');
|
const d = document.createElement('div');
|
||||||
let position = Dom.findPosition(d);
|
let position = Dom.findElPosition(d);
|
||||||
d.style.top = '10px';
|
d.style.top = '10px';
|
||||||
d.style.left = '20px';
|
d.style.left = '20px';
|
||||||
d.style.position = 'absolute';
|
d.style.position = 'absolute';
|
||||||
@ -169,10 +148,10 @@ test('Dom.findPosition should find top and left position', function() {
|
|||||||
deepEqual(position, {left: 0, top: 0}, 'If element isn\'t in the DOM, we should get zeros');
|
deepEqual(position, {left: 0, top: 0}, 'If element isn\'t in the DOM, we should get zeros');
|
||||||
|
|
||||||
document.body.appendChild(d);
|
document.body.appendChild(d);
|
||||||
position = Dom.findPosition(d);
|
position = Dom.findElPosition(d);
|
||||||
deepEqual(position, {left: 20, top: 10}, 'The position was not correct');
|
deepEqual(position, {left: 20, top: 10}, 'The position was not correct');
|
||||||
|
|
||||||
d.getBoundingClientRect = null;
|
d.getBoundingClientRect = null;
|
||||||
position = Dom.findPosition(d);
|
position = Dom.findElPosition(d);
|
||||||
deepEqual(position, {left: 0, top: 0}, 'If there is no gBCR, we should get zeros');
|
deepEqual(position, {left: 0, top: 0}, 'If there is no gBCR, we should get zeros');
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import videojs from '../../src/js/video.js';
|
import videojs from '../../src/js/video.js';
|
||||||
import TestHelpers from './test-helpers.js';
|
import TestHelpers from './test-helpers.js';
|
||||||
import Player from '../../src/js/player.js';
|
import Player from '../../src/js/player.js';
|
||||||
import Options from '../../src/js/options.js';
|
import globalOptions from '../../src/js/global-options.js';
|
||||||
import document from 'global/document';
|
import document from 'global/document';
|
||||||
|
|
||||||
q.module('video.js');
|
q.module('video.js');
|
||||||
@ -41,9 +41,9 @@ test('should add the value to the languages object', function() {
|
|||||||
data = {'Hello': 'Hola'};
|
data = {'Hello': 'Hola'};
|
||||||
result = videojs.addLanguage(code, data);
|
result = videojs.addLanguage(code, data);
|
||||||
|
|
||||||
ok(Options['languages'][code], 'should exist');
|
ok(globalOptions.languages[code], 'should exist');
|
||||||
equal(Options['languages'][code], data, 'should match');
|
equal(globalOptions.languages['es']['Hello'], 'Hola', 'should match');
|
||||||
deepEqual(result[code], Options['languages'][code], 'should also match');
|
deepEqual(result['Hello'], globalOptions.languages['es']['Hello'], 'should also match');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user