UNPKG

5 kBJavaScriptView Raw
1import {Feature} from '../feature';
2import {createElm, elm, removeElm} from '../dom';
3import {isEmpty, EMPTY_FN} from '../types';
4import {NONE} from '../const';
5import {defaultsStr, defaultsFn} from '../settings';
6
7/**
8 * UI when filtering yields no matches
9 * @export
10 * @class NoResults
11 * @extends {Feature}
12 */
13export class NoResults extends Feature {
14
15 /**
16 * Creates an instance of NoResults
17 * @param {TableFilter} tf TableFilter instance
18 */
19 constructor(tf) {
20 super(tf, NoResults);
21
22 //configuration object
23 let f = this.config.no_results_message || {};
24
25 /**
26 * Text (accepts HTML)
27 * @type {String}
28 */
29 this.content = defaultsStr(f.content, 'No results');
30
31 /**
32 * Custom container DOM element
33 * @type {DOMElement}
34 */
35 this.customContainer = defaultsStr(f.custom_container, null);
36
37 /**
38 * ID of custom container element
39 * @type {String}
40 */
41 this.customContainerId = defaultsStr(f.custom_container_id, null);
42
43 /**
44 * Indicates if UI is contained in a external element
45 * @type {Boolean}
46 * @private
47 */
48 this.isExternal = !isEmpty(this.customContainer) ||
49 !isEmpty(this.customContainerId);
50
51 /**
52 * Css class assigned to container element
53 * @type {String}
54 */
55 this.cssClass = defaultsStr(f.css_class, 'no-results');
56
57 /**
58 * Stores container DOM element
59 * @type {DOMElement}
60 */
61 this.cont = null;
62
63 /**
64 * Callback fired before the message is displayed
65 * @type {Function}
66 */
67 this.onBeforeShow = defaultsFn(f.on_before_show_msg, EMPTY_FN);
68
69 /**
70 * Callback fired after the message is displayed
71 * @type {Function}
72 */
73 this.onAfterShow = defaultsFn(f.on_after_show_msg, EMPTY_FN);
74
75 /**
76 * Callback fired before the message is hidden
77 * @type {Function}
78 */
79 this.onBeforeHide = defaultsFn(f.on_before_hide_msg, EMPTY_FN);
80
81 /**
82 * Callback fired after the message is hidden
83 * @type {Function}
84 */
85 this.onAfterHide = defaultsFn(f.on_after_hide_msg, EMPTY_FN);
86 }
87
88 /**
89 * Initializes NoResults instance
90 */
91 init() {
92 if (this.initialized) {
93 return;
94 }
95 let tf = this.tf;
96 let target = this.customContainer || elm(this.customContainerId) ||
97 tf.dom();
98
99 //container
100 let cont = createElm('div');
101 cont.className = this.cssClass;
102 cont.innerHTML = this.content;
103
104 if (this.isExternal) {
105 target.appendChild(cont);
106 } else {
107 target.parentNode.insertBefore(cont, target.nextSibling);
108 }
109
110 this.cont = cont;
111
112 // subscribe to after-filtering event
113 this.emitter.on(
114 ['initialized', 'after-filtering'],
115 () => this.toggle()
116 );
117
118 /** @inherited */
119 this.initialized = true;
120 }
121
122 /**
123 * Toggle no results message
124 */
125 toggle() {
126 if (this.tf.getValidRowsNb() > 0) {
127 this.hide();
128 } else {
129 this.show();
130 }
131 }
132
133 /**
134 * Show no results message
135 */
136 show() {
137 if (!this.initialized || !this.isEnabled()) {
138 return;
139 }
140 this.onBeforeShow(this.tf, this);
141
142 this.setWidth();
143 this.cont.style.display = 'block';
144
145 this.onAfterShow(this.tf, this);
146 }
147
148 /**
149 * Hide no results message
150 */
151 hide() {
152 if (!this.initialized || !this.isEnabled()) {
153 return;
154 }
155 this.onBeforeHide(this.tf, this);
156
157 this.cont.style.display = NONE;
158
159 this.onAfterHide(this.tf, this);
160 }
161
162 /**
163 * Sets no results container width
164 * @private
165 */
166 setWidth() {
167 if (!this.initialized || this.isExternal || !this.isEnabled()) {
168 return;
169 }
170 let tf = this.tf;
171 if (tf.gridLayout) {
172 let gridLayout = tf.feature('gridLayout');
173 this.cont.style.width = gridLayout.headTbl.clientWidth + 'px';
174 } else {
175 this.cont.style.width = (tf.dom().tHead ?
176 tf.dom().tHead.clientWidth :
177 tf.dom().tBodies[0].clientWidth) + 'px';
178 }
179 }
180
181 /** Remove feature */
182 destroy() {
183 if (!this.initialized) {
184 return;
185 }
186 removeElm(this.cont);
187 this.cont = null;
188 // unsubscribe to after-filtering event
189 this.emitter.off(['after-filtering'], () => this.toggle());
190
191 this.initialized = false;
192 }
193}