UNPKG

phonon

Version:

Phonon is an open source HTML, CSS and JavaScript agnostic framework that allows to create a website or a hybrid Web app.

527 lines (514 loc) 21.7 kB
/*! * Offcanvas v2.0.0-alpha.1 (https://github.com/quark-dev/Phonon-Framework) * Copyright 2015-2019 qathom * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ 'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var Util = _interopDefault(require('../util.js')); /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } function __awaiter(thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } var Component = (function () { function Component(name, defaultProps, props) { var _this = this; this.template = ''; this.id = null; this.eventHandlers = []; this.registeredElements = []; this.name = name; var element = typeof props.element === 'string' ? document.querySelector(props.element) : props.element; var config = {}; if (element) { var dataConfig = Util.Selector.attrConfig(element); if (dataConfig) { config = dataConfig; } } this.defaultProps = defaultProps; this.props = Object.assign(defaultProps, config, props, { element: element }); this.id = this.uid(); this.elementListener = function (event) { return _this.onBeforeElementEvent(event); }; this.setEventsHandler(); } Component.prototype.setTemplate = function (template) { this.template = template; }; Component.prototype.getTemplate = function () { return this.template; }; Component.prototype.getElement = function () { return this.getProp('element') || null; }; Component.prototype.setElement = function (element) { this.props.element = element; }; Component.prototype.getId = function () { return this.id; }; Component.prototype.uid = function () { return Math.random().toString(36).substr(2, 10); }; Component.prototype.getName = function () { return this.name; }; Component.prototype.getProps = function () { return this.props; }; Component.prototype.getProp = function (name) { var defaultValue = this.defaultProps[name]; return typeof this.props[name] !== 'undefined' ? this.props[name] : defaultValue; }; Component.prototype.setProps = function (props) { var componentProps = Object.assign({}, props); this.props = Object.assign(this.props, componentProps); }; Component.prototype.setProp = function (name, value) { if (typeof this.props[name] === 'undefined') { throw new Error('Cannot set an invalid prop'); } this.props[name] = value; }; Component.prototype.registerElements = function (elements) { var _this = this; elements.forEach(function (element) { return _this.registerElement(element); }); }; Component.prototype.registerElement = function (element) { element.target.addEventListener(element.event, this.elementListener); this.registeredElements.push(element); }; Component.prototype.unregisterElements = function () { var _this = this; this.registeredElements.forEach(function (element) { _this.unregisterElement(element); }); }; Component.prototype.unregisterElement = function (element) { var registeredElementIndex = this.registeredElements .findIndex(function (el) { return el.target === element.target && el.event === element.event; }); if (registeredElementIndex > -1) { element.target.removeEventListener(element.event, this.elementListener); this.registeredElements.splice(registeredElementIndex, 1); } else { console.error('Warning! Could not remove element:' + ' ' + (element.target + " with event: " + element.event + ".")); } }; Component.prototype.triggerEvent = function (eventName, detail, objectEventOnly) { var _this = this; if (detail === void 0) { detail = {}; } if (objectEventOnly === void 0) { objectEventOnly = false; } var eventNameObject = eventName.split('.').reduce(function (acc, current, index) { if (index === 0) { return current; } return acc + current.charAt(0).toUpperCase() + current.slice(1); }); var eventNameAlias = "on" + eventNameObject .charAt(0).toUpperCase() + eventNameObject.slice(1); var props = this.getProps(); this.eventHandlers.forEach(function (scope) { if (typeof scope[eventNameObject] === 'function') { scope[eventNameObject].apply(_this, [detail]); } if (typeof scope[eventNameAlias] === 'function') { props[eventNameAlias].apply(_this, [detail]); } }); if (objectEventOnly) { return; } var element = this.getElement(); if (element) { Util.Dispatch.elementEvent(element, eventName, this.name, detail); } else { Util.Dispatch.winDocEvent(eventName, this.name, detail); } }; Component.prototype.preventClosable = function () { return false; }; Component.prototype.destroy = function () { this.unregisterElements(); }; Component.prototype.onElementEvent = function (event) { }; Component.prototype.setEventsHandler = function () { var props = this.getProps(); var scope = Object.keys(props).reduce(function (cur, key) { if (typeof props[key] === 'function') { cur[key] = props[key]; } return cur; }, {}); if (Object.keys(scope).length > 0) { this.eventHandlers.push(scope); } }; Component.prototype.onBeforeElementEvent = function (event) { if (this.preventClosable()) { return; } this.onElementEvent(event); }; return Component; }()); var OffCanvas = (function (_super) { __extends(OffCanvas, _super); function OffCanvas(props) { var _this = _super.call(this, 'off-canvas', { toggle: false, closableKeyCodes: [27], container: document.body, setupContainer: true, aside: { md: false, lg: true, xl: true, }, }, props) || this; _this.currentWidthName = null; _this.animate = true; _this.showAside = false; _this.directions = ['left', 'right']; _this.direction = null; _this.sizes = []; _this.backdropSelector = 'offcanvas-backdrop'; var sm = { name: 'sm', media: window.matchMedia('(min-width: 1px)') }; var md = { name: 'md', media: window.matchMedia('(min-width: 768px)') }; var lg = { name: 'lg', media: window.matchMedia('(min-width: 992px)') }; var xl = { name: 'xl', media: window.matchMedia('(min-width: 1200px)') }; _this.sizes = [sm, md, lg, xl].reverse(); _this.checkDirection(); if (_this.getProp('setupContainer')) { _this.checkWidth(); } var toggle = _this.getProp('toggle'); if (toggle) { _this.toggle(); } window.addEventListener('resize', function () { return _this.checkWidth(); }, false); return _this; } OffCanvas.attachDOM = function () { var className = 'offcanvas'; Util.Observer.subscribe({ componentClass: className, onAdded: function (element, create) { create(new OffCanvas({ element: element })); }, onRemoved: function (element, remove) { remove('OffCanvas', element); }, }); document.addEventListener(Util.Event.CLICK, function (event) { var target = event.target; if (!target) { return; } var toggleEl = Util.Selector.closest(target, "[data-toggle=\"" + className + "\"]"); if (toggleEl) { var selector = toggleEl.getAttribute('data-target'); if (!selector) { return; } var offCanvas = document.querySelector(selector); if (!offCanvas) { return; } var offCanvasComponent = Util.Observer.getComponent(className, { element: offCanvas }); if (!offCanvasComponent) { return; } target.blur(); offCanvasComponent.toggle(); } }); }; OffCanvas.prototype.checkDirection = function () { var _this = this; var element = this.getElement(); this.directions.every(function (direction) { if (element.classList.contains("offcanvas-" + direction)) { _this.direction = direction; return false; } return true; }); }; OffCanvas.prototype.checkWidth = function () { if (!('matchMedia' in window)) { return; } var size = this.sizes.find(function (s) { var mediaQuery = s.media; var match = mediaQuery.media.match(/[a-z]?-width:\s?([0-9]+)/); return match && mediaQuery.matches ? true : false; }); if (!size) { return; } this.setAside(size.name); }; OffCanvas.prototype.setAside = function (sizeName) { var container = this.getContainer(); if (this.currentWidthName === sizeName || !container) { return; } this.currentWidthName = sizeName; var aside = this.getProp('aside'); this.showAside = aside[sizeName] === true; if (aside[sizeName] === true) { if (!container.classList.contains("offcanvas-aside-" + this.direction)) { container.classList.add("offcanvas-aside-" + this.direction); } this.animate = false; if (this.getBackdrop()) { this.removeBackdrop(); } var containerShowClass = this.getShowClass(); if (this.isVisible() && !container.classList.contains(containerShowClass)) { container.classList.add(containerShowClass); } else if (!this.isVisible() && container.classList.contains(containerShowClass)) { container.classList.remove(containerShowClass); } } else { if (container.classList.contains("offcanvas-aside-" + this.direction)) { container.classList.remove("offcanvas-aside-" + this.direction); } this.animate = true; this.hide(); } }; OffCanvas.prototype.onElementEvent = function (event) { var closableKeyCodes = this.getProp('closableKeyCodes'); if (event.type === 'keyup' && !closableKeyCodes.find(function (k) { return k === event.keyCode; })) { return; } this.hide(); }; OffCanvas.prototype.isVisible = function () { return this.getElement().classList.contains('show'); }; OffCanvas.prototype.show = function () { var _this = this; if (this.getElement().classList.contains('show')) { return false; } this.triggerEvent(Util.Event.SHOW); if (!this.showAside) { this.createBackdrop(); } (function () { return __awaiter(_this, void 0, void 0, function () { var onShown, container, containerShowClass, el; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, Util.sleep(20)]; case 1: _a.sent(); this.attachEvents(); onShown = function () { _this.triggerEvent(Util.Event.SHOWN); if (_this.animate) { var element = _this.getElement(); element.removeEventListener(Util.Event.TRANSITION_END, onShown); element.classList.remove('animate'); } }; if (this.showAside) { container = this.getContainer(); containerShowClass = this.getShowClass(); if (container && !container.classList.contains(containerShowClass)) { container.classList.add(containerShowClass); } } el = this.getElement(); if (this.animate) { el.addEventListener(Util.Event.TRANSITION_END, onShown); el.classList.add('animate'); } else { onShown(); } el.classList.add('show'); return [2]; } }); }); })(); return true; }; OffCanvas.prototype.hide = function () { var _this = this; var element = this.getElement(); if (!element.classList.contains('show')) { return false; } this.triggerEvent(Util.Event.HIDE); this.detachEvents(); if (this.animate) { element.classList.add('animate'); } element.classList.remove('show'); if (this.showAside) { var container = this.getContainer(); var containerShowClass = this.getShowClass(); if (container && container.classList.contains(containerShowClass)) { container.classList.remove(containerShowClass); } } if (!this.showAside) { var backdrop_1 = this.getBackdrop(); if (!backdrop_1) { return true; } var onHidden_1 = function () { if (_this.animate) { element.classList.remove('animate'); } backdrop_1.removeEventListener(Util.Event.TRANSITION_END, onHidden_1); _this.triggerEvent(Util.Event.HIDDEN); _this.removeBackdrop(); }; if (backdrop_1) { backdrop_1.addEventListener(Util.Event.TRANSITION_END, onHidden_1); backdrop_1.classList.add('fadeout'); } } return true; }; OffCanvas.prototype.toggle = function () { if (this.isVisible()) { return this.hide(); } return this.show(); }; OffCanvas.prototype.createBackdrop = function () { var backdrop = document.createElement('div'); var id = this.getId(); if (id) { backdrop.setAttribute('data-id', id); } backdrop.classList.add(this.backdropSelector); var container = this.getContainer(); if (container) { container.appendChild(backdrop); } }; OffCanvas.prototype.getBackdrop = function () { return document.querySelector("." + this.backdropSelector + "[data-id=\"" + this.getId() + "\"]"); }; OffCanvas.prototype.removeBackdrop = function () { var backdrop = this.getBackdrop(); if (backdrop && backdrop.parentNode) { backdrop.parentNode.removeChild(backdrop); } }; OffCanvas.prototype.attachEvents = function () { var _this = this; var element = this.getElement(); Array.from(element.querySelectorAll('[data-dismiss]') || []) .forEach(function (button) { return _this.registerElement({ target: button, event: Util.Event.CLICK, }); }); var backdrop = this.getBackdrop(); if (!this.showAside && backdrop) { this.registerElement({ target: backdrop, event: Util.Event.START }); } this.registerElement({ target: document, event: 'keyup' }); }; OffCanvas.prototype.detachEvents = function () { var _this = this; var element = this.getElement(); var dismissButtons = element.querySelectorAll('[data-dismiss]'); if (dismissButtons) { Array .from(dismissButtons) .forEach(function (button) { return _this.unregisterElement({ target: button, event: Util.Event.CLICK, }); }); } var backdrop = this.getBackdrop(); if (!this.showAside && backdrop) { this.unregisterElement({ target: backdrop, event: Util.Event.START }); } this.unregisterElement({ target: document, event: 'keyup' }); }; OffCanvas.prototype.getContainer = function () { var container = this.getProp('container'); if (typeof container === 'string') { container = document.querySelector(container); } return container; }; OffCanvas.prototype.getShowClass = function () { return "show-" + this.direction; }; return OffCanvas; }(Component)); OffCanvas.attachDOM(); module.exports = OffCanvas; //# sourceMappingURL=offcanvas.js.map