UNPKG

7.09 kBJavaScriptView Raw
1import {Feature} from '../feature';
2import {createElm, createText, elm, removeElm} from '../dom';
3import {addEvt, targetEvt, removeEvt} from '../event';
4import {NONE} from '../const';
5import {root} from '../root';
6import {isEmpty, isNull} from '../types';
7import {defaultsStr} from '../settings';
8import {RIGHT} from './toolbar';
9
10const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' +
11 '4.-Filter-operators';
12const WEBSITE_URL = 'https://www.tablefilter.com/';
13
14/**
15 * Help UI component
16 */
17export class Help extends Feature {
18
19 /**
20 * Creates an instance of Help
21 * @param {TableFilter} tf TableFilter instance
22 */
23 constructor(tf) {
24 super(tf, 'help');
25
26 let f = this.config.help_instructions || {};
27
28 /**
29 * ID of main custom container element
30 * @type {String}
31 */
32 this.tgtId = defaultsStr(f.target_id, null);
33
34 /**
35 * ID of custom container element for instructions
36 * @type {String}
37 */
38 this.contTgtId = defaultsStr(f.container_target_id, null);
39
40 /**
41 * Instructions text (accepts HTML)
42 * @type {String}
43 */
44 this.instrText = !isEmpty(f.text) ? f.text :
45 'Use the filters above each column to filter and limit table ' +
46 'data. Advanced searches can be performed by using the following ' +
47 'operators: <br /><b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, ' +
48 '<b>&gt;=</b>, <b>=</b>, <b>*</b>, <b>!</b>, <b>{</b>, <b>}</b>, ' +
49 '<b>||</b>,<b>&amp;&amp;</b>, <b>[empty]</b>, <b>[nonempty]</b>, ' +
50 '<b>rgx:</b><br/><a href="' + WIKI_URL + '" target="_blank">' +
51 'Learn more</a><hr/>';
52
53 /**
54 * Instructions HTML
55 * @type {String}
56 */
57 this.instrHtml = defaultsStr(f.html, null);
58
59 /**
60 * Help button text ('?')
61 * @type {String}
62 */
63 this.btnText = defaultsStr(f.btn_text, '?');
64
65 /**
66 * Custom help button HTML
67 * @type {String}
68 */
69 this.btnHtml = defaultsStr(f.btn_html, null);
70
71 /**
72 * Css class for help button
73 * @type {String}
74 */
75 this.btnCssClass = defaultsStr(f.btn_css_class, 'helpBtn');
76
77 /**
78 * Css class for help container element
79 * @type {String}
80 */
81 this.contCssClass = defaultsStr(f.container_css_class, 'helpCont');
82
83 /**
84 * Button DOM element
85 * @type {DOMElement}
86 */
87 this.btn = null;
88
89 /**
90 * Help container DOM element
91 * @type {DOMElement}
92 */
93 this.cont = null;
94
95 /**
96 * Bound mouseup wrapper
97 * @private
98 */
99 this.boundMouseup = null;
100
101 /**
102 * Default HTML appended to instructions text
103 * @type {String}
104 */
105 this.defaultHtml = '<div class="helpFooter"><h4>TableFilter ' +
106 'v' + tf.version + '</h4>' + '<a href="' + WEBSITE_URL +
107 '" target="_blank">' + WEBSITE_URL + '</a>' +
108 '<br/><span>&copy;2015-' + tf.year + ' {AUTHOR}</span>' +
109 '<div align="center" style="margin-top:8px;">' +
110 '<a href="javascript:void(0);" class="close">Close</a></div></div>';
111
112 /**
113 * Default position in toolbar ('left'|'center'|'right')
114 * @type {String}
115 */
116 this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT);
117
118 this.emitter.on(['init-help'], () => this.init());
119 }
120
121 /**
122 * Mouse-up event handler handling popup auto-close behaviour
123 * @private
124 */
125 onMouseup(evt) {
126 let targetElm = targetEvt(evt);
127
128 while (targetElm && targetElm !== this.cont && targetElm !== this.btn) {
129 targetElm = targetElm.parentNode;
130 }
131
132 if (targetElm !== this.cont && targetElm !== this.btn) {
133 this.toggle();
134 }
135
136 return;
137 }
138
139 /**
140 * Initialise Help instance
141 */
142 init() {
143 if (this.initialized) {
144 return;
145 }
146
147 this.emitter.emit('initializing-feature', this, !isNull(this.tgtId));
148
149 let tf = this.tf;
150
151 let btn = createElm('span');
152 let cont = createElm('div');
153
154 this.boundMouseup = this.onMouseup.bind(this);
155
156 //help button is added to defined element
157 let targetEl = !this.tgtId ?
158 tf.feature('toolbar').container(this.toolbarPosition) :
159 elm(this.tgtId);
160 targetEl.appendChild(btn);
161
162 let divContainer = !this.contTgtId ? btn : elm(this.contTgtId);
163
164 if (!this.btnHtml) {
165 divContainer.appendChild(cont);
166 let helplink = createElm('a', ['href', 'javascript:void(0);']);
167 helplink.className = this.btnCssClass;
168 helplink.appendChild(createText(this.btnText));
169 btn.appendChild(helplink);
170 addEvt(helplink, 'click', () => this.toggle());
171 } else {
172 btn.innerHTML = this.btnHtml;
173 let helpEl = btn.firstChild;
174 addEvt(helpEl, 'click', () => this.toggle());
175 divContainer.appendChild(cont);
176 }
177
178 if (!this.instrHtml) {
179 cont.innerHTML = this.instrText;
180 cont.className = this.contCssClass;
181 } else {
182 if (this.contTgtId) {
183 divContainer.appendChild(cont);
184 }
185 cont.innerHTML = this.instrHtml;
186 if (!this.contTgtId) {
187 cont.className = this.contCssClass;
188 }
189 }
190 cont.innerHTML += this.defaultHtml;
191 addEvt(cont, 'click', () => this.toggle());
192
193 this.cont = cont;
194 this.btn = btn;
195 /** @inherited */
196 this.initialized = true;
197
198 this.emitter.emit('feature-initialized', this);
199 }
200
201 /**
202 * Toggle help pop-up
203 */
204 toggle() {
205 // check only if explicitily disabled as in this case undefined
206 // signifies the help feature is enabled by default
207 if (!this.isEnabled()) {
208 return;
209 }
210
211 // ensure mouseup event handler is removed
212 removeEvt(root, 'mouseup', this.boundMouseup);
213
214 let divDisplay = this.cont.style.display;
215 if (divDisplay === '' || divDisplay === NONE) {
216 this.cont.style.display = 'inline';
217 addEvt(root, 'mouseup', this.boundMouseup);
218 } else {
219 this.cont.style.display = NONE;
220 }
221 }
222
223 /**
224 * Remove help UI
225 */
226 destroy() {
227 if (!this.initialized) {
228 return;
229 }
230 removeElm(this.btn);
231 this.btn = null;
232
233 removeElm(this.cont);
234 this.cont = null;
235
236 this.boundMouseup = null;
237 this.initialized = false;
238 }
239
240}