u
This commit is contained in:
1 parent
e893ef2e48
commit
b6415c0d65
25 files changed
+1495
-112
No files matched your search
+384
@@ -0,0 +1,384 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Dialog Final</title>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
|
||||
|
||||
<style>
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.35);
|
||||
z-index: 999;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.win-dialog {
|
||||
position: fixed;
|
||||
background: #fff;
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, .25);
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.win-header {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #eee;
|
||||
cursor: move;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.win-title {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.win-btn {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.btn-item {
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-item:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.win-body {
|
||||
height: calc(100% - 40px);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.resizer {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.br {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
|
||||
.r {
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
|
||||
.b {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
.l {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
|
||||
.t {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<template id="file-template">
|
||||
<div class="layout">
|
||||
<div class="left">分类树</div>
|
||||
<div class="middle">列表</div>
|
||||
<div class="right">预览</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<button onclick="handleShowDialog()">
|
||||
打开窗口
|
||||
</button>
|
||||
|
||||
<script>
|
||||
function handleShowDialog() {
|
||||
Dialog.open({
|
||||
title: 'Test Window',
|
||||
template: '#file-template',
|
||||
width: '80%',
|
||||
height: '80%'
|
||||
})
|
||||
}
|
||||
|
||||
// Dialog
|
||||
const Dialog = (() => {
|
||||
let $mask = $('<div class="mask"></div>').appendTo('body');
|
||||
let $el = null;
|
||||
let isMax = false;
|
||||
let old = {};
|
||||
let opt = null;
|
||||
|
||||
// ====== 工具函数 ======
|
||||
function parseSize(val, max) {
|
||||
if (typeof val === 'number') return val;
|
||||
|
||||
if (typeof val === 'string') {
|
||||
if (val.includes('%')) return max * parseFloat(val) / 100;
|
||||
if (val.includes('vw')) return window.innerWidth * parseFloat(val) / 100;
|
||||
if (val.includes('vh')) return window.innerHeight * parseFloat(val) / 100;
|
||||
return parseFloat(val);
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
// ====== 核心方法 ======
|
||||
function applySize() {
|
||||
const maxW = window.innerWidth;
|
||||
const maxH = window.innerHeight;
|
||||
|
||||
let w = parseSize(opt.width || 600, maxW);
|
||||
let h = parseSize(opt.height || 400, maxH);
|
||||
|
||||
w = Math.min(w, maxW);
|
||||
h = Math.min(h, maxH);
|
||||
|
||||
$el.css({
|
||||
width: w,
|
||||
height: h,
|
||||
left: (maxW - w) / 2,
|
||||
top: (maxH - h) / 2
|
||||
});
|
||||
}
|
||||
|
||||
function bindResize() {
|
||||
$(window).on('resize.dialog', () => {
|
||||
if (isMax) {
|
||||
$el.css({
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const w = opt.width;
|
||||
const h = opt.height;
|
||||
|
||||
if (
|
||||
(typeof w === 'string' && (w.includes('%') || w.includes('vw'))) ||
|
||||
(typeof h === 'string' && (h.includes('%') || h.includes('vh')))
|
||||
) {
|
||||
applySize();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
const self = {
|
||||
get el() { return $el; }
|
||||
};
|
||||
|
||||
$el.find('.close').on('click', close);
|
||||
|
||||
// drag
|
||||
let move = false, ox = 0, oy = 0;
|
||||
|
||||
$el.find('.win-header').on('mousedown', function (e) {
|
||||
if (isMax) return;
|
||||
|
||||
move = true;
|
||||
const pos = $el.position();
|
||||
ox = e.clientX - pos.left;
|
||||
oy = e.clientY - pos.top;
|
||||
|
||||
$(document).on('mousemove.drag', function (e) {
|
||||
if (!move) return;
|
||||
|
||||
$el.css({
|
||||
left: e.clientX - ox,
|
||||
top: e.clientY - oy
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('mouseup.drag', function () {
|
||||
move = false;
|
||||
$(document).off('.drag');
|
||||
});
|
||||
});
|
||||
|
||||
// resize
|
||||
const MIN_W = 300;
|
||||
const MIN_H = 200;
|
||||
|
||||
$el.find('.resizer').on('mousedown', function (e) {
|
||||
if (isMax) return;
|
||||
|
||||
let type = $(this).attr('class').split(' ')[1];
|
||||
|
||||
const startX = e.clientX;
|
||||
const startY = e.clientY;
|
||||
|
||||
const startW = $el.width();
|
||||
const startH = $el.height();
|
||||
const startL = parseFloat($el.css('left'));
|
||||
const startT = parseFloat($el.css('top'));
|
||||
|
||||
const MAX_W = window.innerWidth;
|
||||
const MAX_H = window.innerHeight;
|
||||
|
||||
function onMove(e) {
|
||||
if (e.buttons !== 1) return;
|
||||
|
||||
let dx = e.clientX - startX;
|
||||
let dy = e.clientY - startY;
|
||||
|
||||
let newW = startW;
|
||||
let newH = startH;
|
||||
let newL = startL;
|
||||
let newT = startT;
|
||||
|
||||
if (type === 'br') { newW += dx; newH += dy; }
|
||||
if (type === 'r') newW += dx;
|
||||
if (type === 'b') newH += dy;
|
||||
if (type === 'l') { newW -= dx; newL += dx; }
|
||||
if (type === 't') { newH -= dy; newT += dy; }
|
||||
|
||||
if (newW < MIN_W) newW = MIN_W;
|
||||
if (newH < MIN_H) newH = MIN_H;
|
||||
|
||||
if (newW > MAX_W) newW = MAX_W;
|
||||
if (newH > MAX_H) newH = MAX_H;
|
||||
|
||||
$el.css({
|
||||
width: newW,
|
||||
height: newH,
|
||||
left: newL,
|
||||
top: newT
|
||||
});
|
||||
}
|
||||
|
||||
function onUp() {
|
||||
$(document).off('.resize');
|
||||
}
|
||||
|
||||
$(document)
|
||||
.on('mousemove.resize', onMove)
|
||||
.on('mouseup.resize', onUp);
|
||||
});
|
||||
|
||||
// max
|
||||
$el.find('.max').on('click', function () {
|
||||
if (!isMax) {
|
||||
old = {
|
||||
width: $el.width(),
|
||||
height: $el.height(),
|
||||
left: $el.position().left,
|
||||
top: $el.position().top
|
||||
};
|
||||
|
||||
$el.css({
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight
|
||||
});
|
||||
|
||||
isMax = true;
|
||||
} else {
|
||||
$el.css(old);
|
||||
isMax = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
if ($el) {
|
||||
$el.remove();
|
||||
$el = null;
|
||||
}
|
||||
isMax = false;
|
||||
$mask.off().hide();
|
||||
$(window).off('resize.dialog');
|
||||
}
|
||||
|
||||
// ====== API ======
|
||||
function open(o) {
|
||||
destroy();
|
||||
opt = o;
|
||||
|
||||
$el = $(`
|
||||
<div class="win-dialog">
|
||||
<div class="win-header">
|
||||
<div class="win-title"></div>
|
||||
<div class="win-btn">
|
||||
<div class="btn-item max">MAX</div>
|
||||
<div class="btn-item close">X</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="win-body"></div>
|
||||
</div>
|
||||
`).appendTo('body');
|
||||
|
||||
$el.find('.win-title').text(opt.title || 'Dialog');
|
||||
const $body = $el.find('.win-body');
|
||||
|
||||
if (opt.template) {
|
||||
const tpl = document.querySelector(opt.template);
|
||||
const node = tpl.content.cloneNode(true);
|
||||
$body.empty().append(node);
|
||||
}
|
||||
else if (opt.content instanceof HTMLElement) {
|
||||
$body.empty().append(opt.content);
|
||||
}
|
||||
else {
|
||||
$body.html(opt.content || '');
|
||||
}
|
||||
applySize();
|
||||
|
||||
$mask.fadeIn(120);
|
||||
$el.fadeIn(180);
|
||||
|
||||
bindEvents();
|
||||
bindResize();
|
||||
}
|
||||
|
||||
function close() {
|
||||
$el?.fadeOut(120);
|
||||
$mask.fadeOut(120);
|
||||
|
||||
setTimeout(() => destroy(), 120);
|
||||
}
|
||||
|
||||
// ====== 单例导出 ======
|
||||
return {
|
||||
open,
|
||||
close
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in new issue
Block a user