UNPKG

8.52 kBJavaScriptView Raw
1import {Feature} from '../../feature';
2import {createElm, removeElm, elm} from '../../dom';
3import {EMPTY_FN, isNull} from '../../types';
4import {addEvt} from '../../event';
5import {
6 defaultsBool, defaultsStr, defaultsFn, defaultsNb,
7} from '../../settings';
8import {RIGHT} from '../../modules/toolbar';
9
10/**
11 * Filters Visibility extension
12 */
13export default class FiltersVisibility extends Feature {
14
15 /**
16 * Creates an instance of FiltersVisibility
17 * @param {TableFilter} tf TableFilter instance
18 * @param {Object} Configuration object
19 */
20 constructor(tf, f) {
21 super(tf, f.name);
22
23 /**
24 * Module name
25 * @type {String}
26 */
27 this.name = f.name;
28
29 /**
30 * Module description
31 * @type {String}
32 */
33 this.desc = defaultsStr(f.description,
34 'Filters row visibility manager');
35
36 /**
37 * Extension's stylesheet filename
38 * @type {String}
39 */
40 this.stylesheet = defaultsStr(f.stylesheet , 'filtersVisibility.css');
41
42 /**
43 * Expand icon filename
44 * @type {String}
45 */
46 this.icnExpand = defaultsStr(f.expand_icon_name, 'icn_exp.png');
47
48 /**
49 * Collapse icon filename
50 * @type {String}
51 */
52 this.icnCollapse = defaultsStr(f.collapse_icon_name, 'icn_clp.png');
53
54 /**
55 * Main container element
56 * @private
57 */
58 this.contEl = null;
59
60 /**
61 * Button element
62 * @private
63 */
64 this.btnEl = null;
65
66 /**
67 * Expand icon HTML
68 * @private
69 */
70 this.icnExpandHtml = '<img src="' + tf.themesPath + this.icnExpand +
71 '" alt="Expand filters" >';
72
73 /**
74 * Collapse icon HTML
75 * @private
76 */
77 this.icnCollapseHtml = '<img src="' + tf.themesPath + this.icnCollapse +
78 '" alt="Collapse filters" >';
79
80 /**
81 * Default text
82 * @private
83 */
84 this.defaultText = 'Toggle filters';
85
86 /**
87 * ID of main container element
88 * @type {String}
89 */
90 this.targetId = f.target_id || null;
91
92 /**
93 * Enable expand/collapse icon, defaults to true
94 * @type {Boolean}
95 */
96 this.enableIcon = defaultsBool(f.enable_icon, true);
97
98 /**
99 * Custom text for button
100 * @type {String}
101 */
102 this.btnText = defaultsStr(f.btn_text, '');
103
104 /**
105 * Collapse button HTML
106 * @private
107 */
108 this.collapseBtnHtml = this.enableIcon ?
109 this.icnCollapseHtml + this.btnText :
110 this.btnText || this.defaultText;
111
112 /**
113 * Expand button HTML
114 * @private
115 */
116 this.expandBtnHtml = this.enableIcon ?
117 this.icnExpandHtml + this.btnText :
118 this.btnText || this.defaultText;
119
120 /**
121 * Button's custom HTML
122 * @type {String}
123 */
124 this.btnHtml = defaultsStr(f.btn_html, null);
125
126 /**
127 * Css class for expand/collapse filters button
128 * @type {String}
129 */
130 this.btnCssClass = defaultsStr(f.btn_css_class, 'btnExpClpFlt');
131
132 /**
133 * Css class for main container
134 * @type {String}
135 */
136 this.contCssClass = defaultsStr(f.cont_css_class, 'expClpFlt');
137
138 /**
139 * Filters row index
140 * @type {Number}
141 */
142 this.filtersRowIndex = defaultsNb(f.filters_row_index,
143 tf.getFiltersRowIndex());
144
145 /**
146 * Make filters visible at initialization, defaults to true
147 * @type {Boolean}
148 */
149 this.visibleAtStart = defaultsNb(f.visible_at_start, true);
150
151 /**
152 * Default position in toolbar ('left'|'center'|'right')
153 * @type {String}
154 */
155 this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
156
157 /**
158 * Callback fired before filters row is shown
159 * @type {Function}
160 */
161 this.onBeforeShow = defaultsFn(f.on_before_show, EMPTY_FN);
162
163 /**
164 * Callback fired after filters row is shown
165 * @type {Function}
166 */
167 this.onAfterShow = defaultsFn(f.on_after_show, EMPTY_FN);
168
169 /**
170 * Callback fired before filters row is hidden
171 * @type {Function}
172 */
173 this.onBeforeHide = defaultsFn(f.on_before_hide, EMPTY_FN);
174
175 /**
176 * Callback fired after filters row is hidden
177 * @type {Function}
178 */
179 this.onAfterHide = defaultsFn(f.on_after_hide, EMPTY_FN);
180
181 //Import extension's stylesheet
182 tf.import(f.name + 'Style', tf.getStylePath() + this.stylesheet, null,
183 'link');
184
185 this.enable();
186 }
187
188 /**
189 * Initialise extension
190 */
191 init() {
192 if (this.initialized) {
193 return;
194 }
195
196 this.emitter.emit('initializing-extension', this,
197 !isNull(this.targetId));
198
199 this.buildUI();
200
201 /** @inherited */
202 this.initialized = true;
203
204 this.emitter.on(['show-filters'], (tf, visible) => this.show(visible));
205 this.emitter.emit('filters-visibility-initialized', this.tf, this);
206 this.emitter.emit('extension-initialized', this);
207 }
208
209 /**
210 * Build UI elements
211 */
212 buildUI() {
213 let tf = this.tf;
214 let span = createElm('span');
215 span.className = this.contCssClass;
216
217 // Container element (rdiv or custom element)
218 let targetEl = !this.targetId ?
219 tf.feature('toolbar').container(this.toolbarPosition) :
220 elm(this.targetId);
221
222 if (!this.targetId) {
223 let firstChild = targetEl.firstChild;
224 firstChild.parentNode.insertBefore(span, firstChild);
225 } else {
226 targetEl.appendChild(span);
227 }
228
229 let btn;
230 if (!this.btnHtml) {
231 btn = createElm('a', ['href', 'javascript:void(0);']);
232 btn.className = this.btnCssClass;
233 btn.title = this.btnText || this.defaultText;
234 btn.innerHTML = this.collapseBtnHtml;
235 span.appendChild(btn);
236 } else { // Custom html
237 span.innerHTML = this.btnHtml;
238 btn = span.firstChild;
239 }
240
241 addEvt(btn, 'click', () => this.toggle());
242
243 this.contEl = span;
244 this.btnEl = btn;
245
246 if (!this.visibleAtStart) {
247 this.toggle();
248 }
249 }
250
251 /**
252 * Toggle filters visibility
253 */
254 toggle() {
255 let tf = this.tf;
256 let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.dom();
257 let fltRow = tbl.rows[this.filtersRowIndex];
258 let isDisplayed = fltRow.style.display === '';
259
260 this.show(!isDisplayed);
261 }
262
263 /**
264 * Show or hide filters
265 *
266 * @param {boolean} [visible=true] Visibility flag
267 */
268 show(visible = true) {
269 let tf = this.tf;
270 let tbl = tf.gridLayout ? tf.feature('gridLayout').headTbl : tf.dom();
271 let fltRow = tbl.rows[this.filtersRowIndex];
272
273 if (visible) {
274 this.onBeforeShow(this);
275 }
276 if (!visible) {
277 this.onBeforeHide(this);
278 }
279
280 fltRow.style.display = visible ? '' : 'none';
281 if (this.enableIcon && !this.btnHtml) {
282 this.btnEl.innerHTML = visible ?
283 this.collapseBtnHtml : this.expandBtnHtml;
284 }
285
286 if (visible) {
287 this.onAfterShow(this);
288 }
289 if (!visible) {
290 this.onAfterHide(this);
291 }
292
293 this.emitter.emit('filters-toggled', tf, this, visible);
294 }
295
296 /**
297 * Destroy the UI
298 */
299 destroy() {
300 if (!this.initialized) {
301 return;
302 }
303
304 this.emitter.off(['show-filters'], (tf, visible) => this.show(visible));
305
306 this.btnEl.innerHTML = '';
307 removeElm(this.btnEl);
308 this.btnEl = null;
309
310 this.contEl.innerHTML = '';
311 removeElm(this.contEl);
312 this.contEl = null;
313 this.initialized = false;
314 }
315
316}