Home Reference Source

js/template/WritePost/WritePostSubheaderTemplate.js

import Template from '~/template/Template';
import NavigationItemDelegate from '~/delegate/NavigationItemDelegate';
import anime from 'animejs';

export default class WritePostSubheaderTemplate extends Template {
    /**
     * Creates
     */
    constructor() {
        const list = <ol class="write-post__subheader__list content"></ol>;
        const root = (
            <div class="write-post__subheader__wrapper">
                { list }
            </div>
        );

        super(root);

        /** @type {NavigationItemDelegate} */
        this.delegate = new NavigationItemDelegate();

        this._list = list;
        this._tabs = [];
        this._activeTab = -1;
    }

    /** @type {WritePostNavigationItemTemplate[]} */
    get allTabs() { return this._tabs; }

    /** @type {number} */
    get activeTab() { return this._activeTab; }

    /** @type {number} */
    set activeTab(index) {
        if (index === this._activeTab) return;
        const curTab = this._tabs[index];
        if (!curTab) return;

        this.delegate.shouldOpen(this, curTab.id);

        const oldTab = this._tabs[this._activeTab];
        if (oldTab) {
            oldTab.isActive = false;
        }

        this._activeTab = index;
        curTab.isActive = true;

        // Check if we need to scroll to center the tab item
        //  for mobile because we scroll the step list
        if (this._list.scrollWidth > this._list.clientWidth) {
            const tabItem = curTab.underlyingNode;
            const animationTime = 100;

            // If the tabItem won't fit, then show as much as possible
            if (tabItem.offsetWidth > this._list.clientWidth) {
                anime({
                    targets: this._list,
                    scrollLeft: tabItem.offsetLeft,
                    duration: 200,
                });
            } else {
                // If it can fit then center
                let parentOffset = this._list.clientWidth / 2;
                let tabItemOffset = tabItem.offsetWidth / 2;
                anime({
                    targets: this._list,
                    scrollLeft: Math.max(tabItem.offsetLeft - parentOffset + tabItemOffset, 0),
                    duration: 600,
                    elasticity: 10
                });
            }
        }
    }

    /**
     * Goes to next tab if possible otherwise does nothing
     */
    nextTab() {
        this.activeTab += 1;
    }


    /** @override */
    didLoad() {
        if (this.activeTab !== -1) {
            this.delegate.shouldOpen(this, this._tabs[this.activeTab].id);
        }
    }

    /**
     * @param {WrietPostNavigationItemTemplate} item
     * @param {boolean} isActive - if is active
     */
    appendNavigationItem(item, isActive = false) {
        this._tabs.push(item);

        if (isActive) {
            this.activeTab = this._tabs.length - 1;
        } else if (this.activeTab === -1) {
            this.activeTab = this._tabs.length - 1;
        }

        item.index = this._tabs.length;
        item.loadInContext(this._list);

        item.delegate.shouldOpen = (item, id) => {
            this.activeTab = item.index - 1;
        };
    }
}