uiik 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/LICENSE +21 -0
- package/README.md +35 -0
- package/index.esm.js +1971 -0
- package/index.js +1995 -0
- package/package.json +60 -0
- package/types/detector.d.ts +34 -0
- package/types/draggable.d.ts +25 -0
- package/types/droppable.d.ts +30 -0
- package/types/index.d.ts +25 -0
- package/types/resizable.d.ts +19 -0
- package/types/rotatable.d.ts +23 -0
- package/types/selectable.d.ts +32 -0
- package/types/splittable.d.ts +23 -0
- package/types/types.d.ts +320 -0
- package/types/utils.d.ts +19 -0
package/index.js
ADDED
|
@@ -0,0 +1,1995 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* uiik v1.0.0
|
|
3
|
+
* A UI interaction kit includes draggable, splittable, rotatable, selectable, etc.
|
|
4
|
+
* https://github.com/holyhigh2/uii
|
|
5
|
+
* c) 2021-2023 @holyhigh2 may be freely distributed under the MIT license
|
|
6
|
+
*/
|
|
7
|
+
(function (global, factory) {
|
|
8
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@holyhigh/func.js')) :
|
|
9
|
+
typeof define === 'function' && define.amd ? define(['exports', '@holyhigh/func.js'], factory) :
|
|
10
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.uii = {}, global.func_js));
|
|
11
|
+
})(this, (function (exports, func_js) { 'use strict';
|
|
12
|
+
|
|
13
|
+
/******************************************************************************
|
|
14
|
+
Copyright (c) Microsoft Corporation.
|
|
15
|
+
|
|
16
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
17
|
+
purpose with or without fee is hereby granted.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
20
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
21
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
22
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
23
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
24
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
25
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
26
|
+
***************************************************************************** */
|
|
27
|
+
|
|
28
|
+
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
29
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
30
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
31
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
35
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
36
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
37
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
38
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
var _Uii_listeners;
|
|
42
|
+
/**
|
|
43
|
+
* A Base class for all Uii classes
|
|
44
|
+
*/
|
|
45
|
+
class Uii {
|
|
46
|
+
constructor(ele, opts) {
|
|
47
|
+
this.enabled = true;
|
|
48
|
+
_Uii_listeners.set(this, []);
|
|
49
|
+
this.opts = opts || {};
|
|
50
|
+
if (func_js.isArrayLike(ele) && !func_js.isString(ele)) {
|
|
51
|
+
this.ele = func_js.map(ele, (el) => {
|
|
52
|
+
let e = func_js.isString(el) ? document.querySelector(el) : el;
|
|
53
|
+
if (!func_js.isElement(e)) {
|
|
54
|
+
console.error('Invalid element "' + el + '"');
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return e;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const el = func_js.isString(ele) ? document.querySelectorAll(ele) : ele;
|
|
62
|
+
if (!func_js.isElement(el) && !func_js.isArrayLike(el)) {
|
|
63
|
+
console.error('Invalid element "' + ele + '"');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.ele = func_js.isArrayLike(el) ? func_js.toArray(el) : [el];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 销毁uii对象,包括卸载事件、清空元素等
|
|
71
|
+
*/
|
|
72
|
+
destroy() {
|
|
73
|
+
func_js.each(__classPrivateFieldGet(this, _Uii_listeners, "f"), ev => {
|
|
74
|
+
ev[0].removeEventListener(ev[1], ev[2], ev[3]);
|
|
75
|
+
});
|
|
76
|
+
__classPrivateFieldSet(this, _Uii_listeners, [], "f");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 注册事件,以便在{@link destroy}方法中卸载
|
|
80
|
+
* @param el dom元素
|
|
81
|
+
* @param event 事件名
|
|
82
|
+
* @param hook 回调函数
|
|
83
|
+
* @param useCapture 默认false
|
|
84
|
+
*/
|
|
85
|
+
registerEvent(el, event, hook, useCapture = false) {
|
|
86
|
+
const wrapper = ((ev) => {
|
|
87
|
+
if (!this.enabled)
|
|
88
|
+
return;
|
|
89
|
+
hook(ev);
|
|
90
|
+
}).bind(this);
|
|
91
|
+
el.addEventListener(event, wrapper, useCapture);
|
|
92
|
+
__classPrivateFieldGet(this, _Uii_listeners, "f").push([el, event, wrapper, useCapture]);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 禁用uii实例,禁用后的dom不会响应事件
|
|
96
|
+
*/
|
|
97
|
+
disable() {
|
|
98
|
+
this.enabled = false;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 启用uii实例
|
|
102
|
+
*/
|
|
103
|
+
enable() {
|
|
104
|
+
this.enabled = true;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 获取指定名称的选项值
|
|
108
|
+
* @param name
|
|
109
|
+
* @returns
|
|
110
|
+
*/
|
|
111
|
+
getOption(name) {
|
|
112
|
+
return name ? this.opts[name] : this.opts;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 一次设置多个选项值。触发`onOptionChanged`
|
|
116
|
+
* @param options
|
|
117
|
+
*/
|
|
118
|
+
setOptions(options) {
|
|
119
|
+
func_js.assign(this.opts, options);
|
|
120
|
+
this.onOptionChanged(this.opts);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 设置指定name的选项值。触发`onOptionChanged`
|
|
124
|
+
* @param name
|
|
125
|
+
* @param value
|
|
126
|
+
*/
|
|
127
|
+
setOption(name, value) {
|
|
128
|
+
this.opts[name] = value;
|
|
129
|
+
this.onOptionChanged(this.opts);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* @internal
|
|
133
|
+
*/
|
|
134
|
+
onOptionChanged(opts) {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
_Uii_listeners = new WeakMap();
|
|
138
|
+
|
|
139
|
+
/* eslint-disable max-len */
|
|
140
|
+
/**
|
|
141
|
+
* 工具包
|
|
142
|
+
* @author holyhigh2
|
|
143
|
+
*/
|
|
144
|
+
/**
|
|
145
|
+
* 获取child相对于parent的offset信息。含border宽度
|
|
146
|
+
* @returns
|
|
147
|
+
*/
|
|
148
|
+
function getOffset(child, parent) {
|
|
149
|
+
const rs = { x: 0, y: 0 };
|
|
150
|
+
let op = child.offsetParent;
|
|
151
|
+
while (op && parent && op !== parent) {
|
|
152
|
+
const style = window.getComputedStyle(op);
|
|
153
|
+
rs.x += op.offsetLeft + parseFloat(style.borderLeftWidth);
|
|
154
|
+
rs.y += op.offsetTop + parseFloat(style.borderTopWidth);
|
|
155
|
+
op = op.offsetParent;
|
|
156
|
+
}
|
|
157
|
+
rs.x += child.offsetLeft;
|
|
158
|
+
rs.y += child.offsetTop;
|
|
159
|
+
return rs;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* 边缘检测最小内部边距
|
|
163
|
+
*/
|
|
164
|
+
const EDGE_THRESHOLD = 5;
|
|
165
|
+
const DRAGGING_RULE = "body * { pointer-events: none; }";
|
|
166
|
+
function lockPage() {
|
|
167
|
+
document.styleSheets[0].insertRule(DRAGGING_RULE, 0);
|
|
168
|
+
}
|
|
169
|
+
function unlockPage() {
|
|
170
|
+
document.styleSheets[0].deleteRule(0);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
var _Splittable_instances, _Splittable_checkDirection, _Splittable_bindHandle;
|
|
174
|
+
const THRESHOLD$3 = 1;
|
|
175
|
+
const CLASS_SPLITTABLE = "uii-splittable";
|
|
176
|
+
const CLASS_SPLITTABLE_HANDLE = "uii-splittable-handle";
|
|
177
|
+
const CLASS_SPLITTABLE_HANDLE_GHOST = "uii-splittable-handle-ghost";
|
|
178
|
+
const CLASS_SPLITTABLE_HANDLE_ACTIVE = "uii-splittable-handle-active";
|
|
179
|
+
const CLASS_SPLITTABLE_V = "uii-splittable-v";
|
|
180
|
+
const CLASS_SPLITTABLE_H = "uii-splittable-h";
|
|
181
|
+
function getRootEl(el, root) {
|
|
182
|
+
let rs = el.parentNode;
|
|
183
|
+
while (rs && rs.parentNode !== root) {
|
|
184
|
+
rs = rs.parentNode;
|
|
185
|
+
}
|
|
186
|
+
return rs;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* 用于表示一个或多个分割器的定义
|
|
190
|
+
* > 可用CSS接口
|
|
191
|
+
* - .uii-splittable
|
|
192
|
+
* - .uii-splittable-handle
|
|
193
|
+
* - .uii-splittable-handle-ghost
|
|
194
|
+
* - .uii-splittable-handle-active
|
|
195
|
+
* - .uii-splittable-v
|
|
196
|
+
* - .uii-splittable-h
|
|
197
|
+
* @public
|
|
198
|
+
*/
|
|
199
|
+
class Splittable extends Uii {
|
|
200
|
+
constructor(container, opts) {
|
|
201
|
+
super(container, func_js.assign({
|
|
202
|
+
handleSize: 10,
|
|
203
|
+
minSize: 0,
|
|
204
|
+
sticky: false,
|
|
205
|
+
inside: false,
|
|
206
|
+
ghost: false
|
|
207
|
+
}, opts));
|
|
208
|
+
_Splittable_instances.add(this);
|
|
209
|
+
const con = this.ele[0];
|
|
210
|
+
//detect container position
|
|
211
|
+
const pos = window.getComputedStyle(con).position;
|
|
212
|
+
if (pos === "static") {
|
|
213
|
+
con.style.position = "relative";
|
|
214
|
+
}
|
|
215
|
+
con.classList.toggle(CLASS_SPLITTABLE, true);
|
|
216
|
+
const handleDoms = con.querySelectorAll(this.opts.handle);
|
|
217
|
+
const children = func_js.reject(con.children, c => {
|
|
218
|
+
if (func_js.includes(handleDoms, c))
|
|
219
|
+
return true;
|
|
220
|
+
return false;
|
|
221
|
+
});
|
|
222
|
+
const dir = __classPrivateFieldGet(this, _Splittable_instances, "m", _Splittable_checkDirection).call(this, con);
|
|
223
|
+
con.classList.toggle(dir === 'v' ? CLASS_SPLITTABLE_V : CLASS_SPLITTABLE_H, true);
|
|
224
|
+
const minSizeAry = func_js.map(children, (c, i) => {
|
|
225
|
+
if (func_js.isArray(this.opts.minSize)) {
|
|
226
|
+
return this.opts.minSize[i] || 0;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
return this.opts.minSize;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
const stickyAry = func_js.map(children, (c, i) => {
|
|
233
|
+
if (func_js.isArray(this.opts.sticky)) {
|
|
234
|
+
return this.opts.sticky[i] || false;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
return this.opts.sticky;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
if (func_js.isEmpty(handleDoms)) {
|
|
241
|
+
const len = children.length - 1;
|
|
242
|
+
for (let i = 0; i < len; i++) {
|
|
243
|
+
__classPrivateFieldGet(this, _Splittable_instances, "m", _Splittable_bindHandle).call(this, minSizeAry.slice(i, i + 2), stickyAry.slice(i, i + 2), this.opts, dir, children[i], children[i + 1]);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
func_js.each(handleDoms, (h, i) => {
|
|
248
|
+
const isRoot = h.parentNode.classList.contains(CLASS_SPLITTABLE);
|
|
249
|
+
let dom1, dom2;
|
|
250
|
+
if (isRoot) {
|
|
251
|
+
dom1 = h.previousElementSibling;
|
|
252
|
+
dom2 = h.nextElementSibling;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
dom2 = getRootEl(h, con);
|
|
256
|
+
dom1 = dom2.previousElementSibling;
|
|
257
|
+
}
|
|
258
|
+
__classPrivateFieldGet(this, _Splittable_instances, "m", _Splittable_bindHandle).call(this, minSizeAry.slice(i, i + 2), stickyAry.slice(i, i + 2), this.opts, dir, dom1, dom2, h);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
_Splittable_instances = new WeakSet(), _Splittable_checkDirection = function _Splittable_checkDirection(container) {
|
|
264
|
+
let dir = 'h';
|
|
265
|
+
const child = container.children[0];
|
|
266
|
+
let lastY = child.offsetTop;
|
|
267
|
+
func_js.each(container.children, c => {
|
|
268
|
+
if (c.offsetTop != lastY) {
|
|
269
|
+
dir = 'v';
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
return dir;
|
|
274
|
+
}, _Splittable_bindHandle = function _Splittable_bindHandle(minSizeAry, stickyAry, opts, dir, dom1, dom2, handle) {
|
|
275
|
+
var _a;
|
|
276
|
+
const handleSize = opts.handleSize;
|
|
277
|
+
if (!handle) {
|
|
278
|
+
handle = document.createElement('div');
|
|
279
|
+
let initPos = 0;
|
|
280
|
+
if (!opts.inside) {
|
|
281
|
+
initPos = (dir === 'v' ? dom2.offsetTop : dom2.offsetLeft);
|
|
282
|
+
}
|
|
283
|
+
const sensorHCss = `width:${handleSize}px;height:100%;top:0;left:${initPos - handleSize / 2}px;z-index:9;`;
|
|
284
|
+
const sensorVCss = `height:${handleSize}px;width:100%;left:0;top:${initPos - handleSize / 2}px;z-index:9;`;
|
|
285
|
+
handle.style.cssText =
|
|
286
|
+
'position: absolute;' + (dir === 'v' ? sensorVCss : sensorHCss);
|
|
287
|
+
if (opts.inside) {
|
|
288
|
+
dom2.appendChild(handle);
|
|
289
|
+
}
|
|
290
|
+
(_a = dom2.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(handle, dom2);
|
|
291
|
+
}
|
|
292
|
+
handle.style.cursor = dir === 'v' ? 's-resize' : 'e-resize';
|
|
293
|
+
handle.dataset.cursor = handle.style.cursor;
|
|
294
|
+
handle.classList.add(CLASS_SPLITTABLE_HANDLE);
|
|
295
|
+
const minSize1 = minSizeAry[0];
|
|
296
|
+
const minSize2 = minSizeAry[1];
|
|
297
|
+
let sticky1 = stickyAry[0];
|
|
298
|
+
let sticky2 = stickyAry[1];
|
|
299
|
+
const onStart = opts.onStart;
|
|
300
|
+
const onSplit = opts.onSplit;
|
|
301
|
+
const onEnd = opts.onEnd;
|
|
302
|
+
const onSticky = opts.onSticky;
|
|
303
|
+
const onClone = opts.onClone;
|
|
304
|
+
const oneSideMode = opts.oneSideMode;
|
|
305
|
+
const updateStart = !oneSideMode || oneSideMode === 'start';
|
|
306
|
+
const updateEnd = !oneSideMode || oneSideMode === 'end';
|
|
307
|
+
handle.onmousedown = function (e) {
|
|
308
|
+
// 1. 获取原始高度/宽度;设置宽度/高度
|
|
309
|
+
let originSize = 0;
|
|
310
|
+
let originSize1 = 0;
|
|
311
|
+
const originPosX = e.clientX;
|
|
312
|
+
const originPosY = e.clientY;
|
|
313
|
+
let splitterSize = 1;
|
|
314
|
+
let blockSize = 0; // 分割区size
|
|
315
|
+
switch (dir) {
|
|
316
|
+
case 'v':
|
|
317
|
+
originSize = dom1.offsetHeight;
|
|
318
|
+
originSize1 = dom2.offsetHeight;
|
|
319
|
+
splitterSize = handle.offsetHeight;
|
|
320
|
+
break;
|
|
321
|
+
case 'h':
|
|
322
|
+
originSize = dom1.offsetWidth;
|
|
323
|
+
originSize1 = dom2.offsetWidth;
|
|
324
|
+
splitterSize = handle.offsetWidth;
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
blockSize = splitterSize + originSize + originSize1;
|
|
328
|
+
const dom1Style = dom1.style;
|
|
329
|
+
const dom2Style = dom2.style;
|
|
330
|
+
//ghost
|
|
331
|
+
const ghost = opts.ghost;
|
|
332
|
+
const ghostClass = opts.ghostClass;
|
|
333
|
+
let ghostNode = null;
|
|
334
|
+
// 初始化sticked位置
|
|
335
|
+
let sticked = 'none';
|
|
336
|
+
if (originSize < minSize1 / 2) {
|
|
337
|
+
sticked = 'start';
|
|
338
|
+
}
|
|
339
|
+
else if (blockSize - originSize - splitterSize < minSize2 / 2) {
|
|
340
|
+
sticked = 'end';
|
|
341
|
+
}
|
|
342
|
+
let dragging = false;
|
|
343
|
+
let bodyCursor = document.body.style.cursor;
|
|
344
|
+
let startPos = dir === 'v' ? dom1.offsetTop : dom1.offsetLeft;
|
|
345
|
+
let ds1, anotherSize;
|
|
346
|
+
const dragListener = (ev) => {
|
|
347
|
+
var _a;
|
|
348
|
+
const offsetx = ev.clientX - originPosX;
|
|
349
|
+
const offsety = ev.clientY - originPosY;
|
|
350
|
+
if (!dragging) {
|
|
351
|
+
if (Math.abs(offsetx) > THRESHOLD$3 || Math.abs(offsety) > THRESHOLD$3) {
|
|
352
|
+
dragging = true;
|
|
353
|
+
handle === null || handle === void 0 ? void 0 : handle.classList.add(CLASS_SPLITTABLE_HANDLE_ACTIVE);
|
|
354
|
+
if (ghost) {
|
|
355
|
+
ghostNode = handle.cloneNode(true);
|
|
356
|
+
ghostNode.style.opacity = '0.3';
|
|
357
|
+
ghostNode.style.pointerEvents = 'none';
|
|
358
|
+
ghostNode.classList.add(CLASS_SPLITTABLE_HANDLE_GHOST);
|
|
359
|
+
if (ghostNode) {
|
|
360
|
+
if (ghostClass) {
|
|
361
|
+
ghostNode.className =
|
|
362
|
+
ghostNode.className.replace(ghostClass, '') + ' ' + ghostClass;
|
|
363
|
+
}
|
|
364
|
+
(_a = handle === null || handle === void 0 ? void 0 : handle.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(ghostNode);
|
|
365
|
+
func_js.call(onClone, ghostNode, e);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
lockPage();
|
|
369
|
+
document.body.style.cursor = (handle === null || handle === void 0 ? void 0 : handle.dataset.cursor) || '';
|
|
370
|
+
func_js.call(onStart, originSize, originSize1);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
ev.preventDefault();
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
let doSticky = false;
|
|
378
|
+
ds1 = dir === 'v' ? originSize + offsety : originSize + offsetx;
|
|
379
|
+
if (ds1 < minSize1 / 2 && sticky1 && minSize1 > 0) {
|
|
380
|
+
if (sticked == 'none') {
|
|
381
|
+
doSticky = true;
|
|
382
|
+
sticked = 'start';
|
|
383
|
+
}
|
|
384
|
+
ds1 = 0;
|
|
385
|
+
}
|
|
386
|
+
else if (ds1 < minSize1) {
|
|
387
|
+
ds1 = minSize1;
|
|
388
|
+
if (sticked == 'start' && sticky1) {
|
|
389
|
+
// 重置状态
|
|
390
|
+
doSticky = true;
|
|
391
|
+
sticked = 'none';
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
else if (blockSize - ds1 - splitterSize < minSize2 / 2 &&
|
|
395
|
+
sticky2) {
|
|
396
|
+
if (sticked == 'none') {
|
|
397
|
+
doSticky = true;
|
|
398
|
+
sticked = 'end';
|
|
399
|
+
}
|
|
400
|
+
ds1 = blockSize - splitterSize;
|
|
401
|
+
}
|
|
402
|
+
else if (blockSize - ds1 - splitterSize < minSize2) {
|
|
403
|
+
ds1 = blockSize - minSize2 - splitterSize;
|
|
404
|
+
if (sticked == 'end' && sticky2) {
|
|
405
|
+
// 重置状态
|
|
406
|
+
doSticky = true;
|
|
407
|
+
sticked = 'none';
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
anotherSize = blockSize - ds1 - splitterSize;
|
|
411
|
+
if (ghostNode) {
|
|
412
|
+
if (dir === 'v') {
|
|
413
|
+
ghostNode.style.top = startPos + ds1 - handleSize / 2 + 'px';
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
ghostNode.style.left = startPos + ds1 - handleSize / 2 + 'px';
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
const updateProp = dir === 'v' ? 'height' : 'width';
|
|
421
|
+
if (updateStart) {
|
|
422
|
+
dom1Style.setProperty(updateProp, ds1 + 'px', 'important');
|
|
423
|
+
}
|
|
424
|
+
if (updateEnd) {
|
|
425
|
+
dom2Style.setProperty(updateProp, anotherSize + 'px', 'important');
|
|
426
|
+
}
|
|
427
|
+
if (doSticky) {
|
|
428
|
+
func_js.call(onSticky, ds1, anotherSize, sticked);
|
|
429
|
+
}
|
|
430
|
+
//update handle
|
|
431
|
+
if (dir === 'v') {
|
|
432
|
+
handle.style.top = dom2.offsetTop - handleSize / 2 + 'px';
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
handle.style.left = dom2.offsetLeft - handleSize / 2 + 'px';
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
func_js.call(onSplit, ds1, anotherSize);
|
|
439
|
+
ev.preventDefault();
|
|
440
|
+
return false;
|
|
441
|
+
};
|
|
442
|
+
const dragEndListener = (ev) => {
|
|
443
|
+
var _a;
|
|
444
|
+
document.removeEventListener('mousemove', dragListener, false);
|
|
445
|
+
document.removeEventListener('mouseup', dragEndListener, false);
|
|
446
|
+
window.removeEventListener('blur', dragEndListener, false);
|
|
447
|
+
if (dragging) {
|
|
448
|
+
switch (dir) {
|
|
449
|
+
case 'v':
|
|
450
|
+
originSize = (dom1 === null || dom1 === void 0 ? void 0 : dom1.offsetHeight) || -1;
|
|
451
|
+
originSize1 = (dom2 === null || dom2 === void 0 ? void 0 : dom2.offsetHeight) || -1;
|
|
452
|
+
break;
|
|
453
|
+
case 'h':
|
|
454
|
+
originSize = (dom1 === null || dom1 === void 0 ? void 0 : dom1.offsetWidth) || -1;
|
|
455
|
+
originSize1 = (dom2 === null || dom2 === void 0 ? void 0 : dom2.offsetWidth) || -1;
|
|
456
|
+
break;
|
|
457
|
+
}
|
|
458
|
+
handle === null || handle === void 0 ? void 0 : handle.classList.remove(CLASS_SPLITTABLE_HANDLE_ACTIVE);
|
|
459
|
+
if (ghostNode) {
|
|
460
|
+
const updateProp = dir === 'v' ? 'height' : 'width';
|
|
461
|
+
if (updateStart) {
|
|
462
|
+
dom1Style.setProperty(updateProp, ds1 + 'px', 'important');
|
|
463
|
+
}
|
|
464
|
+
if (updateEnd) {
|
|
465
|
+
dom2Style.setProperty(updateProp, anotherSize + 'px', 'important');
|
|
466
|
+
}
|
|
467
|
+
//update handle
|
|
468
|
+
if (dir === 'v') {
|
|
469
|
+
handle.style.top = startPos + ds1 - handleSize / 2 + 'px';
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
handle.style.left = startPos + ds1 - handleSize / 2 + 'px';
|
|
473
|
+
}
|
|
474
|
+
(_a = ghostNode.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(ghostNode);
|
|
475
|
+
}
|
|
476
|
+
unlockPage();
|
|
477
|
+
document.body.style.cursor = bodyCursor;
|
|
478
|
+
func_js.call(onEnd, originSize, originSize1);
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
document.addEventListener('mousemove', dragListener, false);
|
|
482
|
+
document.addEventListener('mouseup', dragEndListener, false);
|
|
483
|
+
window.addEventListener('blur', dragEndListener, false);
|
|
484
|
+
e.preventDefault();
|
|
485
|
+
return false;
|
|
486
|
+
};
|
|
487
|
+
};
|
|
488
|
+
/**
|
|
489
|
+
* Add one or more splittors into the container
|
|
490
|
+
* @param container css selector or html element
|
|
491
|
+
* @param opts SplittableOptions
|
|
492
|
+
* @returns
|
|
493
|
+
*/
|
|
494
|
+
function newSplittable(container, opts) {
|
|
495
|
+
return new Splittable(container, opts);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/* eslint-disable max-len */
|
|
499
|
+
const THRESHOLD$2 = 2;
|
|
500
|
+
const CLASS_RESIZABLE_HANDLE = "uii-resizable-handle";
|
|
501
|
+
const CLASS_RESIZABLE_HANDLE_DIR = "uii-resizable-handle-";
|
|
502
|
+
const CLASS_RESIZABLE_HANDLE_ACTIVE = "uii-resizable-handle-active";
|
|
503
|
+
/**
|
|
504
|
+
* 用于表示一个或多个可改变尺寸元素的定义
|
|
505
|
+
* > 可用CSS接口
|
|
506
|
+
* - .uii-resizable-handle
|
|
507
|
+
* - .uii-resizable-handle-[n/s/e/w/ne/nw/se/sw]
|
|
508
|
+
* - .uii-resizable-handle-active
|
|
509
|
+
* @public
|
|
510
|
+
*/
|
|
511
|
+
class Resizable extends Uii {
|
|
512
|
+
constructor(els, opts) {
|
|
513
|
+
super(els, func_js.assign({
|
|
514
|
+
handleSize: 8,
|
|
515
|
+
minSize: 50,
|
|
516
|
+
dir: ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'],
|
|
517
|
+
ghost: false,
|
|
518
|
+
offset: 0
|
|
519
|
+
}, opts));
|
|
520
|
+
func_js.each(this.ele, (el) => {
|
|
521
|
+
initHandle$1(el, this.opts);
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function bindHandle$1(handle, dir, panel, opts) {
|
|
526
|
+
const onStart = opts.onStart;
|
|
527
|
+
const onResize = opts.onResize;
|
|
528
|
+
const onEnd = opts.onEnd;
|
|
529
|
+
const onClone = opts.onClone;
|
|
530
|
+
handle.onmousedown = function (e) {
|
|
531
|
+
// 获取panel当前信息
|
|
532
|
+
const originW = panel.offsetWidth;
|
|
533
|
+
const originH = panel.offsetHeight;
|
|
534
|
+
const originX = panel.offsetLeft;
|
|
535
|
+
const originY = panel.offsetTop;
|
|
536
|
+
let changeW = false;
|
|
537
|
+
let changeH = false;
|
|
538
|
+
let changeX = false;
|
|
539
|
+
let changeY = false;
|
|
540
|
+
switch (dir) {
|
|
541
|
+
case 's':
|
|
542
|
+
changeH = true;
|
|
543
|
+
break;
|
|
544
|
+
case 'e':
|
|
545
|
+
changeW = true;
|
|
546
|
+
break;
|
|
547
|
+
case 'n':
|
|
548
|
+
changeY = true;
|
|
549
|
+
changeH = true;
|
|
550
|
+
break;
|
|
551
|
+
case 'w':
|
|
552
|
+
changeX = true;
|
|
553
|
+
changeW = true;
|
|
554
|
+
break;
|
|
555
|
+
case 'se':
|
|
556
|
+
changeW = true;
|
|
557
|
+
changeH = true;
|
|
558
|
+
break;
|
|
559
|
+
case 'sw':
|
|
560
|
+
changeX = true;
|
|
561
|
+
changeW = true;
|
|
562
|
+
changeH = true;
|
|
563
|
+
break;
|
|
564
|
+
case 'ne':
|
|
565
|
+
changeY = true;
|
|
566
|
+
changeW = true;
|
|
567
|
+
changeH = true;
|
|
568
|
+
break;
|
|
569
|
+
case 'nw':
|
|
570
|
+
changeX = true;
|
|
571
|
+
changeY = true;
|
|
572
|
+
changeW = true;
|
|
573
|
+
changeH = true;
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
const originPosX = e.clientX;
|
|
577
|
+
const originPosY = e.clientY;
|
|
578
|
+
// boundary
|
|
579
|
+
let minWidth;
|
|
580
|
+
let minHeight;
|
|
581
|
+
let maxWidth;
|
|
582
|
+
let maxHeight;
|
|
583
|
+
if (func_js.isArray(opts.minSize)) {
|
|
584
|
+
minWidth = opts.minSize[0];
|
|
585
|
+
minHeight = opts.minSize[1];
|
|
586
|
+
}
|
|
587
|
+
else if (func_js.isNumber(opts.minSize)) {
|
|
588
|
+
minWidth = opts.minSize;
|
|
589
|
+
minHeight = opts.minSize;
|
|
590
|
+
}
|
|
591
|
+
if (func_js.isArray(opts.maxSize)) {
|
|
592
|
+
maxWidth = opts.maxSize[0];
|
|
593
|
+
maxHeight = opts.maxSize[1];
|
|
594
|
+
}
|
|
595
|
+
else if (func_js.isNumber(opts.maxSize)) {
|
|
596
|
+
maxWidth = opts.maxSize;
|
|
597
|
+
maxHeight = opts.maxSize;
|
|
598
|
+
}
|
|
599
|
+
const minX = maxWidth ? originX - maxWidth + originW : null;
|
|
600
|
+
const minY = maxHeight ? originY - maxHeight + originH : null;
|
|
601
|
+
const maxX = minWidth ? originX + originW - minWidth : null;
|
|
602
|
+
const maxY = minHeight ? originY + originH - minHeight : null;
|
|
603
|
+
//ghost
|
|
604
|
+
const ghost = opts.ghost;
|
|
605
|
+
const ghostClass = opts.ghostClass;
|
|
606
|
+
let ghostNode = null;
|
|
607
|
+
//aspectRatio
|
|
608
|
+
const aspectRatio = opts.aspectRatio;
|
|
609
|
+
const panelStyle = panel.style;
|
|
610
|
+
let style = panelStyle;
|
|
611
|
+
let currentW = originW;
|
|
612
|
+
let currentH = originH;
|
|
613
|
+
let dragging = false;
|
|
614
|
+
let bodyCursor = document.body.style.cursor;
|
|
615
|
+
const dragListener = (ev) => {
|
|
616
|
+
var _a;
|
|
617
|
+
const offsetx = ev.clientX - originPosX;
|
|
618
|
+
const offsety = ev.clientY - originPosY;
|
|
619
|
+
if (!dragging) {
|
|
620
|
+
if (Math.abs(offsetx) > THRESHOLD$2 || Math.abs(offsety) > THRESHOLD$2) {
|
|
621
|
+
dragging = true;
|
|
622
|
+
handle.classList.add(CLASS_RESIZABLE_HANDLE_ACTIVE);
|
|
623
|
+
if (ghost) {
|
|
624
|
+
if (func_js.isFunction(ghost)) {
|
|
625
|
+
ghostNode = ghost();
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
ghostNode = panel.cloneNode(true);
|
|
629
|
+
ghostNode.style.opacity = '0.3';
|
|
630
|
+
ghostNode.style.pointerEvents = 'none';
|
|
631
|
+
}
|
|
632
|
+
if (ghostNode) {
|
|
633
|
+
if (ghostClass) {
|
|
634
|
+
ghostNode.className =
|
|
635
|
+
ghostNode.className.replace(ghostClass, '') + ' ' + ghostClass;
|
|
636
|
+
}
|
|
637
|
+
(_a = panel.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(ghostNode);
|
|
638
|
+
func_js.call(onClone, ghostNode, e);
|
|
639
|
+
}
|
|
640
|
+
style = ghostNode === null || ghostNode === void 0 ? void 0 : ghostNode.style;
|
|
641
|
+
}
|
|
642
|
+
lockPage();
|
|
643
|
+
document.body.style.cursor = handle.dataset.cursor || '';
|
|
644
|
+
func_js.call(onStart, originW, originH);
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
ev.preventDefault();
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
let w = originW;
|
|
652
|
+
let h = originH;
|
|
653
|
+
let y = originY;
|
|
654
|
+
let x = originX;
|
|
655
|
+
if (changeW) {
|
|
656
|
+
w = originW + offsetx * (changeX ? -1 : 1);
|
|
657
|
+
if (minWidth && w < minWidth)
|
|
658
|
+
w = minWidth;
|
|
659
|
+
if (maxWidth && w > maxWidth)
|
|
660
|
+
w = maxWidth;
|
|
661
|
+
}
|
|
662
|
+
if (changeH) {
|
|
663
|
+
h = originH + offsety * (changeY ? -1 : 1);
|
|
664
|
+
if (minHeight && h < minHeight)
|
|
665
|
+
h = minHeight;
|
|
666
|
+
if (maxHeight && h > maxHeight)
|
|
667
|
+
h = maxHeight;
|
|
668
|
+
}
|
|
669
|
+
if (changeY) {
|
|
670
|
+
y = originY + offsety;
|
|
671
|
+
if (minY && y < minY)
|
|
672
|
+
y = minY;
|
|
673
|
+
if (maxY && y > maxY)
|
|
674
|
+
y = maxY;
|
|
675
|
+
}
|
|
676
|
+
if (changeX) {
|
|
677
|
+
x = originX + offsetx;
|
|
678
|
+
if (minX && x < minX)
|
|
679
|
+
x = minX;
|
|
680
|
+
if (maxX && x > maxX)
|
|
681
|
+
x = maxX;
|
|
682
|
+
}
|
|
683
|
+
if (aspectRatio) {
|
|
684
|
+
if (changeW) {
|
|
685
|
+
style.width = w + 'px';
|
|
686
|
+
style.height = w / aspectRatio + 'px';
|
|
687
|
+
}
|
|
688
|
+
if (changeH && dir !== 'sw') {
|
|
689
|
+
if (dir === 'nw') {
|
|
690
|
+
y = originY - w / aspectRatio + originH;
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
style.width = h * aspectRatio + 'px';
|
|
694
|
+
style.height = h + 'px';
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
if (changeW) {
|
|
700
|
+
style.width = w + 'px';
|
|
701
|
+
}
|
|
702
|
+
if (changeH) {
|
|
703
|
+
style.height = h + 'px';
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
if (changeY) {
|
|
707
|
+
style.top = y + 'px';
|
|
708
|
+
}
|
|
709
|
+
if (changeX) {
|
|
710
|
+
style.left = x + 'px';
|
|
711
|
+
}
|
|
712
|
+
currentW = w;
|
|
713
|
+
currentH = h;
|
|
714
|
+
func_js.call(onResize, w, h);
|
|
715
|
+
ev.preventDefault();
|
|
716
|
+
return false;
|
|
717
|
+
};
|
|
718
|
+
const dragEndListener = (ev) => {
|
|
719
|
+
var _a;
|
|
720
|
+
document.removeEventListener('mousemove', dragListener, false);
|
|
721
|
+
document.removeEventListener('mouseup', dragEndListener, false);
|
|
722
|
+
window.removeEventListener('blur', dragEndListener, false);
|
|
723
|
+
if (ghost && ghostNode) {
|
|
724
|
+
(_a = panel.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(ghostNode);
|
|
725
|
+
panelStyle.left = ghostNode.style.left;
|
|
726
|
+
panelStyle.top = ghostNode.style.top;
|
|
727
|
+
panelStyle.width = ghostNode.style.width;
|
|
728
|
+
panelStyle.height = ghostNode.style.height;
|
|
729
|
+
}
|
|
730
|
+
handle.classList.remove(CLASS_RESIZABLE_HANDLE_ACTIVE);
|
|
731
|
+
unlockPage();
|
|
732
|
+
document.body.style.cursor = bodyCursor;
|
|
733
|
+
func_js.call(onEnd, currentW, currentH);
|
|
734
|
+
};
|
|
735
|
+
document.addEventListener('mousemove', dragListener, false);
|
|
736
|
+
document.addEventListener('mouseup', dragEndListener, false);
|
|
737
|
+
window.addEventListener('blur', dragEndListener, false);
|
|
738
|
+
e.preventDefault();
|
|
739
|
+
return false;
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
function initHandle$1(panel, opts) {
|
|
743
|
+
// create handles
|
|
744
|
+
const handleSize = opts.handleSize;
|
|
745
|
+
const offset = opts.offset || 0;
|
|
746
|
+
func_js.each(opts.dir || ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'], (dir) => {
|
|
747
|
+
const handle = document.createElement('div');
|
|
748
|
+
handle.classList.add(CLASS_RESIZABLE_HANDLE, CLASS_RESIZABLE_HANDLE_DIR + dir);
|
|
749
|
+
handle.setAttribute('name', 'handle');
|
|
750
|
+
let css = '';
|
|
751
|
+
switch (dir) {
|
|
752
|
+
case 'n':
|
|
753
|
+
css = `left:0px;top:${-offset}px;width:100%;height:${handleSize}px;`;
|
|
754
|
+
break;
|
|
755
|
+
case 's':
|
|
756
|
+
css = `left:0px;bottom:${-offset}px;width:100%;height:${handleSize}px;`;
|
|
757
|
+
break;
|
|
758
|
+
case 'w':
|
|
759
|
+
css = `top:0px;left:${-offset}px;width:${handleSize}px;height:100%;`;
|
|
760
|
+
break;
|
|
761
|
+
case 'e':
|
|
762
|
+
css = `top:0px;right:${-offset}px;width:${handleSize}px;height:100%;`;
|
|
763
|
+
break;
|
|
764
|
+
default:
|
|
765
|
+
css = `width:${handleSize}px;height:${handleSize}px;z-index:9;`;
|
|
766
|
+
switch (dir) {
|
|
767
|
+
case 'ne':
|
|
768
|
+
css += `top:${-offset}px;right:${-offset}px;`;
|
|
769
|
+
break;
|
|
770
|
+
case 'nw':
|
|
771
|
+
css += `top:${-offset}px;left:${-offset}px;`;
|
|
772
|
+
break;
|
|
773
|
+
case 'se':
|
|
774
|
+
css += `bottom:${-offset}px;right:${-offset}px;`;
|
|
775
|
+
break;
|
|
776
|
+
case 'sw':
|
|
777
|
+
css += `bottom:${-offset}px;left:${-offset}px;`;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
bindHandle$1(handle, dir, panel, opts);
|
|
781
|
+
handle.style.cssText = `position: absolute;cursor: ${dir}-resize;` + css;
|
|
782
|
+
handle.dataset.cursor = `${dir}-resize`;
|
|
783
|
+
panel.appendChild(handle);
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Make els resizable
|
|
788
|
+
* @param els selector string / html element
|
|
789
|
+
* @param opts
|
|
790
|
+
* @returns
|
|
791
|
+
*/
|
|
792
|
+
function newResizable(els, opts) {
|
|
793
|
+
return new Resizable(els, opts);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
var _Draggable_handleMap;
|
|
797
|
+
const DRAGGER_GROUPS = {};
|
|
798
|
+
const CLASS_DRAGGABLE = "uii-draggable";
|
|
799
|
+
const CLASS_DRAGGABLE_HANDLE = "uii-draggable-handle";
|
|
800
|
+
const CLASS_DRAGGABLE_ACTIVE = "uii-draggable-active";
|
|
801
|
+
const CLASS_DRAGGABLE_GHOST = "uii-draggable-ghost";
|
|
802
|
+
/**
|
|
803
|
+
* 用于表示一个或多个可拖动元素的定义
|
|
804
|
+
* > 可用CSS接口
|
|
805
|
+
* - .uii-draggable
|
|
806
|
+
* - .uii-draggable-handle
|
|
807
|
+
* - .uii-draggable-active
|
|
808
|
+
* - .uii-draggable-ghost
|
|
809
|
+
* @public
|
|
810
|
+
*/
|
|
811
|
+
class Draggable extends Uii {
|
|
812
|
+
constructor(els, opts) {
|
|
813
|
+
super(els, func_js.assign({
|
|
814
|
+
container: false,
|
|
815
|
+
threshold: 0,
|
|
816
|
+
ghost: false,
|
|
817
|
+
direction: "",
|
|
818
|
+
scroll: true,
|
|
819
|
+
snapOptions: {
|
|
820
|
+
tolerance: 10,
|
|
821
|
+
}
|
|
822
|
+
}, opts));
|
|
823
|
+
_Draggable_handleMap.set(this, new WeakMap());
|
|
824
|
+
if (this.opts.handle) {
|
|
825
|
+
func_js.each(this.ele, (el) => {
|
|
826
|
+
const h = el.querySelector(this.opts.handle);
|
|
827
|
+
if (!h) {
|
|
828
|
+
console.error('No handle found "' + this.opts.handle + '"');
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
__classPrivateFieldGet(this, _Draggable_handleMap, "f").set(el, h);
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
this.onOptionChanged(this.opts);
|
|
835
|
+
//put into group
|
|
836
|
+
if (this.opts.group) {
|
|
837
|
+
if (!DRAGGER_GROUPS[this.opts.group]) {
|
|
838
|
+
DRAGGER_GROUPS[this.opts.group] = [];
|
|
839
|
+
}
|
|
840
|
+
DRAGGER_GROUPS[this.opts.group].push(...this.ele);
|
|
841
|
+
}
|
|
842
|
+
func_js.each(this.ele, (el) => {
|
|
843
|
+
bindEvent(this.registerEvent.bind(this), el, this.opts, __classPrivateFieldGet(this, _Draggable_handleMap, "f"));
|
|
844
|
+
if (func_js.isDefined(this.opts.type))
|
|
845
|
+
el.dataset.dropType = this.opts.type;
|
|
846
|
+
el.classList.toggle(CLASS_DRAGGABLE, true);
|
|
847
|
+
const ee = __classPrivateFieldGet(this, _Draggable_handleMap, "f").get(el) || el;
|
|
848
|
+
ee.classList.toggle(CLASS_DRAGGABLE_HANDLE, true);
|
|
849
|
+
if (func_js.isDefined(this.opts.cursor)) {
|
|
850
|
+
el.style.cursor = this.opts.cursor.default || 'move';
|
|
851
|
+
if (func_js.isDefined(this.opts.cursor.over)) {
|
|
852
|
+
el.dataset.cursorOver = this.opts.cursor.over;
|
|
853
|
+
el.dataset.cursorActive = this.opts.cursor.active || 'move';
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* @internal
|
|
860
|
+
*/
|
|
861
|
+
onOptionChanged(opts) {
|
|
862
|
+
const droppable = opts.droppable;
|
|
863
|
+
if (!func_js.isFunction(droppable)) {
|
|
864
|
+
if (func_js.isUndefined(droppable)) {
|
|
865
|
+
opts.droppable = () => { };
|
|
866
|
+
}
|
|
867
|
+
else if (func_js.isString(droppable)) {
|
|
868
|
+
opts.droppable = () => document.querySelectorAll(droppable);
|
|
869
|
+
}
|
|
870
|
+
else if (func_js.isArrayLike(droppable)) {
|
|
871
|
+
opts.droppable = () => droppable;
|
|
872
|
+
}
|
|
873
|
+
else if (func_js.isElement(droppable)) {
|
|
874
|
+
opts.droppable = () => [droppable];
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
if (opts.snap) {
|
|
878
|
+
opts.snapTargets = func_js.map(document.querySelectorAll(opts.snap), (el) => {
|
|
879
|
+
let offX = 0, offY = 0;
|
|
880
|
+
func_js.closest(el, (el) => {
|
|
881
|
+
offX += el.offsetLeft;
|
|
882
|
+
offY += el.offsetTop;
|
|
883
|
+
return false;
|
|
884
|
+
}, "offsetParent");
|
|
885
|
+
return {
|
|
886
|
+
x1: offX,
|
|
887
|
+
y1: offY,
|
|
888
|
+
x2: offX + el.offsetWidth,
|
|
889
|
+
y2: offY + el.offsetHeight,
|
|
890
|
+
el: el,
|
|
891
|
+
};
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
_Draggable_handleMap = new WeakMap();
|
|
897
|
+
function bindEvent(registerEvent, el, opts, handleMap) {
|
|
898
|
+
registerEvent(el, "mousedown", (e) => {
|
|
899
|
+
// get options
|
|
900
|
+
let dragDom = e.currentTarget;
|
|
901
|
+
let t = e.target;
|
|
902
|
+
if (!t)
|
|
903
|
+
return;
|
|
904
|
+
let handle = handleMap.get(dragDom);
|
|
905
|
+
if (handle && !handle.contains(t)) {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
const filter = opts.filter;
|
|
909
|
+
//check filter
|
|
910
|
+
if (filter) {
|
|
911
|
+
if (func_js.some(el.querySelectorAll(filter), ele => ele.contains(t)))
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
const computedStyle = window.getComputedStyle(dragDom);
|
|
915
|
+
const container = dragDom.offsetParent || document.body;
|
|
916
|
+
const inContainer = opts.container;
|
|
917
|
+
const threshold = opts.threshold;
|
|
918
|
+
const ghost = opts.ghost;
|
|
919
|
+
const ghostClass = opts.ghostClass;
|
|
920
|
+
const direction = opts.direction;
|
|
921
|
+
const onStart = opts.onStart;
|
|
922
|
+
const onDrag = opts.onDrag;
|
|
923
|
+
const onEnd = opts.onEnd;
|
|
924
|
+
const onClone = opts.onClone;
|
|
925
|
+
const originalZIndex = computedStyle.zIndex;
|
|
926
|
+
let zIndex = opts.zIndex || originalZIndex;
|
|
927
|
+
const classes = opts.classes;
|
|
928
|
+
const group = opts.group;
|
|
929
|
+
if (group) {
|
|
930
|
+
let i = -1;
|
|
931
|
+
func_js.each(DRAGGER_GROUPS[group], el => {
|
|
932
|
+
const z = parseInt(window.getComputedStyle(el).zIndex);
|
|
933
|
+
if (z > i)
|
|
934
|
+
i = z;
|
|
935
|
+
});
|
|
936
|
+
zIndex = i + 1;
|
|
937
|
+
}
|
|
938
|
+
const scroll = opts.scroll;
|
|
939
|
+
const scrollSpeed = opts.scrollSpeed || 10;
|
|
940
|
+
let gridX, gridY;
|
|
941
|
+
const grid = opts.grid;
|
|
942
|
+
if (func_js.isArray(grid)) {
|
|
943
|
+
gridX = grid[0];
|
|
944
|
+
gridY = grid[1];
|
|
945
|
+
}
|
|
946
|
+
else if (func_js.isNumber(grid)) {
|
|
947
|
+
gridX = gridY = grid;
|
|
948
|
+
}
|
|
949
|
+
const snapOn = opts.snap;
|
|
950
|
+
const snappable = opts.snapTargets;
|
|
951
|
+
const snapTolerance = opts.snapOptions.tolerance;
|
|
952
|
+
const onSnap = opts.onSnap;
|
|
953
|
+
let lastSnapDirY = "", lastSnapDirX = "";
|
|
954
|
+
let lastSnapping = "";
|
|
955
|
+
let parentOffsetX = 0, parentOffsetY = 0;
|
|
956
|
+
if (snapOn) {
|
|
957
|
+
func_js.closest(dragDom, (el, times) => {
|
|
958
|
+
if (times > 0) {
|
|
959
|
+
parentOffsetX += el.offsetLeft;
|
|
960
|
+
parentOffsetY += el.offsetTop;
|
|
961
|
+
}
|
|
962
|
+
return false;
|
|
963
|
+
}, "offsetParent");
|
|
964
|
+
}
|
|
965
|
+
const originW = dragDom.offsetWidth + parseFloat(computedStyle.borderLeftWidth) + parseFloat(computedStyle.borderRightWidth);
|
|
966
|
+
const originH = dragDom.offsetHeight + parseFloat(computedStyle.borderTopWidth) + parseFloat(computedStyle.borderBottomWidth);
|
|
967
|
+
// boundary
|
|
968
|
+
let minX;
|
|
969
|
+
let minY;
|
|
970
|
+
let maxX;
|
|
971
|
+
let maxY;
|
|
972
|
+
if (inContainer) {
|
|
973
|
+
minX = 0;
|
|
974
|
+
minY = 0;
|
|
975
|
+
maxX = container.scrollWidth - originW;
|
|
976
|
+
maxY = container.scrollHeight - originH;
|
|
977
|
+
}
|
|
978
|
+
//start point
|
|
979
|
+
const rect = container.getBoundingClientRect();
|
|
980
|
+
const offset = getOffset(t, container);
|
|
981
|
+
const ox = e.offsetX || 0;
|
|
982
|
+
const oy = e.offsetY || 0;
|
|
983
|
+
let hitPosX = offset.x + ox + container.scrollLeft;
|
|
984
|
+
let hitPosY = offset.y + oy + container.scrollTop;
|
|
985
|
+
let cursorX = ox, cursorY = e.offsetY;
|
|
986
|
+
if (e.target !== dragDom) {
|
|
987
|
+
const offset = getOffset(t, dragDom);
|
|
988
|
+
const style = window.getComputedStyle(t);
|
|
989
|
+
cursorX = offset.x + ox + parseFloat(style.borderLeftWidth);
|
|
990
|
+
cursorY = offset.y + oy + parseFloat(style.borderTopWidth);
|
|
991
|
+
}
|
|
992
|
+
const cursorAt = opts.cursorAt;
|
|
993
|
+
if (cursorAt) {
|
|
994
|
+
const l = cursorAt.left;
|
|
995
|
+
const t = cursorAt.top;
|
|
996
|
+
if (func_js.isString(l)) {
|
|
997
|
+
cursorX = parseFloat(l) / 100 * dragDom.offsetWidth;
|
|
998
|
+
}
|
|
999
|
+
else {
|
|
1000
|
+
cursorX = l;
|
|
1001
|
+
}
|
|
1002
|
+
if (func_js.isString(t)) {
|
|
1003
|
+
cursorY = parseFloat(t) / 100 * dragDom.offsetWidth;
|
|
1004
|
+
}
|
|
1005
|
+
else {
|
|
1006
|
+
cursorY = t;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
const style = dragDom.style;
|
|
1010
|
+
let dragging = false;
|
|
1011
|
+
let copyNode;
|
|
1012
|
+
let timer = null;
|
|
1013
|
+
let toLeft = false;
|
|
1014
|
+
let toTop = false;
|
|
1015
|
+
let toRight = false;
|
|
1016
|
+
let toBottom = false;
|
|
1017
|
+
let bodyCursor = document.body.style.cursor;
|
|
1018
|
+
const dragListener = (ev) => {
|
|
1019
|
+
var _a;
|
|
1020
|
+
const newX = ev.clientX - rect.x + container.scrollLeft;
|
|
1021
|
+
const newY = ev.clientY - rect.y + container.scrollTop;
|
|
1022
|
+
let offsetx = newX - hitPosX;
|
|
1023
|
+
let offsety = newY - hitPosY;
|
|
1024
|
+
if (!dragging) {
|
|
1025
|
+
if (Math.abs(offsetx) > threshold || Math.abs(offsety) > threshold) {
|
|
1026
|
+
dragging = true;
|
|
1027
|
+
if (ghost) {
|
|
1028
|
+
if (func_js.isFunction(ghost)) {
|
|
1029
|
+
copyNode = ghost(dragDom);
|
|
1030
|
+
}
|
|
1031
|
+
else {
|
|
1032
|
+
copyNode = dragDom.cloneNode(true);
|
|
1033
|
+
copyNode.style.opacity = "0.3";
|
|
1034
|
+
copyNode.style.pointerEvents = "none";
|
|
1035
|
+
copyNode.style.position = "absolute";
|
|
1036
|
+
}
|
|
1037
|
+
copyNode.style.left = dragDom.style.left;
|
|
1038
|
+
copyNode.style.top = dragDom.style.top;
|
|
1039
|
+
copyNode.style.zIndex = zIndex;
|
|
1040
|
+
if (ghostClass) {
|
|
1041
|
+
copyNode.classList.add(...func_js.compact(func_js.split(ghostClass, ' ')));
|
|
1042
|
+
}
|
|
1043
|
+
copyNode.classList.add(...func_js.compact(func_js.split(classes, ' ')));
|
|
1044
|
+
copyNode.classList.toggle(CLASS_DRAGGABLE_GHOST, true);
|
|
1045
|
+
(_a = dragDom.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(copyNode);
|
|
1046
|
+
if (onClone) {
|
|
1047
|
+
onClone(copyNode, ev);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
//apply classes
|
|
1051
|
+
dragDom.classList.add(...func_js.compact(func_js.split(classes, ' ')));
|
|
1052
|
+
dragDom.style.zIndex = zIndex;
|
|
1053
|
+
dragDom.classList.toggle(CLASS_DRAGGABLE_ACTIVE, true);
|
|
1054
|
+
func_js.call(onStart, dragDom, ev);
|
|
1055
|
+
lockPage();
|
|
1056
|
+
if (func_js.isDefined(opts.cursor)) {
|
|
1057
|
+
document.body.style.cursor = opts.cursor.active || 'move';
|
|
1058
|
+
}
|
|
1059
|
+
//notify
|
|
1060
|
+
const customEv = new Event("uii-dragactive", { "bubbles": true, "cancelable": false });
|
|
1061
|
+
dragDom.dispatchEvent(customEv);
|
|
1062
|
+
}
|
|
1063
|
+
else {
|
|
1064
|
+
ev.preventDefault();
|
|
1065
|
+
return false;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
//edge detect
|
|
1069
|
+
if (scroll) {
|
|
1070
|
+
const ltX = ev.clientX - rect.x;
|
|
1071
|
+
const ltY = ev.clientY - rect.y;
|
|
1072
|
+
const rbX = rect.x + rect.width - ev.clientX;
|
|
1073
|
+
const rbY = rect.y + rect.height - ev.clientY;
|
|
1074
|
+
toLeft = ltX < EDGE_THRESHOLD;
|
|
1075
|
+
toTop = ltY < EDGE_THRESHOLD;
|
|
1076
|
+
toRight = rbX < EDGE_THRESHOLD;
|
|
1077
|
+
toBottom = rbY < EDGE_THRESHOLD;
|
|
1078
|
+
if (toLeft || toTop
|
|
1079
|
+
||
|
|
1080
|
+
toRight || toBottom) {
|
|
1081
|
+
if (!timer) {
|
|
1082
|
+
timer = setInterval(() => {
|
|
1083
|
+
if (toLeft) {
|
|
1084
|
+
container.scrollLeft -= scrollSpeed;
|
|
1085
|
+
}
|
|
1086
|
+
else if (toRight) {
|
|
1087
|
+
container.scrollLeft += scrollSpeed;
|
|
1088
|
+
}
|
|
1089
|
+
if (toTop) {
|
|
1090
|
+
container.scrollTop -= scrollSpeed;
|
|
1091
|
+
}
|
|
1092
|
+
else if (toBottom) {
|
|
1093
|
+
container.scrollTop += scrollSpeed;
|
|
1094
|
+
}
|
|
1095
|
+
}, 20);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
else {
|
|
1099
|
+
if (timer) {
|
|
1100
|
+
clearInterval(timer);
|
|
1101
|
+
timer = null;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
let x = newX - cursorX;
|
|
1106
|
+
let y = newY - cursorY;
|
|
1107
|
+
//grid
|
|
1108
|
+
if (func_js.isNumber(gridX) && func_js.isNumber(gridY)) {
|
|
1109
|
+
x = ((x / gridX) >> 0) * gridX;
|
|
1110
|
+
y = ((y / gridY) >> 0) * gridY;
|
|
1111
|
+
}
|
|
1112
|
+
if (inContainer) {
|
|
1113
|
+
if (x < minX)
|
|
1114
|
+
x = minX;
|
|
1115
|
+
if (y < minY)
|
|
1116
|
+
y = minY;
|
|
1117
|
+
if (x > maxX)
|
|
1118
|
+
x = maxX;
|
|
1119
|
+
if (y > maxY)
|
|
1120
|
+
y = maxY;
|
|
1121
|
+
}
|
|
1122
|
+
let canDrag = true;
|
|
1123
|
+
let emitSnap = false;
|
|
1124
|
+
if (snapOn) {
|
|
1125
|
+
const currPageX1 = parentOffsetX + x;
|
|
1126
|
+
const currPageY1 = parentOffsetY + y;
|
|
1127
|
+
const currPageX2 = currPageX1 + originW;
|
|
1128
|
+
const currPageY2 = currPageY1 + originH;
|
|
1129
|
+
//check snappable
|
|
1130
|
+
let snapX = NaN, snapY = NaN;
|
|
1131
|
+
let targetX, targetY;
|
|
1132
|
+
let snapDirX, snapDirY;
|
|
1133
|
+
if (!direction || direction === "v") {
|
|
1134
|
+
func_js.each(snappable, (data) => {
|
|
1135
|
+
if (Math.abs(data.y1 - currPageY1) <= snapTolerance) {
|
|
1136
|
+
//top parallel
|
|
1137
|
+
snapY = data.y1;
|
|
1138
|
+
snapDirY = "t2t";
|
|
1139
|
+
}
|
|
1140
|
+
else if (Math.abs(data.y2 - currPageY1) <= snapTolerance) {
|
|
1141
|
+
//b2t
|
|
1142
|
+
snapY = data.y2;
|
|
1143
|
+
snapDirY = "t2b";
|
|
1144
|
+
}
|
|
1145
|
+
else if (Math.abs(data.y1 - currPageY2) <= snapTolerance) {
|
|
1146
|
+
//t2b
|
|
1147
|
+
snapY = data.y1 - originH;
|
|
1148
|
+
snapDirY = "b2t";
|
|
1149
|
+
}
|
|
1150
|
+
else if (Math.abs(data.y2 - currPageY2) <= snapTolerance) {
|
|
1151
|
+
//bottom parallel
|
|
1152
|
+
snapY = data.y2 - originH;
|
|
1153
|
+
snapDirY = "b2b";
|
|
1154
|
+
}
|
|
1155
|
+
if (snapY) {
|
|
1156
|
+
lastSnapDirY = snapDirY;
|
|
1157
|
+
targetY = data.el;
|
|
1158
|
+
return false;
|
|
1159
|
+
}
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
if (!direction || direction === "h") {
|
|
1163
|
+
func_js.each(snappable, (data) => {
|
|
1164
|
+
if (Math.abs(data.x1 - currPageX1) <= snapTolerance) {
|
|
1165
|
+
//left parallel
|
|
1166
|
+
snapX = data.x1;
|
|
1167
|
+
snapDirX = "l2l";
|
|
1168
|
+
}
|
|
1169
|
+
else if (Math.abs(data.x2 - currPageX1) <= snapTolerance) {
|
|
1170
|
+
//r2l
|
|
1171
|
+
snapX = data.x2;
|
|
1172
|
+
snapDirX = "l2r";
|
|
1173
|
+
}
|
|
1174
|
+
else if (Math.abs(data.x1 - currPageX2) <= snapTolerance) {
|
|
1175
|
+
//l2r
|
|
1176
|
+
snapX = data.x1 - originW;
|
|
1177
|
+
snapDirX = "r2l";
|
|
1178
|
+
}
|
|
1179
|
+
else if (Math.abs(data.x2 - currPageX2) <= snapTolerance) {
|
|
1180
|
+
//right parallel
|
|
1181
|
+
snapX = data.x2 - originW;
|
|
1182
|
+
snapDirX = "r2r";
|
|
1183
|
+
}
|
|
1184
|
+
if (snapX) {
|
|
1185
|
+
lastSnapDirX = snapDirX;
|
|
1186
|
+
targetX = data.el;
|
|
1187
|
+
return false;
|
|
1188
|
+
}
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
if (snapX || snapY) {
|
|
1192
|
+
if (snapX) {
|
|
1193
|
+
x = snapX - parentOffsetX;
|
|
1194
|
+
}
|
|
1195
|
+
if (snapY) {
|
|
1196
|
+
y = snapY - parentOffsetY;
|
|
1197
|
+
}
|
|
1198
|
+
if (onSnap && lastSnapping !== lastSnapDirX + "" + lastSnapDirY) {
|
|
1199
|
+
setTimeout(() => {
|
|
1200
|
+
//emit after relocate
|
|
1201
|
+
onSnap(copyNode || dragDom, targetX, targetY, snapDirX, snapDirY);
|
|
1202
|
+
}, 0);
|
|
1203
|
+
lastSnapping = lastSnapDirX + "" + lastSnapDirY;
|
|
1204
|
+
}
|
|
1205
|
+
emitSnap = true;
|
|
1206
|
+
}
|
|
1207
|
+
else {
|
|
1208
|
+
lastSnapDirX = lastSnapDirY = lastSnapping = "";
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
if (onDrag && !emitSnap) {
|
|
1212
|
+
if (onDrag(dragDom, ev, offsetx, offsety, x, y) === false) {
|
|
1213
|
+
canDrag = false;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
if (canDrag) {
|
|
1217
|
+
if (copyNode) {
|
|
1218
|
+
if (direction === "v") {
|
|
1219
|
+
copyNode.style.top = `${y}px`;
|
|
1220
|
+
}
|
|
1221
|
+
else if (direction === "v") {
|
|
1222
|
+
copyNode.style.left = `${x}px`;
|
|
1223
|
+
}
|
|
1224
|
+
else {
|
|
1225
|
+
copyNode.style.left = `${x}px`;
|
|
1226
|
+
copyNode.style.top = `${y}px`;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
else {
|
|
1230
|
+
if (direction === "v") {
|
|
1231
|
+
style.top = `${y}px`;
|
|
1232
|
+
}
|
|
1233
|
+
else if (direction === "v") {
|
|
1234
|
+
style.left = `${x}px`;
|
|
1235
|
+
}
|
|
1236
|
+
else {
|
|
1237
|
+
style.left = `${x}px`;
|
|
1238
|
+
style.top = `${y}px`;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
ev.preventDefault();
|
|
1243
|
+
return false;
|
|
1244
|
+
};
|
|
1245
|
+
const dragEndListener = (ev) => {
|
|
1246
|
+
var _a;
|
|
1247
|
+
document.removeEventListener("mousemove", dragListener);
|
|
1248
|
+
document.removeEventListener("mouseup", dragEndListener);
|
|
1249
|
+
window.removeEventListener("blur", dragEndListener);
|
|
1250
|
+
if (scroll) {
|
|
1251
|
+
if (timer) {
|
|
1252
|
+
clearInterval(timer);
|
|
1253
|
+
timer = null;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
//restore classes
|
|
1257
|
+
dragDom.classList.remove(...func_js.compact(func_js.split(classes, ' ')));
|
|
1258
|
+
dragDom.style.zIndex = originalZIndex;
|
|
1259
|
+
dragDom.classList.remove(CLASS_DRAGGABLE_ACTIVE);
|
|
1260
|
+
let moveToGhost = true;
|
|
1261
|
+
if (dragging) {
|
|
1262
|
+
moveToGhost = func_js.call(onEnd, dragDom, ev);
|
|
1263
|
+
}
|
|
1264
|
+
//notify
|
|
1265
|
+
const customEv = new Event("uii-dragdeactive", { "bubbles": true, "cancelable": false });
|
|
1266
|
+
dragDom.dispatchEvent(customEv);
|
|
1267
|
+
if (dragging) {
|
|
1268
|
+
unlockPage();
|
|
1269
|
+
document.body.style.cursor = bodyCursor;
|
|
1270
|
+
if (ghost) {
|
|
1271
|
+
(_a = dragDom.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(copyNode);
|
|
1272
|
+
if (moveToGhost !== false) {
|
|
1273
|
+
style.left = copyNode.style.left;
|
|
1274
|
+
style.top = copyNode.style.top;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
document.addEventListener("mousemove", dragListener);
|
|
1280
|
+
document.addEventListener("mouseup", dragEndListener);
|
|
1281
|
+
window.addEventListener("blur", dragEndListener);
|
|
1282
|
+
e.preventDefault();
|
|
1283
|
+
return false;
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* create a draggable pattern for one or more elements with opts
|
|
1288
|
+
* @param els selector string / html element
|
|
1289
|
+
* @param opts
|
|
1290
|
+
* @returns Draggable instance
|
|
1291
|
+
*/
|
|
1292
|
+
function newDraggable(els, opts) {
|
|
1293
|
+
return new Draggable(els, opts);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
var _Droppable_active;
|
|
1297
|
+
const Droppables = [];
|
|
1298
|
+
const CLASS_DROPPABLE = "uii-droppable";
|
|
1299
|
+
/**
|
|
1300
|
+
* 用于表示一个或多个可响应拖动元素的定义
|
|
1301
|
+
* > 可用CSS接口
|
|
1302
|
+
* - .uii-droppable
|
|
1303
|
+
* @public
|
|
1304
|
+
*/
|
|
1305
|
+
class Droppable extends Uii {
|
|
1306
|
+
constructor(el, opts) {
|
|
1307
|
+
super(el, func_js.assign({}, opts));
|
|
1308
|
+
_Droppable_active.set(this, void 0);
|
|
1309
|
+
Droppables.push(this);
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* @internal
|
|
1313
|
+
*/
|
|
1314
|
+
bindEvent(el, opts) {
|
|
1315
|
+
//dragenter
|
|
1316
|
+
this.registerEvent(el, "mouseenter", (e) => {
|
|
1317
|
+
if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
|
|
1318
|
+
return;
|
|
1319
|
+
if (opts.hoverClass) {
|
|
1320
|
+
func_js.each(func_js.split(opts.hoverClass, ' '), cls => {
|
|
1321
|
+
el.classList.toggle(cls, true);
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
if (__classPrivateFieldGet(this, _Droppable_active, "f").dataset.cursorOver) {
|
|
1325
|
+
document.body.style.cursor = __classPrivateFieldGet(this, _Droppable_active, "f").dataset.cursorOver;
|
|
1326
|
+
}
|
|
1327
|
+
func_js.call(opts.onEnter, el, e);
|
|
1328
|
+
});
|
|
1329
|
+
//dragleave
|
|
1330
|
+
this.registerEvent(el, "mouseleave", (e) => {
|
|
1331
|
+
if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
|
|
1332
|
+
return;
|
|
1333
|
+
if (opts.hoverClass) {
|
|
1334
|
+
func_js.each(func_js.split(opts.hoverClass, ' '), cls => {
|
|
1335
|
+
el.classList.toggle(cls, false);
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
if (__classPrivateFieldGet(this, _Droppable_active, "f").dataset.cursorOver) {
|
|
1339
|
+
document.body.style.cursor = __classPrivateFieldGet(this, _Droppable_active, "f").dataset.cursorActive || '';
|
|
1340
|
+
}
|
|
1341
|
+
func_js.call(opts.onLeave, el, e);
|
|
1342
|
+
});
|
|
1343
|
+
//dragover
|
|
1344
|
+
this.registerEvent(el, "mousemove", (e) => {
|
|
1345
|
+
if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
|
|
1346
|
+
return;
|
|
1347
|
+
if (opts.onDragOver) {
|
|
1348
|
+
opts.onDragOver(el, e);
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
//drop
|
|
1352
|
+
this.registerEvent(el, "mouseup", (e) => {
|
|
1353
|
+
if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
|
|
1354
|
+
return;
|
|
1355
|
+
if (opts.hoverClass) {
|
|
1356
|
+
func_js.each(func_js.split(opts.hoverClass, ' '), cls => {
|
|
1357
|
+
el.classList.toggle(cls, false);
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
func_js.call(opts.onDrop, el, e);
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* @internal
|
|
1365
|
+
*/
|
|
1366
|
+
active(target) {
|
|
1367
|
+
let valid = true;
|
|
1368
|
+
//check accepts
|
|
1369
|
+
if (func_js.isString(this.opts.accepts)) {
|
|
1370
|
+
valid = !!target.dataset.dropType && func_js.test(this.opts.accepts, target.dataset.dropType);
|
|
1371
|
+
}
|
|
1372
|
+
else if (func_js.isFunction(this.opts.accepts)) {
|
|
1373
|
+
valid = this.opts.accepts(this.ele, target);
|
|
1374
|
+
}
|
|
1375
|
+
if (!valid)
|
|
1376
|
+
return;
|
|
1377
|
+
__classPrivateFieldSet(this, _Droppable_active, target, "f");
|
|
1378
|
+
if (this.opts.activeClass) {
|
|
1379
|
+
func_js.each(this.ele, el => {
|
|
1380
|
+
func_js.each(func_js.split(this.opts.activeClass, ' '), cls => {
|
|
1381
|
+
el.classList.toggle(cls, true);
|
|
1382
|
+
});
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
func_js.call(this.opts.onActive, target, this.ele);
|
|
1386
|
+
//bind events
|
|
1387
|
+
func_js.each(this.ele, (el) => {
|
|
1388
|
+
el.classList.toggle(CLASS_DROPPABLE, true);
|
|
1389
|
+
el.style.pointerEvents = 'initial';
|
|
1390
|
+
this.bindEvent(el, this.opts);
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* @internal
|
|
1395
|
+
*/
|
|
1396
|
+
deactive(target) {
|
|
1397
|
+
if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
|
|
1398
|
+
return;
|
|
1399
|
+
__classPrivateFieldSet(this, _Droppable_active, null, "f");
|
|
1400
|
+
if (this.opts.activeClass) {
|
|
1401
|
+
func_js.each(this.ele, el => {
|
|
1402
|
+
func_js.each(func_js.split(this.opts.activeClass, ' '), cls => {
|
|
1403
|
+
el.classList.toggle(cls, false);
|
|
1404
|
+
});
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
func_js.call(this.opts.onDeactive, target, this.ele);
|
|
1408
|
+
//unbind events
|
|
1409
|
+
this.destroy();
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
_Droppable_active = new WeakMap();
|
|
1413
|
+
//uii-drag active
|
|
1414
|
+
document.addEventListener("uii-dragactive", (e) => {
|
|
1415
|
+
func_js.each(Droppables, dpb => {
|
|
1416
|
+
dpb.active(e.target);
|
|
1417
|
+
});
|
|
1418
|
+
});
|
|
1419
|
+
document.addEventListener("uii-dragdeactive", (e) => {
|
|
1420
|
+
func_js.each(Droppables, dpb => {
|
|
1421
|
+
dpb.deactive(e.target);
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
/**
|
|
1425
|
+
* Enable els to response to draggable objects
|
|
1426
|
+
* @param els selector string / html element
|
|
1427
|
+
* @param opts
|
|
1428
|
+
* @returns
|
|
1429
|
+
*/
|
|
1430
|
+
function newDroppable(els, opts) {
|
|
1431
|
+
return new Droppable(els, opts);
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
/* eslint-disable max-len */
|
|
1435
|
+
const ONE_DEG = 180 / Math.PI;
|
|
1436
|
+
const THRESHOLD$1 = 2;
|
|
1437
|
+
const CLASS_ROTATABLE = "uii-rotatable";
|
|
1438
|
+
const CLASS_ROTATABLE_HANDLE = "uii-rotatable-handle";
|
|
1439
|
+
const CLASS_ROTATABLE_ACTIVE = "uii-rotatable-active";
|
|
1440
|
+
/**
|
|
1441
|
+
* 用于表示一个或多个可旋转元素的定义
|
|
1442
|
+
* > 可用CSS接口
|
|
1443
|
+
* - .uii-rotatable
|
|
1444
|
+
* - .uii-rotatable-handle
|
|
1445
|
+
* - .uii-rotatable-active
|
|
1446
|
+
* @public
|
|
1447
|
+
*/
|
|
1448
|
+
class Rotatable extends Uii {
|
|
1449
|
+
constructor(els, opts) {
|
|
1450
|
+
super(els, opts);
|
|
1451
|
+
func_js.each(this.ele, (el) => {
|
|
1452
|
+
initHandle(el, this.opts);
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
function initHandle(el, opts) {
|
|
1457
|
+
var _a;
|
|
1458
|
+
const handle = document.createElement('div');
|
|
1459
|
+
handle.className = CLASS_ROTATABLE_HANDLE;
|
|
1460
|
+
handle.style.cssText = `
|
|
1461
|
+
position:absolute;
|
|
1462
|
+
width:12px;
|
|
1463
|
+
height:12px;
|
|
1464
|
+
border-radius:50%;
|
|
1465
|
+
left: calc(50% - 6px);
|
|
1466
|
+
top: -24px;
|
|
1467
|
+
`;
|
|
1468
|
+
handle.style.cursor = ((_a = opts.cursor) === null || _a === void 0 ? void 0 : _a.default) || 'crosshair';
|
|
1469
|
+
bindHandle(handle, el, opts);
|
|
1470
|
+
el.classList.toggle(CLASS_ROTATABLE, true);
|
|
1471
|
+
el.appendChild(handle);
|
|
1472
|
+
}
|
|
1473
|
+
function bindHandle(handle, el, opts) {
|
|
1474
|
+
const onStart = opts.onStart;
|
|
1475
|
+
const onRotate = opts.onRotate;
|
|
1476
|
+
const onEnd = opts.onEnd;
|
|
1477
|
+
handle.onmousedown = function (e) {
|
|
1478
|
+
var _a, _b;
|
|
1479
|
+
// calc center
|
|
1480
|
+
const center = window.getComputedStyle(el).transformOrigin || '';
|
|
1481
|
+
const centerPair = center.split(' ');
|
|
1482
|
+
const shadowDom = el.cloneNode();
|
|
1483
|
+
shadowDom.style.cssText = 'transform:rotate(0);z-index:-999;position:absolute;';
|
|
1484
|
+
(_a = el.parentElement) === null || _a === void 0 ? void 0 : _a.appendChild(shadowDom);
|
|
1485
|
+
const offsetXY = shadowDom.getBoundingClientRect();
|
|
1486
|
+
(_b = el.parentElement) === null || _b === void 0 ? void 0 : _b.removeChild(shadowDom);
|
|
1487
|
+
let centerX = parseFloat(centerPair[0]) + offsetXY.x;
|
|
1488
|
+
let centerY = parseFloat(centerPair[1]) + offsetXY.y;
|
|
1489
|
+
let a = 0, b = 0;
|
|
1490
|
+
const matrix = window.getComputedStyle(el).transform;
|
|
1491
|
+
if (matrix.indexOf('matrix') > -1) {
|
|
1492
|
+
const abcd = matrix.replace(/^matrix\(|\)$/mg, '').split(',');
|
|
1493
|
+
a = parseFloat(abcd[0]);
|
|
1494
|
+
b = parseFloat(abcd[1]);
|
|
1495
|
+
}
|
|
1496
|
+
let deg = Math.atan2(b, a) * ONE_DEG;
|
|
1497
|
+
if (deg < 0)
|
|
1498
|
+
deg = 360 - deg;
|
|
1499
|
+
if (deg > 360)
|
|
1500
|
+
deg = 360 - deg % 360;
|
|
1501
|
+
const style = el.style;
|
|
1502
|
+
let startDeg = Math.atan2(e.clientY - centerY, e.clientX - centerX) * ONE_DEG + 90;
|
|
1503
|
+
if (startDeg < 0)
|
|
1504
|
+
startDeg = 360 + startDeg;
|
|
1505
|
+
const offsetDeg = startDeg - deg;
|
|
1506
|
+
let dragging = false;
|
|
1507
|
+
let bodyCursor = document.body.style.cursor;
|
|
1508
|
+
const dragListener = (ev) => {
|
|
1509
|
+
var _a;
|
|
1510
|
+
const offsetx = ev.clientX - centerX;
|
|
1511
|
+
const offsety = ev.clientY - centerY;
|
|
1512
|
+
if (!dragging) {
|
|
1513
|
+
if (Math.abs(offsetx) > THRESHOLD$1 || Math.abs(offsety) > THRESHOLD$1) {
|
|
1514
|
+
dragging = true;
|
|
1515
|
+
//apply classes
|
|
1516
|
+
el.classList.toggle(CLASS_ROTATABLE_ACTIVE, true);
|
|
1517
|
+
func_js.call(onStart, deg);
|
|
1518
|
+
lockPage();
|
|
1519
|
+
if (func_js.isDefined(opts.cursor)) {
|
|
1520
|
+
document.body.style.cursor = ((_a = opts.cursor) === null || _a === void 0 ? void 0 : _a.active) || 'crosshair';
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
else {
|
|
1524
|
+
ev.preventDefault();
|
|
1525
|
+
return false;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
deg = Math.atan2(offsety, offsetx) * ONE_DEG + 90 - offsetDeg;
|
|
1529
|
+
if (deg < 0)
|
|
1530
|
+
deg = 360 + deg;
|
|
1531
|
+
func_js.call(onRotate, deg);
|
|
1532
|
+
style.transform = style.transform.replace(/rotateZ\(.*?\)/, '') + ' rotateZ(' + deg + 'deg)';
|
|
1533
|
+
ev.preventDefault();
|
|
1534
|
+
return false;
|
|
1535
|
+
};
|
|
1536
|
+
const dragEndListener = (ev) => {
|
|
1537
|
+
document.removeEventListener('mousemove', dragListener, false);
|
|
1538
|
+
document.removeEventListener('mouseup', dragEndListener, false);
|
|
1539
|
+
window.removeEventListener('blur', dragEndListener, false);
|
|
1540
|
+
if (dragging) {
|
|
1541
|
+
unlockPage();
|
|
1542
|
+
document.body.style.cursor = bodyCursor;
|
|
1543
|
+
el.classList.toggle(CLASS_ROTATABLE_ACTIVE, false);
|
|
1544
|
+
func_js.call(onEnd, deg);
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
document.addEventListener('mousemove', dragListener, false);
|
|
1548
|
+
document.addEventListener('mouseup', dragEndListener, false);
|
|
1549
|
+
window.addEventListener('blur', dragEndListener, false);
|
|
1550
|
+
e.preventDefault();
|
|
1551
|
+
return false;
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Make els rotatable
|
|
1556
|
+
* @param els selector string / html element
|
|
1557
|
+
* @param opts
|
|
1558
|
+
* @returns
|
|
1559
|
+
*/
|
|
1560
|
+
function newRotatable(els, opts) {
|
|
1561
|
+
return new Rotatable(els, opts);
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
var _CollisionDetector__targets;
|
|
1565
|
+
class CollisionDetector {
|
|
1566
|
+
constructor(el, targets, opts) {
|
|
1567
|
+
_CollisionDetector__targets.set(this, void 0);
|
|
1568
|
+
__classPrivateFieldSet(this, _CollisionDetector__targets, targets, "f");
|
|
1569
|
+
this.opts = {
|
|
1570
|
+
container: document.body
|
|
1571
|
+
};
|
|
1572
|
+
this.opts = func_js.assign(this.opts, opts);
|
|
1573
|
+
const domEl = func_js.isString(el) ? document.querySelector(el) : el;
|
|
1574
|
+
if (!domEl) {
|
|
1575
|
+
console.error('Invalid selector "' + el + '"');
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
const ele = domEl;
|
|
1579
|
+
this.el = domEl;
|
|
1580
|
+
//el data
|
|
1581
|
+
const offset = getOffset(ele, this.opts.container);
|
|
1582
|
+
const rect = { x: offset.x, y: offset.y, width: ele.offsetWidth, height: ele.offsetHeight };
|
|
1583
|
+
this.elData = {
|
|
1584
|
+
x1: rect.x,
|
|
1585
|
+
y1: rect.y,
|
|
1586
|
+
x2: rect.x + rect.width,
|
|
1587
|
+
y2: rect.y + rect.height,
|
|
1588
|
+
};
|
|
1589
|
+
//targets data
|
|
1590
|
+
this.update();
|
|
1591
|
+
}
|
|
1592
|
+
/**
|
|
1593
|
+
* update targets data if them changed
|
|
1594
|
+
*/
|
|
1595
|
+
update() {
|
|
1596
|
+
let targets;
|
|
1597
|
+
if (func_js.isFunction(__classPrivateFieldGet(this, _CollisionDetector__targets, "f"))) {
|
|
1598
|
+
targets = __classPrivateFieldGet(this, _CollisionDetector__targets, "f").call(this);
|
|
1599
|
+
}
|
|
1600
|
+
else if (func_js.isString(__classPrivateFieldGet(this, _CollisionDetector__targets, "f"))) {
|
|
1601
|
+
targets = this.opts.container.querySelectorAll(__classPrivateFieldGet(this, _CollisionDetector__targets, "f"));
|
|
1602
|
+
}
|
|
1603
|
+
else if (func_js.isElement(__classPrivateFieldGet(this, _CollisionDetector__targets, "f"))) {
|
|
1604
|
+
targets = [__classPrivateFieldGet(this, _CollisionDetector__targets, "f")];
|
|
1605
|
+
}
|
|
1606
|
+
else {
|
|
1607
|
+
targets = __classPrivateFieldGet(this, _CollisionDetector__targets, "f");
|
|
1608
|
+
}
|
|
1609
|
+
this.targetsData = func_js.flatMap(targets, t => {
|
|
1610
|
+
if (!t)
|
|
1611
|
+
return [];
|
|
1612
|
+
if (!func_js.isElement(t))
|
|
1613
|
+
return [];
|
|
1614
|
+
const offset = getOffset(t, this.opts.container);
|
|
1615
|
+
const rect = { x: offset.x, y: offset.y, width: t.offsetWidth, height: t.offsetHeight };
|
|
1616
|
+
return {
|
|
1617
|
+
x1: rect.x,
|
|
1618
|
+
y1: rect.y,
|
|
1619
|
+
x2: rect.x + rect.width,
|
|
1620
|
+
y2: rect.y + rect.height,
|
|
1621
|
+
el: t
|
|
1622
|
+
};
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
getOverlaps(x1, y1, x2, y2) {
|
|
1626
|
+
let elData = this.elData;
|
|
1627
|
+
if (x1 && x2 && y1 && y2) {
|
|
1628
|
+
elData = {
|
|
1629
|
+
x1,
|
|
1630
|
+
y1,
|
|
1631
|
+
x2,
|
|
1632
|
+
y2,
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
let overlaps = func_js.flatMap(this.targetsData, (td, i) => {
|
|
1636
|
+
if (elData.x2 < td.x1 || elData.x1 > td.x2 || elData.y2 < td.y1 || elData.y1 > td.y2)
|
|
1637
|
+
return [];
|
|
1638
|
+
return td.el;
|
|
1639
|
+
});
|
|
1640
|
+
return overlaps;
|
|
1641
|
+
}
|
|
1642
|
+
getInclusions(x1, y1, x2, y2) {
|
|
1643
|
+
let elData = this.elData;
|
|
1644
|
+
if (x1 && x2 && y1 && y2) {
|
|
1645
|
+
elData = {
|
|
1646
|
+
x1,
|
|
1647
|
+
y1,
|
|
1648
|
+
x2,
|
|
1649
|
+
y2,
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
let contains = func_js.flatMap(this.targetsData, (td, i) => {
|
|
1653
|
+
if (elData.x2 >= td.x2 && elData.x1 <= td.x1 && elData.y2 >= td.y2 && elData.y1 <= td.y1)
|
|
1654
|
+
return td.el;
|
|
1655
|
+
return [];
|
|
1656
|
+
});
|
|
1657
|
+
return contains;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
_CollisionDetector__targets = new WeakMap();
|
|
1661
|
+
/**
|
|
1662
|
+
* create a detector for the el and return
|
|
1663
|
+
* @param el element to be detected
|
|
1664
|
+
* @param targets
|
|
1665
|
+
* @param opts CollisionDetectorOptions
|
|
1666
|
+
* @param opts.container a root element of targets
|
|
1667
|
+
* @returns
|
|
1668
|
+
*/
|
|
1669
|
+
function newCollisionDetector(el, targets, opts) {
|
|
1670
|
+
return new CollisionDetector(el, targets, opts);
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
/* eslint-disable max-len */
|
|
1674
|
+
/**
|
|
1675
|
+
* selector
|
|
1676
|
+
* @author holyhigh2
|
|
1677
|
+
*/
|
|
1678
|
+
var _Selectable_instances, _Selectable__detector, _Selectable__lastSelected, _Selectable_bindEvent;
|
|
1679
|
+
const CLASS_SELECTOR = "uii-selector";
|
|
1680
|
+
const CLASS_SELECTING = "uii-selecting";
|
|
1681
|
+
const CLASS_SELECTED = "uii-selected";
|
|
1682
|
+
const THRESHOLD = 2;
|
|
1683
|
+
/**
|
|
1684
|
+
* 用于表示一个元素选择器的定义
|
|
1685
|
+
* > 可用CSS接口
|
|
1686
|
+
* - .uii-selector
|
|
1687
|
+
* - .uii-selecting
|
|
1688
|
+
* - .uii-selected
|
|
1689
|
+
* @public
|
|
1690
|
+
*/
|
|
1691
|
+
class Selectable extends Uii {
|
|
1692
|
+
constructor(container, opts) {
|
|
1693
|
+
super(container, func_js.assign({
|
|
1694
|
+
targets: [],
|
|
1695
|
+
scroll: true,
|
|
1696
|
+
}, opts));
|
|
1697
|
+
_Selectable_instances.add(this);
|
|
1698
|
+
_Selectable__detector.set(this, void 0);
|
|
1699
|
+
_Selectable__lastSelected.set(this, void 0);
|
|
1700
|
+
const domEl = this.ele[0];
|
|
1701
|
+
//create selector
|
|
1702
|
+
const selector = document.createElement("div");
|
|
1703
|
+
selector.className = CLASS_SELECTOR;
|
|
1704
|
+
selector.style.cssText = `
|
|
1705
|
+
position:absolute;
|
|
1706
|
+
left:-9999px;
|
|
1707
|
+
`;
|
|
1708
|
+
if (this.opts.class) {
|
|
1709
|
+
selector.className += " " + this.opts.class;
|
|
1710
|
+
}
|
|
1711
|
+
else {
|
|
1712
|
+
selector.style.cssText += "border:1px dashed #000;";
|
|
1713
|
+
}
|
|
1714
|
+
domEl.appendChild(selector);
|
|
1715
|
+
//create detector
|
|
1716
|
+
__classPrivateFieldSet(this, _Selectable__detector, newCollisionDetector(selector, this.opts.targets, {
|
|
1717
|
+
container: domEl,
|
|
1718
|
+
}), "f");
|
|
1719
|
+
__classPrivateFieldGet(this, _Selectable_instances, "m", _Selectable_bindEvent).call(this, selector, domEl);
|
|
1720
|
+
}
|
|
1721
|
+
/**
|
|
1722
|
+
* 更新targets
|
|
1723
|
+
*/
|
|
1724
|
+
updateTargets() {
|
|
1725
|
+
__classPrivateFieldGet(this, _Selectable__detector, "f").update();
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* @internal
|
|
1729
|
+
*/
|
|
1730
|
+
onOptionChanged() {
|
|
1731
|
+
this.updateTargets();
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
_Selectable__detector = new WeakMap(), _Selectable__lastSelected = new WeakMap(), _Selectable_instances = new WeakSet(), _Selectable_bindEvent = function _Selectable_bindEvent(selector, con) {
|
|
1735
|
+
const that = this;
|
|
1736
|
+
this.registerEvent(con, "mousedown", (e) => {
|
|
1737
|
+
const t = e.target;
|
|
1738
|
+
const onStart = that.opts.onStart;
|
|
1739
|
+
const onSelect = that.opts.onSelect;
|
|
1740
|
+
const onEnd = that.opts.onEnd;
|
|
1741
|
+
const mode = that.opts.mode || "overlap";
|
|
1742
|
+
const scroll = that.opts.scroll;
|
|
1743
|
+
const scrollSpeed = that.opts.scrollSpeed || 10;
|
|
1744
|
+
const filter = that.opts.filter;
|
|
1745
|
+
const selectingClassAry = func_js.compact(func_js.split(that.opts.selectingClass, " "));
|
|
1746
|
+
const selectedClassAry = func_js.compact(func_js.split(that.opts.selectedClass, " "));
|
|
1747
|
+
//check filter
|
|
1748
|
+
if (filter) {
|
|
1749
|
+
if (func_js.isFunction(filter)) {
|
|
1750
|
+
if (filter(t))
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
else if (func_js.some(con.querySelectorAll(filter), (el) => el.contains(t)))
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
let originPos = "";
|
|
1757
|
+
//offset
|
|
1758
|
+
const rect = con.getBoundingClientRect();
|
|
1759
|
+
const conStyle = window.getComputedStyle(con);
|
|
1760
|
+
const blw = parseFloat(conStyle.borderLeftWidth);
|
|
1761
|
+
const btw = parseFloat(conStyle.borderTopWidth);
|
|
1762
|
+
let hitPosX = e.offsetX + con.scrollLeft, hitPosY = e.offsetY + con.scrollTop;
|
|
1763
|
+
if (t !== con) {
|
|
1764
|
+
const offset = getOffset(t, con);
|
|
1765
|
+
const style = window.getComputedStyle(t);
|
|
1766
|
+
hitPosX = offset.x + e.offsetX + parseFloat(style.borderLeftWidth);
|
|
1767
|
+
hitPosY = offset.y + e.offsetY + parseFloat(style.borderTopWidth);
|
|
1768
|
+
}
|
|
1769
|
+
const style = selector.style;
|
|
1770
|
+
let selection = [];
|
|
1771
|
+
let lastSelection = [];
|
|
1772
|
+
let x1 = hitPosX, y1 = hitPosY;
|
|
1773
|
+
let dragging = false;
|
|
1774
|
+
let timer = null;
|
|
1775
|
+
let toLeft = false;
|
|
1776
|
+
let toTop = false;
|
|
1777
|
+
let toRight = false;
|
|
1778
|
+
let toBottom = false;
|
|
1779
|
+
const dragListener = (ev) => {
|
|
1780
|
+
const newX = ev.clientX - rect.x + con.scrollLeft - blw;
|
|
1781
|
+
const newY = ev.clientY - rect.y + con.scrollTop - btw;
|
|
1782
|
+
const offsetx = newX - hitPosX;
|
|
1783
|
+
const offsety = newY - hitPosY;
|
|
1784
|
+
if (!dragging) {
|
|
1785
|
+
if (Math.abs(offsetx) > THRESHOLD || Math.abs(offsety) > THRESHOLD) {
|
|
1786
|
+
dragging = true;
|
|
1787
|
+
//update targets count & positions
|
|
1788
|
+
__classPrivateFieldGet(this, _Selectable__detector, "f").update();
|
|
1789
|
+
//detect container position
|
|
1790
|
+
const pos = window.getComputedStyle(con).position;
|
|
1791
|
+
if (pos === "static") {
|
|
1792
|
+
originPos = con.style.position;
|
|
1793
|
+
con.style.position = "relative";
|
|
1794
|
+
}
|
|
1795
|
+
//clear _lastSelected
|
|
1796
|
+
func_js.each(__classPrivateFieldGet(this, _Selectable__lastSelected, "f"), t => {
|
|
1797
|
+
t.classList.toggle(CLASS_SELECTED, false);
|
|
1798
|
+
});
|
|
1799
|
+
func_js.call(onStart, t);
|
|
1800
|
+
}
|
|
1801
|
+
else {
|
|
1802
|
+
ev.preventDefault();
|
|
1803
|
+
return false;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
//edge detect
|
|
1807
|
+
if (scroll) {
|
|
1808
|
+
const ltX = ev.clientX - rect.x;
|
|
1809
|
+
const ltY = ev.clientY - rect.y;
|
|
1810
|
+
const rbX = rect.x + rect.width - ev.clientX;
|
|
1811
|
+
const rbY = rect.y + rect.height - ev.clientY;
|
|
1812
|
+
toLeft = ltX < EDGE_THRESHOLD;
|
|
1813
|
+
toTop = ltY < EDGE_THRESHOLD;
|
|
1814
|
+
toRight = rbX < EDGE_THRESHOLD;
|
|
1815
|
+
toBottom = rbY < EDGE_THRESHOLD;
|
|
1816
|
+
if (toLeft || toTop || toRight || toBottom) {
|
|
1817
|
+
if (!timer) {
|
|
1818
|
+
timer = setInterval(() => {
|
|
1819
|
+
if (toLeft) {
|
|
1820
|
+
con.scrollLeft -= scrollSpeed;
|
|
1821
|
+
}
|
|
1822
|
+
else if (toRight) {
|
|
1823
|
+
con.scrollLeft += scrollSpeed;
|
|
1824
|
+
}
|
|
1825
|
+
if (toTop) {
|
|
1826
|
+
con.scrollTop -= scrollSpeed;
|
|
1827
|
+
}
|
|
1828
|
+
else if (toBottom) {
|
|
1829
|
+
con.scrollTop += scrollSpeed;
|
|
1830
|
+
}
|
|
1831
|
+
}, 20);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
else {
|
|
1835
|
+
if (timer) {
|
|
1836
|
+
clearInterval(timer);
|
|
1837
|
+
timer = null;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
let x = hitPosX, y = hitPosY, w = Math.abs(offsetx), h = Math.abs(offsety);
|
|
1842
|
+
if (offsetx > 0 && offsety > 0) {
|
|
1843
|
+
x1 = hitPosX;
|
|
1844
|
+
y1 = hitPosY;
|
|
1845
|
+
}
|
|
1846
|
+
else if (offsetx < 0 && offsety < 0) {
|
|
1847
|
+
x = x1 = newX;
|
|
1848
|
+
y = y1 = newY;
|
|
1849
|
+
}
|
|
1850
|
+
else if (offsetx < 0) {
|
|
1851
|
+
x = x1 = newX;
|
|
1852
|
+
}
|
|
1853
|
+
else if (offsety < 0) {
|
|
1854
|
+
y = y1 = newY;
|
|
1855
|
+
}
|
|
1856
|
+
style.left = x + "px";
|
|
1857
|
+
style.top = y + "px";
|
|
1858
|
+
style.width = w + "px";
|
|
1859
|
+
style.height = h + "px";
|
|
1860
|
+
//detect collision
|
|
1861
|
+
if (mode === "overlap") {
|
|
1862
|
+
selection = __classPrivateFieldGet(that, _Selectable__detector, "f").getOverlaps(x1, y1, x1 + w, y1 + h);
|
|
1863
|
+
}
|
|
1864
|
+
else if (mode === "inclusion") {
|
|
1865
|
+
selection = __classPrivateFieldGet(that, _Selectable__detector, "f").getInclusions(x1, y1, x1 + w, y1 + h);
|
|
1866
|
+
}
|
|
1867
|
+
func_js.each(lastSelection, (t) => {
|
|
1868
|
+
if (!func_js.includes(selection, t)) {
|
|
1869
|
+
t.classList.toggle(CLASS_SELECTING, false);
|
|
1870
|
+
func_js.each(selectingClassAry, (cls) => {
|
|
1871
|
+
t.classList.toggle(cls, false);
|
|
1872
|
+
});
|
|
1873
|
+
}
|
|
1874
|
+
});
|
|
1875
|
+
func_js.each(selection, (t) => {
|
|
1876
|
+
t.classList.toggle(CLASS_SELECTING, true);
|
|
1877
|
+
func_js.each(selectingClassAry, (cls) => {
|
|
1878
|
+
t.classList.toggle(cls, true);
|
|
1879
|
+
});
|
|
1880
|
+
});
|
|
1881
|
+
const changed = lastSelection.length != selection.length;
|
|
1882
|
+
lastSelection = selection;
|
|
1883
|
+
if (changed)
|
|
1884
|
+
func_js.call(onSelect, selection);
|
|
1885
|
+
ev.preventDefault();
|
|
1886
|
+
return false;
|
|
1887
|
+
};
|
|
1888
|
+
const dragEndListener = (ev) => {
|
|
1889
|
+
style.left = "-9999px";
|
|
1890
|
+
style.width = style.height = "0px";
|
|
1891
|
+
document.removeEventListener("mousemove", dragListener, false);
|
|
1892
|
+
document.removeEventListener("mouseup", dragEndListener, false);
|
|
1893
|
+
window.removeEventListener("blur", dragEndListener, false);
|
|
1894
|
+
if (scroll) {
|
|
1895
|
+
if (timer) {
|
|
1896
|
+
clearInterval(timer);
|
|
1897
|
+
timer = null;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
//restore container position
|
|
1901
|
+
if (originPos) {
|
|
1902
|
+
con.style.position = originPos;
|
|
1903
|
+
}
|
|
1904
|
+
func_js.each(selection, (t) => {
|
|
1905
|
+
func_js.each(selectingClassAry, (cls) => {
|
|
1906
|
+
t.classList.toggle(cls, false);
|
|
1907
|
+
});
|
|
1908
|
+
func_js.each(selectedClassAry, (cls) => {
|
|
1909
|
+
t.classList.toggle(cls, true);
|
|
1910
|
+
});
|
|
1911
|
+
t.classList.toggle(CLASS_SELECTING, false);
|
|
1912
|
+
t.classList.toggle(CLASS_SELECTED, true);
|
|
1913
|
+
});
|
|
1914
|
+
__classPrivateFieldSet(this, _Selectable__lastSelected, selection, "f");
|
|
1915
|
+
if (dragging)
|
|
1916
|
+
func_js.call(onEnd, selection);
|
|
1917
|
+
};
|
|
1918
|
+
document.addEventListener("mousemove", dragListener, false);
|
|
1919
|
+
document.addEventListener("mouseup", dragEndListener, false);
|
|
1920
|
+
window.addEventListener("blur", dragEndListener, false);
|
|
1921
|
+
e.preventDefault();
|
|
1922
|
+
return false;
|
|
1923
|
+
});
|
|
1924
|
+
};
|
|
1925
|
+
/**
|
|
1926
|
+
* Add a selector into the container
|
|
1927
|
+
* @param container css selector or html element
|
|
1928
|
+
* @param opts
|
|
1929
|
+
* @returns
|
|
1930
|
+
*/
|
|
1931
|
+
function newSelectable(container, opts) {
|
|
1932
|
+
return new Selectable(container, opts);
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
var version = "1.0.0";
|
|
1936
|
+
var repository = {
|
|
1937
|
+
type: "git",
|
|
1938
|
+
url: "https://github.com/holyhigh2/uii"
|
|
1939
|
+
};
|
|
1940
|
+
|
|
1941
|
+
// welcome info
|
|
1942
|
+
const welcome = globalThis.top
|
|
1943
|
+
? globalThis.top.welcome
|
|
1944
|
+
: globalThis.welcome;
|
|
1945
|
+
if (!welcome) {
|
|
1946
|
+
const ssAry = [];
|
|
1947
|
+
['102,227,255', '59,208,251', '67,180,255'].forEach((v, i) => {
|
|
1948
|
+
const cu = 'background:rgb(' + v + ');';
|
|
1949
|
+
if (i < 2) {
|
|
1950
|
+
ssAry[i] = ssAry[5 - 1 - i] = cu;
|
|
1951
|
+
}
|
|
1952
|
+
else {
|
|
1953
|
+
ssAry[i] = 'color:#fff;' + cu;
|
|
1954
|
+
}
|
|
1955
|
+
});
|
|
1956
|
+
console.info(`%c %c %c Uii - UI Interactions | v${version} %c %c `, ...ssAry, `💎 ${repository.url}`);
|
|
1957
|
+
if (globalThis.top) {
|
|
1958
|
+
globalThis.top.welcome = true;
|
|
1959
|
+
}
|
|
1960
|
+
else {
|
|
1961
|
+
globalThis.welcome = true;
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
const VERSION = version;
|
|
1965
|
+
var index = {
|
|
1966
|
+
VERSION: version,
|
|
1967
|
+
newSplittable,
|
|
1968
|
+
newResizable,
|
|
1969
|
+
newDraggable,
|
|
1970
|
+
newDroppable,
|
|
1971
|
+
newRotatable,
|
|
1972
|
+
newSelectable
|
|
1973
|
+
};
|
|
1974
|
+
|
|
1975
|
+
exports.CollisionDetector = CollisionDetector;
|
|
1976
|
+
exports.Draggable = Draggable;
|
|
1977
|
+
exports.Droppable = Droppable;
|
|
1978
|
+
exports.Resizable = Resizable;
|
|
1979
|
+
exports.Rotatable = Rotatable;
|
|
1980
|
+
exports.Selectable = Selectable;
|
|
1981
|
+
exports.Splittable = Splittable;
|
|
1982
|
+
exports.Uii = Uii;
|
|
1983
|
+
exports.VERSION = VERSION;
|
|
1984
|
+
exports["default"] = index;
|
|
1985
|
+
exports.newCollisionDetector = newCollisionDetector;
|
|
1986
|
+
exports.newDraggable = newDraggable;
|
|
1987
|
+
exports.newDroppable = newDroppable;
|
|
1988
|
+
exports.newResizable = newResizable;
|
|
1989
|
+
exports.newRotatable = newRotatable;
|
|
1990
|
+
exports.newSelectable = newSelectable;
|
|
1991
|
+
exports.newSplittable = newSplittable;
|
|
1992
|
+
|
|
1993
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1994
|
+
|
|
1995
|
+
}));
|