UNPKG

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