Source: widget/help/view2/TileTile.js

(function() {
    /** tile helper for {@link Help4.widget.help.view2.Tile} */
    Help4.widget.help.view2.TileTile = class {
        /**
         * @param {Help4.widget.help.view2.Tile} tile
         * @param {boolean} hotspotVisible
         */
        static updateTileControl(tile, hotspotVisible) {
            const {projectTile, __tileView, descriptor, tileControlId, tilePosition, widgetActive} = tile;

            if (widgetActive) {
                // show tile

                // calculate parameters for tile control
                const {Help} = Help4.widget.companionCore.data;
                const params = Help.helpTileToTileParams(projectTile, {descriptor, hotspotVisible});
                this.selectTile(tile, params);

                if (tileControlId) {
                    // update the existing tile control
                    _updateTileControlValues(tile, params);
                } else {
                    // add tile control
                    const control = typeof tilePosition === 'number'
                        ? __tileView.insertAt(params, tilePosition)  // insert at a position
                        : __tileView.add(params);  // insert at the end
                    control.getDom().setAttribute('data-descriptor', descriptor);

                    const {_data} = params;
                    _data && _setDataAttribute(control, _data);
                    tile.tileControlId = control.id;
                }
            } else if (tileControlId) {
                // remove tile control
                __tileView.remove(tileControlId);
                tile.tileControlId = null;
            }
        }

        /**
         * @param {Help4.widget.help.view2.Tile} tile
         * @param {?Help4.widget.help.TileParams} [tileParams = null]
         * @returns {boolean}
         */
        static selectTile(tile, tileParams = null) {
            const {_selected, _hovered, __widget, projectTile} = tile;
            const {showShortDescription} = __widget.getContext().configuration.help;

            const {type, linkLightbox} = projectTile;
            const allowSelection = type !== 'link' || !!linkLightbox;  // do not mark link tiles that open in new window
            const active = (_selected || _hovered) && allowSelection;

            let originalDescription, isGlobalHelp, item;

            if (tileParams) {
                // work with tile params only
                const {_metadata} = tileParams;
                originalDescription = _metadata.originalDescription;
                isGlobalHelp = _metadata.isGlobalHelp;
                item = tileParams;
            } else {
                // work with the tile control
                const {tileControlId, __tileView} = tile;
                item = __tileView.get(tileControlId);
                if (!item) return false;

                originalDescription = item.getMetadata('originalDescription');
                isGlobalHelp = item.getMetadata('isGlobalHelp');
            }

            item.active = active;

            if (type !== 'tour') {
                if (showShortDescription || active || isGlobalHelp) {
                    item.description = originalDescription;
                    item.title = '';
                } else {
                    item.description = '';
                    item.title = originalDescription;
                }
            }

            return _selected === active;
        }

        /** @param {Help4.widget.help.view2.Tile} tile */
        static updateTileControlPosition(tile) {
            const {__tileView, tileControlId, tilePosition} = tile;
            if (typeof tilePosition !== 'number') return;  // not yet initialized

            tileControlId && __tileView.moveTo(tileControlId, tilePosition);
        }

        /** @param {Help4.widget.help.view2.Tile} tile */
        static scrollTileIntoView(tile) {
            const {__tileView, tileControlId} = tile;
            const index = tileControlId ? __tileView.getIndex(tileControlId) : -1;
            if (index < 0) return;

            const dom = __tileView.getOwnerDom();
            if (index === 0) {
                // tile is the 1st one; scroll to top
                dom.scrollTop = 0;
            } else {
                // find upper edge of tile
                let position = 0;
                for (let i = index - 1; i >= 0; i--) {
                    position += __tileView.get(i).getSize().h;
                }

                const current = dom.scrollTop;
                const height = __tileView.get(index).getSize().h;
                if (position < current || position + height > current + dom.offsetHeight) {
                    // upper edge of tile is out of visible area or
                    // lower edge of tile is out of visible area
                    dom.scrollTop = position;
                }
            }
        }
    }

    /**
     * @private
     * @param {Help4.widget.help.view2.Tile} tile
     * @param {Help4.widget.help.TileParams} params
     */
    function _updateTileControlValues(tile, params) {
        const {
            _data,
            icon,
            caption,
            description,
            title,
            active,
            visible,
            showAsButton,
            linkLightbox,
            hidden,
            isGlobalHelp,
            type
        } = params;

        const {__tileView, tileControlId} = tile;
        const control = __tileView.get(tileControlId);
        control.caption = caption;
        control.description = description;
        control.title = title;
        control.active = active;
        control.visible = visible;

        const {BUTTON_CSS, LIGHTBOX_CSS, HIDDEN_CSS} = Help4.widget.help.view2;

        if (showAsButton || isGlobalHelp) {
            control.addCss(BUTTON_CSS);
            control.icon = null;
        } else {
            control.removeCss(BUTTON_CSS);
            control.icon = icon;
        }

        _data && _setDataAttribute(control, _data);

        hidden
            ? control.addCss(HIDDEN_CSS)
            : control.removeCss(HIDDEN_CSS);

        if (type === 'link') {
            linkLightbox
                ? control.addCss(LIGHTBOX_CSS)
                : control.removeCss(LIGHTBOX_CSS);
        }
    }

    /**
     * @private
     * @param {Help4.control2.Control} control
     * @param {Object} data
     */
    function _setDataAttribute(control, data) {
        const {Element} = Help4;
        for (const [key, value] of Object.entries(data)) {
            Element.setAttribute(control.getDom(), {[`data-${key}`]: value || undefined});
        }
    }
})();