From a8734a57d333280adc139cc94433030bc349d8ff Mon Sep 17 00:00:00 2001 From: Antonio Laguna Date: Sun, 12 Mar 2017 22:01:36 +0100 Subject: [PATCH] Adding video plugin #54 --- src/js/modules/slide.js | 68 ++++++++++++++++++++++++++++++++++++- src/js/modules/webslides.js | 8 ++++- src/js/plugins/plugins.js | 4 ++- src/js/plugins/video.js | 53 +++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 src/js/plugins/video.js diff --git a/src/js/modules/slide.js b/src/js/modules/slide.js index 6203cb9..dcd4741 100644 --- a/src/js/modules/slide.js +++ b/src/js/modules/slide.js @@ -28,8 +28,20 @@ export default class Slide { * @type {number} */ this.i = i; + /** + * Enable callbacks. + * @type {Array} + * @private + */ + this.onEnable_ = []; + /** + * Disable callbacks + * @type {Array} + * @private + */ + this.onDisable_ = []; - this.el.id = 'section-' + (i + 1); + this.el.id = `section-${(i + 1)}`; this.el.classList.add(CLASSES.SLIDE); // Hide slides by default @@ -70,6 +82,36 @@ export default class Slide { this.parent.insertBefore(this.el, first); } + /** + * Adds a callback to the enable event. + * @param {Function} cb Callback to add. + */ + onEnable(cb) { + this.onEnable_.push(cb); + } + + /** + * Adds a callback to the disable event. + * @param {Function} cb Callback to add. + */ + onDisable(cb) { + this.onDisable_.push(cb); + } + + /** + * Runs every on enable callback. + */ + enable() { + this.onEnable_.forEach(f => f(this)); + } + + /** + * Runs every on disable callback. + */ + disable() { + this.onDisable_.forEach(f => f(this)); + } + /** * Checks whether an element is a valid candidate to be a slide by ensuring * it's a "section" element. @@ -79,4 +121,28 @@ export default class Slide { static isCandidate(el) { return el.nodeType === 1 && el.tagName === 'SECTION'; } + + /** + * Gets the section element from an inner element. + * @param {Node} el + * @return {{section: ?Node, i: ?number}} A map with the section and the + * position of the section. + */ + static getSectionFromEl(el) { + let parent = el; + let section = null; + let i = null; + + while (parent.parentElement && + !parent.classList.contains(CLASSES.SLIDE)) { + parent = parent.parentElement; + } + + if (parent.classList.contains(CLASSES.SLIDE)) { + section = parent; + i = parseInt(section.id.replace('section-', ''), 10); + } + + return {section, i}; + } } diff --git a/src/js/modules/webslides.js b/src/js/modules/webslides.js index 39f51f1..2f7fe42 100644 --- a/src/js/modules/webslides.js +++ b/src/js/modules/webslides.js @@ -15,7 +15,8 @@ const PLUGINS = { 'keyboard': Plugins.Keyboard, 'nav': Plugins.Navigation, 'scroll': Plugins.Scroll, - 'touch': Plugins.Touch + 'touch': Plugins.Touch, + 'video': Plugins.Video }; @@ -293,8 +294,13 @@ export default class WebSlides { * @private */ onSlideChange_(slide) { + if (this.currentSlide_) { + this.currentSlide_.disable(); + } + this.currentSlide_ = slide; this.currentSlideI_ = slide.i; + this.currentSlide_.enable(); this.isMoving = false; DOM.fireEvent(this.el, 'ws:slide-change', { diff --git a/src/js/plugins/plugins.js b/src/js/plugins/plugins.js index 6b35620..a76b2fe 100644 --- a/src/js/plugins/plugins.js +++ b/src/js/plugins/plugins.js @@ -5,6 +5,7 @@ import Keyboard from './keyboard'; import Navigation from './navigation'; import Scroll from './scroll'; import Touch from './touch'; +import Video from './video'; export default { ClickNav, @@ -13,5 +14,6 @@ export default { Keyboard, Navigation, Scroll, - Touch + Touch, + Video }; diff --git a/src/js/plugins/video.js b/src/js/plugins/video.js new file mode 100644 index 0000000..c3a373c --- /dev/null +++ b/src/js/plugins/video.js @@ -0,0 +1,53 @@ +/* eslint no-console: 0 */ +import DOM from '../utils/dom'; +import Slide from '../modules/slide'; + +/** + * Video plugin. + */ +export default class Video { + /** + * Grid plugin that shows a grid on top of the WebSlides for easy prototyping. + * @param {WebSlides} wsInstance The WebSlides instance + */ + constructor(wsInstance) { + /** + * @type {WebSlides} + * @private + */ + this.ws_ = wsInstance; + + const videos = DOM.toArray(this.ws_.el.querySelectorAll('video')); + + if (videos.length) { + videos.forEach(video => { + video.removeAttribute('autoplay'); + const {i} = Slide.getSectionFromEl(video); + const slide = wsInstance.slides[i - 1]; + + /** + * @type {HTMLMediaElement} + */ + slide.video = video; + slide.onEnable(Video.onSectionEnabled); + slide.onDisable(Video.onSectionDisabled); + }); + } + } + + /** + * On Section enable hook. Will play the video. + * @param {Slide} slide + */ + static onSectionEnabled(slide) { + slide.video.play(); + } + + /** + * On Section enable hook. Will pause the video. + * @param {Slide} slide + */ + static onSectionDisabled(slide) { + slide.video.pause(); + } +}