From 5557b0bd584ef4a3c959c219cc5971d3851ea292 Mon Sep 17 00:00:00 2001 From: Yair Ansbacher Date: Thu, 21 Jun 2018 00:12:43 +0300 Subject: [PATCH] feat(FEC-8046): 360 support (#239) * expose VR API's and event * enable to pass options to event target (needed to pass passive by 'vr' plugin) * enrich the Dom util --- src/error/category.js | 5 +++- src/error/code.js | 7 +++++- src/event/event-manager.js | 21 ++++++++++------ src/event/event-type.js | 6 ++++- src/player.js | 40 ++++++++++++++++++++++++++++++- src/utils/util.js | 30 +++++++++++++++++++++-- test/src/event/event-type.spec.js | 3 ++- 7 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/error/category.js b/src/error/category.js index 41b5a584e..fc79c88bd 100644 --- a/src/error/category.js +++ b/src/error/category.js @@ -28,7 +28,10 @@ const Category: CategoryType = { 'ADS': 8, /** Errors in the database storage (offline). */ - 'STORAGE': 9 + 'STORAGE': 9, + + /** Errors from VR plugin. */ + 'VR': 11 }; export {Category} diff --git a/src/error/code.js b/src/error/code.js index 90a4ca750..d9f71a498 100644 --- a/src/error/code.js +++ b/src/error/code.js @@ -615,7 +615,12 @@ const Code: CodeType = { * When the manifest contains no period playable streams, it means the * manifest is unsupported by the browser. */ - 'CONTENT_UNSUPPORTED_BY_BROWSER': 9009 + 'CONTENT_UNSUPPORTED_BY_BROWSER': 9009, + + /** + * VR plugin is not supported. + */ + 'VR_NOT_SUPPORTED': 11000 }; diff --git a/src/event/event-manager.js b/src/event/event-manager.js index 4c8b576ab..2a96e5a6d 100644 --- a/src/event/event-manager.js +++ b/src/event/event-manager.js @@ -36,14 +36,15 @@ class EventManager { * @param {EventTarget} target - The event target. * @param {string} type - The event type. * @param {EventManager.ListenerType} listener - The event listener. + * @param {?Object} options - The event options. * @returns {void} */ - listenOnce(target: any, type: string, listener: ListenerType): void { + listenOnce(target: any, type: string, listener: ListenerType, options: ?Object): void { let oneListener = (event) => { this.unlisten(target, type, oneListener); listener.call(this, event) }; - this.listen(target, type, oneListener); + this.listen(target, type, oneListener, options); } @@ -52,10 +53,11 @@ class EventManager { * @param {EventTarget} target The event target. * @param {string} type The event type. * @param {EventManager.ListenerType} listener The event listener. + * @param {?Object} options The event options. * @returns {void} */ - listen(target: any, type: string, listener: ListenerType): void { - let binding = new Binding_(target, type, listener); + listen(target: any, type: string, listener: ListenerType, options: ?Object): void { + let binding = new Binding_(target, type, listener, options); if (this._bindingMap) { this._bindingMap.push(type, binding); } @@ -121,8 +123,9 @@ class Binding_ { target: any; type: string; listener: ?ListenerType; + options: ?Object; - constructor(target, type, listener) { + constructor(target, type, listener, options) { /** @type {EventTarget} */ this.target = target; @@ -132,7 +135,10 @@ class Binding_ { /** @type {?EventManager.ListenerType} */ this.listener = listener; - this.target.addEventListener(type, listener, false); + /** @type {?Object} */ + this.options = options; + + this.target.addEventListener(type, listener, options); } @@ -145,10 +151,11 @@ class Binding_ { if (!this.target) return; - this.target.removeEventListener(this.type, this.listener, false); + this.target.removeEventListener(this.type, this.listener, this.options); this.target = null; this.listener = null; + this.options = null; } } diff --git a/src/event/event-type.js b/src/event/event-type.js index cff3159ea..584ea1fba 100644 --- a/src/event/event-type.js +++ b/src/event/event-type.js @@ -262,7 +262,11 @@ const CustomEventType: EventTypes = { /** * Fired when the adapter recovered from a media error */ - MEDIA_RECOVERED: 'mediarecovered' + MEDIA_RECOVERED: 'mediarecovered', + /** + * Fired when the vr stereo mode changed + */ + VR_STEREO_MODE_CHANGED: 'vrstereomodechanged' }; const EventType: EventTypes = Utils.Object.merge([Html5EventType, CustomEventType]); diff --git a/src/player.js b/src/player.js index 9afd6bf22..ba59eb7a0 100644 --- a/src/player.js +++ b/src/player.js @@ -571,7 +571,7 @@ export default class Player extends FakeEventTarget { /** * Resets the necessary components before change media. - * @private + * @public * @returns {void} */ reset(): void { @@ -1182,6 +1182,44 @@ export default class Player extends FakeEventTarget { // + // + + /** + * Checking if the selected source is VR. + * @returns {boolean} - Whether is VR. + * @public + */ + isVr(): boolean { + return !!(this._config.sources.vr); + } + + /** + * Toggling the VR mode + * @returns {void} + * @public + */ + toggleVrStereoMode(): void { + const vrPlugin: ?BasePlugin = this._pluginManager.get('vr'); + if (vrPlugin && typeof vrPlugin.toggleVrStereoMode === 'function') { + vrPlugin.toggleVrStereoMode(); + } + } + + /** + * Checking if the VR stereo mode is active. + * @returns {boolean} - Whether is active. + * @public + */ + isInVrStereoMode(): boolean { + const vrPlugin: ?BasePlugin = this._pluginManager.get('vr'); + if (vrPlugin && typeof vrPlugin.isInStereoMode === 'function') { + return vrPlugin.isInStereoMode(); + } + return false; + } + + // + // /** diff --git a/src/utils/util.js b/src/utils/util.js index 94dba0ca9..afb59f332 100644 --- a/src/utils/util.js +++ b/src/utils/util.js @@ -118,10 +118,10 @@ const _Object = { } }); } else if (data !== null && typeof data === "object") { - if (data.clone && typeof data.clone === "function"){ + if (data.clone && typeof data.clone === "function") { node = data.clone(); } else { - node = Object.assign({ __proto__: data.__proto__ }, data); + node = Object.assign({__proto__: data.__proto__}, data); Object.keys(node).forEach((key) => { if ( (typeof node[key] === "object" && node[key] !== {}) || @@ -431,6 +431,32 @@ const _Dom = { t.parentNode.insertBefore(s, t); } }); + }, + /** + * Returns the first element that matches a specified CSS selector(s) in the document. + * @param {string} selector - One or more CSS selectors to match the element. + * @returns {Element} - The first element that matches a specified CSS selector(s) in the document. + */ + getElementBySelector(selector: string): any { + try { + return document.querySelector(selector) + } catch (e) { + return; + } + }, + /** + * Inserts a node as a child, right before an existing child. + * @param {HTMLElement} parent - The parent node object. + * @param {HTMLElement} newChild - The node object to insert. + * @param {?HTMLElement} existingChild - The child node to insert the new node before. If set to null, the insertBefore method will insert the newChild at the end. + * @returns {Element} - The first element that matches a specified CSS selector(s) in the document. + */ + insertBefore(parent: HTMLElement, newChild: HTMLElement, existingChild: ?HTMLElement): ?HTMLElement { + try { + return parent.insertBefore(newChild, existingChild); + } catch (e) { + return null; + } } }; diff --git a/test/src/event/event-type.spec.js b/test/src/event/event-type.spec.js index 78e1c3725..a87d0e39a 100644 --- a/test/src/event/event-type.spec.js +++ b/test/src/event/event-type.spec.js @@ -69,7 +69,8 @@ describe('events', () => { AD_VOLUME_CHANGED: 'advolumechanged', AD_MUTED: 'admuted', AD_PROGRESS: 'adprogress', - MEDIA_RECOVERED: 'mediarecovered' + MEDIA_RECOVERED: 'mediarecovered', + VR_STEREO_MODE_CHANGED: 'vrstereomodechanged' }); EventType.should.deep.equals(ObjectUtils.merge([Html5EventType, CustomEventType])); });