Source: control2/InfoBar.js

(function() {
    /**
     * @typedef {Help4.control2.Control.Params} Help4.control2.InfoBar.Params
     * @property {boolean} [showCloseButton = true]
     * @property {boolean} [autoClose = true]
     * @property {boolean} [clickable = false]
     * @property {string} [content = '']
     * @property {Number} [timeout = 3000] - in milliseconds
     * @property {string} [type = 'info']
     * @property {string} [role = 'dialog']
     */

    /**
     * Creates InfoBar control.
     * @augments Help4.control2.Control
     * @property {boolean} showCloseButton
     * @property {boolean} autoClose
     * @property {boolean} clickable
     * @property {string} content
     * @property {Number} timeout
     * @property {string} type
     * @property {?number} _timer
     * @property {?Help4.control2.button.Button} _closeButton
     */
    Help4.control2.InfoBar = class extends Help4.control2.Control {
        /**
         * @override
         * @param {Help4.control2.InfoBar.Params} [params]
         * @param {Help4.jscore.ControlBase.Params} [derived]
         */
        constructor(params, derived) {
            const T = Help4.jscore.ControlBase.TYPES;
            super(params, {
                params: {
                    showCloseButton: {type: T.boolean, init: true, readonly: true},
                    autoClose:       {type: T.boolean, init: true, readonly: true},
                    clickable:       {type: T.boolean, init: false, readonly: true},
                    content:         {type: T.string, init: '', readonly: true},
                    timeout:         {type: T.number, init: 3000, readonly: true},
                    type:            {type: T.string, init: 'info', readonly: true},

                    role:            {init: 'dialog'}
                },
                config: {
                    css: 'control-infobar'
                },
                statics: {
                    _timer:       {destroy: false},
                    _closeButton: {}
                },
                derived
            });
        }

        /** @type {Object} */
        static TYPES = {
            info: 'info',
            error: 'error',
            success: 'success',
            warning: 'warning',
            whatsnew: 'whatsnew'
        };

        /** @override */
        _onBeforeDestroy() {
            _stopTimer.call(this);
            Help4.Event.stopObserving(this.getDom());

            super._onBeforeDestroy();
        }

        /**
         * @override
         * @param {HTMLElement} dom - control DOM
         */
        _onDomCreated(dom) {
            super._onDomCreated(dom);

            const {
                Element,
                Event,
                control2: {ICONS, InfoBar: {TYPES}}
            } = Help4;
            const {id, type, clickable, role, content} = this;

            const contentDom = this._createElement('section', {id: '-con', dom, css: 'content', tabIndex: 0, ariaLabelledby: id + '-msg'});
            this._createElement('aside', {id: '-ico', css: 'icon', dom: contentDom, ariaHidden: true, text: ICONS[type]});
            this._createElement('section', {id: '-msg', css: 'inner', dom: contentDom, html: content});

            _createCloseButton.call(this);
            _startTimer.call(this);

            this.addCss(type);
            clickable && this.addCss('clickable');

            if (Help4.includes([TYPES.error, TYPES.warning], role)) Element.setAttribute(dom, {role: 'alertdialog'});

            Event.observe(dom, {
                type: 'simple',
                callback: event => _onEvent.call(this, event),
                scope: this
            });
        }
    }

    /**
     * @memberof Help4.control2.InfoBar#
     * @private
     */
    function _createCloseButton() {
        if (this.showCloseButton) {
            const footer = this._createElement('footer', {css: 'footer'});

            const {
                control2: {
                    button: {APPEARANCES, Button},
                    ICONS
                },
                Localization,
            } = Help4;

            const title = Localization.getText('tooltip.closedialog');
            this._closeButton = this._createControl(Button, {
                dom: footer,
                css: 'close',
                appearance: APPEARANCES.icon,
                icon: ICONS.close,
                title,
                ariaLabel: title
            })
            .addListener('click', () => _onClose.call(this));
        }
    }

    /**
     * @memberof Help4.control2.InfoBar#
     * @private
     */
    function _startTimer() {
        const {autoClose, timeout} = this;
        if (autoClose && timeout > 0) this._timer = setTimeout(() => _onClose.call(this), timeout);
    }

    /**
     * @memberof Help4.control2.InfoBar#
     * @private
     */
    function _stopTimer() {
        if (this._timer) {
            clearTimeout(this._timer);
            this._timer = null;
        }
    }

    /**
     * @memberof Help4.control2.InfoBar#
     * @private
     */
    function _onClose() {
        this._fireEvent({type: 'close'});
        this.destroy();
    }

    /**
     * @memberof Help4.control2.InfoBar#
     * @param {Object} event - triggered event
     * @private
     */
    function _onEvent(event) {
        const {type} = event;

        switch (type) {
            case 'click':
                if (this.clickable) {
                    this._fireEvent({type: 'click', data: event});

                    // allow for the click event to be handled before the infobar is closed
                    setTimeout(() => _onClose.call(this), 100);
                }
                break;

            case 'mouseover':
                _stopTimer.call(this);
                break;

            case 'keyup':
                const key = Help4.service.HotkeyService.getKey(event);
                if (Help4.includes(['space', 'enter'], key)) {   // space or enter
                    event.type = 'click';
                    _onEvent.call(this, event);
                }
                break;
        }
    }
})();