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:
parent
524f868e31
commit
b387437aed
@ -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"
|
||||
},
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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: {},
|
||||
|
@ -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;
|
1078
src/js/tech/flash.js
1078
src/js/tech/flash.js
File diff suppressed because it is too large
Load Diff
@ -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
98
src/js/utils/dom-data.js
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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]) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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');
|
||||
});
|
||||
|
@ -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');
|
||||
|
||||
|
@ -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'));
|
||||
});
|
@ -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');
|
||||
});
|
@ -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');
|
||||
|
@ -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 => {
|
||||
|
23
test/unit/utils/dom-data.test.js
Normal file
23
test/unit/utils/dom-data.test.js
Normal 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');
|
||||
});
|
@ -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');
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user