TaoLer/public/static/component/pear/module/drawer.js
2023-03-16 22:40:15 +08:00

421 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);