1
0
mirror of https://github.com/videojs/video.js.git synced 2025-03-29 22:07:10 +02:00

feat: remove flash tech (#3956)

Remove Flash Tech from core. Use videojs-flash if flash is needed.
Also, update DOM method names.

BREAKING CHANGE: remove flash tech from core.
This commit is contained in:
Brandon Casey 2017-01-19 16:01:56 -05:00 committed by Gary Katsevman
parent 524f868e31
commit b387437aed
22 changed files with 294 additions and 1879 deletions

View File

@ -41,7 +41,6 @@
"tsml": "1.0.1",
"videojs-font": "2.0.0",
"videojs-ie8": "1.1.2",
"videojs-swf": "5.1.0",
"videojs-vtt.js": "0.12.1",
"xhr": "2.2.2"
},

View File

@ -5,6 +5,7 @@
*/
import window from 'global/window';
import * as Dom from './utils/dom.js';
import * as DomData from './utils/dom-data';
import * as Fn from './utils/fn.js';
import * as Guid from './utils/guid.js';
import * as Events from './utils/events.js';
@ -141,7 +142,7 @@ class Component {
this.el_.parentNode.removeChild(this.el_);
}
Dom.removeElData(this.el_);
DomData.removeData(this.el_);
this.el_ = null;
}
@ -816,7 +817,7 @@ class Component {
* - False if the `Component` does not have the class`
*/
hasClass(classToCheck) {
return Dom.hasElClass(this.el_, classToCheck);
return Dom.hasClass(this.el_, classToCheck);
}
/**
@ -826,7 +827,7 @@ class Component {
* CSS class name to add
*/
addClass(classToAdd) {
Dom.addElClass(this.el_, classToAdd);
Dom.addClass(this.el_, classToAdd);
}
/**
@ -836,7 +837,7 @@ class Component {
* CSS class name to remove
*/
removeClass(classToRemove) {
Dom.removeElClass(this.el_, classToRemove);
Dom.removeClass(this.el_, classToRemove);
}
/**
@ -851,7 +852,7 @@ class Component {
* An {@link Dom~predicate} function or a boolean
*/
toggleClass(classToToggle, predicate) {
Dom.toggleElClass(this.el_, classToToggle, predicate);
Dom.toggleClass(this.el_, classToToggle, predicate);
}
/**

View File

@ -88,9 +88,9 @@ class MuteToggle extends Button {
// TODO improve muted icon classes
for (let i = 0; i < 4; i++) {
Dom.removeElClass(this.el_, `vjs-vol-${i}`);
Dom.removeClass(this.el_, `vjs-vol-${i}`);
}
Dom.addElClass(this.el_, `vjs-vol-${level}`);
Dom.addClass(this.el_, `vjs-vol-${level}`);
}
}

View File

@ -83,7 +83,7 @@ class MenuButton extends ClickableComponent {
});
menu.children_.unshift(title);
Dom.insertElFirst(title, menu.contentEl());
Dom.prependTo(title, menu.contentEl());
}
this.items = this.createItems();

View File

@ -31,7 +31,6 @@ import {ALL as TRACK_TYPES} from './tracks/track-types';
// are always included in the video.js package. Importing the modules will
// execute them and they will register themselves with video.js.
import './tech/loader.js';
import './tech/flash.js';
import './poster-image.js';
import './tracks/text-track-display.js';
import './loading-spinner.js';
@ -281,7 +280,7 @@ class Player extends Component {
let element = tag;
while (element && element.nodeType === 1) {
if (Dom.getElAttributes(element).hasOwnProperty('lang')) {
if (Dom.getAttributes(element).hasOwnProperty('lang')) {
options.language = element.getAttribute('lang');
break;
}
@ -307,7 +306,7 @@ class Player extends Component {
this.tag = tag;
// Store the tag attributes used to restore html5 element
this.tagAttributes = tag && Dom.getElAttributes(tag);
this.tagAttributes = tag && Dom.getAttributes(tag);
// Update current language
this.language(this.options_.language);
@ -487,7 +486,7 @@ class Player extends Component {
// Copy over all the attributes from the tag, including ID and class
// ID will now reference player box, not the video tag
const attrs = Dom.getElAttributes(tag);
const attrs = Dom.getAttributes(tag);
Object.getOwnPropertyNames(attrs).forEach(function(attr) {
// workaround so we don't totally break IE7
@ -534,7 +533,7 @@ class Player extends Component {
for (let i = 0; i < links.length; i++) {
const linkEl = links.item(i);
Dom.addElClass(linkEl, 'vjs-hidden');
Dom.addClass(linkEl, 'vjs-hidden');
linkEl.setAttribute('hidden', 'hidden');
}
@ -552,7 +551,7 @@ class Player extends Component {
// will work properly for other components
//
// Breaks iPhone, fixed in HTML5 setup.
Dom.insertElFirst(tag, el);
Dom.prependTo(tag, el);
this.children_.unshift(tag);
this.el_ = el;
@ -893,7 +892,7 @@ class Player extends Component {
// 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
if (this.tech_.el().parentNode !== this.el() && (techName !== 'Html5' || !this.tag)) {
Dom.insertElFirst(this.tech_.el(), this.el());
Dom.prependTo(this.tech_.el(), this.el());
}
// Get rid of the original video tag reference after the first tech is loaded
@ -1999,7 +1998,7 @@ class Player extends Component {
document.documentElement.style.overflow = 'hidden';
// Apply fullscreen styles
Dom.addElClass(document.body, 'vjs-full-window');
Dom.addClass(document.body, 'vjs-full-window');
/**
* @event Player#enterFullWindow
@ -2038,7 +2037,7 @@ class Player extends Component {
document.documentElement.style.overflow = this.docOrigOverflow;
// Remove fullscreen styles
Dom.removeElClass(document.body, 'vjs-full-window');
Dom.removeClass(document.body, 'vjs-full-window');
// Resize the box, controller, and poster to original sizes
// this.positionAll();
@ -3042,10 +3041,10 @@ class Player extends Component {
tracks: []
};
const tagOptions = Dom.getElAttributes(tag);
const tagOptions = Dom.getAttributes(tag);
const dataSetup = tagOptions['data-setup'];
if (Dom.hasElClass(tag, 'vjs-fluid')) {
if (Dom.hasClass(tag, 'vjs-fluid')) {
tagOptions.fluid = true;
}
@ -3073,9 +3072,9 @@ class Player extends Component {
const childName = child.nodeName.toLowerCase();
if (childName === 'source') {
baseOptions.sources.push(Dom.getElAttributes(child));
baseOptions.sources.push(Dom.getAttributes(child));
} else if (childName === 'track') {
baseOptions.tracks.push(Dom.getElAttributes(child));
baseOptions.tracks.push(Dom.getAttributes(child));
}
}
}
@ -3187,8 +3186,7 @@ const navigator = window.navigator;
*/
Player.prototype.options_ = {
// Default order of fallback technology
techOrder: ['html5', 'flash'],
// techOrder: ['flash','html5'],
techOrder: ['html5'],
html5: {},
flash: {},

View File

@ -1,199 +0,0 @@
/**
* @file flash-rtmp.js
* @module flash-rtmp
*/
/**
* Add RTMP properties to the {@link Flash} Tech.
*
* @param {Flash} Flash
* The flash tech class.
*
* @mixin FlashRtmpDecorator
*/
function FlashRtmpDecorator(Flash) {
Flash.streamingFormats = {
'rtmp/mp4': 'MP4',
'rtmp/flv': 'FLV'
};
/**
* Join connection and stream with an ampersand.
*
* @param {string} connection
* The connection string.
*
* @param {string} stream
* The stream string.
*/
Flash.streamFromParts = function(connection, stream) {
return connection + '&' + stream;
};
/**
* The flash parts object that contains connection and stream info.
*
* @typedef {Object} Flash~PartsObject
*
* @property {string} connection
* The connection string of a source, defaults to an empty string.
*
* @property {string} stream
* The stream string of the source, defaults to an empty string.
*/
/**
* Convert a source url into a stream and connection parts.
*
* @param {string} src
* the source url
*
* @return {Flash~PartsObject}
* The parts object that contains a connection and a stream
*/
Flash.streamToParts = function(src) {
const parts = {
connection: '',
stream: ''
};
if (!src) {
return parts;
}
// Look for the normal URL separator we expect, '&'.
// If found, we split the URL into two pieces around the
// first '&'.
let connEnd = src.search(/&(?!\w+=)/);
let streamBegin;
if (connEnd !== -1) {
streamBegin = connEnd + 1;
} else {
// If there's not a '&', we use the last '/' as the delimiter.
connEnd = streamBegin = src.lastIndexOf('/') + 1;
if (connEnd === 0) {
// really, there's not a '/'?
connEnd = streamBegin = src.length;
}
}
parts.connection = src.substring(0, connEnd);
parts.stream = src.substring(streamBegin, src.length);
return parts;
};
/**
* Check if the source type is a streaming type.
*
* @param {string} srcType
* The mime type to check.
*
* @return {boolean}
* - True if the source type is a streaming type.
* - False if the source type is not a streaming type.
*/
Flash.isStreamingType = function(srcType) {
return srcType in Flash.streamingFormats;
};
// RTMP has four variations, any string starting
// with one of these protocols should be valid
/**
* Regular expression used to check if the source is an rtmp source.
*
* @property {RegExp} Flash.RTMP_RE
*/
Flash.RTMP_RE = /^rtmp[set]?:\/\//i;
/**
* Check if the source itself is a streaming type.
*
* @param {string} src
* The url to the source.
*
* @return {boolean}
* - True if the source url indicates that the source is streaming.
* - False if the shource url indicates that the source url is not streaming.
*/
Flash.isStreamingSrc = function(src) {
return Flash.RTMP_RE.test(src);
};
/**
* A source handler for RTMP urls
* @type {Object}
*/
Flash.rtmpSourceHandler = {};
/**
* Check if Flash can play the given mime type.
*
* @param {string} type
* The mime type to check
*
* @return {string}
* 'maybe', or '' (empty string)
*/
Flash.rtmpSourceHandler.canPlayType = function(type) {
if (Flash.isStreamingType(type)) {
return 'maybe';
}
return '';
};
/**
* Check if Flash can handle the source natively
*
* @param {Object} source
* The source object
*
* @param {Object} [options]
* The options passed to the tech
*
* @return {string}
* 'maybe', or '' (empty string)
*/
Flash.rtmpSourceHandler.canHandleSource = function(source, options) {
const can = Flash.rtmpSourceHandler.canPlayType(source.type);
if (can) {
return can;
}
if (Flash.isStreamingSrc(source.src)) {
return 'maybe';
}
return '';
};
/**
* Pass the source to the flash object.
*
* @param {Object} source
* The source object
*
* @param {Flash} tech
* The instance of the Flash tech
*
* @param {Object} [options]
* The options to pass to the source
*/
Flash.rtmpSourceHandler.handleSource = function(source, tech, options) {
const srcParts = Flash.streamToParts(source.src);
tech.setRtmpConnection(srcParts.connection);
tech.setRtmpStream(srcParts.stream);
};
// Register the native source handler
Flash.registerSourceHandler(Flash.rtmpSourceHandler);
return Flash;
}
export default FlashRtmpDecorator;

File diff suppressed because it is too large Load Diff

View File

@ -214,14 +214,14 @@ class Html5 extends Tech {
el = document.createElement('video');
// determine if native controls should be used
const tagAttributes = this.options_.tag && Dom.getElAttributes(this.options_.tag);
const tagAttributes = this.options_.tag && Dom.getAttributes(this.options_.tag);
const attributes = mergeOptions({}, tagAttributes);
if (!browser.TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) {
delete attributes.controls;
}
Dom.setElAttributes(el,
Dom.setAttributes(el,
assign(attributes, {
id: this.options_.techId,
class: 'vjs-tech'
@ -242,7 +242,7 @@ class Html5 extends Tech {
if (typeof this.options_[attr] !== 'undefined') {
overwriteAttrs[attr] = this.options_[attr];
}
Dom.setElAttributes(el, overwriteAttrs);
Dom.setAttributes(el, overwriteAttrs);
}
return el;

98
src/js/utils/dom-data.js Normal file
View File

@ -0,0 +1,98 @@
/**
* @file dom-data.js
* @module dom-data
*/
import * as Guid from './guid.js';
/**
* Element Data Store.
*
* Allows for binding data to an element without putting it directly on the
* element. Ex. Event listeners are stored here.
* (also from jsninja.com, slightly modified and updated for closure compiler)
*
* @type {Object}
* @private
*/
const elData = {};
/*
* Unique attribute name to store an element's guid in
*
* @type {String}
* @constant
* @private
*/
const elIdAttr = 'vdata' + (new Date()).getTime();
/**
* Returns the cache object where data for an element is stored
*
* @param {Element} el
* Element to store data for.
*
* @return {Object}
* The cache object for that el that was passed in.
*/
export function getData(el) {
let id = el[elIdAttr];
if (!id) {
id = el[elIdAttr] = Guid.newGUID();
}
if (!elData[id]) {
elData[id] = {};
}
return elData[id];
}
/**
* Returns whether or not an element has cached data
*
* @param {Element} el
* Check if this element has cached data.
*
* @return {boolean}
* - True if the DOM element has cached data.
* - False otherwise.
*/
export function hasData(el) {
const id = el[elIdAttr];
if (!id) {
return false;
}
return !!Object.getOwnPropertyNames(elData[id]).length;
}
/**
* Delete data for the element from the cache and the guid attr from getElementById
*
* @param {Element} el
* Remove cached data for this element.
*/
export function removeData(el) {
const id = el[elIdAttr];
if (!id) {
return;
}
// Remove all stored data
delete elData[id];
// Remove the elIdAttr property from the DOM node
try {
delete el[elIdAttr];
} catch (e) {
if (el.removeAttribute) {
el.removeAttribute(elIdAttr);
} else {
// IE doesn't appear to support removeAttribute on the document element
el[elIdAttr] = null;
}
}
}

View File

@ -4,7 +4,6 @@
*/
import document from 'global/document';
import window from 'global/window';
import * as Guid from './guid.js';
import log from './log.js';
import tsml from 'tsml';
import {isObject} from './obj';
@ -110,24 +109,6 @@ function createQuerier(method) {
};
}
/**
* Shorthand for document.getElementById()
* Also allows for CSS (jQuery) ID syntax. But nothing other than IDs.
*
* @param {string} id
* The id of the element to get
*
* @return {Element|null}
* Element with supplied ID or null if there wasn't one.
*/
export function getEl(id) {
if (id.indexOf('#') === 0) {
id = id.slice(1);
}
return document.getElementById(id);
}
/**
* Creates an element and applies properties.
*
@ -210,9 +191,8 @@ export function textContent(el, text) {
*
* @param {Element} parent
* Element to insert child into
*
*/
export function insertElFirst(child, parent) {
export function prependTo(child, parent) {
if (parent.firstChild) {
parent.insertBefore(child, parent.firstChild);
} else {
@ -220,97 +200,6 @@ export function insertElFirst(child, parent) {
}
}
/**
* Element Data Store. Allows for binding data to an element without putting it directly on the element.
* Ex. Event listeners are stored here.
* (also from jsninja.com, slightly modified and updated for closure compiler)
*
* @type {Object}
* @private
*/
const elData = {};
/*
* Unique attribute name to store an element's guid in
*
* @type {string}
* @constant
* @private
*/
const elIdAttr = 'vdata' + (new Date()).getTime();
/**
* Returns the cache object where data for an element is stored
*
* @param {Element} el
* Element to store data for.
*
* @return {Object}
* The cache object for that el that was passed in.
*/
export function getElData(el) {
let id = el[elIdAttr];
if (!id) {
id = el[elIdAttr] = Guid.newGUID();
}
if (!elData[id]) {
elData[id] = {};
}
return elData[id];
}
/**
* Returns whether or not an element has cached data
*
* @param {Element} el
* Check if this element has cached data.
*
* @return {boolean}
* - True if the DOM element has cached data.
* - False otherwise.
*/
export function hasElData(el) {
const id = el[elIdAttr];
if (!id) {
return false;
}
return !!Object.getOwnPropertyNames(elData[id]).length;
}
/**
* Delete data for the element from the cache and the guid attr from getElementById
*
* @param {Element} el
* Remove cached data for this element.
*/
export function removeElData(el) {
const id = el[elIdAttr];
if (!id) {
return;
}
// Remove all stored data
delete elData[id];
// Remove the elIdAttr property from the DOM node
try {
delete el[elIdAttr];
} catch (e) {
if (el.removeAttribute) {
el.removeAttribute(elIdAttr);
} else {
// IE doesn't appear to support removeAttribute on the document element
el[elIdAttr] = null;
}
}
}
/**
* Check if an element has a CSS class
*
@ -327,7 +216,7 @@ export function removeElData(el) {
* @throws {Error}
* Throws an error if `classToCheck` has white space.
*/
export function hasElClass(element, classToCheck) {
export function hasClass(element, classToCheck) {
throwIfWhitespace(classToCheck);
if (element.classList) {
return element.classList.contains(classToCheck);
@ -347,13 +236,13 @@ export function hasElClass(element, classToCheck) {
* @return {Element}
* The dom element with the added class name.
*/
export function addElClass(element, classToAdd) {
export function addClass(element, classToAdd) {
if (element.classList) {
element.classList.add(classToAdd);
// Don't need to `throwIfWhitespace` here because `hasElClass` will do it
// in the case of classList not being supported.
} else if (!hasElClass(element, classToAdd)) {
} else if (!hasClass(element, classToAdd)) {
element.className = (element.className + ' ' + classToAdd).trim();
}
@ -372,7 +261,7 @@ export function addElClass(element, classToAdd) {
* @return {Element}
* The dom element with class name removed.
*/
export function removeElClass(element, classToRemove) {
export function removeClass(element, classToRemove) {
if (element.classList) {
element.classList.remove(classToRemove);
} else {
@ -417,12 +306,12 @@ export function removeElClass(element, classToRemove) {
* @return {Element}
* The element with a class that has been toggled.
*/
export function toggleElClass(element, classToToggle, predicate) {
export function toggleClass(element, classToToggle, predicate) {
// This CANNOT use `classList` internally because IE does not support the
// second parameter to the `classList.toggle()` method! Which is fine because
// `classList` will be used by the add/remove functions.
const has = hasElClass(element, classToToggle);
const has = hasClass(element, classToToggle);
if (typeof predicate === 'function') {
predicate = predicate(element, classToToggle);
@ -439,9 +328,9 @@ export function toggleElClass(element, classToToggle, predicate) {
}
if (predicate) {
addElClass(element, classToToggle);
addClass(element, classToToggle);
} else {
removeElClass(element, classToToggle);
removeClass(element, classToToggle);
}
return element;
@ -456,7 +345,7 @@ export function toggleElClass(element, classToToggle, predicate) {
* @param {Object} [attributes]
* Attributes to be applied.
*/
export function setElAttributes(el, attributes) {
export function setAttributes(el, attributes) {
Object.getOwnPropertyNames(attributes).forEach(function(attrName) {
const attrValue = attributes[attrName];
@ -480,7 +369,7 @@ export function setElAttributes(el, attributes) {
* @return {Object}
* All attributes of the element.
*/
export function getElAttributes(tag) {
export function getAttributes(tag) {
const obj = {};
// known boolean attributes
@ -642,7 +531,7 @@ export function getBoundingClientRect(el) {
* @return {Dom~Position}
* The position of the element that was passed in.
*/
export function findElPosition(el) {
export function findPosition(el) {
let box;
if (el.getBoundingClientRect && el.parentNode) {
@ -703,7 +592,7 @@ export function findElPosition(el) {
*/
export function getPointerPosition(el, event) {
const position = {};
const box = findElPosition(el);
const box = findPosition(el);
const boxW = el.offsetWidth;
const boxH = el.offsetHeight;

View File

@ -7,7 +7,7 @@
* @module events
*/
import * as Dom from './dom.js';
import * as DomData from './dom-data';
import * as Guid from './guid.js';
import log from './log.js';
import window from 'global/window';
@ -23,7 +23,7 @@ import document from 'global/document';
* Type of event to clean up
*/
function _cleanUpEvents(elem, type) {
const data = Dom.getElData(elem);
const data = DomData.getData(elem);
// Remove the events of a particular type if there are none left
if (data.handlers[type].length === 0) {
@ -48,7 +48,7 @@ function _cleanUpEvents(elem, type) {
// Finally remove the element data if there is no data left
if (Object.getOwnPropertyNames(data).length === 0) {
Dom.removeElData(elem);
DomData.removeData(elem);
}
}
@ -222,7 +222,7 @@ export function on(elem, type, fn) {
return _handleMultipleEvents(on, elem, type, fn);
}
const data = Dom.getElData(elem);
const data = DomData.getData(elem);
// We need a place to store all our handler data
if (!data.handlers) {
@ -295,11 +295,11 @@ export function on(elem, type, fn) {
*/
export function off(elem, type, fn) {
// Don't want to add a cache object through getElData if not needed
if (!Dom.hasElData(elem)) {
if (!DomData.hasData(elem)) {
return;
}
const data = Dom.getElData(elem);
const data = DomData.getData(elem);
// If no events exist, nothing to unbind
if (!data.handlers) {
@ -369,7 +369,7 @@ export function trigger(elem, event, hash) {
// Fetches element data and a reference to the parent (for bubbling).
// Don't want to add a data object to cache for every parent,
// so checking hasElData first.
const elemData = (Dom.hasElData(elem)) ? Dom.getElData(elem) : {};
const elemData = (DomData.hasData(elem)) ? DomData.getData(elem) : {};
const parent = elem.parentNode || elem.ownerDocument;
// type = event.type || event,
// handler;
@ -393,7 +393,7 @@ export function trigger(elem, event, hash) {
// If at the top of the DOM, triggers the default action unless disabled.
} else if (!parent && !event.defaultPrevented) {
const targetData = Dom.getElData(event.target);
const targetData = DomData.getData(event.target);
// Checks if the target has a default action for this event.
if (event.target[event.type]) {

View File

@ -63,6 +63,7 @@ function videojs(id, options, ready) {
// Allow for element or ID to be passed in
// String ID
if (typeof id === 'string') {
const players = videojs.getPlayers();
// Adjust for jQuery ID syntax
if (id.indexOf('#') === 0) {
@ -70,22 +71,22 @@ function videojs(id, options, ready) {
}
// If a player instance has already been created for this ID return it.
if (videojs.getPlayers()[id]) {
if (players[id]) {
// If options or ready funtion are passed, warn
// If options or ready function are passed, warn
if (options) {
log.warn(`Player "${id}" is already initialised. Options will not be applied.`);
}
if (ready) {
videojs.getPlayers()[id].ready(ready);
players[id].ready(ready);
}
return videojs.getPlayers()[id];
return players[id];
}
// Otherwise get element for ID
tag = Dom.getEl(id);
tag = Dom.$('#' + id);
// ID is a media element
} else {
@ -558,58 +559,58 @@ videojs.VideoTrack = VideoTrack;
* Determines, via duck typing, whether or not a value is a DOM element.
*
* @borrows dom:isEl as videojs.isEl
* @deprecated Use videojs.dom.isEl() instead
*/
videojs.isEl = Dom.isEl;
/**
* Determines, via duck typing, whether or not a value is a text node.
*
* @borrows dom:isTextNode as videojs.isTextNode
* @deprecated Use videojs.dom.isTextNode() instead
*/
videojs.isTextNode = Dom.isTextNode;
/**
* Creates an element and applies properties.
*
* @borrows dom:createEl as videojs.createEl
* @deprecated Use videojs.dom.createEl() instead
*/
videojs.createEl = Dom.createEl;
/**
* Check if an element has a CSS class
*
* @borrows dom:hasElClass as videojs.hasClass
* @deprecated Use videojs.dom.hasClass() instead
*/
videojs.hasClass = Dom.hasElClass;
/**
* Add a CSS class name to an element
*
* @borrows dom:addElClass as videojs.addClass
* @deprecated Use videojs.dom.addClass() instead
*/
videojs.addClass = Dom.addElClass;
/**
* Remove a CSS class name from an element
*
* @borrows dom:removeElClass as videojs.removeClass
* @deprecated Use videojs.dom.removeClass() instead
*/
videojs.removeClass = Dom.removeElClass;
/**
* Adds or removes a CSS class name on an element depending on an optional
* condition or the presence/absence of the class name.
*
* @borrows dom:toggleElClass as videojs.toggleClass
* @deprecated Use videojs.dom.toggleClass() instead
*/
videojs.toggleClass = Dom.toggleElClass;
/**
* Apply attributes to an HTML element.
*
* @borrows dom:setElAttributes as videojs.setAttribute
* @deprecated Use videojs.dom.setAttributes() instead
*/
videojs.setAttributes = Dom.setElAttributes;
/**
* Get an element's attribute values, as defined on the HTML tag
@ -618,15 +619,15 @@ videojs.setAttributes = Dom.setElAttributes;
* This will return true or false for boolean attributes.
*
* @borrows dom:getElAttributes as videojs.getAttributes
* @deprecated Use videojs.dom.getAttributes() instead
*/
videojs.getAttributes = Dom.getElAttributes;
/**
* Empties the contents of an element.
*
* @borrows dom:emptyEl as videojs.emptyEl
* @deprecated Use videojs.dom.emptyEl() instead
*/
videojs.emptyEl = Dom.emptyEl;
/**
* Normalizes and appends content to an element.
@ -649,8 +650,8 @@ videojs.emptyEl = Dom.emptyEl;
* node, or array.
*
* @borrows dom:appendContents as videojs.appendContet
* @deprecated Use videojs.dom.appendContent() instead
*/
videojs.appendContent = Dom.appendContent;
/**
* Normalizes and inserts content into an element; this is identical to
@ -674,8 +675,27 @@ videojs.appendContent = Dom.appendContent;
* node, or array.
*
* @borrows dom:insertContent as videojs.insertContent
* @deprecated Use videojs.dom.insertContent() instead
*/
videojs.insertContent = Dom.insertContent;
[
'isEl',
'isTextNode',
'createEl',
'hasClass',
'addClass',
'removeClass',
'toggleClass',
'setAttributes',
'getAttributes',
'emptyEl',
'appendContent',
'insertContent'
].forEach(k => {
videojs[k] = function() {
log.warn(`videojs.${k}() is deprecated; use videojs.dom.${k}() instead`);
return Dom[k].apply(null, arguments);
};
});
/**
* A safe getComputedStyle with an IE8 fallback.
@ -689,6 +709,19 @@ videojs.insertContent = Dom.insertContent;
*/
videojs.computedStyle = computedStyle;
/**
* Export the Dom utilities for use in external plugins
* and Tech's
*/
videojs.dom = Dom;
/**
* Export the Url utilities for use in external plugins
* and Tech's
*/
videojs.url = Url;
// We use Node-style module.exports here instead of ES6 because it is more
// compatible with different module systems.
module.exports = videojs;

View File

@ -124,12 +124,9 @@ QUnit.test('should be able to access expected MediaTech API methods', function(a
const mediaProto = media.prototype;
const html5 = videojs.getComponent('Html5');
const html5Proto = html5.prototype;
const flash = videojs.getComponent('Flash');
const flashProto = flash.prototype;
assert.ok(mediaProto.setPoster, 'setPoster should exist on the Media tech');
assert.ok(html5Proto.setPoster, 'setPoster should exist on the HTML5 tech');
assert.ok(flashProto.setPoster, 'setPoster should exist on the Flash tech');
assert.ok(html5.patchCanPlayType, 'patchCanPlayType should exist for HTML5');
assert.ok(html5.unpatchCanPlayType, 'unpatchCanPlayType should exist for HTML5');
@ -143,13 +140,6 @@ QUnit.test('should be able to access expected MediaTech API methods', function(a
assert.ok(html5.prototype.setSource, 'setSource should exist for Html5');
assert.ok(html5.prototype.disposeSourceHandler,
'disposeSourceHandler should exist for Html5');
assert.ok(flash.canPlaySource, 'canPlaySource should exist for Flash');
assert.ok(flash.registerSourceHandler, 'registerSourceHandler should exist for Flash');
assert.ok(flash.selectSourceHandler, 'selectSourceHandler should exist for Flash');
assert.ok(flash.prototype.setSource, 'setSource should exist for Flash');
assert.ok(flash.prototype.disposeSourceHandler,
'disposeSourceHandler should exist for Flash');
});
QUnit.test('should export ready api call to public', function(assert) {

View File

@ -2,6 +2,7 @@
import window from 'global/window';
import Component from '../../src/js/component.js';
import * as Dom from '../../src/js/utils/dom.js';
import * as DomData from '../../src/js/utils/dom-data';
import * as Events from '../../src/js/utils/events.js';
import * as browser from '../../src/js/utils/browser.js';
import document from 'global/document';
@ -294,7 +295,7 @@ QUnit.test('should dispose of component and children', function(assert) {
return true;
});
const el = comp.el();
const data = Dom.getElData(el);
const data = DomData.getData(el);
let hasDisposed = false;
let bubbles = null;
@ -312,7 +313,7 @@ QUnit.test('should dispose of component and children', function(assert) {
assert.ok(!comp.el(), 'component element was deleted');
assert.ok(!child.children(), 'child children were deleted');
assert.ok(!child.el(), 'child element was deleted');
assert.ok(!Dom.hasElData(el), 'listener data nulled');
assert.ok(!DomData.hasData(el), 'listener data nulled');
assert.ok(!Object.getOwnPropertyNames(data).length,
'original listener data object was emptied');
});

View File

@ -87,7 +87,7 @@ QUnit.test('should accept options from multiple sources and override in correct
});
QUnit.test('should get tag, source, and track settings', function(assert) {
// Partially tested in lib->getElAttributes
// Partially tested in lib->getAttributes
const fixture = document.getElementById('qunit-fixture');

View File

@ -1,58 +0,0 @@
/* eslint-env qunit */
import Flash from '../../../src/js/tech/flash.js';
QUnit.module('Flash RTMP');
const streamToPartsAndBack = function(url) {
const parts = Flash.streamToParts(url);
return Flash.streamFromParts(parts.connection, parts.stream);
};
QUnit.test('test using both streamToParts and streamFromParts', function(assert) {
assert.ok(streamToPartsAndBack('rtmp://myurl.com/isthis') === 'rtmp://myurl.com/&isthis');
assert.ok(streamToPartsAndBack('rtmp://myurl.com/&isthis') === 'rtmp://myurl.com/&isthis');
assert.ok(streamToPartsAndBack('rtmp://myurl.com/isthis/andthis') === 'rtmp://myurl.com/isthis/&andthis');
});
QUnit.test('test streamToParts', function(assert) {
let parts = Flash.streamToParts('http://myurl.com/streaming&/is/fun');
assert.ok(parts.connection === 'http://myurl.com/streaming');
assert.ok(parts.stream === '/is/fun');
parts = Flash.streamToParts('http://myurl.com/&streaming&/is/fun');
assert.ok(parts.connection === 'http://myurl.com/');
assert.ok(parts.stream === 'streaming&/is/fun');
parts = Flash.streamToParts('http://myurl.com/really?streaming=fun&really=fun');
assert.ok(parts.connection === 'http://myurl.com/');
assert.ok(parts.stream === 'really?streaming=fun&really=fun');
parts = Flash.streamToParts('http://myurl.com/streaming/is/fun');
assert.ok(parts.connection === 'http://myurl.com/streaming/is/');
assert.ok(parts.stream === 'fun');
parts = Flash.streamToParts('whatisgoingonhere');
assert.ok(parts.connection === 'whatisgoingonhere');
assert.ok(parts.stream === '');
parts = Flash.streamToParts();
assert.ok(parts.connection === '');
assert.ok(parts.stream === '');
});
QUnit.test('test isStreamingSrc', function(assert) {
const isStreamingSrc = Flash.isStreamingSrc;
assert.ok(isStreamingSrc('rtmp://streaming.is/fun'));
assert.ok(isStreamingSrc('rtmps://streaming.is/fun'));
assert.ok(isStreamingSrc('rtmpe://streaming.is/fun'));
assert.ok(isStreamingSrc('rtmpt://streaming.is/fun'));
// test invalid protocols
assert.ok(!isStreamingSrc('rtmp:streaming.is/fun'));
assert.ok(!isStreamingSrc('rtmpz://streaming.is/fun'));
assert.ok(!isStreamingSrc('http://streaming.is/fun'));
assert.ok(!isStreamingSrc('https://streaming.is/fun'));
assert.ok(!isStreamingSrc('file://streaming.is/fun'));
});

View File

@ -1,263 +0,0 @@
/* eslint-env qunit */
import Flash from '../../../src/js/tech/flash.js';
import { createTimeRange } from '../../../src/js/utils/time-ranges.js';
import document from 'global/document';
import sinon from 'sinon';
// fake out the <object> interaction but leave all the other logic intact
class MockFlash extends Flash {
constructor() {
super({});
}
}
QUnit.module('Flash');
QUnit.test('Flash.canPlaySource', function(assert) {
const canPlaySource = Flash.canPlaySource;
// Supported
assert.ok(canPlaySource({type: 'video/mp4; codecs=avc1.42E01E,mp4a.40.2' }, {}),
'codecs supported');
assert.ok(canPlaySource({type: 'video/mp4' }, {}), 'video/mp4 supported');
assert.ok(canPlaySource({type: 'video/x-flv' }, {}), 'video/x-flv supported');
assert.ok(canPlaySource({type: 'video/flv' }, {}), 'video/flv supported');
assert.ok(canPlaySource({type: 'video/m4v' }, {}), 'video/m4v supported');
assert.ok(canPlaySource({type: 'VIDEO/FLV' }, {}), 'capitalized mime type');
// Not supported
assert.ok(!canPlaySource({ type: 'video/webm; codecs="vp8, vorbis"' }, {}));
assert.ok(!canPlaySource({ type: 'video/webm' }, {}));
});
QUnit.test('currentTime', function(assert) {
const getCurrentTime = Flash.prototype.currentTime;
const setCurrentTime = Flash.prototype.setCurrentTime;
let seekingCount = 0;
let seeking = false;
let setPropVal;
let getPropVal;
let result;
// Mock out a Flash instance to avoid creating the swf object
const mockFlash = {
el_: {
/* eslint-disable camelcase */
vjs_setProperty(prop, val) {
setPropVal = val;
},
vjs_getProperty() {
return getPropVal;
}
/* eslint-enable camelcase */
},
seekable() {
return createTimeRange(5, 1000);
},
trigger(event) {
if (event === 'seeking') {
seekingCount++;
}
},
seeking() {
return seeking;
}
};
// Test the currentTime getter
getPropVal = 3;
result = getCurrentTime.call(mockFlash);
assert.equal(result, 3, 'currentTime is retreived from the swf element');
// Test the currentTime setter
setCurrentTime.call(mockFlash, 10);
assert.equal(setPropVal, 10, 'currentTime is set on the swf element');
assert.equal(seekingCount, 1, 'triggered seeking');
// Test current time while seeking
setCurrentTime.call(mockFlash, 20);
seeking = true;
result = getCurrentTime.call(mockFlash);
assert.equal(result,
20,
'currentTime is retrieved from the lastSeekTarget while seeking');
assert.notEqual(result,
getPropVal,
'currentTime is not retrieved from the element while seeking');
assert.equal(seekingCount, 2, 'triggered seeking');
// clamp seeks to seekable
setCurrentTime.call(mockFlash, 1001);
result = getCurrentTime.call(mockFlash);
assert.equal(result, mockFlash.seekable().end(0), 'clamped to the seekable end');
assert.equal(seekingCount, 3, 'triggered seeking');
setCurrentTime.call(mockFlash, 1);
result = getCurrentTime.call(mockFlash);
assert.equal(result, mockFlash.seekable().start(0), 'clamped to the seekable start');
assert.equal(seekingCount, 4, 'triggered seeking');
});
QUnit.test('dispose removes the object element even before ready fires', function(assert) {
// This test appears to test bad functionaly that was fixed
// so it's debateable whether or not it's useful
const dispose = Flash.prototype.dispose;
const mockFlash = new MockFlash();
const noop = function() {};
// Mock required functions for dispose
mockFlash.off = noop;
mockFlash.trigger = noop;
mockFlash.el_ = {};
dispose.call(mockFlash);
assert.strictEqual(mockFlash.el_, null, 'swf el is nulled');
});
QUnit.test('ready triggering before and after disposing the tech', function(assert) {
const checkReady = sinon.stub(Flash, 'checkReady');
const fixtureDiv = document.getElementById('qunit-fixture');
const playerDiv = document.createElement('div');
const techEl = document.createElement('div');
techEl.id = 'foo1234';
playerDiv.appendChild(techEl);
fixtureDiv.appendChild(playerDiv);
// Mock the swf element
techEl.tech = {
el() {
return techEl;
}
};
playerDiv.player = {
tech: techEl.tech
};
Flash.onReady(techEl.id);
assert.ok(checkReady.called, 'checkReady should be called before the tech is disposed');
// remove the tech el from the player div to simulate being disposed
playerDiv.removeChild(techEl);
Flash.onReady(techEl.id);
assert.ok(!checkReady.calledTwice,
'checkReady should not be called after the tech is disposed');
Flash.checkReady.restore();
});
QUnit.test('should have the source handler interface', function(assert) {
assert.ok(Flash.registerSourceHandler, 'has the registerSourceHandler function');
});
QUnit.test('canPlayType should select the correct types to play', function(assert) {
const canPlayType = Flash.nativeSourceHandler.canPlayType;
assert.equal(canPlayType('video/flv'), 'maybe', 'should be able to play FLV files');
assert.equal(canPlayType('video/x-flv'), 'maybe', 'should be able to play x-FLV files');
assert.equal(canPlayType('video/mp4'), 'maybe', 'should be able to play MP4 files');
assert.equal(canPlayType('video/m4v'), 'maybe', 'should be able to play M4V files');
assert.equal(canPlayType('video/ogg'),
'',
'should return empty string if it can not play the video');
});
QUnit.test('canHandleSource should be able to work with src objects without a type', function(assert) {
const canHandleSource = Flash.nativeSourceHandler.canHandleSource;
assert.equal('maybe',
canHandleSource({ src: 'test.video.mp4' }, {}),
'should guess that it is a mp4 video');
assert.equal('maybe',
canHandleSource({ src: 'test.video.m4v' }, {}),
'should guess that it is a m4v video');
assert.equal('maybe',
canHandleSource({ src: 'test.video.flv' }, {}),
'should guess that it is a flash video');
assert.equal('',
canHandleSource({ src: 'test.video.wgg' }, {}),
'should return empty string if it can not play the video');
});
QUnit.test('seekable', function(assert) {
const seekable = Flash.prototype.seekable;
let result;
const mockFlash = {
duration() {
return this.duration_;
}
};
// Test a normal duration
mockFlash.duration_ = 23;
result = seekable.call(mockFlash);
assert.equal(result.length, 1, 'seekable is non-empty');
assert.equal(result.start(0), 0, 'starts at zero');
assert.equal(result.end(0), mockFlash.duration_, 'ends at the duration');
// Test a zero duration
mockFlash.duration_ = 0;
result = seekable.call(mockFlash);
assert.equal(result.length, mockFlash.duration_,
'seekable is empty with a zero duration');
});
QUnit.test('play after ended seeks to the beginning', function(assert) {
let plays = 0;
const seeks = [];
Flash.prototype.play.call({
el_: {
/* eslint-disable camelcase */
vjs_play() {
plays++;
}
/* eslint-enable camelcase */
},
ended() {
return true;
},
setCurrentTime(time) {
seeks.push(time);
}
});
assert.equal(plays, 1, 'called play on the SWF');
assert.equal(seeks.length, 1, 'seeked on play');
assert.equal(seeks[0], 0, 'seeked to the beginning');
});
QUnit.test('duration returns NaN, Infinity or duration according to the HTML standard', function(assert) {
const duration = Flash.prototype.duration;
let mockedDuration = -1;
let mockedReadyState = 0;
let result;
const mockFlash = {
el_: {
/* eslint-disable camelcase */
vjs_getProperty() {
return mockedDuration;
}
/* eslint-enable camelcase */
},
readyState() {
return mockedReadyState;
}
};
result = duration.call(mockFlash);
assert.ok(Number.isNaN(result), 'duration returns NaN when readyState equals 0');
mockedReadyState = 1;
result = duration.call(mockFlash);
assert.ok(!Number.isFinite(result),
'duration returns Infinity when duration property is less then 0');
mockedDuration = 1;
result = duration.call(mockFlash);
assert.equal(result,
1,
'duration returns duration property when readyState' +
' and duration property are both higher than 0');
});

View File

@ -1,7 +1,6 @@
/* eslint-env qunit */
import Tech from '../../../src/js/tech/tech.js';
import Html5 from '../../../src/js/tech/html5.js';
import Flash from '../../../src/js/tech/flash.js';
import Button from '../../../src/js/button.js';
import { createTimeRange } from '../../../src/js/utils/time-ranges.js';
import extendFn from '../../../src/js/extend.js';
@ -498,7 +497,6 @@ QUnit.test('Tech.isTech returns correct answers for techs and components', funct
assert.ok(isTech(Tech), 'Tech is a Tech');
assert.ok(isTech(Html5), 'Html5 is a Tech');
assert.ok(isTech(new Html5({}, {})), 'An html5 instance is a Tech');
assert.ok(isTech(Flash), 'Flash is a Tech');
assert.ok(!isTech(5), 'A number is not a Tech');
assert.ok(!isTech('this is a tech'), 'A string is not a Tech');
assert.ok(!isTech(Button), 'A Button is not a Tech');

View File

@ -108,7 +108,7 @@ const TestHelpers = {
const msg = `el should have the "${c}" class in its ` +
`className, which is "${el.className}"`;
assert.ok(Dom.hasElClass(el, c), msg);
assert.ok(Dom.hasClass(el, c), msg);
});
props.forEach(p => {

View File

@ -0,0 +1,23 @@
/* eslint-env qunit */
import document from 'global/document';
import * as DomData from '../../../src/js/utils/dom-data';
QUnit.module('dom-data');
QUnit.test('should get and remove data from an element', function(assert) {
const el = document.createElement('div');
const data = DomData.getData(el);
assert.strictEqual(typeof data, 'object', 'data object created');
// Add data
const testData = {asdf: 'fdsa'};
data.test = testData;
assert.strictEqual(DomData.getData(el).test, testData, 'data added');
// Remove all data
DomData.removeData(el);
assert.notOk(DomData.hasData(el), 'cached item emptied');
});

View File

@ -6,21 +6,6 @@ import * as Dom from '../../../src/js/utils/dom.js';
QUnit.module('dom');
QUnit.test('should return the element with the ID', function(assert) {
const el1 = document.createElement('div');
const el2 = document.createElement('div');
const fixture = document.getElementById('qunit-fixture');
fixture.appendChild(el1);
fixture.appendChild(el2);
el1.id = 'test_id1';
el2.id = 'test_id2';
assert.strictEqual(Dom.getEl('test_id1'), el1, 'found element for ID');
assert.strictEqual(Dom.getEl('#test_id2'), el2, 'found element for CSS ID');
});
QUnit.test('should create an element', function(assert) {
const div = Dom.createEl();
const span = Dom.createEl('span', {
@ -57,97 +42,79 @@ QUnit.test('should insert an element first in another', function(assert) {
const el2 = document.createElement('div');
const parent = document.createElement('div');
Dom.insertElFirst(el1, parent);
Dom.prependTo(el1, parent);
assert.strictEqual(parent.firstChild, el1, 'inserts first into empty parent');
Dom.insertElFirst(el2, parent);
Dom.prependTo(el2, parent);
assert.strictEqual(parent.firstChild, el2, 'inserts first into parent with child');
});
QUnit.test('should get and remove data from an element', function(assert) {
const el = document.createElement('div');
const data = Dom.getElData(el);
assert.strictEqual(typeof data, 'object', 'data object created');
// Add data
const testData = {asdf: 'fdsa'};
data.test = testData;
assert.strictEqual(Dom.getElData(el).test, testData, 'data added');
// Remove all data
Dom.removeElData(el);
assert.notOk(Dom.hasElData(el), 'cached item emptied');
});
QUnit.test('addElClass()', function(assert) {
QUnit.test('addClass()', function(assert) {
const el = document.createElement('div');
assert.expect(5);
Dom.addElClass(el, 'test-class');
Dom.addClass(el, 'test-class');
assert.strictEqual(el.className, 'test-class', 'adds a single class');
Dom.addElClass(el, 'test-class');
Dom.addClass(el, 'test-class');
assert.strictEqual(el.className, 'test-class', 'does not duplicate classes');
assert.throws(function() {
Dom.addElClass(el, 'foo foo-bar');
Dom.addClass(el, 'foo foo-bar');
}, 'throws when attempting to add a class with whitespace');
Dom.addElClass(el, 'test2_className');
Dom.addClass(el, 'test2_className');
assert.strictEqual(el.className, 'test-class test2_className', 'adds second class');
Dom.addElClass(el, 'FOO');
Dom.addClass(el, 'FOO');
assert.strictEqual(el.className, 'test-class test2_className FOO', 'adds third class');
});
QUnit.test('removeElClass()', function(assert) {
QUnit.test('removeClass()', function(assert) {
const el = document.createElement('div');
el.className = 'test-class test2_className FOO bar';
assert.expect(4);
Dom.removeElClass(el, 'test-class');
Dom.removeClass(el, 'test-class');
assert.strictEqual(el.className, 'test2_className FOO bar', 'removes one class');
assert.throws(function() {
Dom.removeElClass(el, 'test2_className bar');
Dom.removeClass(el, 'test2_className bar');
}, 'throws when attempting to remove a class with whitespace');
Dom.removeElClass(el, 'test2_className');
Dom.removeClass(el, 'test2_className');
assert.strictEqual(el.className, 'FOO bar', 'removes another class');
Dom.removeElClass(el, 'FOO');
Dom.removeClass(el, 'FOO');
assert.strictEqual(el.className, 'bar', 'removes another class');
});
QUnit.test('hasElClass()', function(assert) {
QUnit.test('hasClass()', function(assert) {
const el = document.createElement('div');
el.className = 'test-class foo foo test2_className FOO bar';
assert.strictEqual(Dom.hasElClass(el, 'test-class'), true, 'class detected');
assert.strictEqual(Dom.hasElClass(el, 'foo'), true, 'class detected');
assert.strictEqual(Dom.hasElClass(el, 'test2_className'), true, 'class detected');
assert.strictEqual(Dom.hasElClass(el, 'FOO'), true, 'class detected');
assert.strictEqual(Dom.hasElClass(el, 'bar'), true, 'class detected');
assert.strictEqual(Dom.hasElClass(el, 'test2'),
assert.strictEqual(Dom.hasClass(el, 'test-class'), true, 'class detected');
assert.strictEqual(Dom.hasClass(el, 'foo'), true, 'class detected');
assert.strictEqual(Dom.hasClass(el, 'test2_className'), true, 'class detected');
assert.strictEqual(Dom.hasClass(el, 'FOO'), true, 'class detected');
assert.strictEqual(Dom.hasClass(el, 'bar'), true, 'class detected');
assert.strictEqual(Dom.hasClass(el, 'test2'),
false,
'valid substring - but not a class - correctly not detected');
assert.strictEqual(Dom.hasElClass(el, 'className'),
assert.strictEqual(Dom.hasClass(el, 'className'),
false,
'valid substring - but not a class - correctly not detected');
assert.throws(function() {
Dom.hasElClass(el, 'FOO bar');
Dom.hasClass(el, 'FOO bar');
}, 'throws when attempting to detect a class with whitespace');
});
QUnit.test('toggleElClass()', function(assert) {
QUnit.test('toggleClass()', function(assert) {
const el = Dom.createEl('div', {className: 'foo bar'});
const predicateToggles = [
@ -235,18 +202,18 @@ QUnit.test('toggleElClass()', function(assert) {
assert.expect(3 + predicateToggles.length);
Dom.toggleElClass(el, 'bar');
Dom.toggleClass(el, 'bar');
assert.strictEqual(el.className, 'foo', 'toggles a class off, if present');
Dom.toggleElClass(el, 'bar');
Dom.toggleClass(el, 'bar');
assert.strictEqual(el.className, 'foo bar', 'toggles a class on, if absent');
assert.throws(function() {
Dom.toggleElClass(el, 'foo bar');
Dom.toggleClass(el, 'foo bar');
}, 'throws when attempting to toggle a class with whitespace');
predicateToggles.forEach(x => {
Dom.toggleElClass(el, x.toggle, x.predicate);
Dom.toggleClass(el, x.toggle, x.predicate);
assert.strictEqual(el.className, x.className, x.message);
});
});
@ -255,7 +222,7 @@ QUnit.test('should set element attributes from object', function(assert) {
const el = document.createElement('div');
el.id = 'el1';
Dom.setElAttributes(el, {'controls': true, 'data-test': 'asdf'});
Dom.setAttributes(el, {'controls': true, 'data-test': 'asdf'});
assert.equal(el.getAttribute('id'), 'el1');
assert.equal(el.getAttribute('controls'), '');
@ -277,9 +244,9 @@ QUnit.test('should read tag attributes from elements, including HTML5 in all bro
// Also it must be added to the page body, not just in memory.
fixture.innerHTML += tags;
const vid1Vals = Dom.getElAttributes(fixture.getElementsByTagName('video')[0]);
const sourceVals = Dom.getElAttributes(fixture.getElementsByTagName('source')[0]);
const trackVals = Dom.getElAttributes(fixture.getElementsByTagName('track')[0]);
const vid1Vals = Dom.getAttributes(fixture.getElementsByTagName('video')[0]);
const sourceVals = Dom.getAttributes(fixture.getElementsByTagName('source')[0]);
const trackVals = Dom.getAttributes(fixture.getElementsByTagName('track')[0]);
// vid1
// was using deepEqual, but ie8 would send all properties as attributes
@ -311,9 +278,9 @@ QUnit.test('should read tag attributes from elements, including HTML5 in all bro
assert.equal(trackVals.title, 'test');
});
QUnit.test('Dom.findElPosition should find top and left position', function(assert) {
QUnit.test('Dom.findPosition should find top and left position', function(assert) {
const d = document.createElement('div');
let position = Dom.findElPosition(d);
let position = Dom.findPosition(d);
d.style.top = '10px';
d.style.left = '20px';
@ -324,11 +291,11 @@ QUnit.test('Dom.findElPosition should find top and left position', function(asse
'If element isn\'t in the DOM, we should get zeros');
document.body.appendChild(d);
position = Dom.findElPosition(d);
position = Dom.findPosition(d);
assert.deepEqual(position, {left: 20, top: 10}, 'The position was not correct');
d.getBoundingClientRect = null;
position = Dom.findElPosition(d);
position = Dom.findPosition(d);
assert.deepEqual(position,
{left: 0, top: 0},
'If there is no gBCR, we should get zeros');

View File

@ -182,33 +182,49 @@ QUnit.test('should expose options and players properties for backward-compatibil
});
QUnit.test('should expose DOM functions', function(assert) {
const origWarnLog = log.warn;
const warnLogs = [];
// Keys are videojs methods, values are Dom methods.
const methods = {
isEl: 'isEl',
isTextNode: 'isTextNode',
createEl: 'createEl',
hasClass: 'hasElClass',
addClass: 'addElClass',
removeClass: 'removeElClass',
toggleClass: 'toggleElClass',
setAttributes: 'setElAttributes',
getAttributes: 'getElAttributes',
emptyEl: 'emptyEl',
insertContent: 'insertContent',
appendContent: 'appendContent'
log.warn = (args) => {
warnLogs.push(args);
};
const keys = Object.keys(methods);
const methods = [
'isEl',
'isTextNode',
'createEl',
'hasClass',
'addClass',
'removeClass',
'toggleClass',
'setAttributes',
'getAttributes',
'emptyEl',
'insertContent',
'appendContent'
];
assert.expect(keys.length);
keys.forEach(function(vjsName) {
const domName = methods[vjsName];
methods.forEach(name => {
assert.strictEqual(typeof videojs[name], 'function', `function videojs.${name}`);
assert.strictEqual(typeof Dom[name], 'function', `Dom.${name} function exists`);
assert.strictEqual(videojs[vjsName],
Dom[domName],
`videojs.${vjsName} is a reference to Dom.${domName}`);
const oldMethod = Dom[name];
let domCalls = 0;
Dom[name] = () => domCalls++;
videojs[name]();
assert.equal(domCalls, 1, `Dom.${name} was called when videojs.${name} is run.`);
assert.equal(warnLogs.length, 1, `videojs.${name} logs a deprecation warning`);
// reset
warnLogs.length = 0;
Dom[name] = oldMethod;
});
// reset log
log.warn = origWarnLog;
});
QUnit.test('ingest player div if data-vjs-player attribute is present on video parentNode', function(assert) {