modal.js 3.58 KB
/**
 *  Modal 组件: 仿BOOTSTRAP:MODAL
 *  @author xuan.chen@yoho.cn
 */
'use strict';

/* config */
let NAME = 'yModal';
let DATA_KEY = 'yoho.modal';
let Selector = {
    DATA_TOGGLE: '[data-toggle="ymodal"]',
    DATA_DISMISS: '[data-dismiss="ymodal"]'
};
let ClassName = {
    BACKDROP: 'ymodal-backdrop'
};
let Modal = function(elem, config) {
    this.$element = $(elem);
    this.$body = $(document.body);
    this._backdrop = null;
    this._config = $.extend(
            {},
            Modal.DEFAULT,
            toString.call(config) === '[object Object]' && config
    );
    this._isShown = false;
};

/* ------------------------static attribute ------------------*/
Modal.DEFAULT = {
    backdrop: true,
    show: true
};

/* ------------------------public method ------------------*/
Modal.prototype.show = function(relatedTarget) {
    if (this._isShown) {
        return this;
    }
    this.$body.toggleClass('ymodal-open', true);
    this.$element.trigger('show.yoho.modal', relatedTarget);

    this.$element.on('click.dismiss.yoho.modal', Selector.DATA_DISMISS, $.proxy(this.hide, this));

    this._isShown = true;
    this.$element.show().focus();
    this.backdrop();

    this.$element.trigger('shown.yoho.modal', relatedTarget);
};

Modal.prototype.hide = function(e) {
    if (e) {
        e.preventDefault();
        e.stopPropagation();
    }

    this._isShown = false;
    this.$element
        .off('click.dismiss.yoho.modal')
        .hide();
    this.$body.removeClass('ymodal-open');
    this.backdrop();
    this.$element.trigger('hiden.yoho.modal');
};

Modal.prototype.toggle = function(relatedTarget) {
    this._isShown ? this.hide() : this.show(relatedTarget);
    return this;
};

Modal.prototype.backdrop = function() {
    let self = this;

    if (this._isShown && this._config.backdrop) {
        this._backdrop = document.createElement('div');

        $(this._backdrop)
            .addClass(ClassName.BACKDROP)
            .appendTo(document.body);
        this.$element.on('click.dismiss.yoho.modal', function(event) {
            if (event.target !== event.currentTarget) {
                return;
            }

            self.hide();
        });
    } else if (!this._isShown && this._backdrop) {
        $(this._backdrop).remove();
    }
};

/* ------------------------private method ------------------*/


/* ------------------------static method ------------------*/
Modal._jqueryBridge = function(config, relatedTarget) {
    return this.each(function() {
        let $this = $(this);
        let data = $this.data(DATA_KEY);
        let configs = $this.data(DATA_KEY) ? 'toggle' : $.extend(
            {},
            Modal.DEFAULT,
            $this.data(),
            toString.call(config) === '[object Object]' && config
        );

        if (!data) {
            $this.data(DATA_KEY, data = new Modal($this, config));
        }

        if (typeof config === 'string') {
            data[config](relatedTarget);
        } else if (configs.show) {
            data.show(relatedTarget);
        }
    });
};

/* ----------------------- DATA-API ----------------------*/

$(document).on('click.yoho.modal.data-api', Selector.DATA_TOGGLE, function(event) {
    let $this = $(this);
    let selector = this.getAttribute('data-target');
    let $target = $(selector);
    let config = $target.data(DATA_KEY) ? 'toggle' : $.extend($target.data(), $this.data());

    if ($target[0].tagName.toUpperCase() === 'A') {
        event.preventDefault();
    }

    Modal._jqueryBridge.call($target, config, this);


});


$.fn[NAME] = Modal._jqueryBridge;
$.fn[NAME].constructor = Modal;

module.exports = Modal;