import {Feature} from '../feature'; import {createElm, createText, elm, removeElm} from '../dom'; import {addEvt, targetEvt, removeEvt} from '../event'; import {NONE} from '../const'; import {root} from '../root'; import {isEmpty, isNull} from '../types'; import {defaultsStr, defaultsNb} from '../settings'; import {RIGHT} from './toolbar'; const WIKI_URL = 'https://github.com/koalyptus/TableFilter/wiki/' + '4.-Filter-operators'; const WEBSITE_URL = 'https://www.tablefilter.com/'; /** * Help UI component */ export class Help extends Feature { /** * Creates an instance of Help * @param {TableFilter} tf TableFilter instance */ constructor(tf) { super(tf, Help); let f = this.config.help_instructions || {}; /** * ID of main custom container element * @type {String} */ this.tgtId = defaultsStr(f.target_id, null); /** * ID of custom container element for instructions * @type {String} */ this.contTgtId = defaultsStr(f.container_target_id, null); /** * Instructions text (accepts HTML) * @type {String} */ this.instrText = !isEmpty(f.text) ? f.text : 'Use the filters above each column to filter and limit table ' + 'data. Advanced searches can be performed by using the following ' + 'operators:
<, <=, >, ' + '>=, =, *, !, {, }, ' + '||,&&, [empty], [nonempty], ' + 'rgx:
' + 'Learn more
'; /** * Instructions HTML * @type {String} */ this.instrHtml = defaultsStr(f.html, null); /** * Help button text ('?') * @type {String} */ this.btnText = defaultsStr(f.btn_text, '?'); /** * Custom help button HTML * @type {String} */ this.btnHtml = defaultsStr(f.btn_html, null); /** * Css class for help button * @type {String} */ this.btnCssClass = defaultsStr(f.btn_css_class, 'helpBtn'); /** * Css class for help container element * @type {String} */ this.contCssClass = defaultsStr(f.container_css_class, 'helpCont'); /** * Button DOM element * @type {DOMElement} */ this.btn = null; /** * Help container DOM element * @type {DOMElement} */ this.cont = null; /** * Adjust container left position when table's horizontal scroll is * on, typically when `responsive` option is enabled. * @type {Number} * @defaultValue 25 */ this.contAdjustLeftPosition = defaultsNb(f.container_adjust_left_position, 25); /** * Bound mouseup wrapper * @private */ this.boundMouseup = null; /** * Default HTML appended to instructions text * @type {String} */ this.defaultHtml = '

TableFilter ' + 'v' + tf.version + '

' + '' + WEBSITE_URL + '' + '
©2015-' + tf.year + ' {AUTHOR}' + '
' + 'Close
'; /** * Default position in toolbar ('left'|'center'|'right') * @type {String} */ this.toolbarPosition = defaultsStr(f.toolbar_position, RIGHT); this.emitter.on(['init-help'], () => this.init()); } /** * Mouse-up event handler handling popup auto-close behaviour * @private */ onMouseup(evt) { let targetElm = targetEvt(evt); while (targetElm && targetElm !== this.cont && targetElm !== this.btn) { targetElm = targetElm.parentNode; } if (targetElm !== this.cont && targetElm !== this.btn) { this.toggle(); } return; } /** * Initialise Help instance */ init() { if (this.initialized) { return; } this.emitter.emit('initializing-feature', this, !isNull(this.tgtId)); let tf = this.tf; let btn = createElm('span'); let cont = createElm('div'); this.boundMouseup = this.onMouseup.bind(this); //help button is added to defined element let targetEl = !this.tgtId ? tf.feature('toolbar').container(this.toolbarPosition) : elm(this.tgtId); targetEl.appendChild(btn); let divContainer = !this.contTgtId ? btn : elm(this.contTgtId); if (!this.btnHtml) { divContainer.appendChild(cont); let helplink = createElm('a', ['href', 'javascript:void(0);']); helplink.className = this.btnCssClass; helplink.appendChild(createText(this.btnText)); btn.appendChild(helplink); addEvt(helplink, 'click', () => this.toggle()); } else { btn.innerHTML = this.btnHtml; let helpEl = btn.firstChild; addEvt(helpEl, 'click', () => this.toggle()); divContainer.appendChild(cont); } if (!this.instrHtml) { cont.innerHTML = this.instrText; cont.className = this.contCssClass; } else { if (this.contTgtId) { divContainer.appendChild(cont); } cont.innerHTML = this.instrHtml; if (!this.contTgtId) { cont.className = this.contCssClass; } } cont.innerHTML += this.defaultHtml; addEvt(cont, 'click', () => this.toggle()); this.cont = cont; this.btn = btn; /** @inherited */ this.initialized = true; this.emitter.emit('feature-initialized', this); } /** * Toggle help pop-up */ toggle() { // check only if explicitily disabled as in this case undefined // signifies the help feature is enabled by default if (!this.isEnabled()) { return; } // ensure mouseup event handler is removed removeEvt(root, 'mouseup', this.boundMouseup); let divDisplay = this.cont.style.display; if (divDisplay === '' || divDisplay === NONE) { this.cont.style.display = 'inline'; // if table element has an horizontal scrollbar adjust container // left position accordingly if (this.tf.dom().scrollLeft > 0) { this.cont.style.left = `${ this.btn.offsetLeft - this.tf.dom().scrollLeft + this.contAdjustLeftPosition }px`; } addEvt(root, 'mouseup', this.boundMouseup); } else { this.cont.style.display = NONE; this.cont.style.left = ''; } } /** * Remove help UI */ destroy() { if (!this.initialized) { return; } removeElm(this.btn); this.btn = null; removeElm(this.cont); this.cont = null; this.boundMouseup = null; this.initialized = false; } } // TODO: remove as soon as feature name is fixed Help.meta = {alwaysInstantiate: true};