UNPKG

4.2 kBJavaScriptView Raw
1import {Feature} from '../feature';
2import {createElm, createText, elm, removeElm} from '../dom';
3import {EMPTY_FN} from '../types';
4import {root} from '../root';
5import {NONE} from '../const';
6import {defaultsStr, defaultsFn} from '../settings';
7
8const EVENTS = [
9 'before-filtering',
10 'before-populating-filter',
11 'before-page-change',
12 'before-clearing-filters',
13 'before-page-length-change',
14 'before-reset-page',
15 'before-reset-page-length',
16 'before-loading-extensions',
17 'before-loading-themes'
18];
19
20/**
21 * Activity indicator
22 *
23 * @export
24 * @class Loader
25 * @extends {Feature}
26 */
27export class Loader extends Feature {
28
29 /**
30 * Creates an instance of Loader.
31 *
32 * @param {TableFilter} tf TableFilter instance
33 */
34 constructor(tf) {
35 super(tf, 'loader');
36
37 let f = this.config.loader || {};
38
39 /**
40 * ID of custom container element
41 * @type {String}
42 */
43 this.targetId = defaultsStr(f.target_id, null);
44
45 /**
46 * Loader container DOM element
47 * @type {DOMElement}
48 */
49 this.cont = null;
50
51 /**
52 * Text displayed when indicator is visible
53 * @type {String}
54 */
55 this.text = defaultsStr(f.text, 'Loading...');
56
57 /**
58 * Custom HTML injected in Loader's container element
59 * @type {String}
60 */
61 this.html = defaultsStr(f.html, null);
62
63 /**
64 * Css class for Loader's container element
65 * @type {String}
66 */
67 this.cssClass = defaultsStr(f.css_class, 'loader');
68
69 /**
70 * Close delay in milliseconds
71 * @type {Number}
72 */
73 this.closeDelay = 250;
74
75 /**
76 * Callback fired when loader is displayed
77 * @type {Function}
78 */
79 this.onShow = defaultsFn(f.on_show_loader, EMPTY_FN);
80
81 /**
82 * Callback fired when loader is closed
83 * @type {Function}
84 */
85 this.onHide = defaultsFn(f.on_hide_loader, EMPTY_FN);
86 }
87
88 /**
89 * Initializes Loader instance
90 */
91 init() {
92 if (this.initialized) {
93 return;
94 }
95
96 let tf = this.tf;
97 let emitter = this.emitter;
98
99 let containerDiv = createElm('div');
100 containerDiv.className = this.cssClass;
101
102 let targetEl = !this.targetId ?
103 tf.dom().parentNode : elm(this.targetId);
104 if (!this.targetId) {
105 targetEl.insertBefore(containerDiv, tf.dom());
106 } else {
107 targetEl.appendChild(containerDiv);
108 }
109 this.cont = containerDiv;
110 if (!this.html) {
111 this.cont.appendChild(createText(this.text));
112 } else {
113 this.cont.innerHTML = this.html;
114 }
115
116 this.show(NONE);
117
118 // Subscribe to events
119 emitter.on(EVENTS, () => this.show(''));
120 emitter.on(EVENTS, () => this.show(NONE));
121
122 /** @inherited */
123 this.initialized = true;
124 }
125
126 /**
127 * Shows or hides activity indicator
128 * @param {String} Two possible values: '' or 'none'
129 */
130 show(p) {
131 if (!this.isEnabled()) {
132 return;
133 }
134
135 let displayLoader = () => {
136 if (!this.cont) {
137 return;
138 }
139 if (p !== NONE) {
140 this.onShow(this);
141 }
142 this.cont.style.display = p;
143 if (p === NONE) {
144 this.onHide(this);
145 }
146 };
147
148 let t = p === NONE ? this.closeDelay : 1;
149 root.setTimeout(displayLoader, t);
150 }
151
152 /**
153 * Removes feature
154 */
155 destroy() {
156 if (!this.initialized) {
157 return;
158 }
159
160 let emitter = this.emitter;
161
162 removeElm(this.cont);
163 this.cont = null;
164
165 // Unsubscribe to events
166 emitter.off(EVENTS, () => this.show(''));
167 emitter.off(EVENTS, () => this.show(NONE));
168
169 this.initialized = false;
170 }
171}