import { uuid } from 'utils'; var containerName = 'modal-archo-container'; var backdropName = 'modal-archo-backdrop'; var defaultOption = { containerCss: 'modal-container', backdropCss: 'modal-backdrop', okEventCss: 'modal-ok', cancelEventCss: 'modal-cancel', closeEventCss: 'modal-close' }; var defaultConfig = { title: '温馨提示', modalCss: 'modal', okText: '确认', okCss: 'button button-middle button-primary', cancelText: '取消', cancelCss: 'button button-middle button-primary button-outline', showBackdrop: true, closeByBackdrop: false, autoClose: true, animation: true, autoMiddle: true // 自动垂直居中 }; export class Modal { option body backdrop container config closeEventHandle cancelEventHandle okEventHandle element okEventElement cancelEventElement data constructor(option?){ this.init(option); } // == 初始化弹窗背景、容器和基础配置 init = (option) => { option = Object.assign({}, defaultOption, option); this.option = option; this.body = document.body; // 生成背景和容器 var id = uuid(); var backdropUuidCss = this.getUuidCss(option.backdropCss, id); var backdropElem = this.getMainElem(backdropName,option.backdropCss, backdropUuidCss); var containerUuidCss = this.getUuidCss(option.containerCss, id); var containerElem = this.getMainElem(containerName,option.containerCss, containerUuidCss); this.body.insertAdjacentHTML('beforeend',backdropElem); this.body.insertAdjacentHTML('beforeend',containerElem); this.backdrop = this.body.querySelector('.' + backdropUuidCss); // 背景 this.container = this.body.querySelector('.' + containerUuidCss); // 容器 } getUuidCss = (mainCss, uuid) => { return mainCss + '-' + uuid; } getMainElem = (name, mainCss, uuidCss) => { return '
'; } // 载人弹窗模板并打开 open = (template, config, callback) => { if(this.element) return; config = this.parseConfig(config); this.config = config; this.data = this.parseData(config); // 弹窗载入容器之前 if(config.beforeMount) config.beforeMount(this); // 解析模板并放入容器,并获取当前弹窗主体 var template = this.parseTemplate(template, this.data); this.container.insertAdjacentHTML('beforeend',template); this.element = this.container.childNodes[this.container.childNodes.length - 1]; // 自动垂直居中 if(config.autoMiddle) this.autoMiddle(this.element); // 弹窗载入容器之后 if(config.mounted) config.mounted(this); // 显示弹窗 this.show(config.animation); // 获取弹窗关闭触发元素 this.okEventElement = this.container.querySelector('.' + this.option.okEventCss); this.cancelEventElement = this.container.querySelector('.' + this.option.cancelEventCss); // 确认按钮关闭 if(this.okEventElement){ this.okEventHandle = (e) => { e.stopPropagation(); this.doCloseEvent(1, config.autoClose, callback); } this.okEventElement.addEventListener('click', this.okEventHandle); } // 取消按钮关闭 if(this.cancelEventElement){ this.cancelEventHandle = (e) => { e.stopPropagation(); this.doCloseEvent(0, config.autoClose, callback); } this.cancelEventElement.addEventListener('click', this.cancelEventHandle); } // 背景关闭,不受autoClose影响 if(config.closeByBackdrop){ this.closeEventHandle = () => { this.doCloseEvent(-1, true, callback); } this.container.addEventListener('click', this.closeEventHandle); } // 弹窗显示激活之后 if(config.activated) config.activated(this); return this; } // == 关闭事件 doCloseEvent = (isOk, autoClose, callback) => { if(autoClose) { this.close(() => { if(callback) callback(isOk); }); }else{ if(callback) callback(isOk); } } // == 自动垂直居中 autoMiddle = (elem) => { var height = elem.offsetHeight; elem.style.marginTop = '-' + height/2 + 'px'; } // == 解析config parseConfig = (config) => { if(typeof config == 'string'){ var content = config; config = Object.assign({}, defaultConfig); config.content = content; }else{ config = Object.assign({}, defaultConfig, config); } return config; } // == 解析要挂载的数据 parseData = (config) => { var configData = config.data || {}; delete config.data; var data = Object.assign({}, config, configData); data.okEventCss = this.option.okEventCss; data.cancelEventCss = this.option.cancelEventCss; data.closeEventCss = this.option.closeEventCss; return data; } // == 根据模板配置解析模板 parseTemplate = (template, data) => { for (var key in data) { var replaceValue = data[key]; var replaceKey = new RegExp("{{" + key + "}}"); template = template.replace(replaceKey, replaceValue); } return template; } // == 关闭弹窗 close = (callback) => { this.container.removeEventListener('click',this.closeEventHandle); // 解绑事件 if(this.config.beforeDestroy) this.config.beforeDestroy(this); this.hide(this.config.animation, () => { this.destroy(); if(this.config.destroyed) this.config.destroyed(this); if(callback) callback(); }); } // 销毁弹窗 destroy = () => { this.body.contains(this.backdrop) if(this.backdrop && this.body.contains(this.backdrop)) this.body.removeChild(this.backdrop); if(this.container && this.body.contains(this.container)) this.body.removeChild(this.container); this.element = null; this.okEventElement = null; this.cancelEventElement = null; } // == 显示弹窗 show = (animation) => { // 存在上一个弹窗则进行下降 var pre = getPreContainer(); if(pre) { pre.classList.add('down'); pre.classList.remove('active'); } this.container.classList.add('active'); if(animation) this.opening(); // 显示背景蒙版 var showBackdrop = this.config.showBackdrop && !pre; if(showBackdrop) { this.backdrop.classList.add('active'); if(animation) { this.backdrop.classList.add('in'); setTimeout( () => { this.backdrop.classList.remove('in'); },300) } this.disableScroll(); } } // 隐藏弹窗 hide = (animation,callback) => { var pre = getPreContainer(); if(animation){ this.closing(); this.backdrop.classList.add('out'); setTimeout(() => { this.container.classList.remove('active'); this.backdrop.classList.remove('active'); this.backdrop.classList.remove('out'); if(pre) { pre.classList.add('active'); pre.classList.remove('down'); } callback(); this.enableScroll(); // 允许滚动 },200); }else{ this.container.classList.remove('active'); this.backdrop.classList.remove('active'); if(pre) { pre.classList.add('active'); pre.classList.remove('down'); } callback(); this.enableScroll(); // 允许滚动 } } opening = () => { this.element.classList.remove('modal-closing'); this.element.classList.add('modal-opening'); } closing = () => { this.element.classList.remove('modal-opening'); this.element.classList.add('modal-closing'); } disableScroll = () => { document.body.classList.add('modal-disable-scroll'); } enableScroll = () => { document.body.classList.remove('modal-disable-scroll'); } } // 获取当前弹窗数量 function getCount() { var containers = getAllContainer(); return containers.length; } // 获取全部弹窗容器 function getAllContainer() { return document.body.querySelectorAll('.' + containerName); } // 获取上一个弹窗容器 function getPreContainer() { var containers = getAllContainer(); var len = containers.length; return containers[len - 2]; } // == 创建tip类型弹窗实例 export function tip(config, callback?) { var modal = new Modal(); config = modal.parseConfig(config); config.modalCss = 'modal-tip'; config.closeByBackdrop = true; var template = '
' + '' + '' + '
'; return modal.open(template, config, callback); } // == 创建alert类型弹窗实例 export function alert(config, callback?) { var modal = new Modal(); config = modal.parseConfig(config); config.modalCss = 'modal-alert'; var template = '
' + '' + '' + '
' + '
{{okText}}
' + '
'+ '
'; return modal.open(template, config, callback); } // == 创建confirm类型弹窗实例 export function confirm(config, callback?) { var modal = new Modal(); config = modal.parseConfig(config); config.modalCss = 'modal-confirm'; var template = '
' + '' + '' + '
' + '
{{cancelText}}
' + '
{{okText}}
' + '
'+ '
'; return modal.open(template, config, callback); }