overlay.js 2.78 KB
/**
 * Modal 覆盖层组件
 *
 * @author: Aiden Xu<aiden.xu@yoho.cn>
 * @date: 2016/07/18
 */

'use strict';

const $ = require('jquery');

const ANIMATIONS = {
    none: {
        in: 'overlay-in',
        out: 'overlay-out'
    },
    fade: {
        in: 'overlay-fade-in',
        out: 'overlay-fade-out'
    }
};

class Overlay {
    constructor(opts) {
        this.isVisible = false;

        // 默认参数
        this.defaults = {
            className: 'overlay',
            clickToClose: true, // 点击关闭
            onClose: $.noop,    // 关闭回调函数
            animation: 'fade',   // 动画效果
            disableScrolling: true // 是否禁止
        };

        // 初始化参数
        this.settings = Object.assign({}, this.defaults, opts);

        this.settings.animationClasses = {
            in: ANIMATIONS[this.settings.animation].in,
            out: ANIMATIONS[this.settings.animation].out
        };

        this.elem = $('<div/>', {
            class: this.settings.className
        });

        // 点击关闭
        this.elem.click(()=> {
            if (this.settings.clickToClose) {
                this.hide();
            }
        });

        // if (this.settings.disableScrolling) {
        //     // 覆盖层出现时阻止滚动
        //     $(window).on('touchmove', (e)=> {
        //         if (this.isVisible) {
        //             e.preventDefault();
        //         }
        //     });
        // }

        this.elem[0].addEventListener('webkitTransitionEnd', this._cleanup.bind(this));
    }

    _cleanup() {
        if (!this.isVisible) {
            this.elem.detach();
        }
    }

    /**
     * 显示覆盖层
     */
    show() {
        if (this.elem.parent().length === 0 && !this.isVisible) {
            this.elem.appendTo('body');

            this.elem.css({
                visibility: 'visible'
            }).show()
                .removeClass(this.settings.animationClasses.out)
                .addClass(this.settings.animationClasses.in);

            if (this.settings.disableScrolling) {
                $('body').css({
                    overflow: 'hidden'
                });
            }

            this.isVisible = true;
        }
    }

    /**
     * 关闭覆盖层
     */
    hide() {
        if (this.isVisible) {
            this.elem
                .removeClass(this.settings.animationClasses.in)
                .addClass(this.settings.animationClasses.out);

            if (this.settings.disableScrolling) {
                $('body').css({
                    overflow: 'auto'
                });
            }

            setTimeout(()=> {
                this._cleanup();
            }, 200);

            this.isVisible = false;
            this.settings.onClose();
        }
    }
}

module.exports = Overlay;