UNPKG

21.7 kBJavaScriptView Raw
1/*!
2 * Offcanvas v2.0.0-alpha.1 (https://github.com/quark-dev/Phonon-Framework)
3 * Copyright 2015-2019 qathom
4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 */
6'use strict';
7
8function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
9
10var Util = _interopDefault(require('../util.js'));
11
12/*! *****************************************************************************
13Copyright (c) Microsoft Corporation. All rights reserved.
14Licensed under the Apache License, Version 2.0 (the "License"); you may not use
15this file except in compliance with the License. You may obtain a copy of the
16License at http://www.apache.org/licenses/LICENSE-2.0
17
18THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
20WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
21MERCHANTABLITY OR NON-INFRINGEMENT.
22
23See the Apache Version 2.0 License for specific language governing permissions
24and limitations under the License.
25***************************************************************************** */
26/* global Reflect, Promise */
27
28var extendStatics = function(d, b) {
29 extendStatics = Object.setPrototypeOf ||
30 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
31 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
32 return extendStatics(d, b);
33};
34
35function __extends(d, b) {
36 extendStatics(d, b);
37 function __() { this.constructor = d; }
38 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
39}
40
41function __awaiter(thisArg, _arguments, P, generator) {
42 return new (P || (P = Promise))(function (resolve, reject) {
43 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
44 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
45 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
46 step((generator = generator.apply(thisArg, _arguments || [])).next());
47 });
48}
49
50function __generator(thisArg, body) {
51 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
52 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
53 function verb(n) { return function (v) { return step([n, v]); }; }
54 function step(op) {
55 if (f) throw new TypeError("Generator is already executing.");
56 while (_) try {
57 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;
58 if (y = 0, t) op = [op[0] & 2, t.value];
59 switch (op[0]) {
60 case 0: case 1: t = op; break;
61 case 4: _.label++; return { value: op[1], done: false };
62 case 5: _.label++; y = op[1]; op = [0]; continue;
63 case 7: op = _.ops.pop(); _.trys.pop(); continue;
64 default:
65 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
66 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
67 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
68 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
69 if (t[2]) _.ops.pop();
70 _.trys.pop(); continue;
71 }
72 op = body.call(thisArg, _);
73 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
74 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
75 }
76}
77
78var Component = (function () {
79 function Component(name, defaultProps, props) {
80 var _this = this;
81 this.template = '';
82 this.id = null;
83 this.eventHandlers = [];
84 this.registeredElements = [];
85 this.name = name;
86 var element = typeof props.element === 'string'
87 ? document.querySelector(props.element) : props.element;
88 var config = {};
89 if (element) {
90 var dataConfig = Util.Selector.attrConfig(element);
91 if (dataConfig) {
92 config = dataConfig;
93 }
94 }
95 this.defaultProps = defaultProps;
96 this.props = Object.assign(defaultProps, config, props, { element: element });
97 this.id = this.uid();
98 this.elementListener = function (event) { return _this.onBeforeElementEvent(event); };
99 this.setEventsHandler();
100 }
101 Component.prototype.setTemplate = function (template) {
102 this.template = template;
103 };
104 Component.prototype.getTemplate = function () {
105 return this.template;
106 };
107 Component.prototype.getElement = function () {
108 return this.getProp('element') || null;
109 };
110 Component.prototype.setElement = function (element) {
111 this.props.element = element;
112 };
113 Component.prototype.getId = function () {
114 return this.id;
115 };
116 Component.prototype.uid = function () {
117 return Math.random().toString(36).substr(2, 10);
118 };
119 Component.prototype.getName = function () {
120 return this.name;
121 };
122 Component.prototype.getProps = function () {
123 return this.props;
124 };
125 Component.prototype.getProp = function (name) {
126 var defaultValue = this.defaultProps[name];
127 return typeof this.props[name] !== 'undefined' ? this.props[name] : defaultValue;
128 };
129 Component.prototype.setProps = function (props) {
130 var componentProps = Object.assign({}, props);
131 this.props = Object.assign(this.props, componentProps);
132 };
133 Component.prototype.setProp = function (name, value) {
134 if (typeof this.props[name] === 'undefined') {
135 throw new Error('Cannot set an invalid prop');
136 }
137 this.props[name] = value;
138 };
139 Component.prototype.registerElements = function (elements) {
140 var _this = this;
141 elements.forEach(function (element) { return _this.registerElement(element); });
142 };
143 Component.prototype.registerElement = function (element) {
144 element.target.addEventListener(element.event, this.elementListener);
145 this.registeredElements.push(element);
146 };
147 Component.prototype.unregisterElements = function () {
148 var _this = this;
149 this.registeredElements.forEach(function (element) {
150 _this.unregisterElement(element);
151 });
152 };
153 Component.prototype.unregisterElement = function (element) {
154 var registeredElementIndex = this.registeredElements
155 .findIndex(function (el) { return el.target === element.target && el.event === element.event; });
156 if (registeredElementIndex > -1) {
157 element.target.removeEventListener(element.event, this.elementListener);
158 this.registeredElements.splice(registeredElementIndex, 1);
159 }
160 else {
161 console.error('Warning! Could not remove element:'
162 + ' ' + (element.target + " with event: " + element.event + "."));
163 }
164 };
165 Component.prototype.triggerEvent = function (eventName, detail, objectEventOnly) {
166 var _this = this;
167 if (detail === void 0) { detail = {}; }
168 if (objectEventOnly === void 0) { objectEventOnly = false; }
169 var eventNameObject = eventName.split('.').reduce(function (acc, current, index) {
170 if (index === 0) {
171 return current;
172 }
173 return acc + current.charAt(0).toUpperCase() + current.slice(1);
174 });
175 var eventNameAlias = "on" + eventNameObject
176 .charAt(0).toUpperCase() + eventNameObject.slice(1);
177 var props = this.getProps();
178 this.eventHandlers.forEach(function (scope) {
179 if (typeof scope[eventNameObject] === 'function') {
180 scope[eventNameObject].apply(_this, [detail]);
181 }
182 if (typeof scope[eventNameAlias] === 'function') {
183 props[eventNameAlias].apply(_this, [detail]);
184 }
185 });
186 if (objectEventOnly) {
187 return;
188 }
189 var element = this.getElement();
190 if (element) {
191 Util.Dispatch.elementEvent(element, eventName, this.name, detail);
192 }
193 else {
194 Util.Dispatch.winDocEvent(eventName, this.name, detail);
195 }
196 };
197 Component.prototype.preventClosable = function () {
198 return false;
199 };
200 Component.prototype.destroy = function () {
201 this.unregisterElements();
202 };
203 Component.prototype.onElementEvent = function (event) {
204 };
205 Component.prototype.setEventsHandler = function () {
206 var props = this.getProps();
207 var scope = Object.keys(props).reduce(function (cur, key) {
208 if (typeof props[key] === 'function') {
209 cur[key] = props[key];
210 }
211 return cur;
212 }, {});
213 if (Object.keys(scope).length > 0) {
214 this.eventHandlers.push(scope);
215 }
216 };
217 Component.prototype.onBeforeElementEvent = function (event) {
218 if (this.preventClosable()) {
219 return;
220 }
221 this.onElementEvent(event);
222 };
223 return Component;
224}());
225
226var OffCanvas = (function (_super) {
227 __extends(OffCanvas, _super);
228 function OffCanvas(props) {
229 var _this = _super.call(this, 'off-canvas', {
230 toggle: false,
231 closableKeyCodes: [27],
232 container: document.body,
233 setupContainer: true,
234 aside: {
235 md: false,
236 lg: true,
237 xl: true,
238 },
239 }, props) || this;
240 _this.currentWidthName = null;
241 _this.animate = true;
242 _this.showAside = false;
243 _this.directions = ['left', 'right'];
244 _this.direction = null;
245 _this.sizes = [];
246 _this.backdropSelector = 'offcanvas-backdrop';
247 var sm = { name: 'sm', media: window.matchMedia('(min-width: 1px)') };
248 var md = { name: 'md', media: window.matchMedia('(min-width: 768px)') };
249 var lg = { name: 'lg', media: window.matchMedia('(min-width: 992px)') };
250 var xl = { name: 'xl', media: window.matchMedia('(min-width: 1200px)') };
251 _this.sizes = [sm, md, lg, xl].reverse();
252 _this.checkDirection();
253 if (_this.getProp('setupContainer')) {
254 _this.checkWidth();
255 }
256 var toggle = _this.getProp('toggle');
257 if (toggle) {
258 _this.toggle();
259 }
260 window.addEventListener('resize', function () { return _this.checkWidth(); }, false);
261 return _this;
262 }
263 OffCanvas.attachDOM = function () {
264 var className = 'offcanvas';
265 Util.Observer.subscribe({
266 componentClass: className,
267 onAdded: function (element, create) {
268 create(new OffCanvas({ element: element }));
269 },
270 onRemoved: function (element, remove) {
271 remove('OffCanvas', element);
272 },
273 });
274 document.addEventListener(Util.Event.CLICK, function (event) {
275 var target = event.target;
276 if (!target) {
277 return;
278 }
279 var toggleEl = Util.Selector.closest(target, "[data-toggle=\"" + className + "\"]");
280 if (toggleEl) {
281 var selector = toggleEl.getAttribute('data-target');
282 if (!selector) {
283 return;
284 }
285 var offCanvas = document.querySelector(selector);
286 if (!offCanvas) {
287 return;
288 }
289 var offCanvasComponent = Util.Observer.getComponent(className, { element: offCanvas });
290 if (!offCanvasComponent) {
291 return;
292 }
293 target.blur();
294 offCanvasComponent.toggle();
295 }
296 });
297 };
298 OffCanvas.prototype.checkDirection = function () {
299 var _this = this;
300 var element = this.getElement();
301 this.directions.every(function (direction) {
302 if (element.classList.contains("offcanvas-" + direction)) {
303 _this.direction = direction;
304 return false;
305 }
306 return true;
307 });
308 };
309 OffCanvas.prototype.checkWidth = function () {
310 if (!('matchMedia' in window)) {
311 return;
312 }
313 var size = this.sizes.find(function (s) {
314 var mediaQuery = s.media;
315 var match = mediaQuery.media.match(/[a-z]?-width:\s?([0-9]+)/);
316 return match && mediaQuery.matches ? true : false;
317 });
318 if (!size) {
319 return;
320 }
321 this.setAside(size.name);
322 };
323 OffCanvas.prototype.setAside = function (sizeName) {
324 var container = this.getContainer();
325 if (this.currentWidthName === sizeName || !container) {
326 return;
327 }
328 this.currentWidthName = sizeName;
329 var aside = this.getProp('aside');
330 this.showAside = aside[sizeName] === true;
331 if (aside[sizeName] === true) {
332 if (!container.classList.contains("offcanvas-aside-" + this.direction)) {
333 container.classList.add("offcanvas-aside-" + this.direction);
334 }
335 this.animate = false;
336 if (this.getBackdrop()) {
337 this.removeBackdrop();
338 }
339 var containerShowClass = this.getShowClass();
340 if (this.isVisible() && !container.classList.contains(containerShowClass)) {
341 container.classList.add(containerShowClass);
342 }
343 else if (!this.isVisible() && container.classList.contains(containerShowClass)) {
344 container.classList.remove(containerShowClass);
345 }
346 }
347 else {
348 if (container.classList.contains("offcanvas-aside-" + this.direction)) {
349 container.classList.remove("offcanvas-aside-" + this.direction);
350 }
351 this.animate = true;
352 this.hide();
353 }
354 };
355 OffCanvas.prototype.onElementEvent = function (event) {
356 var closableKeyCodes = this.getProp('closableKeyCodes');
357 if (event.type === 'keyup' && !closableKeyCodes.find(function (k) { return k === event.keyCode; })) {
358 return;
359 }
360 this.hide();
361 };
362 OffCanvas.prototype.isVisible = function () {
363 return this.getElement().classList.contains('show');
364 };
365 OffCanvas.prototype.show = function () {
366 var _this = this;
367 if (this.getElement().classList.contains('show')) {
368 return false;
369 }
370 this.triggerEvent(Util.Event.SHOW);
371 if (!this.showAside) {
372 this.createBackdrop();
373 }
374 (function () { return __awaiter(_this, void 0, void 0, function () {
375 var onShown, container, containerShowClass, el;
376 var _this = this;
377 return __generator(this, function (_a) {
378 switch (_a.label) {
379 case 0: return [4, Util.sleep(20)];
380 case 1:
381 _a.sent();
382 this.attachEvents();
383 onShown = function () {
384 _this.triggerEvent(Util.Event.SHOWN);
385 if (_this.animate) {
386 var element = _this.getElement();
387 element.removeEventListener(Util.Event.TRANSITION_END, onShown);
388 element.classList.remove('animate');
389 }
390 };
391 if (this.showAside) {
392 container = this.getContainer();
393 containerShowClass = this.getShowClass();
394 if (container && !container.classList.contains(containerShowClass)) {
395 container.classList.add(containerShowClass);
396 }
397 }
398 el = this.getElement();
399 if (this.animate) {
400 el.addEventListener(Util.Event.TRANSITION_END, onShown);
401 el.classList.add('animate');
402 }
403 else {
404 onShown();
405 }
406 el.classList.add('show');
407 return [2];
408 }
409 });
410 }); })();
411 return true;
412 };
413 OffCanvas.prototype.hide = function () {
414 var _this = this;
415 var element = this.getElement();
416 if (!element.classList.contains('show')) {
417 return false;
418 }
419 this.triggerEvent(Util.Event.HIDE);
420 this.detachEvents();
421 if (this.animate) {
422 element.classList.add('animate');
423 }
424 element.classList.remove('show');
425 if (this.showAside) {
426 var container = this.getContainer();
427 var containerShowClass = this.getShowClass();
428 if (container && container.classList.contains(containerShowClass)) {
429 container.classList.remove(containerShowClass);
430 }
431 }
432 if (!this.showAside) {
433 var backdrop_1 = this.getBackdrop();
434 if (!backdrop_1) {
435 return true;
436 }
437 var onHidden_1 = function () {
438 if (_this.animate) {
439 element.classList.remove('animate');
440 }
441 backdrop_1.removeEventListener(Util.Event.TRANSITION_END, onHidden_1);
442 _this.triggerEvent(Util.Event.HIDDEN);
443 _this.removeBackdrop();
444 };
445 if (backdrop_1) {
446 backdrop_1.addEventListener(Util.Event.TRANSITION_END, onHidden_1);
447 backdrop_1.classList.add('fadeout');
448 }
449 }
450 return true;
451 };
452 OffCanvas.prototype.toggle = function () {
453 if (this.isVisible()) {
454 return this.hide();
455 }
456 return this.show();
457 };
458 OffCanvas.prototype.createBackdrop = function () {
459 var backdrop = document.createElement('div');
460 var id = this.getId();
461 if (id) {
462 backdrop.setAttribute('data-id', id);
463 }
464 backdrop.classList.add(this.backdropSelector);
465 var container = this.getContainer();
466 if (container) {
467 container.appendChild(backdrop);
468 }
469 };
470 OffCanvas.prototype.getBackdrop = function () {
471 return document.querySelector("." + this.backdropSelector + "[data-id=\"" + this.getId() + "\"]");
472 };
473 OffCanvas.prototype.removeBackdrop = function () {
474 var backdrop = this.getBackdrop();
475 if (backdrop && backdrop.parentNode) {
476 backdrop.parentNode.removeChild(backdrop);
477 }
478 };
479 OffCanvas.prototype.attachEvents = function () {
480 var _this = this;
481 var element = this.getElement();
482 Array.from(element.querySelectorAll('[data-dismiss]') || [])
483 .forEach(function (button) { return _this.registerElement({
484 target: button,
485 event: Util.Event.CLICK,
486 }); });
487 var backdrop = this.getBackdrop();
488 if (!this.showAside && backdrop) {
489 this.registerElement({ target: backdrop, event: Util.Event.START });
490 }
491 this.registerElement({ target: document, event: 'keyup' });
492 };
493 OffCanvas.prototype.detachEvents = function () {
494 var _this = this;
495 var element = this.getElement();
496 var dismissButtons = element.querySelectorAll('[data-dismiss]');
497 if (dismissButtons) {
498 Array
499 .from(dismissButtons)
500 .forEach(function (button) { return _this.unregisterElement({
501 target: button,
502 event: Util.Event.CLICK,
503 }); });
504 }
505 var backdrop = this.getBackdrop();
506 if (!this.showAside && backdrop) {
507 this.unregisterElement({ target: backdrop, event: Util.Event.START });
508 }
509 this.unregisterElement({ target: document, event: 'keyup' });
510 };
511 OffCanvas.prototype.getContainer = function () {
512 var container = this.getProp('container');
513 if (typeof container === 'string') {
514 container = document.querySelector(container);
515 }
516 return container;
517 };
518 OffCanvas.prototype.getShowClass = function () {
519 return "show-" + this.direction;
520 };
521 return OffCanvas;
522}(Component));
523OffCanvas.attachDOM();
524
525module.exports = OffCanvas;
526//# sourceMappingURL=offcanvas.js.map