UNPKG

26.1 kBJavaScriptView Raw
1/*!
2 * ModalLoader 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 Size;
227(function (Size) {
228 Size["sm"] = "sm";
229 Size["md"] = "md";
230 Size["lg"] = "lg";
231 Size["xl"] = "xl";
232})(Size || (Size = {}));
233var Color;
234(function (Color) {
235 Color["primary"] = "primary";
236 Color["secondary"] = "secondary";
237 Color["success"] = "success";
238 Color["warning"] = "warning";
239 Color["danger"] = "danger";
240})(Color || (Color = {}));
241var Direction;
242(function (Direction) {
243 Direction["top"] = "top";
244 Direction["right"] = "right";
245 Direction["bottom"] = "bottom";
246 Direction["left"] = "left";
247})(Direction || (Direction = {}));
248
249var Loader = (function (_super) {
250 __extends(Loader, _super);
251 function Loader(props) {
252 if (props === void 0) { props = { color: Color.primary, size: Size.md }; }
253 return _super.call(this, 'loader', { fade: true, size: Size.md, color: Color.primary }, props) || this;
254 }
255 Loader.prototype.show = function () {
256 var element = this.getElement();
257 if (element.classList.contains('hide')) {
258 element.classList.remove('hide');
259 }
260 this.triggerEvent(Util.Event.SHOW);
261 var size = this.getProp('size');
262 Util.Selector.removeClasses(element, Object.values(Size), 'loader');
263 element.classList.add("loader-" + size);
264 var color = this.getProp('color');
265 var spinner = this.getSpinner();
266 Util.Selector.removeClasses(spinner, Object.values(Color), 'loader');
267 spinner.classList.add("loader-" + color);
268 this.triggerEvent(Util.Event.SHOWN);
269 return true;
270 };
271 Loader.prototype.animate = function (startAnimation) {
272 if (startAnimation === void 0) { startAnimation = true; }
273 if (startAnimation) {
274 this.show();
275 }
276 else {
277 this.hide();
278 }
279 var loaderSpinner = this.getSpinner();
280 if (startAnimation
281 && !loaderSpinner.classList.contains('loader-spinner-animated')) {
282 loaderSpinner.classList.add('loader-spinner-animated');
283 return true;
284 }
285 if (!startAnimation
286 && loaderSpinner.classList.contains('loader-spinner-animated')) {
287 loaderSpinner.classList.remove('loader-spinner-animated');
288 }
289 return true;
290 };
291 Loader.prototype.hide = function () {
292 var element = this.getElement();
293 if (!element.classList.contains('hide')) {
294 element.classList.add('hide');
295 }
296 this.triggerEvent(Util.Event.HIDE);
297 this.triggerEvent(Util.Event.HIDDEN);
298 return true;
299 };
300 Loader.prototype.getSpinner = function () {
301 return this.getElement().querySelector('.loader-spinner');
302 };
303 return Loader;
304}(Component));
305
306var Modal = (function (_super) {
307 __extends(Modal, _super);
308 function Modal(props, autoCreate) {
309 if (autoCreate === void 0) { autoCreate = true; }
310 var _this = _super.call(this, 'modal', {
311 title: null,
312 message: null,
313 cancelable: true,
314 background: null,
315 cancelableKeyCodes: [
316 27,
317 13,
318 ],
319 buttons: [
320 { event: 'confirm', text: 'Ok', dismiss: true, class: 'btn btn-primary' },
321 ],
322 center: true,
323 }, props) || this;
324 _this.backdropSelector = 'modal-backdrop';
325 _this.elementGenerated = false;
326 _this.setTemplate(''
327 + '<div class="modal" tabindex="-1" role="modal" data-no-boot>'
328 + '<div class="modal-inner" role="document">'
329 + '<div class="modal-content">'
330 + '<div class="modal-header">'
331 + '<h5 class="modal-title"></h5>'
332 + '<button type="button" class="icon-close" data-dismiss="modal" aria-label="Close">'
333 + '<span class="icon" aria-hidden="true"></span>'
334 + '</button>'
335 + '</div>'
336 + '<div class="modal-body">'
337 + '<p></p>'
338 + '</div>'
339 + '<div class="modal-footer">'
340 + '</div>'
341 + '</div>'
342 + '</div>'
343 + '</div>');
344 if (autoCreate && _this.getElement() === null) {
345 _this.build();
346 }
347 return _this;
348 }
349 Modal.attachDOM = function () {
350 var className = 'modal';
351 Util.Observer.subscribe({
352 componentClass: className,
353 onAdded: function (element, create) {
354 create(new Modal({ element: element }));
355 },
356 onRemoved: function (element, remove) {
357 remove('Modal', element);
358 },
359 });
360 document.addEventListener(Util.Event.CLICK, function (event) {
361 var target = event.target;
362 if (!target) {
363 return;
364 }
365 var toggleEl = Util.Selector.closest(target, "[data-toggle=\"" + className + "\"]");
366 if (toggleEl) {
367 var selector = toggleEl.getAttribute('data-target');
368 if (!selector) {
369 return;
370 }
371 var modal = document.querySelector(selector);
372 if (!modal) {
373 return;
374 }
375 var modalComponent = Util.Observer.getComponent(className, { element: modal });
376 if (!modalComponent) {
377 return;
378 }
379 target.blur();
380 modalComponent.show();
381 }
382 });
383 };
384 Modal.prototype.build = function () {
385 var _this = this;
386 this.elementGenerated = true;
387 var builder = document.createElement('div');
388 builder.innerHTML = this.getTemplate();
389 this.setElement(builder.firstChild);
390 var element = this.getElement();
391 var title = this.getProp('title');
392 if (title !== null) {
393 element.querySelector('.modal-title').innerHTML = title;
394 }
395 var message = this.getProp('message');
396 if (message !== null) {
397 element.querySelector('.modal-body').firstChild.innerHTML = message;
398 }
399 else {
400 this.removeTextBody();
401 }
402 var cancelable = this.getProp('cancelable');
403 if (!cancelable) {
404 element.querySelector('.close').style.display = 'none';
405 }
406 var buttons = this.getProp('buttons');
407 if (Array.isArray(buttons) && buttons.length > 0) {
408 buttons.forEach(function (button) {
409 element.querySelector('.modal-footer').appendChild(_this.buildButton(button));
410 });
411 }
412 else {
413 this.removeFooter();
414 }
415 document.body.appendChild(element);
416 };
417 Modal.prototype.show = function () {
418 var _this = this;
419 var element = this.getElement();
420 if (element === null) {
421 this.build();
422 }
423 if (element.classList.contains('show')) {
424 return false;
425 }
426 document.body.style.overflow = 'hidden';
427 (function () { return __awaiter(_this, void 0, void 0, function () {
428 var onShown;
429 var _this = this;
430 return __generator(this, function (_a) {
431 switch (_a.label) {
432 case 0: return [4, Util.sleep(20)];
433 case 1:
434 _a.sent();
435 this.triggerEvent(Util.Event.SHOW);
436 this.buildBackdrop();
437 this.attachEvents();
438 onShown = function () {
439 _this.triggerEvent(Util.Event.SHOWN);
440 element.removeEventListener(Util.Event.TRANSITION_END, onShown);
441 };
442 element.addEventListener(Util.Event.TRANSITION_END, onShown);
443 if (this.getProp('center')) {
444 this.center();
445 }
446 element.classList.add('show');
447 return [2];
448 }
449 });
450 }); })();
451 return true;
452 };
453 Modal.prototype.hide = function () {
454 var _this = this;
455 var element = this.getElement();
456 if (!element.classList.contains('show')) {
457 return false;
458 }
459 document.body.style.overflow = 'visible';
460 this.triggerEvent(Util.Event.HIDE);
461 this.detachEvents();
462 element.classList.add('hide');
463 element.classList.remove('show');
464 var backdrop = this.getBackdrop();
465 var onHidden = function () {
466 if (backdrop) {
467 document.body.removeChild(backdrop);
468 backdrop.removeEventListener(Util.Event.TRANSITION_END, onHidden);
469 }
470 element.classList.remove('hide');
471 _this.triggerEvent(Util.Event.HIDDEN);
472 if (_this.elementGenerated) {
473 document.body.removeChild(element);
474 }
475 };
476 if (backdrop) {
477 backdrop.addEventListener(Util.Event.TRANSITION_END, onHidden);
478 backdrop.classList.add('fadeout');
479 }
480 return true;
481 };
482 Modal.prototype.onElementEvent = function (event) {
483 if (event.type === 'keyup') {
484 var keycodes = this.getProp('cancelableKeyCodes');
485 if (keycodes.find(function (k) { return k === event.keyCode; })) {
486 this.hide();
487 }
488 return;
489 }
490 if (event.type === Util.Event.START) {
491 this.hide();
492 return;
493 }
494 if (event.type === Util.Event.CLICK) {
495 var target = event.target;
496 var eventName = target.getAttribute('data-event');
497 if (eventName) {
498 this.triggerEvent(eventName);
499 }
500 var dismissButton = Util.Selector.closest(target, '[data-dismiss]');
501 if (dismissButton && dismissButton.getAttribute('data-dismiss') === 'modal') {
502 this.hide();
503 }
504 }
505 };
506 Modal.prototype.setBackgroud = function () {
507 var element = this.getElement();
508 var background = this.getProp('background');
509 if (!background) {
510 return;
511 }
512 if (!element.classList.contains("modal-" + background)) {
513 element.classList.add("modal-" + background);
514 }
515 if (!element.classList.contains('text-white')) {
516 element.classList.add('text-white');
517 }
518 };
519 Modal.prototype.buildButton = function (buttonInfo) {
520 var button = document.createElement('button');
521 button.setAttribute('type', 'button');
522 button.setAttribute('class', buttonInfo.class || 'btn');
523 button.setAttribute('data-event', buttonInfo.event);
524 button.innerHTML = buttonInfo.text;
525 if (buttonInfo.dismiss) {
526 button.setAttribute('data-dismiss', 'modal');
527 }
528 return button;
529 };
530 Modal.prototype.buildBackdrop = function () {
531 var backdrop = document.createElement('div');
532 backdrop.setAttribute('data-id', this.getId());
533 backdrop.classList.add(this.backdropSelector);
534 document.body.appendChild(backdrop);
535 };
536 Modal.prototype.getBackdrop = function () {
537 return document.querySelector("." + this.backdropSelector + "[data-id=\"" + this.getId() + "\"]");
538 };
539 Modal.prototype.removeTextBody = function () {
540 var element = this.getElement();
541 element.querySelector('.modal-body')
542 .removeChild(element.querySelector('.modal-body').firstChild);
543 };
544 Modal.prototype.removeFooter = function () {
545 var element = this.getElement();
546 var footer = element.querySelector('.modal-footer');
547 element.querySelector('.modal-content').removeChild(footer);
548 };
549 Modal.prototype.center = function () {
550 var element = this.getElement();
551 var computedStyle = window.getComputedStyle(element);
552 if (computedStyle && computedStyle.height) {
553 var height = computedStyle.height.slice(0, computedStyle.height.length - 2);
554 var top_1 = (window.innerHeight / 2) - (parseFloat(height) / 2);
555 element.style.top = top_1 + "px";
556 }
557 };
558 Modal.prototype.attachEvents = function () {
559 var _this = this;
560 var element = this.getElement();
561 var buttons = Array
562 .from(element.querySelectorAll('[data-dismiss], .modal-footer button') || []);
563 buttons.forEach(function (button) { return _this.registerElement({
564 target: button,
565 event: Util.Event.CLICK,
566 }); });
567 var cancelable = this.getProp('cancelable');
568 var backdrop = this.getBackdrop();
569 if (cancelable && backdrop) {
570 this.registerElement({ target: backdrop, event: Util.Event.START });
571 this.registerElement({ target: document, event: 'keyup' });
572 }
573 };
574 Modal.prototype.detachEvents = function () {
575 var _this = this;
576 var element = this.getElement();
577 var buttons = Array
578 .from(element.querySelectorAll('[data-dismiss], .modal-footer button') || []);
579 buttons.forEach(function (button) { return _this.unregisterElement({
580 target: button,
581 event: Util.Event.CLICK,
582 }); });
583 var cancelable = this.getProp('cancelable');
584 if (cancelable) {
585 var backdrop = this.getBackdrop();
586 this.unregisterElement({ target: backdrop, event: Util.Event.START });
587 this.unregisterElement({ target: document, event: 'keyup' });
588 }
589 };
590 return Modal;
591}(Component));
592Modal.attachDOM();
593
594var ModalLoader = (function (_super) {
595 __extends(ModalLoader, _super);
596 function ModalLoader(props) {
597 var _this = _super.call(this, Object.assign({
598 buttons: [
599 { event: 'cancel', text: 'Cancel', dismiss: true, class: 'btn btn-secondary' },
600 { event: 'confirm', text: 'Ok', dismiss: true, class: 'btn btn-primary' },
601 ],
602 }, props), false) || this;
603 _this.loader = null;
604 _this.setTemplate(''
605 + '<div class="modal" tabindex="-1" role="modal" data-no-boot>'
606 + '<div class="modal-inner" role="document">'
607 + '<div class="modal-content">'
608 + '<div class="modal-header">'
609 + '<h5 class="modal-title"></h5>'
610 + '<button type="button" class="icon-close" data-dismiss="modal" aria-label="Close">'
611 + '<span class="icon" aria-hidden="true"></span>'
612 + '</button>'
613 + '</div>'
614 + '<div class="modal-body">'
615 + '<p></p>'
616 + '<div class="mx-auto text-center">'
617 + '<div class="loader mx-auto d-block">'
618 + '<div class="loader-spinner"></div>'
619 + '</div>'
620 + '</div>'
621 + '</div>'
622 + '<div class="modal-footer">'
623 + '</div>'
624 + '</div>'
625 + '</div>'
626 + '</div>');
627 if (_this.getElement() === null) {
628 _this.build();
629 }
630 return _this;
631 }
632 ModalLoader.prototype.show = function () {
633 _super.prototype.show.call(this);
634 this.loader = new Loader({ element: this.getElement().querySelector('.loader') });
635 this.loader.animate(true);
636 return true;
637 };
638 ModalLoader.prototype.hide = function () {
639 _super.prototype.hide.call(this);
640 if (this.loader) {
641 this.loader.animate(false);
642 }
643 this.loader = null;
644 return true;
645 };
646 return ModalLoader;
647}(Modal));
648
649module.exports = ModalLoader;
650//# sourceMappingURL=modalloader.js.map