diff --git a/.gitignore b/.gitignore index 51b5f2d..99c57fe 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,3 @@ node_modules/ .Trashes ehthumbs.db Thumbs.db -static/js/webslides* diff --git a/static/js/webslides.js b/static/js/webslides.js new file mode 100644 index 0000000..633ebb9 --- /dev/null +++ b/static/js/webslides.js @@ -0,0 +1,1684 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.l = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; + +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; + +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; + +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/static/js/"; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 15); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__custom_event__ = __webpack_require__(12); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + +/** + * Static class for DOM helper. + */ + +var DOM = function () { + function DOM() { + _classCallCheck(this, DOM); + } + + _createClass(DOM, null, [{ + key: 'createNode', + + /** + * Creates a node with optional parameters. + * @param {string} tag The name of the tag of the needed element. + * @param {string} id The desired id for the element. It defaults to an + * empty string. + * @param {string} text The desired text to go inside of the element. It defaults + * to an empty string. + * @return {Element} + */ + value: function createNode(tag) { + var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var text = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + + var node = document.createElement(tag); + node.id = id; + + if (text) { + node.textContent = text; + } + + return node; + } + + /** + * Hides an element setting the display to none. + * @param {Element} el Element to be hidden. + */ + + }, { + key: 'hide', + value: function hide(el) { + el.style.display = 'none'; + } + + /** + * Shows an element by removing the display property. This is only intended + * to be used in conjunction with DOM.hide. + * @param {Element} el Element to be shown. + */ + + }, { + key: 'show', + value: function show(el) { + el.style.display = ''; + } + + /** + * Locks the scroll on the document by setting the HTML to have a hidden + * overflow. + */ + + }, { + key: 'lockScroll', + value: function lockScroll() { + document.documentElement.style.overflow = 'hidden'; + } + + /** + * Unlocks the scroll on the document by setting the HTML to have an auto + * overflow. + */ + + }, { + key: 'unlockScroll', + value: function unlockScroll() { + document.documentElement.style.overflow = 'auto'; + } + + /** + * Fires a custom event on the given target. + * @param {Element} target The target of the event. + * @param {string} eventType The event type. + * @param {Object} eventInfo Optional parameter to provide additional data + * to the event. + */ + + }, { + key: 'fireEvent', + value: function fireEvent(target, eventType) { + var eventInfo = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + var event = new __WEBPACK_IMPORTED_MODULE_0__custom_event__["a" /* default */](eventType, { + detail: eventInfo + }); + + target.dispatchEvent(event); + } + }]); + + return DOM; +}(); + +/* harmony default export */ __webpack_exports__["a"] = DOM; + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var Keys = { + ENTER: 13, + SPACE: 32, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40 +}; + +/* harmony default export */ __webpack_exports__["a"] = Keys; + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__easing__ = __webpack_require__(13); + + +var SCROLLABLE_CONTAINER = getScrollableContainer(); + +/** + * Returns the correct DOM element to be used for scrolling the + * page, due to Firefox not scrolling on document.body. + * @return {Element} Scrollable Element. + */ +function getScrollableContainer() { + if (SCROLLABLE_CONTAINER) { + return SCROLLABLE_CONTAINER; + } + + var documentElement = window.document.documentElement; + var scrollableContainer = void 0; + + documentElement.scrollTop = 1; + + if (documentElement.scrollTop === 1) { + documentElement.scrollTop = 0; + scrollableContainer = documentElement; + } else { + scrollableContainer = document.body; + } + + SCROLLABLE_CONTAINER = scrollableContainer; + + return scrollableContainer; +} + +/** + * Smoothly scrolls to a given Y position using Easing.Swing. It'll run a + * callback upon finishing. + * @param {number} y Offset of the page to scroll to. + * @param {number} duration Duration of the animation. 500ms by default. + * @param {function} cb Callback function to call upon completion. + */ +function scrollTo(y) { + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500; + var cb = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; + + var scrollableContainer = getScrollableContainer(); + var delta = y - scrollableContainer.scrollTop; + var startLocation = scrollableContainer.scrollTop; + var increment = 16; + + if (!duration) { + scrollableContainer.scrollTop = y; + cb(); + return; + } + + var animateScroll = function animateScroll(elapsedTime) { + elapsedTime += increment; + var percent = Math.min(1, elapsedTime / duration); + var easingP = __WEBPACK_IMPORTED_MODULE_0__easing__["a" /* default */].swing(percent, elapsedTime * percent, y, delta, duration); + + scrollableContainer.scrollTop = Math.floor(startLocation + easingP * delta); + + if (elapsedTime < duration) { + setTimeout(function () { + return animateScroll(elapsedTime); + }, increment); + } else { + cb(); + } + }; + + animateScroll(0); +} + +/* harmony default export */ __webpack_exports__["a"] = { getScrollableContainer: getScrollableContainer, scrollTo: scrollTo }; + +/***/ }), +/* 3 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__plugins_plugins__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__slide__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__utils_dom__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__utils_scroll_to__ = __webpack_require__(2); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + + + + +var CLASSES = { + VERTICAL: 'vertical' +}; + +// Default plugins +var PLUGINS = { + 'grid': __WEBPACK_IMPORTED_MODULE_0__plugins_plugins__["a" /* default */].Grid, + 'hash': __WEBPACK_IMPORTED_MODULE_0__plugins_plugins__["a" /* default */].Hash, + 'keyboard': __WEBPACK_IMPORTED_MODULE_0__plugins_plugins__["a" /* default */].Keyboard, + 'nav': __WEBPACK_IMPORTED_MODULE_0__plugins_plugins__["a" /* default */].Navigation, + 'scroll': __WEBPACK_IMPORTED_MODULE_0__plugins_plugins__["a" /* default */].Scroll, + 'touch': __WEBPACK_IMPORTED_MODULE_0__plugins_plugins__["a" /* default */].Touch +}; + +var WebSlides = function () { + /** + * Options for WebSlides + * @param {number|boolean} autoslide Is false by default. If a number is + * provided, it will autoslide every given milliseconds. + */ + function WebSlides() { + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref$autoslide = _ref.autoslide, + autoslide = _ref$autoslide === undefined ? false : _ref$autoslide; + + _classCallCheck(this, WebSlides); + + /** + * WebSlide element. + * @type {Element} + */ + this.el = document.getElementById('webslides'); + /** + * Moving flag. + * @type {boolean} + */ + this.isMoving = false; + /** + * Slide's array. + * @type {?Array} + */ + this.slides = null; + /** + * Current slide's index. + * @type {number} + * @private + */ + this.currentSlideI_ = -1; + /** + * Current slide reference. + * @type {?Slide} + * @private + */ + this.currentSlide_ = null; + /** + * Max slide index. + * @type {number} + * @private + */ + this.maxSlide_ = 0; + /** + * Whether the layout is going to be vertical or horizontal. + * @type {boolean} + */ + this.isVertical = this.el.classList.contains(CLASSES.VERTICAL); + /** + * Plugin's dictionary. + * @type {Object} + */ + this.plugins = {}; + /** + * Interval ID reference for the autoslide. + * @type {?number} + * @private + */ + this.interval_ = null; + /** + * Amount of time to wait to go to next slide automatically or false to + * disable the feature. + * @type {boolean|number} + * @private + */ + this.autoslide_ = autoslide; + + if (!this.el) { + throw new Error('Couldn\'t find the webslides container!'); + } + + // Bootstrapping + this.removeChildren_(); + this.grabSlides_(); + this.createPlugins_(); + this.initSlides_(); + this.play(); + // Finished + this.onInit_(); + } + + /** + * Removes all children elements inside of the main container that are not + * eligible to be a Slide Element. + * @private + */ + + + _createClass(WebSlides, [{ + key: 'removeChildren_', + value: function removeChildren_() { + var nodes = this.el.childNodes; + var i = nodes.length; + + while (i--) { + var node = nodes[i]; + + if (!__WEBPACK_IMPORTED_MODULE_1__slide__["a" /* default */].isCandidate(node)) { + this.el.removeChild(node); + } + } + } + + /** + * Creates all the registered plugins and store the instances inside of the + * the webslide instance. + * @private + */ + + }, { + key: 'createPlugins_', + value: function createPlugins_() { + var _this = this; + + Object.keys(PLUGINS).forEach(function (pluginName) { + var pluginCto = PLUGINS[pluginName]; + _this.plugins[pluginName] = new pluginCto(_this); + }); + } + + /** + * Called once the WebSlide instance has finished initialising. + * @private + * @fires WebSlide#ws:init + */ + + }, { + key: 'onInit_', + value: function onInit_() { + __WEBPACK_IMPORTED_MODULE_2__utils_dom__["a" /* default */].fireEvent(this.el, 'ws:init'); + } + + /** + * Grabs the slides from the DOM and creates all the Slides modules. + * @private + */ + + }, { + key: 'grabSlides_', + value: function grabSlides_() { + this.slides = Array.from(this.el.childNodes).map(function (slide, i) { + return new __WEBPACK_IMPORTED_MODULE_1__slide__["a" /* default */](slide, i); + }); + + this.maxSlide_ = this.slides.length; + } + + /** + * Goes to a given slide. + * @param {!number} slideI The slide index. + * @param {?boolean} forward Whether we're forcing moving forward/backwards. + * This parameter is used only from the goNext, goPrev functions to adjust the + * scroll animations. + */ + + }, { + key: 'goToSlide', + value: function goToSlide(slideI) { + var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + if (this.isValidIndexSlide_(slideI) && !this.isMoving) { + this.isMoving = true; + var isMovingForward = false; + + if (forward !== null) { + isMovingForward = forward; + } else { + if (this.currentSlideI_ >= 0) { + isMovingForward = slideI > this.currentSlideI_; + } + } + var nextSlide = this.slides[slideI]; + + if (this.currentSlide_ !== null && this.isVertical && (!this.plugins.touch || !this.plugins.touch.isEnabled)) { + this.scrollTransitionToSlide_(isMovingForward, nextSlide, this.onSlideChange_); + } else { + this.transitionToSlide_(isMovingForward, nextSlide, this.onSlideChange_); + } + } + } + + /** + * Transitions to a slide, doing the scroll animation. + * @param {boolean} isMovingForward Whether we're going forward or backwards. + * @param {Slide} nextSlide Next slide. + * @param {Function} callback Callback to be called upon finishing. This is an + * async function so it'll happen once the scroll animation finishes. + * @private + * @see DOM.lockScroll + * @see DOM.unlockScroll + * @see ScrollHelper.scrollTo + */ + + }, { + key: 'scrollTransitionToSlide_', + value: function scrollTransitionToSlide_(isMovingForward, nextSlide, callback) { + var _this2 = this; + + __WEBPACK_IMPORTED_MODULE_2__utils_dom__["a" /* default */].lockScroll(); + + if (!isMovingForward) { + nextSlide.moveBeforeFirst(); + nextSlide.show(); + __WEBPACK_IMPORTED_MODULE_3__utils_scroll_to__["a" /* default */].scrollTo(this.currentSlide_.el.offsetTop, 0); + } else { + nextSlide.show(); + } + + __WEBPACK_IMPORTED_MODULE_3__utils_scroll_to__["a" /* default */].scrollTo(nextSlide.el.offsetTop, 500, function () { + _this2.currentSlide_.hide(); + + if (isMovingForward) { + _this2.currentSlide_.moveAfterLast(); + } + + __WEBPACK_IMPORTED_MODULE_2__utils_dom__["a" /* default */].unlockScroll(); + setTimeout(function () { + callback.call(_this2, nextSlide); + }, 150); + }); + } + + /** + * Transitions to a slide, without doing the scroll animation. + * @param {boolean} isMovingForward Whether we're going forward or backwards. + * @param {Slide} nextSlide Next slide. + * @param {Function} callback Callback to be called upon finishing. This is a + * sync function so it'll happen on run time. + * @private + */ + + }, { + key: 'transitionToSlide_', + value: function transitionToSlide_(isMovingForward, nextSlide, callback) { + __WEBPACK_IMPORTED_MODULE_3__utils_scroll_to__["a" /* default */].scrollTo(0, 0); + + if (!isMovingForward) { + nextSlide.moveBeforeFirst(); + } + + if (this.currentSlide_) { + if (isMovingForward) { + this.currentSlide_.moveAfterLast(); + } + + this.currentSlide_.hide(); + } + + nextSlide.show(); + callback.call(this, nextSlide); + } + + /** + * Whenever a slide is changed, this function gets called. It updates the + * references to the current slide, disables the moving flag and fires + * a custom event. + * @param {Slide} slide The slide we're transitioning to. + * @fires WebSlide#ws:slide-change + * @private + */ + + }, { + key: 'onSlideChange_', + value: function onSlideChange_(slide) { + this.currentSlide_ = slide; + this.currentSlideI_ = slide.i; + this.isMoving = false; + + __WEBPACK_IMPORTED_MODULE_2__utils_dom__["a" /* default */].fireEvent(this.el, 'ws:slide-change', { + slides: this.maxSlide_, + currentSlide0: this.currentSlideI_, + currentSlide: this.currentSlideI_ + 1 + }); + } + + /** + * Goes to the next slide. + */ + + }, { + key: 'goNext', + value: function goNext() { + var nextIndex = this.currentSlideI_ + 1; + + if (nextIndex >= this.maxSlide_) { + nextIndex = 0; + } + + this.goToSlide(nextIndex, true); + } + + /** + * Goes to the previous slide. + */ + + }, { + key: 'goPrev', + value: function goPrev() { + var prevIndex = this.currentSlideI_ - 1; + + if (prevIndex < 0) { + prevIndex = this.maxSlide_ - 1; + } + + this.goToSlide(prevIndex, false); + } + + /** + * Check if the given number is a valid index to go to. + * @param {number} i The index to check. + * @return {boolean} Whether you can move to that slide or not. + * @private + */ + + }, { + key: 'isValidIndexSlide_', + value: function isValidIndexSlide_(i) { + return i >= 0 && i < this.maxSlide_; + } + + /** + * Init the shown slide on load. It'll fetch it from the Hash if present + * and, otherwise, it'll default to the first one. + * @private + * @see Hash.getSlideNumber + */ + + }, { + key: 'initSlides_', + value: function initSlides_() { + var slideNumber = this.plugins.hash.constructor.getSlideNumber(); + + // Not valid + if (slideNumber === null || slideNumber >= this.maxSlide_) { + slideNumber = 0; + } + + // Keeping the order + if (slideNumber !== 0) { + var i = 0; + while (i < slideNumber) { + this.slides[i].moveAfterLast(); + i++; + } + } + + this.goToSlide(slideNumber); + } + + /** + * Registers a plugin to be loaded when the instance is created. It allows + * (on purpose) to replace default plugins. + * Those being: + * - Navigation + * - Hash + * - Keyboard + * @param {!string} key They key under which it'll be stored inside of the + * instance, inside the plugins dict. + * @param {!Function} cto Plugin constructor. + */ + + }, { + key: 'play', + + + /** + * Starts autosliding all the slides if it's not currently doing it and the + * autoslide option was a number greater than 0. + * @param {?number} time Amount of milliseconds to wait to go to next slide + * automatically. + */ + value: function play(time) { + time = time || this.autoslide_; + + if (!this.interval_ && Number.isInteger(time) && time > 0) { + this.interval_ = setInterval(this.goNext.bind(this), time); + } + } + + /** + * Stops autosliding all the slides. + */ + + }, { + key: 'stop', + value: function stop() { + if (this.interval_) { + clearInterval(this.interval_); + this.interval_ = null; + } + } + }], [{ + key: 'registerPlugin', + value: function registerPlugin(key, cto) { + PLUGINS[key] = cto; + } + }]); + + return WebSlides; +}(); + +/* harmony default export */ __webpack_exports__["a"] = WebSlides; + +/***/ }), +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__utils_dom__ = __webpack_require__(0); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + +var CLASSES = { + SLIDE: 'slide', + CURRENT: 'current' +}; + +/** + * Wrapper for the Slide section. + */ + +var Slide = function () { + /** + * Bootstraps the slide by saving some data, adding a class and hiding it. + * @param {Element} el Section element. + * @param {number} i Zero based index of the slide. + */ + function Slide(el, i) { + _classCallCheck(this, Slide); + + /** + * @type {Element} + */ + this.el = el; + /** + * The section's parent. + * @type {Node} + */ + this.parent = el.parentNode; + /** + * @type {number} + */ + this.i = i; + + this.el.id = 'section-' + (i + 1); + this.el.classList.add(CLASSES.SLIDE); + + // Hide slides by default + this.hide(); + } + + /** + * Hides the node and removes the class that makes it "active". + */ + + + _createClass(Slide, [{ + key: 'hide', + value: function hide() { + __WEBPACK_IMPORTED_MODULE_0__utils_dom__["a" /* default */].hide(this.el); + this.el.classList.remove(CLASSES.CURRENT); + } + + /** + * Shows the node and adds the class that makes it "active". + */ + + }, { + key: 'show', + value: function show() { + __WEBPACK_IMPORTED_MODULE_0__utils_dom__["a" /* default */].show(this.el); + this.el.classList.add(CLASSES.CURRENT); + } + + /** + * Moves the section to the bottom of the section's list. + */ + + }, { + key: 'moveAfterLast', + value: function moveAfterLast() { + var last = this.parent.childNodes[this.parent.childElementCount - 1]; + + this.parent.insertBefore(this.el, last.nextSibling); + } + + /** + * Moves the section to the top of the section's list. + */ + + }, { + key: 'moveBeforeFirst', + value: function moveBeforeFirst() { + var first = this.parent.childNodes[0]; + + this.parent.insertBefore(this.el, first); + } + + /** + * Checks whether an element is a valid candidate to be a slide by ensuring + * it's a "section" element. + * @param {Element} el Element to be checked. + * @return {boolean} Whether is candidate or not. + */ + + }], [{ + key: 'isCandidate', + value: function isCandidate(el) { + return el.nodeType === 1 && el.tagName === 'SECTION'; + } + }]); + + return Slide; +}(); + +/* harmony default export */ __webpack_exports__["a"] = Slide; + +/***/ }), +/* 5 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__utils_keys__ = __webpack_require__(1); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + +var Grid = function () { + /** + * Grid plugin that shows a grid on top of the WebSlides for easy prototyping. + * @param {WebSlides} wsInstance The WebSlides instance + */ + function Grid(wsInstance) { + _classCallCheck(this, Grid); + + /** + * @type {WebSlides} + * @private + */ + this.ws_ = wsInstance; + + var CSS = 'body.baseline {\n background: url(../images/baseline.png) left top .8rem/.8rem;\n }'; + var head = document.head || document.getElementsByTagName('head')[0]; + var style = document.createElement('style'); + + style.type = 'text/css'; + + if (style.styleSheet) { + style.styleSheet.cssText = CSS; + } else { + style.appendChild(document.createTextNode(CSS)); + } + + head.appendChild(style); + + document.addEventListener('keydown', this.onKeyPress_.bind(this), false); + } + + /** + * Reacts to the keydown event. It reacts to ENTER key to toggle the class. + * @param {KeyboardEvent} event The key event. + * @private + */ + + + _createClass(Grid, [{ + key: 'onKeyPress_', + value: function onKeyPress_(event) { + if (event.which === __WEBPACK_IMPORTED_MODULE_0__utils_keys__["a" /* default */].ENTER) { + document.body.toggleClass('baseline'); + } + } + }]); + + return Grid; +}(); + +/* harmony default export */ __webpack_exports__["a"] = Grid; + +/***/ }), +/* 6 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var HASH = '#slide'; +var slideRegex = /#slide=(\d+)/; + +/** + * Static class with methods to manipulate and extract info from the hash of + * the URL. + */ + +var Hash = function () { + /** + * Listens to the slide change event and the hash change events. + * @param wsInstance + */ + function Hash(wsInstance) { + _classCallCheck(this, Hash); + + this.ws_ = wsInstance; + + wsInstance.el.addEventListener('ws:slide-change', Hash.onSlideChange_); + window.addEventListener('hashchange', this.onHashChange_.bind(this), false); + } + + /** + * hashchange event handler, makes the WebSlide instance navigate to the + * needed slide. + */ + + + _createClass(Hash, [{ + key: 'onHashChange_', + value: function onHashChange_() { + var newSlideIndex = Hash.getSlideNumber(); + + if (newSlideIndex !== null) { + this.ws_.goToSlide(newSlideIndex); + } + } + }], [{ + key: 'onSlideChange_', + value: function onSlideChange_(event) { + Hash.setSlideNumber(event.detail.currentSlide); + } + + /** + * Gets the slide number from the hash by a regex matching `#slide=` and gets + * the number after it. If the number is invalid or less than 0, it will + * return null as an invalid value. + * @return {?number} + */ + + }, { + key: 'getSlideNumber', + value: function getSlideNumber() { + var results = document.location.hash.match(slideRegex); + var slide = 0; + + if (Array.isArray(results)) { + slide = parseInt(results[1], 10); + } + + if (!Number.isInteger(slide) || slide < 0 || !Array.isArray(results)) { + slide = null; + } else { + slide--; // Convert to 0 index + } + + return slide; + } + + /** + * It will update the hash (if it's different) so it reflects the slide + * number being visible. + * @param {number} number The number of the slide we're transitioning to. + */ + + }, { + key: 'setSlideNumber', + value: function setSlideNumber(number) { + if (Hash.getSlideNumber() !== number - 1) { + history.pushState({ + slideI: number - 1 + }, 'Slide ' + number, HASH + '=' + number); + } + } + }]); + + return Hash; +}(); + +/* harmony default export */ __webpack_exports__["a"] = Hash; + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__utils_keys__ = __webpack_require__(1); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + +var Keyboard = function () { + /** + * Keyboard interaction plugin. + * @param {WebSlides} wsInstance The WebSlides instance + */ + function Keyboard(wsInstance) { + _classCallCheck(this, Keyboard); + + /** + * @type {WebSlides} + * @private + */ + this.ws_ = wsInstance; + + document.addEventListener('keydown', this.onKeyPress_.bind(this), false); + } + + /** + * Reacts to the keydown event. It reacts to the arrows and space key + * depending on the layout of the page. + * @param {KeyboardEvent} event The key event. + * @private + */ + + + _createClass(Keyboard, [{ + key: 'onKeyPress_', + value: function onKeyPress_(event) { + var method = void 0; + + if (event.which === __WEBPACK_IMPORTED_MODULE_0__utils_keys__["a" /* default */].SPACE) { + method = this.ws_.goNext; + } else { + if (this.ws_.isVertical) { + if (event.which === __WEBPACK_IMPORTED_MODULE_0__utils_keys__["a" /* default */].DOWN) { + method = this.ws_.goNext; + } else if (event.which === __WEBPACK_IMPORTED_MODULE_0__utils_keys__["a" /* default */].UP) { + method = this.ws_.goPrev; + } + } else { + if (event.which === __WEBPACK_IMPORTED_MODULE_0__utils_keys__["a" /* default */].RIGHT) { + method = this.ws_.goNext; + } else if (event.which === __WEBPACK_IMPORTED_MODULE_0__utils_keys__["a" /* default */].LEFT) { + method = this.ws_.goPrev; + } + } + } + + if (method) { + method.call(this.ws_); + } + } + }]); + + return Keyboard; +}(); + +/* harmony default export */ __webpack_exports__["a"] = Keyboard; + +/***/ }), +/* 8 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__utils_dom__ = __webpack_require__(0); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + +var ELEMENT_ID = { + NAV: 'navigation', + NEXT: 'next', + PREV: 'previous', + COUNTER: 'counter' +}; + +var LABELS = { + VERTICAL: { + NEXT: '↓', + PREV: '↑' + }, + HORIZONTAL: { + NEXT: '→', + PREV: '←' + } +}; + +var Navigation = function () { + /** + * The Navigation constructor. It'll create all the nodes needed for the + * navigation such as the arrows and the counter. + * @param {WebSlides} wsInstance The WebSlides instance + */ + function Navigation(wsInstance) { + _classCallCheck(this, Navigation); + + var arrowLabels = wsInstance.isVertical ? LABELS.VERTICAL : LABELS.HORIZONTAL; + /** + * Navigation element. + * @type {Element} + */ + this.el = __WEBPACK_IMPORTED_MODULE_0__utils_dom__["a" /* default */].createNode('div', 'navigation'); + /** + * Next button. + * @type {Element} + */ + this.next = Navigation.createArrow(ELEMENT_ID.NEXT, arrowLabels.NEXT); + /** + * Prev button. + * @type {Element} + */ + this.prev = Navigation.createArrow(ELEMENT_ID.PREV, arrowLabels.PREV); + /** + * Counter Element. + * @type {Element} + */ + this.counter = __WEBPACK_IMPORTED_MODULE_0__utils_dom__["a" /* default */].createNode('span', ELEMENT_ID.COUNTER); + /** + * @type {WebSlides} + * @private + */ + this.ws_ = wsInstance; + + this.el.appendChild(this.next); + this.el.appendChild(this.prev); + this.el.appendChild(this.counter); + + this.ws_.el.appendChild(this.el); + this.bindEvents_(); + } + + /** + * Bind all events for the navigation. + * @private + */ + + + _createClass(Navigation, [{ + key: 'bindEvents_', + value: function bindEvents_() { + this.ws_.el.addEventListener('ws:slide-change', this.onSlideChanged_.bind(this)); + this.next.addEventListener('click', this.onButtonClicked_.bind(this)); + this.prev.addEventListener('click', this.onButtonClicked_.bind(this)); + } + + /** + * Updates the counter inside the navigation. + * @param {string|number} current Current slide number. + * @param {string|number} max Max slide number. + */ + + }, { + key: 'updateCounter', + value: function updateCounter(current, max) { + this.counter.textContent = current + ' / ' + max; + } + + /** + * Creates an arrow to navigate. + * @param {!String} id Desired ID for the arrow. + * @param {!String} text Desired text for the arrow. + * @return {Element} The arrow element. + */ + + }, { + key: 'onSlideChanged_', + + + /** + * Slide Change event handler. Will update the text on the navigation. + * @param {CustomEvent} event + * @private + */ + value: function onSlideChanged_(event) { + this.updateCounter(event.detail.currentSlide, event.detail.slides); + } + + /** + * Handles clicks on the next/prev buttons. + * @param {MouseEvent} event + * @private + */ + + }, { + key: 'onButtonClicked_', + value: function onButtonClicked_(event) { + event.preventDefault(); + if (event.target === this.next) { + this.ws_.goNext(); + } else { + this.ws_.goPrev(); + } + } + }], [{ + key: 'createArrow', + value: function createArrow(id, text) { + var arrow = __WEBPACK_IMPORTED_MODULE_0__utils_dom__["a" /* default */].createNode('a', id, text); + arrow.href = '#'; + arrow.title = 'Arrow Keys'; + + return arrow; + } + }]); + + return Navigation; +}(); + +/* harmony default export */ __webpack_exports__["a"] = Navigation; + +/***/ }), +/* 9 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__grid__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__hash__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__keyboard__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__navigation__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__scroll__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__touch__ = __webpack_require__(11); + + + + + + + +/* harmony default export */ __webpack_exports__["a"] = { + Grid: __WEBPACK_IMPORTED_MODULE_0__grid__["a" /* default */], + Hash: __WEBPACK_IMPORTED_MODULE_1__hash__["a" /* default */], + Keyboard: __WEBPACK_IMPORTED_MODULE_2__keyboard__["a" /* default */], + Navigation: __WEBPACK_IMPORTED_MODULE_3__navigation__["a" /* default */], + Scroll: __WEBPACK_IMPORTED_MODULE_4__scroll__["a" /* default */], + Touch: __WEBPACK_IMPORTED_MODULE_5__touch__["a" /* default */] +}; + +/***/ }), +/* 10 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__utils_scroll_to__ = __webpack_require__(2); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + +var MIN_WHEEL_DELTA = 40; + +var Scroll = function () { + /** + * Scroll handler for the WebSlides. + * @param {WebSlides} wsInstance The WebSlides instance + */ + function Scroll(wsInstance) { + _classCallCheck(this, Scroll); + + /** + * @type {WebSlides} + * @private + */ + this.ws_ = wsInstance; + + this.scrollContainer_ = __WEBPACK_IMPORTED_MODULE_0__utils_scroll_to__["a" /* default */].getScrollableContainer(); + this.isGoingUp_ = false; + + if (this.ws_.isVertical) { + this.scrollContainer_.addEventListener('wheel', this.onMouseWheel_.bind(this)); + } + } + + /** + * Reacts to the wheel event. Detects whether is going up or down and decides + * if it needs to move the slide based on the amount of delta. + * @param {WheelEvent} event The Wheel Event. + * @private + */ + + + _createClass(Scroll, [{ + key: 'onMouseWheel_', + value: function onMouseWheel_(event) { + if (this.ws_.isMoving) { + return; + } + + var wheelDelta = event.deltaY; + + this.isGoingUp_ = wheelDelta < 0; + + if (Math.abs(wheelDelta) >= MIN_WHEEL_DELTA) { + if (this.isGoingUp_) { + this.ws_.goPrev(); + } else { + this.ws_.goNext(); + } + + event.preventDefault(); + } + } + }]); + + return Scroll; +}(); + +/* harmony default export */ __webpack_exports__["a"] = Scroll; +; + +/***/ }), +/* 11 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__utils_mobile_detector__ = __webpack_require__(14); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + +var EVENTS = { + touch: { + START: 'touchstart', + MOVE: 'touchmove', + END: 'touchend' + }, + pointer: { + START: 'pointerdown', + MOVE: 'pointermove', + END: 'pointerup' + } +}; + +var SLIDE_OFFSET = 50; + +var Touch = function () { + /** + * @param {WebSlides} wsInstance The WebSlides instance + */ + function Touch(wsInstance) { + _classCallCheck(this, Touch); + + /** + * @type {WebSlides} + * @private + */ + this.ws_ = wsInstance; + + /** + * Start position for the X coord. + * @type {number} + * @private + */ + this.startX_ = 0; + + /** + * Start position for the Y coord. + * @type {number} + * @private + */ + this.startY_ = 0; + + /** + * Start position for the X coord. + * @type {number} + * @private + */ + this.endX_ = 0; + + /** + * Start position for the Y coord. + * @type {number} + * @private + */ + this.endY_ = 0; + + /** + * Whether is enabled or not. Only enabled for touch devices. + * @type {boolean} + * @private + */ + this.isEnabled = false; + + var events = void 0; + + if (__WEBPACK_IMPORTED_MODULE_0__utils_mobile_detector__["a" /* default */].isAny()) { + // Likely IE + if (window.PointerEvent && (__WEBPACK_IMPORTED_MODULE_0__utils_mobile_detector__["a" /* default */].isWindows() || __WEBPACK_IMPORTED_MODULE_0__utils_mobile_detector__["a" /* default */].isWindowsPhone())) { + events = EVENTS.pointer; + } else { + events = EVENTS.touch; + } + + this.isEnabled = true; + document.addEventListener(events.START, this.onStart_.bind(this), false); + document.addEventListener(events.MOVE, this.onMove_.bind(this), false); + document.addEventListener(events.MOVE, this.onMove_.bind(this), false); + document.addEventListener(events.END, this.onStop_.bind(this), false); + } + } + + /** + * Start touch handler. Saves starting points. + * @param event + * @private + */ + + + _createClass(Touch, [{ + key: 'onStart_', + value: function onStart_(event) { + var info = Touch.normalizeEventInfo(event); + + this.startX_ = info.x; + this.startY_ = info.y; + this.endX_ = info.x; + this.endY_ = info.y; + } + + /** + * Move touch handler. Saves end points. + * @param event + * @private + */ + + }, { + key: 'onMove_', + value: function onMove_(event) { + var info = Touch.normalizeEventInfo(event); + + this.endX_ = info.x; + this.endY_ = info.y; + } + + /** + * Stop touch handler. Checks if it needs to make any actions. + * @private + */ + + }, { + key: 'onStop_', + value: function onStop_() { + var diffX = this.startX_ - this.endX_; + var diffY = this.startY_ - this.endY_; + + // It's an horizontal drag + if (Math.abs(diffX) > Math.abs(diffY)) { + if (diffX < -SLIDE_OFFSET) { + this.ws_.goPrev(); + } else if (diffX > SLIDE_OFFSET) { + this.ws_.goNext(); + } + } + } + + /** + * Normalizes an event to deal with differences between PointerEvent and + * TouchEvent. + * @param event + * @return {*} + */ + + }], [{ + key: 'normalizeEventInfo', + value: function normalizeEventInfo(event) { + var x = void 0; + var y = void 0; + var touchEvent = { pageX: 0, pageY: 0 }; + + if (typeof event.changedTouches !== 'undefined') { + touchEvent = event.changedTouches[0]; + } else if (typeof event.originalEvent !== 'undefined' && typeof event.originalEvent.changedTouches !== 'undefined') { + touchEvent = event.originalEvent.changedTouches[0]; + } + + x = event.offsetX || event.layerX || touchEvent.pageX; + y = event.offsetY || event.layerY || touchEvent.pageY; + + return { x: x, y: y }; + } + }]); + + return Touch; +}(); + +/* harmony default export */ __webpack_exports__["a"] = Touch; +; + +/***/ }), +/* 12 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var NativeCustomEvent = window.CustomEvent; + +/** + * Check for the usage of native support for CustomEvents which is lacking + * completely on IE. + * @return {boolean} Whether it can be used or not. + */ +function canIuseNativeCustom() { + try { + var p = new NativeCustomEvent('t', { detail: { a: 'b' } }); + return 't' === p.type && 'b' === p.detail.a; + } catch (e) {} + return false; +} + +/** + * Lousy polyfill for the Custom Event constructor for IE. + * @param {!string} type The type of the event. + * @param {?Object} params Additional information for the event. + * @return {Event} + * @constructor + */ +var IECustomEvent = function CustomEvent(type, params) { + var e = document.createEvent('CustomEvent'); + + if (params) { + e.initCustomEvent(type, params.bubbles, params.cancelable, params.detail); + } else { + e.initCustomEvent(type, false, false, undefined); + } + + return e; +}; + +var WSCustomEvent = canIuseNativeCustom() ? NativeCustomEvent : IECustomEvent; + +/* harmony default export */ __webpack_exports__["a"] = WSCustomEvent; + +/***/ }), +/* 13 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/** + * Swing easing function. + * @param {number} p The percentage of time that has passed. + * @return {number} + */ +function swing(p) { + return 0.5 - Math.cos(p * Math.PI) / 2; +} + +/** + * Linear easing function. + * @param {number} p The percentage of time that has passed. + * @return {number} + */ +function linear(p) { + return p; +} + +/* harmony default export */ __webpack_exports__["a"] = { swing: swing, linear: linear }; + +/***/ }), +/* 14 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var UA = window.navigator.userAgent; + +var MobileDetector = function () { + function MobileDetector() { + _classCallCheck(this, MobileDetector); + } + + _createClass(MobileDetector, null, [{ + key: "isAndroid", + + /** + * Whether the device is Android or not. + * @return {Boolean} + */ + value: function isAndroid() { + return !!UA.match(/Android/i); + } + + /** + * Whether the device is BlackBerry or not. + * @return {Boolean} + */ + + }, { + key: "isBlackBerry", + value: function isBlackBerry() { + return !!UA.match(/BlackBerry/i); + } + + /** + * Whether the device is iOS or not. + * @return {Boolean} + */ + + }, { + key: "isiOS", + value: function isiOS() { + return !!UA.match(/iPhone/i); + } + + /** + * Whether the device is Opera or not. + * @return {Boolean} + */ + + }, { + key: "isOpera", + value: function isOpera() { + return !!UA.match(/Opera Mini/i); + } + + /** + * Whether the device is Windows or not. + * @return {Boolean} + */ + + }, { + key: "isWindows", + value: function isWindows() { + return !!UA.match(/IEMobile/i); + } + + /** + * Whether the device is Windows Phone or not. + * @return {Boolean} + */ + + }, { + key: "isWindowsPhone", + value: function isWindowsPhone() { + return !!UA.match(/Windows Phone/i); + } + + /** + * Whether the device is any mobile device or not. + * @return {Boolean} + */ + + }, { + key: "isAny", + value: function isAny() { + return MobileDetector.isAndroid() || MobileDetector.isBlackBerry() || MobileDetector.isiOS() || MobileDetector.isOpera() || MobileDetector.isWindows() || MobileDetector.isWindowsPhone(); + } + }]); + + return MobileDetector; +}(); + +/* harmony default export */ __webpack_exports__["a"] = MobileDetector; + +/***/ }), +/* 15 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__modules_webslides__ = __webpack_require__(3); + + +window.WebSlides = __WEBPACK_IMPORTED_MODULE_0__modules_webslides__["a" /* default */]; + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/static/js/webslides.min.js b/static/js/webslides.min.js new file mode 100644 index 0000000..004faaf --- /dev/null +++ b/static/js/webslides.min.js @@ -0,0 +1 @@ +!function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,i){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:i})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/static/js/",t(t.s=15)}([function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=n(12),o=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i=document.createElement(e);return i.id=t,n&&(i.textContent=n),i}},{key:"hide",value:function(e){e.style.display="none"}},{key:"show",value:function(e){e.style.display=""}},{key:"lockScroll",value:function(){document.documentElement.style.overflow="hidden"}},{key:"unlockScroll",value:function(){document.documentElement.style.overflow="auto"}},{key:"fireEvent",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=new r.a(t,{detail:n});e.dispatchEvent(i)}}]),e}();t.a=a},function(e,t,n){"use strict";var i={ENTER:13,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40};t.a=i},function(e,t,n){"use strict";function i(){if(a)return a;var e=window.document.documentElement,t=void 0;return e.scrollTop=1,1===e.scrollTop?(e.scrollTop=0,t=e):t=document.body,a=t,t}function r(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:500,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=i(),a=e-r.scrollTop,s=r.scrollTop,l=16;if(!t)return r.scrollTop=e,void n();var u=function i(u){u+=l;var c=Math.min(1,u/t),h=o.a.swing(c,u*c,e,a,t);r.scrollTop=Math.floor(s+h*a),u0&&void 0!==arguments[0]?arguments[0]:{},n=t.autoslide,r=void 0!==n&&n;if(i(this,e),this.el=document.getElementById("webslides"),this.isMoving=!1,this.slides=null,this.currentSlideI_=-1,this.currentSlide_=null,this.maxSlide_=0,this.isVertical=this.el.classList.contains(u.VERTICAL),this.plugins={},this.interval_=null,this.autoslide_=r,!this.el)throw new Error("Couldn't find the webslides container!");this.removeChildren_(),this.grabSlides_(),this.createPlugins_(),this.initSlides_(),this.play(),this.onInit_()}return l(e,[{key:"removeChildren_",value:function(){for(var e=this.el.childNodes,t=e.length;t--;){var n=e[t];o.a.isCandidate(n)||this.el.removeChild(n)}}},{key:"createPlugins_",value:function(){var e=this;Object.keys(c).forEach(function(t){var n=c[t];e.plugins[t]=new n(e)})}},{key:"onInit_",value:function(){a.a.fireEvent(this.el,"ws:init")}},{key:"grabSlides_",value:function(){this.slides=Array.from(this.el.childNodes).map(function(e,t){return new o.a(e,t)}),this.maxSlide_=this.slides.length}},{key:"goToSlide",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(this.isValidIndexSlide_(e)&&!this.isMoving){this.isMoving=!0;var n=!1;null!==t?n=t:this.currentSlideI_>=0&&(n=e>this.currentSlideI_);var i=this.slides[e];null===this.currentSlide_||!this.isVertical||this.plugins.touch&&this.plugins.touch.isEnabled?this.transitionToSlide_(n,i,this.onSlideChange_):this.scrollTransitionToSlide_(n,i,this.onSlideChange_)}}},{key:"scrollTransitionToSlide_",value:function(e,t,n){var i=this;a.a.lockScroll(),e?t.show():(t.moveBeforeFirst(),t.show(),s.a.scrollTo(this.currentSlide_.el.offsetTop,0)),s.a.scrollTo(t.el.offsetTop,500,function(){i.currentSlide_.hide(),e&&i.currentSlide_.moveAfterLast(),a.a.unlockScroll(),setTimeout(function(){n.call(i,t)},150)})}},{key:"transitionToSlide_",value:function(e,t,n){s.a.scrollTo(0,0),e||t.moveBeforeFirst(),this.currentSlide_&&(e&&this.currentSlide_.moveAfterLast(),this.currentSlide_.hide()),t.show(),n.call(this,t)}},{key:"onSlideChange_",value:function(e){this.currentSlide_=e,this.currentSlideI_=e.i,this.isMoving=!1,a.a.fireEvent(this.el,"ws:slide-change",{slides:this.maxSlide_,currentSlide0:this.currentSlideI_,currentSlide:this.currentSlideI_+1})}},{key:"goNext",value:function(){var e=this.currentSlideI_+1;e>=this.maxSlide_&&(e=0),this.goToSlide(e,!0)}},{key:"goPrev",value:function(){var e=this.currentSlideI_-1;e<0&&(e=this.maxSlide_-1),this.goToSlide(e,!1)}},{key:"isValidIndexSlide_",value:function(e){return e>=0&&e=this.maxSlide_)&&(e=0),0!==e)for(var t=0;t0&&(this.interval_=setInterval(this.goNext.bind(this),e))}},{key:"stop",value:function(){this.interval_&&(clearInterval(this.interval_),this.interval_=null)}}],[{key:"registerPlugin",value:function(e,t){c[e]=t}}]),e}();t.a=h},function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=n(0),o=function(){function e(e,t){for(var n=0;n=a&&(this.isGoingUp_?this.ws_.goPrev():this.ws_.goNext(),e.preventDefault())}}}]),e}();t.a=s},function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=n(14),o=function(){function e(e,t){for(var n=0;nMath.abs(t)&&(e<-s?this.ws_.goPrev():e>s&&this.ws_.goNext())}}],[{key:"normalizeEventInfo",value:function(e){var t=void 0,n=void 0,i={pageX:0,pageY:0};return"undefined"!=typeof e.changedTouches?i=e.changedTouches[0]:"undefined"!=typeof e.originalEvent&&"undefined"!=typeof e.originalEvent.changedTouches&&(i=e.originalEvent.changedTouches[0]),t=e.offsetX||e.layerX||i.pageX,n=e.offsetY||e.layerY||i.pageY,{x:t,y:n}}}]),e}();t.a=l},function(e,t,n){"use strict";function i(){try{var e=new r("t",{detail:{a:"b"}});return"t"===e.type&&"b"===e.detail.a}catch(e){}return!1}var r=window.CustomEvent,o=function(e,t){var n=document.createEvent("CustomEvent");return t?n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail):n.initCustomEvent(e,!1,!1,void 0),n},a=i()?r:o;t.a=a},function(e,t,n){"use strict";function i(e){return.5-Math.cos(e*Math.PI)/2}function r(e){return e}t.a={swing:i,linear:r}},function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(e,t){for(var n=0;n