421 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			421 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| layui.define(['jquery', 'element', 'layer', 'loading'], function (exports) {
 | ||
| 	"use strict";
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Drawer component
 | ||
| 	 * */
 | ||
| 	var MOD_NAME = 'drawer',
 | ||
| 		$ = layui.jquery,
 | ||
| 		element = layui.element,
 | ||
| 		layer = layui.layer,
 | ||
| 		loading = layui.loading;
 | ||
| 
 | ||
| 
 | ||
| 	var drawer = new function () {
 | ||
| 
 | ||
| 		/**
 | ||
| 		 * open drawer
 | ||
| 		 * */
 | ||
| 		this.open = function (option) {
 | ||
| 			//	默认使用 legacy 模式
 | ||
| 			if (option.legacy === undefined) {
 | ||
| 				option.legacy = true;
 | ||
| 			};
 | ||
| 			if (option.legacy) {
 | ||
| 				var obj = new mSlider({
 | ||
| 					target: option.target,
 | ||
| 					dom: option.dom,
 | ||
| 					direction: option.direction,
 | ||
| 					distance: option.distance,
 | ||
| 					time: option.time ? option.time : 0,
 | ||
| 					maskClose: option.maskClose,
 | ||
| 					callback: option.success
 | ||
| 				});
 | ||
| 				obj.open();
 | ||
| 				return obj;
 | ||
| 			} else {
 | ||
| 				return layerDrawer(option);
 | ||
| 			}
 | ||
| 		}
 | ||
| 		this.title = layer.title;
 | ||
| 		this.style = layer.style;
 | ||
| 		this.close = layer.close;
 | ||
| 		this.closeAll = layer.closeAll;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 *
 | ||
| 	 * 封装 layer.open
 | ||
| 	 * type,anim,move,fixed不可用,其它参数和 layer.open 一致
 | ||
| 	 * @param {LayerOption} option
 | ||
| 	 * @returns 原生 layer 的 index
 | ||
| 	 */
 | ||
| 	function layerDrawer(option) {
 | ||
| 		var opt = normalizeOption(option)
 | ||
| 		if (opt.target) appendToTarget(opt);
 | ||
| 		if (opt.url) loadFragment(opt);
 | ||
| 		var layerIndex = layer.open(opt);
 | ||
| 
 | ||
| 		return layerIndex;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * 加载 HTML 片段到 layer content
 | ||
| 	 * @param {*} option
 | ||
| 	 */
 | ||
| 	function loadFragment(option) {
 | ||
| 		option.success = Aspect(option.success, function (layero, index) {
 | ||
| 			var layerID = "#" + layero.attr("id");
 | ||
| 			loading.block({
 | ||
| 				type: 1,
 | ||
| 				elem: layerID,
 | ||
| 				msg: ''
 | ||
| 			});
 | ||
| 			$.ajax({
 | ||
| 				url: option.url,
 | ||
| 				dataType: "html",
 | ||
| 				success: function (result) {
 | ||
| 					layero.children('.layui-layer-content').html(result);
 | ||
| 					loading.blockRemove(layerID);
 | ||
| 				}
 | ||
| 			})
 | ||
| 		})
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 *将 layer 挂载到指定节点
 | ||
| 	 * @param {object} opt
 | ||
| 	 */
 | ||
| 	function appendToTarget(opt) {
 | ||
| 		var targetDOM = $(opt.target);
 | ||
| 		var contentDOM = $(opt.content);
 | ||
| 		contentDOM.appendTo(targetDOM);
 | ||
| 		opt.skin = getDrawerAnimationClass(opt.offset, true);
 | ||
| 		opt.offset = calcOffset(opt.offset, opt.area, targetDOM);
 | ||
| 		// 处理关闭后偶现 DOM 仍显示的问题,layer 的 BUG
 | ||
| 		opt.end = Aspect(opt.end, function () {
 | ||
| 			contentDOM.css("display", "none");
 | ||
| 		})
 | ||
| 		if (opt.shade) {
 | ||
| 			opt.success = Aspect(opt.success, function (layero, index) {
 | ||
| 				var shadeDOM = $("#layui-layer-shade" + index);
 | ||
| 				shadeDOM.css("position", "absolute");
 | ||
| 				shadeDOM.appendTo(layero.parent());
 | ||
| 			})
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 		* 规格化 layer.open 选项,兼容原版 Drawer 所有选项
 | ||
| 		* @param {LayerOption} option layer.open 的选项
 | ||
| 		* @returns 规格化后的 layer.open 选项
 | ||
| 		*/
 | ||
| 	function normalizeOption(option) {
 | ||
| 		if (option.direction && !option.offset) {
 | ||
| 			if (option.direction === "right") {
 | ||
| 				option.offset = "r";
 | ||
| 			} else if (option.direction === "left") {
 | ||
| 				option.offset = "l";
 | ||
| 			} else if (option.direction === "top") {
 | ||
| 				option.offset = "t";
 | ||
| 			} else if (option.direction === "bottom") {
 | ||
| 				option.offset = "b";
 | ||
| 			} else {
 | ||
| 				option.offset = "r";
 | ||
| 			}
 | ||
| 		}
 | ||
| 		if (option.distance && !option.area) {
 | ||
| 			option.area = option.distance;
 | ||
| 		}
 | ||
| 		if (option.dom && !option.content) {
 | ||
| 			option.content = $(option.dom);
 | ||
| 		}
 | ||
| 		if (option.maskClose && option.shadeClose === undefined) {
 | ||
| 			option.shadeClose = (option.maskClose + "").toString() !== "false" ? true : false;
 | ||
| 		}
 | ||
| 
 | ||
| 		option.type = 1
 | ||
| 		option.anim = -1;
 | ||
| 		option.move = false;
 | ||
| 		option.fixed = true;
 | ||
| 		if (option.iframe) {
 | ||
| 			option.type = 2;
 | ||
| 			option.content = option.iframe;
 | ||
| 		}
 | ||
| 		if (option.offset === undefined) option.offset = "r";
 | ||
| 		option.area = calcDrawerArea(option.offset, option.area);
 | ||
| 		if (option.title === undefined) option.title = false;
 | ||
| 		if (option.closeBtn === undefined) option.closeBtn = false;
 | ||
| 		if (option.shade === undefined) option.shade = 0.3;
 | ||
| 		if (option.shadeClose === undefined) option.shadeClose = true;
 | ||
| 		if (option.skin === undefined) option.skin = getDrawerAnimationClass(option.offset);
 | ||
| 		if (option.resize === undefined) option.resize = false;
 | ||
| 		if (option.success === undefined) option.success = function () { }; // 处理遮罩需要
 | ||
| 		if (option.end === undefined) option.end = function () { };
 | ||
| 
 | ||
| 		return option;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * 计算抽屉宽高
 | ||
| 	 * @param {string} offset 抽屉方向 l = 左, r = 右, t = 上, b = 下
 | ||
| 	 * @param {string[] | string} drawerArea 抽屉大小,字符串数组格式:[width, height],字符串格式:百分比或单位 px。
 | ||
| 	 * @returns 抽屉宽高数组
 | ||
| 	 */
 | ||
| 	function calcDrawerArea(offset, drawerArea) {
 | ||
| 		if (drawerArea instanceof Array) {
 | ||
| 			return drawerArea;
 | ||
| 		}
 | ||
| 		if (drawerArea === undefined || drawerArea === "auto") {
 | ||
| 			drawerArea = "30%";
 | ||
| 		}
 | ||
| 		if (offset === "l" || offset === "r") {
 | ||
| 			return [drawerArea, "100%"];
 | ||
| 		} else if (offset === "t" || offset === "b") {
 | ||
| 			return ["100%", drawerArea];
 | ||
| 		}
 | ||
| 		return [drawerArea, "100%"];
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * 获取抽屉动画类
 | ||
| 	 * @param {string} offset 抽屉方向
 | ||
| 	 * @param {boolean} 是否 absolute 布局
 | ||
| 	 * @returns 抽屉入场动画类
 | ||
| 	 */
 | ||
| 	function getDrawerAnimationClass(offset, isAbsolute) {
 | ||
| 		var positionAbsoluteClass = "position-absolute ";
 | ||
| 		var prefixClass = "pear-drawer pear-drawer-anim layui-anim layer-anim-";
 | ||
| 		var suffix = "rl";
 | ||
| 
 | ||
| 		if (isAbsolute) {
 | ||
| 			prefixClass = positionAbsoluteClass + prefixClass;
 | ||
| 		}
 | ||
| 		if (offset === "l") {
 | ||
| 			suffix = "lr";
 | ||
| 		} else if (offset === "r") {
 | ||
| 			suffix = "rl";
 | ||
| 		} else if (offset === "t") {
 | ||
| 			suffix = "tb";
 | ||
| 		} else if (offset === "b") {
 | ||
| 			suffix = "bt";
 | ||
| 		}
 | ||
| 		return prefixClass + suffix;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * 指定挂载容器重新计算 offset
 | ||
| 	 * @param {*} offset 位置
 | ||
| 	 * @param {*} area  范围大小
 | ||
| 	 * @param {*} targetEl 挂载节点
 | ||
| 	 * @returns 包含抽屉位置信息的数组,[top,left]
 | ||
| 	 */
 | ||
| 	function calcOffset(offset, area, targetEl) {
 | ||
| 		if (offset === undefined || offset === "l" || offset === "t") {
 | ||
| 			offset = "lt";
 | ||
| 		} else if (offset === "r") {
 | ||
| 			var left;
 | ||
| 			if (area instanceof Array) {
 | ||
| 				area = area[0];
 | ||
| 			}
 | ||
| 			if (area.indexOf("%") != -1) {
 | ||
| 				left = targetEl.innerWidth() * (1 - area.replace("%", "") / 100);
 | ||
| 			} else {
 | ||
| 				left = targetEl.innerWidth() - area;
 | ||
| 			}
 | ||
| 			offset = [0, left];
 | ||
| 		} else if (offset === "b") {
 | ||
| 			var top;
 | ||
| 			if (area instanceof Array) {
 | ||
| 				area = area[1];
 | ||
| 			}
 | ||
| 			if (area.indexOf("%") != -1) {
 | ||
| 				top = targetEl.innerHeight() * (1 - area.replace("%", "") / 100);
 | ||
| 			} else {
 | ||
| 				top = targetEl.innerHeight() - area;
 | ||
| 			}
 | ||
| 			offset = [top, 0];
 | ||
| 		}
 | ||
| 
 | ||
| 		return offset;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * 简易的切面
 | ||
| 	 * @param {Function} func 被通知的对象,原函数
 | ||
| 	 * @param {Function | undefined} before 前置通知
 | ||
| 	 * @param {Function | undefined} after 后置通知
 | ||
| 	 * @returns 代理函数
 | ||
| 	 */
 | ||
| 	function Aspect(target, before, after) {
 | ||
| 		function proxyFunc() {
 | ||
| 			if (before && typeof before === "function") {
 | ||
| 				before.apply(this, arguments)
 | ||
| 			}
 | ||
| 			target.apply(this, arguments);
 | ||
| 			if (after && typeof after === "function") {
 | ||
| 				after.apply(this, arguments)
 | ||
| 			}
 | ||
| 		}
 | ||
| 		return proxyFunc;
 | ||
| 	}
 | ||
| 
 | ||
| 	exports(MOD_NAME, drawer);
 | ||
| });
 | ||
| 
 | ||
| /**
 | ||
|  * 源码
 | ||
|  * */
 | ||
| (function (b, c) {
 | ||
| 	function a(d) {
 | ||
| 		this.opts = {
 | ||
| 			"target": d.target || "body",
 | ||
| 			"direction": d.direction || "left",
 | ||
| 			"distance": d.distance || "60%",
 | ||
| 			"dom": this.Q(d.dom),
 | ||
| 			"time": d.time || "",
 | ||
| 			"maskClose": (d.maskClose + "").toString() !== "false" ? true : false,
 | ||
| 			"callback": d.callback || ""
 | ||
| 		};
 | ||
| 		this.rnd = this.rnd();
 | ||
| 		this.target = this.opts.target;
 | ||
| 		this.dom = this.opts.dom[0];
 | ||
| 		this.wrap = "";
 | ||
| 		this.inner = "";
 | ||
| 		this.mask = "";
 | ||
| 		this.init()
 | ||
| 	}
 | ||
| 	a.prototype = {
 | ||
| 		Q: function (d) {
 | ||
| 			return document.querySelectorAll(d)
 | ||
| 		},
 | ||
| 		isMobile: function () {
 | ||
| 			return navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i) ? true : false
 | ||
| 		},
 | ||
| 		addEvent: function (f, e, d) {
 | ||
| 			if (f.attachEvent) {
 | ||
| 				f.attachEvent("on" + e, d)
 | ||
| 			} else {
 | ||
| 				f.addEventListener(e, d, false)
 | ||
| 			}
 | ||
| 		},
 | ||
| 		rnd: function () {
 | ||
| 			return Math.random().toString(36).substr(2, 6)
 | ||
| 		},
 | ||
| 		init: function () {
 | ||
| 			var g = this;
 | ||
| 			if (!g.dom) {
 | ||
| 				console.log("未正确绑定弹窗容器");
 | ||
| 				return
 | ||
| 			}
 | ||
| 			g.dom.style.display = "block";  // 兼容 layer 捕获层
 | ||
| 			var d = document.createElement("div");
 | ||
| 			var e = document.createElement("div");
 | ||
| 			var f = document.createElement("div");
 | ||
| 			d.setAttribute("class", "mSlider-main ms-" + g.rnd);
 | ||
| 			e.setAttribute("class", "mSlider-inner");
 | ||
| 			f.setAttribute("class", "mSlider-mask");
 | ||
| 			g.Q(g.target)[0].appendChild(d);
 | ||
| 			g.Q(".ms-" + g.rnd)[0].appendChild(e);
 | ||
| 			g.Q(".ms-" + g.rnd)[0].appendChild(f);
 | ||
| 			g.wrap = g.Q(".ms-" + g.rnd)[0];
 | ||
| 			g.inner = g.Q(".ms-" + g.rnd + " .mSlider-inner")[0];
 | ||
| 			g.mask = g.Q(".ms-" + g.rnd + " .mSlider-mask")[0];
 | ||
| 			g.inner.appendChild(g.dom);
 | ||
| 			switch (g.opts.direction) {
 | ||
| 				case "top":
 | ||
| 					g.top = "0";
 | ||
| 					g.left = "0";
 | ||
| 					g.width = "100%";
 | ||
| 					g.height = g.opts.distance;
 | ||
| 					g.translate = "0,-100%,0";
 | ||
| 					break;
 | ||
| 				case "bottom":
 | ||
| 					g.bottom = "0";
 | ||
| 					g.left = "0";
 | ||
| 					g.width = "100%";
 | ||
| 					g.height = g.opts.distance;
 | ||
| 					g.translate = "0,100%,0";
 | ||
| 					break;
 | ||
| 				case "right":
 | ||
| 					g.top = "0";
 | ||
| 					g.right = "0";
 | ||
| 					g.width = g.opts.distance;
 | ||
| 					g.height = document.documentElement.clientHeight + "px";
 | ||
| 					g.translate = "100%,0,0";
 | ||
| 					break;
 | ||
| 				default:
 | ||
| 					g.top = "0";
 | ||
| 					g.left = "0";
 | ||
| 					g.width = g.opts.distance;
 | ||
| 					g.height = document.documentElement.clientHeight + "px";
 | ||
| 					g.translate = "-100%,0,0"
 | ||
| 			}
 | ||
| 			g.wrap.style.display = "none";
 | ||
| 			g.wrap.style.position = (g.target === "body" ? "fixed" : "absolute");
 | ||
| 			g.wrap.style.top = "0";
 | ||
| 			g.wrap.style.left = "0";
 | ||
| 			g.wrap.style.width = "100%";
 | ||
| 			g.wrap.style.height = "100%";
 | ||
| 			g.wrap.style.zIndex = 9999999;
 | ||
| 			g.inner.style.position = "absolute";
 | ||
| 			g.inner.style.top = g.top;
 | ||
| 			g.inner.style.bottom = g.bottom;
 | ||
| 			g.inner.style.left = g.left;
 | ||
| 			g.inner.style.right = g.right;
 | ||
| 			g.inner.style.width = g.width;
 | ||
| 			g.inner.style.height = (g.target === "body" ? g.height : "100%");
 | ||
| 			g.inner.style.backgroundColor = "#fff";
 | ||
| 			g.inner.style.transform = "translate3d(" + g.translate + ")";
 | ||
| 			g.inner.style.webkitTransition = "all .2s ease-out";
 | ||
| 			g.inner.style.transition = "all .2s ease-out";
 | ||
| 			g.inner.style.zIndex = 10000000;
 | ||
| 			g.mask.style.width = "100%";
 | ||
| 			g.mask.style.height = "100%";
 | ||
| 			g.mask.style.opacity = "0.1";
 | ||
| 			g.mask.style.backgroundColor = "black";
 | ||
| 			g.mask.style.zIndex = "9999998";
 | ||
| 			g.mask.style.webkitBackfaceVisibility = "hidden";
 | ||
| 			g.events()
 | ||
| 		},
 | ||
| 		open: function () {
 | ||
| 			var d = this;
 | ||
| 			d.wrap.style.display = "block";
 | ||
| 			setTimeout(function () {
 | ||
| 				d.inner.style.transform = "translate3d(0,0,0)";
 | ||
| 				d.inner.style.webkitTransform = "translate3d(0,0,0)";
 | ||
| 				d.mask.style.opacity = 0.1
 | ||
| 			}, 30);
 | ||
| 			if (d.opts.time) {
 | ||
| 				d.timer = setTimeout(function () {
 | ||
| 					d.close()
 | ||
| 				}, d.opts.time)
 | ||
| 			}
 | ||
| 		},
 | ||
| 		close: function () {
 | ||
| 			var d = this;
 | ||
| 			d.timer && clearTimeout(d.timer);
 | ||
| 			d.inner.style.webkitTransform = "translate3d(" + d.translate + ")";
 | ||
| 			d.inner.style.transform = "translate3d(" + d.translate + ")";
 | ||
| 			d.mask.style.opacity = 0;
 | ||
| 			setTimeout(function () {
 | ||
| 				d.wrap.style.display = "none";
 | ||
| 				d.timer = null;
 | ||
| 				d.opts.callback && d.opts.callback()
 | ||
| 			}, 300)
 | ||
| 		},
 | ||
| 		events: function () {
 | ||
| 			var d = this;
 | ||
| 			d.addEvent(d.mask, "touchmove", function (f) {
 | ||
| 				f.preventDefault()
 | ||
| 			});
 | ||
| 			d.addEvent(d.mask, (d.isMobile() ? "touchend" : "click"), function (f) {
 | ||
| 				if (d.opts.maskClose) {
 | ||
| 					d.close()
 | ||
| 				}
 | ||
| 			})
 | ||
| 		}
 | ||
| 	};
 | ||
| 	b.mSlider = a
 | ||
| })(window);
 |