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

'use strict';

const $ = require('yoho-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, // 是否禁止
            disableTouchMove: false
        };

        // 初始化参数
        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 && this.settings.disableTouchMove) {
            // 覆盖层出现时阻止滚动
            document.body.addEventListener('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;