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

'use strict';

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.appendTo('body');

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

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

    _clearStylesClasses() {
        this.elem
            .removeClass(this.settings.animationClasses.in)
            .removeClass(this.settings.animationClasses.out);
    }

    /**
     * 显示覆盖层
     */
    show() {
        this._clearStylesClasses();
        this.elem.css({
            visibility: 'visible'
        }).show().addClass(this.settings.animationClasses.in);
        this.isVisible = true;

        $('body').css({
            overflow: 'hidden'
        });
    }

    /**
     * 关闭覆盖层
     */
    hide() {
        this._clearStylesClasses();
        const listener = () => {
            // 一次性监听,动画完成事件触发后删除监听器
            this.elem[0].removeEventListener('webkitTransitionEnd', listener);
            this.elem.css({
                visibility: 'hidden'
            });
            this._clearStylesClasses();
            this.isVisible = false;
            this.elem.remove();
        };

        this.elem[0].addEventListener('webkitTransitionEnd', listener);
        this.elem.addClass(this.settings.animationClasses.out);

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

        this.settings.onClose();
    }
}

((function($) {
    $.overlay = opts => {
        return new Overlay(opts);
    };
})(jQuery));

module.exports = Overlay;