API Docs for:
Show:

File: development/navigations/offcanvas/js/offcanvaslevel.js

import $ from 'jquery';
import DOMModule from '../../../modules/__base/dommodule';
import {eventType} from '../../../js/utils/events';

/**
 * @module Navigations
 */

// PRIVATE METHODS
const handleNextClick = Symbol('_handleNextClick');
const handleBackClick = Symbol('_handleBackClick');

class OffCanvasMenuLevel extends DOMModule {
    constructor(options) {
        super(options);

        this.$triggerNode = this.$rootNode.prev('.nav_box').find('[data-offcanvas-cmd="next"]');
        this.$backNode = this.$rootNode.children('[data-offcanvas-cmd="back"]');

        this._height = this.$rootNode.outerHeight();
    }

    /**
     * Creates a new OffCanvasMenuLevel instance without the "new" keyword but does not
     *     initialize it
     * @method of
     * @static
     * @for Navigations.OffCanvasMenuLevel
     * @param {node|string|configs} node Node, CSS selector or configuration object
     * @return {OffCanvasMenuLevel} A new instance
     * 
     * @example
     *     import OffCanvasMenuLevel from './navigations/offcanvas/js/offcanvaslevel';
     *
     *     const myLevel = OffCanvasMenuLevel.of('[data-widget=OffCanvasMenuLevel]');
     *     myLevel.render().startUp();
     */
    static of (node) {
        return new OffCanvasMenuLevel(node);
    }

    /**
     * Does nothing
     * @method render
     * @for Navigations.OffCanvasMenuLevel
     * @return {this} The instance
     */
    render() {
        return this;
    }
    /**
     * Attaches all eventlisteners to the instance
     * @method startUp
     * @for Navigations.OffCanvasMenuLevel
     * @return {undefined} Nothing
     * 
     * @example
     *     import OffCanvasMenuLevel from './navigations/offcanvas/js/offcanvaslevel';
     *
     *     const myLevel = OffCanvasMenuLevel.of('[data-widget=OffCanvasMenuLevel]');
     *     myLevel.render().startUp();
     */
    startUp() {
        this.$triggerNode.on(eventType.CLICK, this[handleNextClick].bind(this));
        this.$backNode.on(eventType.CLICK, this[handleBackClick].bind(this));
    }
    /**
     * Opens the navigation level
     * @method open
     * @for Navigations.OffCanvasMenuLevel
     * @return {undefined} Nothing
     * 
     * @example
     *     import OffCanvasMenuLevel from './navigations/offcanvas/js/offcanvas';
     *
     *     const myOffCanvasLevel = OffCanvasMenuLevel.of('[data-widget=OffCanvasMenuLevel]');
     *     myOffCanvasLevel.render().startUp();
     *     myOffCanvasLevel.open();
     */
    open() {
        this.$rootNode.addClass('offcanvas_menu_level--open');
    }
    /**
     * Closes the navigation level
     * @method close
     * @for Navigations.OffCanvasMenuLevel
     * @return {undefined} Nothing
     * 
     * @example
     *     import OffCanvasMenuLevel from './navigations/offcanvas/js/offcanvas';
     *
     *     const myOffCanvasLevel = OffCanvasMenuLevel.of('[data-widget=OffCanvasMenuLevel]');
     *     myOffCanvasLevel.render().startUp();
     *     myOffCanvasLevel.open();
     */
    close() {
        // hack to force ie 11 on ms surface to execute css transition properly
        // formerly: this.$rootNode.removeClass('offcanvas_menu_level--open')
        setTimeout(this.$rootNode.removeClass.bind(this.$rootNode, 'offcanvas_menu_level--open'), 0);
    }
    /**
     * Function to manage overflow on opening / closing
     * Scrolls level to top without flickering caused by scrollbar
     *
     * @method setOverflow
     * @for Navigations.OffCanvasMenuLevel
     * @return {Deferred} deferred, that is being resolved after the overlay 
     *      management is finished
     * 
     * @example
     *     import OffCanvasMenuLevel from './navigations/offcanvas/js/offcanvas';
     *
     *     const myOffCanvasLevel = OffCanvasMenuLevel.of('[data-widget=OffCanvasMenuLevel]');
     *     myOffCanvasLevel.render().startUp();
     *     myOffCanvasLevel.open();
     */
    setOverflow(hasOverflow) {
        var _deferred = $.Deferred();
        if (hasOverflow) {
            this.$rootNode.removeClass('offcanvas_menu_level--overlayed');
            return _deferred.resolve();
        } 

        if (this.$rootNode[0].scrollTop === 0) {
            this.$rootNode.addClass('offcanvas_menu_level--overlayed');
            return _deferred.resolve();
        } 

        this.$rootNode.scrollTo(0, 150, {
            onAfter: () => {
                this.$rootNode.addClass('offcanvas_menu_level--overlayed');
                _deferred.resolve();
            }
        });
        return _deferred;
    }

    // === PRIVATE STUFF ===
    // === EVENT HANDLERS ===
    [handleNextClick](event) {
        event.preventDefault();
        event.stopPropagation();

        if (!this.$rootNode.hasClass('offcanvas_menu_level--open')) {
            // this is called after the setOverflow-Deferred (called in update of observer) is resolved
            // this._open();

            this.notifyObservers({
                action: 'open',
                level: this
            });
        }
    }
    [handleBackClick](event) {
        event.preventDefault();
        event.stopPropagation();

        if (this.$rootNode.hasClass('offcanvas_menu_level--open')) {
            // this is called after the setOverflow-Deferred (called in update of observer) is resolved
            // this._close(); 
            
            this.notifyObservers({
                action: 'close',
                level: this
            });
        }
    }
}

export default OffCanvasMenuLevel;