estreui 1.2.3 → 1.2.4
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/index.html +8 -1
- package/package.json +4 -4
- package/scripts/alienese.js +282 -275
- package/scripts/boot.js +107 -67
- package/scripts/doctre.js +330 -6
- package/scripts/estreU0EEOZ.js +25 -4
- package/scripts/estreUi-core.js +555 -0
- package/scripts/estreUi-dialog.js +511 -0
- package/scripts/estreUi-handles.js +7243 -0
- package/scripts/estreUi-interaction.js +1374 -0
- package/scripts/estreUi-main.js +1667 -0
- package/scripts/estreUi-notation.js +596 -0
- package/scripts/estreUi-pageManager.js +625 -0
- package/scripts/estreUi-pageModel.js +4317 -0
- package/scripts/modernism.js +44 -3
- package/serviceWorker.js +10 -3
- package/scripts/estreUi.js +0 -16337
|
@@ -0,0 +1,1374 @@
|
|
|
1
|
+
/*
|
|
2
|
+
EstreUI rimwork — Swipe / Draggable handlers
|
|
3
|
+
Part of the split from estreUi.js (roadmap #002 phase 2).
|
|
4
|
+
|
|
5
|
+
This file is loaded as a plain <script> tag and shares the global scope
|
|
6
|
+
with the other estreUi-*.js files. Load order matters: see index.html.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// MODULE: Interaction -- EstreSwipeHandler, EstreDraggableHandler
|
|
10
|
+
// ======================================================================
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Attachable swipe handler
|
|
14
|
+
*/
|
|
15
|
+
class EstreSwipeHandler {
|
|
16
|
+
|
|
17
|
+
// constants
|
|
18
|
+
static mouseTrigger = "mousedown";
|
|
19
|
+
static pointerTrigger = "pointerdown";
|
|
20
|
+
static touchTrigger = "touchstart";
|
|
21
|
+
|
|
22
|
+
static mouseUpTriggerSet = ["mouseup"];
|
|
23
|
+
static pointerUpTriggerSet = ["pointercancel", "pointerup"];
|
|
24
|
+
static touchUpTriggerSet = ["touchcancel", "touchend"];
|
|
25
|
+
|
|
26
|
+
static mouseHandleSet = ["mouseup", "mousemove"];
|
|
27
|
+
static pointerHandleSet = ["pointercancel", "pointerup", "pointermove"];
|
|
28
|
+
static touchHandleSet = ["touchcancel", "touchend", "touchmove"];
|
|
29
|
+
|
|
30
|
+
defaultThreshold = 80;//80px //20;//20px
|
|
31
|
+
|
|
32
|
+
// statics
|
|
33
|
+
static handlers = [];
|
|
34
|
+
static register(instance) { return this.handlers.push(instance) - 1; }
|
|
35
|
+
|
|
36
|
+
// open property
|
|
37
|
+
stopPropagation = false;
|
|
38
|
+
preventDefault = false;
|
|
39
|
+
|
|
40
|
+
preventDown = false;
|
|
41
|
+
preventCancel = false;
|
|
42
|
+
preventUp = false;
|
|
43
|
+
preventMove = false;
|
|
44
|
+
|
|
45
|
+
thresholdX = -1;
|
|
46
|
+
thresholdY = -1;
|
|
47
|
+
|
|
48
|
+
dropStrayed = false;
|
|
49
|
+
|
|
50
|
+
onDown = null;
|
|
51
|
+
onMove = null;
|
|
52
|
+
onCancel = null;
|
|
53
|
+
onUp = null;
|
|
54
|
+
|
|
55
|
+
isDebug = false;
|
|
56
|
+
debugDisplay = null;
|
|
57
|
+
|
|
58
|
+
cancelDelay = 200;
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
// enclosed property
|
|
62
|
+
#handleIndex = null;
|
|
63
|
+
#handleId = null;
|
|
64
|
+
|
|
65
|
+
#bound = null;
|
|
66
|
+
#$bound = null;
|
|
67
|
+
#data = null;
|
|
68
|
+
#$responseBound = null;
|
|
69
|
+
#$outerBound = null;
|
|
70
|
+
|
|
71
|
+
#triggerEventAllowed = new Set();
|
|
72
|
+
#triggerUpEventAllowed = new Set();
|
|
73
|
+
#handleEventAllowed = new Set();
|
|
74
|
+
|
|
75
|
+
#isMoving = false;
|
|
76
|
+
#eventOrigin = null;
|
|
77
|
+
#directed = null;
|
|
78
|
+
|
|
79
|
+
#startX = null;
|
|
80
|
+
#startY = null;
|
|
81
|
+
|
|
82
|
+
#shiftX = null;
|
|
83
|
+
#shiftY = null;
|
|
84
|
+
|
|
85
|
+
#lastX = null;
|
|
86
|
+
#lastY = null;
|
|
87
|
+
|
|
88
|
+
#grabX = null;
|
|
89
|
+
#grabY = null;
|
|
90
|
+
|
|
91
|
+
#pointerType = null;
|
|
92
|
+
#eventType = null;
|
|
93
|
+
|
|
94
|
+
#grabMarker = null;
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
// getter and setter
|
|
98
|
+
#$wind = $(window);
|
|
99
|
+
get $wind() { return this.#$wind }
|
|
100
|
+
|
|
101
|
+
get allowedDirection() { return this.allowedDirectionX ? (this.allowedDirectionY ? "both": "horizontal") : (this.allowedDirectionY ? "vertical" : "neither"); }
|
|
102
|
+
get allowedDirectionX() { return this.thresholdX > -1; }
|
|
103
|
+
get allowedDirectionY() { return this.thresholdY > -1; }
|
|
104
|
+
get directionFix() { return this.directionFixX ? (this.directionFixY ? "both" : "horizontal") : (this.directionFixY ? "vertical" : "neither"); }
|
|
105
|
+
get directionFixX() { return this.thresholdX > 0; }
|
|
106
|
+
get directionFixY() { return this.thresholdY > 0; }
|
|
107
|
+
get directtion() { return this.grabX > this.grabY ? this.directionX : this.directionY; }
|
|
108
|
+
get directionX() { return this.grabX < 0 ? "left" : (this.grabX > 0 ? "right" : null); }
|
|
109
|
+
get directionY() { return this.grabY < 0 ? "up" : (this.grabY > 0 ? "down" : null); }
|
|
110
|
+
get handledDirection() {
|
|
111
|
+
if (this.isMoving) switch (this.directionFix) {
|
|
112
|
+
case "both":
|
|
113
|
+
if (this.directed != null) {
|
|
114
|
+
const moveX = this.moveX;
|
|
115
|
+
const moveY = this.moveY;
|
|
116
|
+
if (moveX > moveY) {
|
|
117
|
+
if (this.exceedX && moveX - moveY > this.thresholdX) return this.directionX;
|
|
118
|
+
} else if (moveX < moveY) {
|
|
119
|
+
if (this.exceedY && moveY - moveX > this.thresholdY) return this.directionY;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
case "horizontal":
|
|
124
|
+
if (this.directed == "horizontal" && this.exceedX) return this.directionX;
|
|
125
|
+
|
|
126
|
+
case "vertical":
|
|
127
|
+
if (this.directed == "vertical" && this.exceedY) return this.directionY;
|
|
128
|
+
|
|
129
|
+
case "neither":
|
|
130
|
+
if (this.allowedDirectionX && this.grabX != null) return this.directionX;
|
|
131
|
+
if (this.allowedDirectionY && this.grabY != null) return this.directionY;
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
get handled() {
|
|
136
|
+
if (!this.isMoving) return false;
|
|
137
|
+
else {
|
|
138
|
+
switch (this.directionFix) {
|
|
139
|
+
case "both":
|
|
140
|
+
return this.directed != null && (this.exceedX || this.exceedY);
|
|
141
|
+
|
|
142
|
+
case "horizontal":
|
|
143
|
+
return this.directed == "horizontal" && this.exceedX;
|
|
144
|
+
|
|
145
|
+
case "vertical":
|
|
146
|
+
return this.directed == "vertical" && this.exceedY;
|
|
147
|
+
|
|
148
|
+
case "neither":
|
|
149
|
+
return (this.allowedDirectionX && this.grabX != null) || (this.allowedDirectionY && this.grabY != null);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
get moveX() { return Math.abs(this.lastX - this.startX); }
|
|
154
|
+
get moveY() { return Math.abs(this.lastY - this.startY); }
|
|
155
|
+
get exceedX() { return this.directionFixX && this.moveX > this.thresholdX; }
|
|
156
|
+
get exceedY() { return this.directionFixY && this.moveY > this.thresholdY; }
|
|
157
|
+
get strayedX() { return this.directionFixX && this.moveY > this.thresholdX * 2; }
|
|
158
|
+
get strayedY() { return this.directionFixY && this.moveX > this.thresholdY * 2; }
|
|
159
|
+
|
|
160
|
+
get #triggers() { return Array.from(this.#triggerEventAllowed).join(" "); }
|
|
161
|
+
get #upTriggers() { return Array.from(this.#triggerUpEventAllowed).join(" "); }
|
|
162
|
+
get #upDownTriggers() { return [...Array.from(this.#triggerEventAllowed), ...Array.from(this.#triggerUpEventAllowed)].join(" "); }
|
|
163
|
+
get #handles() { return Array.from(this.#handleEventAllowed).join(" "); }
|
|
164
|
+
get #events() { return [...Array.from(this.#triggerEventAllowed), ...Array.from(this.#triggerUpEventAllowed), ...Array.from(this.#handleEventAllowed)].join(" "); }
|
|
165
|
+
|
|
166
|
+
get isMoving() { return this.#isMoving; }
|
|
167
|
+
get eventOrigin() { return this.#eventOrigin; }
|
|
168
|
+
get directed() { return this.#directed; }
|
|
169
|
+
get startX() { return this.#startX; }
|
|
170
|
+
get startY() { return this.#startY; }
|
|
171
|
+
get shiftX() { return this.#shiftX; }
|
|
172
|
+
get shiftY() { return this.#shiftY; }
|
|
173
|
+
get lastX() { return this.#lastX; }
|
|
174
|
+
get lastY() { return this.#lastY; }
|
|
175
|
+
get grabX() { return this.#grabX; }
|
|
176
|
+
get grabY() { return this.#grabY; }
|
|
177
|
+
get pointerType() { return this.#pointerType; }
|
|
178
|
+
get eventType() { return this.#eventType; }
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Set swipe handler for element
|
|
183
|
+
*
|
|
184
|
+
* if need stopPropagation or preventDefault to be set each property.
|
|
185
|
+
* and custom event callbacks to be set methods.
|
|
186
|
+
*
|
|
187
|
+
* @param {Element} element is target element
|
|
188
|
+
* @param {boolean} [onMouse=true] allow mouse handle (must be allowed one in three options)
|
|
189
|
+
* @param {boolean} [onPointer=true] allow pointer handle (must be allowed one in three options)
|
|
190
|
+
* @param {boolean} [onTouch=true] allow touch handle (must be allowed one in three options)
|
|
191
|
+
* @param {number} [thresholdX=this.defaultThreshold] fix direction threshold px - 0 = unuse direction fix, -1 = unallowed horizontal swipe
|
|
192
|
+
* @param {number} [thresholdY=this.defaultThreshold] fix direction threshold px - 0 = unuse direction fix, -1 = unallowed vertical swipe
|
|
193
|
+
* @param {boolean} [debug=false] show event triggers and values when true
|
|
194
|
+
*/
|
|
195
|
+
constructor (element, onMouse = true, onPointer = true, onTouch = true, thresholdX = this.defaultThreshold, thresholdY = this.defaultThreshold, debug = false) {
|
|
196
|
+
this.#setHandleId();
|
|
197
|
+
|
|
198
|
+
this.isDebug = debug;
|
|
199
|
+
|
|
200
|
+
this.setEventMouse(onMouse, false);
|
|
201
|
+
this.setEventPointer(onPointer, false);
|
|
202
|
+
this.setEventTouch(onTouch, false);
|
|
203
|
+
|
|
204
|
+
this.setThresholdX(thresholdX);
|
|
205
|
+
this.setThresholdY(thresholdY);
|
|
206
|
+
|
|
207
|
+
this.setDropStrayed();
|
|
208
|
+
|
|
209
|
+
this.setElement(element);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
#setHandleId() {
|
|
213
|
+
this.#handleIndex = EstreSwipeHandler.register(this);
|
|
214
|
+
this.#handleId = this.constructor.name + "@" + Date.now() + "#" + this.#handleIndex;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
#dropHandle() {
|
|
218
|
+
setTimeout(_ => this.$wind.attr(eds.onSwipe, null), 0);
|
|
219
|
+
//this.#$outerBound.off(this.#upTriggers, null, this.#onClick);
|
|
220
|
+
this.#$bound.off(this.#handles, null, this.#onEvent);
|
|
221
|
+
this.$wind.off(this.#handles, null, this.#onEvent);
|
|
222
|
+
this.#isMoving = false;
|
|
223
|
+
this.#directed = null;
|
|
224
|
+
this.#startX = null;
|
|
225
|
+
this.#startY = null;
|
|
226
|
+
this.#shiftX = null;
|
|
227
|
+
this.#shiftY = null;
|
|
228
|
+
this.#lastX = null;
|
|
229
|
+
this.#lastY = null;
|
|
230
|
+
this.#grabX = null;
|
|
231
|
+
this.#grabY = null;
|
|
232
|
+
this.#pointerType = null;
|
|
233
|
+
this.#eventType = null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
#clearBound() {
|
|
237
|
+
this.#$responseBound.css("--grab-x", "0px");
|
|
238
|
+
this.#$responseBound.css("--grab-y", "0px");
|
|
239
|
+
this.#$responseBound.attr(eds.onGrab, "");
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
release() {
|
|
243
|
+
this.#dropHandle();
|
|
244
|
+
this.#clearBound();
|
|
245
|
+
this.#$responseBound = null;
|
|
246
|
+
//this.#$outerBound.off(this.#triggers, null, this.#onClick);
|
|
247
|
+
this.#$outerBound = null;
|
|
248
|
+
const $blockTarget = this.#$bound.find(uis.blockSwipe);
|
|
249
|
+
$blockTarget.off(this.#events, this.#onBlock);
|
|
250
|
+
this.#$bound.css("user-select", "");
|
|
251
|
+
this.#$bound.off("click", null, this.#onClick);
|
|
252
|
+
//this.#$bound.off(this.#handles, null, this.#onHandle);
|
|
253
|
+
this.#$bound = null;
|
|
254
|
+
if (this.#bound.swipeHandler == this) delete this.#bound.swipeHandler;
|
|
255
|
+
this.#bound = null;
|
|
256
|
+
this.#data = null;
|
|
257
|
+
delete EstreSwipeHandler.handlers[this.#handleIndex];
|
|
258
|
+
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
setEventMouse(enable = true, byUser = true) {
|
|
264
|
+
if (enable) {
|
|
265
|
+
this.#triggerEventAllowed.add(EstreSwipeHandler.mouseTrigger);
|
|
266
|
+
EstreSwipeHandler.mouseUpTriggerSet.forEach(item => this.#triggerUpEventAllowed.add(item));
|
|
267
|
+
EstreSwipeHandler.mouseHandleSet.forEach(item => this.#handleEventAllowed.add(item));
|
|
268
|
+
} else {
|
|
269
|
+
this.#triggerEventAllowed.delete(EstreSwipeHandler.mouseTrigger);
|
|
270
|
+
EstreSwipeHandler.mouseUpTriggerSet.forEach(item => this.#handleEventAllowed.delete(item));
|
|
271
|
+
EstreSwipeHandler.mouseHandleSet.forEach(item => this.#handleEventAllowed.delete(item));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (byUser) this.setElement();
|
|
275
|
+
|
|
276
|
+
return this;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
setEventPointer(enable = true, byUser = true) {
|
|
280
|
+
if (enable) {
|
|
281
|
+
this.#triggerEventAllowed.add(EstreSwipeHandler.pointerTrigger);
|
|
282
|
+
EstreSwipeHandler.pointerUpTriggerSet.forEach(item => this.#triggerUpEventAllowed.add(item));
|
|
283
|
+
EstreSwipeHandler.pointerHandleSet.forEach(item => this.#handleEventAllowed.add(item));
|
|
284
|
+
} else {
|
|
285
|
+
this.#triggerEventAllowed.delete(EstreSwipeHandler.pointerTrigger);
|
|
286
|
+
EstreSwipeHandler.pointerUpTriggerSet.forEach(item => this.#triggerUpEventAllowed.delete(item));
|
|
287
|
+
EstreSwipeHandler.pointerHandleSet.forEach(item => this.#handleEventAllowed.delete(item));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (byUser) this.setElement();
|
|
291
|
+
|
|
292
|
+
return this;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
setEventTouch(enable = true, byUser = true) {
|
|
296
|
+
if (enable) {
|
|
297
|
+
this.#triggerEventAllowed.add(EstreSwipeHandler.touchTrigger);
|
|
298
|
+
EstreSwipeHandler.touchUpTriggerSet.forEach(item => this.#triggerUpEventAllowed.add(item));
|
|
299
|
+
EstreSwipeHandler.touchHandleSet.forEach(item => this.#handleEventAllowed.add(item));
|
|
300
|
+
} else {
|
|
301
|
+
this.#triggerEventAllowed.delete(EstreSwipeHandler.touchTrigger);
|
|
302
|
+
EstreSwipeHandler.touchUpTriggerSet.forEach(item => this.#triggerUpEventAllowed.delete(item));
|
|
303
|
+
EstreSwipeHandler.touchHandleSet.forEach(item => this.#handleEventAllowed.delete(item));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (byUser) this.setElement();
|
|
307
|
+
|
|
308
|
+
return this;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
setThresholdX(threshold = this.thresholdX) {
|
|
313
|
+
this.thresholdX = threshold;
|
|
314
|
+
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
setThresholdY(threshold = this.thresholdY) {
|
|
319
|
+
this.thresholdY = threshold;
|
|
320
|
+
|
|
321
|
+
return this;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
unuseDirectionFixX() {
|
|
325
|
+
this.thresholdX = 0;
|
|
326
|
+
|
|
327
|
+
return this;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
unuseDriectionFixY() {
|
|
331
|
+
this.thresholdY = 0;
|
|
332
|
+
|
|
333
|
+
return this;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
unuseX() {
|
|
337
|
+
this.thresholdX = -1;
|
|
338
|
+
|
|
339
|
+
return this;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
unuseY() {
|
|
343
|
+
this.thresholdY = -1;
|
|
344
|
+
|
|
345
|
+
return this;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
setDropStrayed(enable = true) {
|
|
350
|
+
this.dropStrayed = enable;
|
|
351
|
+
|
|
352
|
+
return this;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
//custom setters
|
|
357
|
+
setResponseBound(bound = this.#$bound) {
|
|
358
|
+
this.#$responseBound = bound instanceof jQuery ? bound : $(bound);
|
|
359
|
+
return this;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
setOuterBound(bound = this.#$bound.parent()) {
|
|
363
|
+
//if (this.#$outerBound != null) this.#$outerBound.off(this.#triggers, null, this.#onClick);
|
|
364
|
+
this.#$outerBound = bound instanceof jQuery ? bound : $(bound);
|
|
365
|
+
//bound.on(this.#triggers, null, this.#onClick);
|
|
366
|
+
return this;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
setStopPropagation(enable = true) {
|
|
370
|
+
this.stopPropagation = enable;
|
|
371
|
+
return this;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
setPreventDefault(enable = true) {
|
|
375
|
+
this.preventDefault = enable;
|
|
376
|
+
return this;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
setPreventDown(enable = true) {
|
|
380
|
+
this.preventDown = enable;
|
|
381
|
+
return this;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
setPreventCancel(enable = true) {
|
|
385
|
+
this.preventCancel = enable;
|
|
386
|
+
return this;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
setPreventUp(enable = true) {
|
|
390
|
+
this.preventUp = enable;
|
|
391
|
+
return this;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
setPreventMove(enable = true) {
|
|
395
|
+
this.preventMove = enable;
|
|
396
|
+
return this;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
setPreventAll(enable = true) {
|
|
400
|
+
return this.setPreventDown(enable).setPreventUp(enable).setPreventCancel(enable).setPreventMove(enable);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
setDebug(enable = true) {
|
|
404
|
+
this.isDebug = enable;
|
|
405
|
+
return this;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
setDebugDisplay(element = null) {
|
|
409
|
+
this.debugDisplay = element;
|
|
410
|
+
return this;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
setCancelDelay(delay = 200) {
|
|
414
|
+
this.cancelDelay = delay;
|
|
415
|
+
return this;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
setOnDown(callback) {
|
|
420
|
+
this.onDown = callback;
|
|
421
|
+
|
|
422
|
+
return this;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
setOnMove(callback) {
|
|
426
|
+
this.onMove = callback;
|
|
427
|
+
|
|
428
|
+
return this;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
setOnCancel(callback) {
|
|
432
|
+
this.onCancel = callback;
|
|
433
|
+
|
|
434
|
+
return this;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
setOnUp(callback) {
|
|
438
|
+
this.onUp = callback;
|
|
439
|
+
|
|
440
|
+
return this;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
//---
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
#onEvent = (e) => {
|
|
447
|
+
const isSelf = e.target == e.delegateTarget;
|
|
448
|
+
var isBlocked = false;
|
|
449
|
+
var curElem = e.target;
|
|
450
|
+
if (!isSelf) do {
|
|
451
|
+
const $curElem = $(curElem);
|
|
452
|
+
if ($curElem.is(uis.allowSwipe)) break;
|
|
453
|
+
else if ($curElem.is(uis.blockSwipe)) {
|
|
454
|
+
isBlocked = true;
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
curElem = curElem.parentElement;
|
|
458
|
+
} while (curElem != document.body && curElem != e.delegateTarget);
|
|
459
|
+
if (isBlocked) return;
|
|
460
|
+
|
|
461
|
+
const isTouch = e.type.indexOf("touch") > -1;
|
|
462
|
+
const isMouse = e.type.indexOf("mouse") > -1;
|
|
463
|
+
const isPointer = e.type.indexOf("pointer") > -1;
|
|
464
|
+
const screenX = isTouch ? (e.touches.length > 0 ? e.touches[0].screenX : null) : e.screenX;
|
|
465
|
+
const screenY = isTouch ? (e.touches.length > 0 ? e.touches[0].screenY : null) : e.screenY;
|
|
466
|
+
const pointerType = isTouch ? "touch" : (isMouse ? "mouse" : (isPointer ? "pointer" : "extra"));
|
|
467
|
+
|
|
468
|
+
var canceled = false;
|
|
469
|
+
switch(e.type) {
|
|
470
|
+
case "pointerdown":
|
|
471
|
+
break;
|
|
472
|
+
case "mousedown":
|
|
473
|
+
if (isMouse && e.button !== 0) break;
|
|
474
|
+
case "touchstart":
|
|
475
|
+
if (this.isMoving) {
|
|
476
|
+
if (this.preventDown) {
|
|
477
|
+
if (this.preventDefault) e.preventDefault();
|
|
478
|
+
if (this.stopPropagation) e.stopPropagation();
|
|
479
|
+
if (this.preventDefault) return false;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
this.#eventType = "down";
|
|
483
|
+
this.#isMoving = true;
|
|
484
|
+
this.#eventOrigin = e.target;
|
|
485
|
+
this.#pointerType = pointerType;
|
|
486
|
+
this.#lastX = screenX;
|
|
487
|
+
this.#lastY = screenY;
|
|
488
|
+
if (this.shiftX == null) this.#shiftX = 0;
|
|
489
|
+
if (this.shiftY == null) this.#shiftY = 0;
|
|
490
|
+
|
|
491
|
+
if (this.startX != null) {
|
|
492
|
+
this.#shiftX += screenX - this.startX;
|
|
493
|
+
if (this.grabX != null) this.#grabX = this.shiftX;
|
|
494
|
+
} else this.#startX = screenX;
|
|
495
|
+
if (this.startY != null) {
|
|
496
|
+
this.#shiftY += screenY - this.startY;
|
|
497
|
+
if (this.grabY != null) this.grabY = this.shiftY;
|
|
498
|
+
} else this.#startY = screenY;
|
|
499
|
+
|
|
500
|
+
if (this.isDebug) {
|
|
501
|
+
var log = "start: " + f4f(this.startX) + ", " + f4f(this.startY) + " / shift: " + f4f(this.shiftX) + ", " + f4f(this.shiftY) + " / last: " + f4f(this.lastX) + ", " + f4f(this.lastY) + " / grab: " + f4f(grabX) + ", " + f4f(grabY);
|
|
502
|
+
console.log(e.type + " - " + log);
|
|
503
|
+
if (this.debugDisplay != null) this.debugDisplay.prepend(e.type + " - " + log + "<br />");
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
this.#$responseBound.css("--grab-x", this.shiftX + "px");
|
|
507
|
+
this.#$responseBound.css("--grab-y", this.shiftY + "px");
|
|
508
|
+
if (this.onDown != null) this.onDown(this.startX, this.startY);
|
|
509
|
+
this.$wind.on(this.#handles, null, this.#onEvent);
|
|
510
|
+
this.#$bound.on(this.#handles, null, this.#onEvent);
|
|
511
|
+
//this.#$outerBound.on(this.#upTriggers, null, this.#onClick);
|
|
512
|
+
//$(this.eventOrigin).on("click", null, this.#onClick);
|
|
513
|
+
if (this.preventDown) {
|
|
514
|
+
if (this.preventDefault) e.preventDefault();
|
|
515
|
+
if (this.stopPropagation) e.stopPropagation();
|
|
516
|
+
if (this.preventDefault) return false;
|
|
517
|
+
}
|
|
518
|
+
break;
|
|
519
|
+
|
|
520
|
+
case "pointercancel":
|
|
521
|
+
case "touchcancel":
|
|
522
|
+
if (!this.isMoving) break;
|
|
523
|
+
if (this.#pointerType != pointerType || this.eventType == "cancel") {
|
|
524
|
+
if (this.handled) {
|
|
525
|
+
if (this.preventCancel) {
|
|
526
|
+
if (this.preventDefault) e.preventDefault();
|
|
527
|
+
if (this.stopPropagation) e.stopPropagation();
|
|
528
|
+
if (this.preventDefault) return false;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
canceled = true;
|
|
534
|
+
this.#eventType = "cancel";
|
|
535
|
+
if (this.isDebug) console.log("canceled");
|
|
536
|
+
if (this.onCancel != null) this.onCancel();
|
|
537
|
+
case "pointerup":
|
|
538
|
+
case "mouseup":
|
|
539
|
+
case "touchend":
|
|
540
|
+
if (!this.isMoving) break;
|
|
541
|
+
if (this.eventType == "up") {
|
|
542
|
+
if (this.handled) {
|
|
543
|
+
if (this.preventUp) {
|
|
544
|
+
if (this.preventDefault) e.preventDefault();
|
|
545
|
+
if (this.stopPropagation) e.stopPropagation();
|
|
546
|
+
if (this.preventDefault) return false;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
if (!canceled) {
|
|
552
|
+
if (this.#pointerType != pointerType) {
|
|
553
|
+
if (this.handled) {
|
|
554
|
+
if (this.preventUp) {
|
|
555
|
+
if (this.preventDefault) e.preventDefault();
|
|
556
|
+
if (this.stopPropagation) e.stopPropagation();
|
|
557
|
+
if (this.preventDefault) return false;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
this.#eventType = "up";
|
|
563
|
+
}
|
|
564
|
+
if (this.isDebug) {
|
|
565
|
+
var log = "directed: " + this.directed + ", start: " + f4f(this.startX) + ", " + f4f(this.startY) + " / shift: " + f4f(this.shiftX) + ", " + f4f(this.shiftY) + " / last: " + f4f(this.lastX) + ", " + f4f(this.lastY) + " / grab: " + f4f(this.grabX) + ", " + f4f(this.grabY);
|
|
566
|
+
console.log(e.type + " - " + log);
|
|
567
|
+
if (this.debugDisplay != null) this.debugDisplay.prepend(e.type + " - " + log + "<br />");
|
|
568
|
+
}
|
|
569
|
+
const clear = () => {
|
|
570
|
+
const grabX = this.#lastX - this.startX + this.#shiftX;
|
|
571
|
+
const grabY = this.#lastY - this.startY + this.#shiftY;
|
|
572
|
+
if (this.isDebug) {
|
|
573
|
+
var log = "directed: " + this.directed + ", start: " + f4f(this.startX) + ", " + f4f(this.startY) + " / shift: " + f4f(this.shiftX) + ", " + f4f(this.shiftY) + " / last: " + f4f(this.lastX) + ", " + f4f(this.lastY) + " / grab: " + f4f(grabX) + ", " + f4f(grabY);
|
|
574
|
+
console.log(e.type + " delayed - " + log);
|
|
575
|
+
if (this.debugDisplay != null) this.debugDisplay.prepend(e.type + " delayed - " + log + "<br />");
|
|
576
|
+
}
|
|
577
|
+
const handled = this.handled;
|
|
578
|
+
var onClearBound = null;
|
|
579
|
+
if (this.onUp != null) onClearBound = this.onUp(grabX, grabY, handled, canceled, this.directed);
|
|
580
|
+
this.#dropHandle();
|
|
581
|
+
if (onClearBound == null) this.#clearBound();
|
|
582
|
+
else if (onClearBound.delay == null) {
|
|
583
|
+
this.#clearBound();
|
|
584
|
+
if (onClearBound.callback != null) onClearBound.callback();
|
|
585
|
+
} else setTimeout(_ => {
|
|
586
|
+
this.#clearBound();
|
|
587
|
+
if (onClearBound.callback != null) onClearBound.callback();
|
|
588
|
+
}, onClearBound.delay);
|
|
589
|
+
if (this.isDebug) {
|
|
590
|
+
console.log("cleared" + (handled ? " with handled" : ""));
|
|
591
|
+
if (this.debugDisplay != null) this.debugDisplay.prepend("cleared<br/>");
|
|
592
|
+
}
|
|
593
|
+
//$(this.eventOrigin).off("click", null, this.#onClick);
|
|
594
|
+
//if (!handled && this.eventOrigin != null) this.eventOrigin.click();
|
|
595
|
+
this.#eventOrigin = null;
|
|
596
|
+
return handled;
|
|
597
|
+
};
|
|
598
|
+
var handled = true;
|
|
599
|
+
if (canceled) setTimeout(_ => { clear(); }, this.cancelDelay);
|
|
600
|
+
else handled = clear();
|
|
601
|
+
if (handled) {
|
|
602
|
+
if (this.preventUp) {
|
|
603
|
+
if (this.preventDefault) e.preventDefault();
|
|
604
|
+
if (this.stopPropagation) e.stopPropagation();
|
|
605
|
+
//if (!canceled && !handled && this.eventOrigin != null) this.eventOrigin.click();
|
|
606
|
+
if (this.preventDefault) return false;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
break;
|
|
610
|
+
|
|
611
|
+
case "pointermove":
|
|
612
|
+
case "mousemove":
|
|
613
|
+
case "touchmove":
|
|
614
|
+
if (this.#bound != null) {
|
|
615
|
+
if (this.preventMove && this.stopPropagation) e.stopPropagation();
|
|
616
|
+
if (this.pointerType != pointerType) {
|
|
617
|
+
if (this.preventMove && this.preventDefault) {
|
|
618
|
+
e.preventDefault();
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
623
|
+
this.#eventType = "move";
|
|
624
|
+
this.#lastX = screenX;
|
|
625
|
+
this.#lastY = screenY;
|
|
626
|
+
const allowedX = this.allowedDirectionX;
|
|
627
|
+
const allowedY = this.allowedDirectionY;
|
|
628
|
+
var grabX = 0;
|
|
629
|
+
var grabY = 0;
|
|
630
|
+
if (allowedX) grabX = screenX - this.startX + this.shiftX;
|
|
631
|
+
if (allowedY) grabY = screenY - this.startY + this.shiftY;
|
|
632
|
+
const moveX = this.moveX;
|
|
633
|
+
const moveY = this.moveY;
|
|
634
|
+
const exceedX = moveX > this.thresholdX;
|
|
635
|
+
const exceedY = moveY > this.thresholdY;
|
|
636
|
+
const strayedX = moveY > this.thresholdX * 2;
|
|
637
|
+
const strayedY = moveX > this.thresholdY * 2;
|
|
638
|
+
var handled = false;
|
|
639
|
+
var applyX = false;
|
|
640
|
+
var applyY = false;
|
|
641
|
+
var fixX = false;
|
|
642
|
+
var fixY = false;
|
|
643
|
+
var dropped = false;
|
|
644
|
+
switch (this.directionFix) {
|
|
645
|
+
case "both":
|
|
646
|
+
if (this.directed != null) {
|
|
647
|
+
handled = true;
|
|
648
|
+
switch (this.directed) {
|
|
649
|
+
case "horizontal":
|
|
650
|
+
applyX = true;
|
|
651
|
+
break;
|
|
652
|
+
|
|
653
|
+
case "vertical":
|
|
654
|
+
applyY = true;
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
} else if (exceedX || exceedY) {
|
|
658
|
+
handled = true;
|
|
659
|
+
if (exceedX) {
|
|
660
|
+
applyX = true;
|
|
661
|
+
fixX = true;
|
|
662
|
+
} else if (exceedY) {
|
|
663
|
+
applyY = true;
|
|
664
|
+
fixY = true;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
break;
|
|
668
|
+
|
|
669
|
+
case "horizontal":
|
|
670
|
+
if (this.directed == "horizontal") {
|
|
671
|
+
handled = true;
|
|
672
|
+
applyX = true;
|
|
673
|
+
} else if (this.dropStrayed && strayedX) {
|
|
674
|
+
dropped = true;
|
|
675
|
+
} else if (exceedX) {
|
|
676
|
+
handled = true;
|
|
677
|
+
applyX = true;
|
|
678
|
+
fixX = true;
|
|
679
|
+
}
|
|
680
|
+
break;
|
|
681
|
+
|
|
682
|
+
case "vertical":
|
|
683
|
+
if (this.directed == "vertical") {
|
|
684
|
+
handled = true;
|
|
685
|
+
applyY = true;
|
|
686
|
+
} else if (this.dropStrayed && strayedY) {
|
|
687
|
+
dropped = true;
|
|
688
|
+
} else if (exceedY) {
|
|
689
|
+
handled = true;
|
|
690
|
+
applyY = true;
|
|
691
|
+
fixY = true;
|
|
692
|
+
}
|
|
693
|
+
break;
|
|
694
|
+
|
|
695
|
+
case "neither":
|
|
696
|
+
if (allowedX || allowedY) {
|
|
697
|
+
handled = true;
|
|
698
|
+
if (allowedX) applyX = true;
|
|
699
|
+
if (allowedY) applyY = true;
|
|
700
|
+
} else if (!allowedX && !allowedY) {
|
|
701
|
+
dropped = true;
|
|
702
|
+
}
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
const onSwipe = handled ? t1 : "";
|
|
707
|
+
if (this.$wind.attr(eds.onSwipe) != onSwipe) this.$wind.attr(eds.onSwipe, onSwipe);
|
|
708
|
+
if (handled) {
|
|
709
|
+
if (applyX) {
|
|
710
|
+
this.#grabX = grabX;
|
|
711
|
+
this.#$responseBound.css("--grab-x", grabX + "px");
|
|
712
|
+
}
|
|
713
|
+
if (applyY) {
|
|
714
|
+
this.#grabY = grabY;
|
|
715
|
+
this.#$responseBound.css("--grab-y", grabY + "px");
|
|
716
|
+
}
|
|
717
|
+
if (fixX) this.#directed = "horizontal";
|
|
718
|
+
if (fixY) this.#directed = "vertical";
|
|
719
|
+
}
|
|
720
|
+
if (this.isDebug) {
|
|
721
|
+
var log = "directed: " + this.directed + ", start: " + f4f(this.startX) + ", " + f4f(this.startY) + " / shift: " + f4f(this.shiftX) + ", " + f4f(this.shiftY) + " / last: " + f4f(this.lastX) + ", " + f4f(this.lastY) + " / grab: " + f4f(grabX) + ", " + f4f(grabY);
|
|
722
|
+
console.log(e.type + " - " + log);
|
|
723
|
+
if (this.debugDisplay != null) this.debugDisplay.prepend(e.type + " - " + log + "<br />");
|
|
724
|
+
}
|
|
725
|
+
if (this.onMove != null) this.onMove(grabX, grabY, handled, dropped, this.directed);
|
|
726
|
+
if (dropped) {
|
|
727
|
+
if (this.isDebug) console.log("dropped");
|
|
728
|
+
this.#dropHandle();
|
|
729
|
+
this.#clearBound();
|
|
730
|
+
//$(this.eventOrigin).off("click", null, this.#onClick);
|
|
731
|
+
//if (!handled && this.eventOrigin != null) this.eventOrigin.click();
|
|
732
|
+
this.#eventOrigin = null;
|
|
733
|
+
} else if (handled) {
|
|
734
|
+
if (this.isDebug) console.log("handled");
|
|
735
|
+
if (this.#grabMarker == null) this.#grabMarker = setTimeout(_ => {
|
|
736
|
+
if (this.handled && this.#$responseBound.attr(eds.onGrab) != t1) {
|
|
737
|
+
this.#$responseBound.attr(eds.onGrab, t1);
|
|
738
|
+
}
|
|
739
|
+
this.#grabMarker = null;
|
|
740
|
+
}, 0);
|
|
741
|
+
if (this.preventMove) {
|
|
742
|
+
if (this.preventDefault) e.preventDefault();
|
|
743
|
+
if (this.stopPropagation) e.stopPropagation();
|
|
744
|
+
if (this.preventDefault) return false;
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
if (this.isDebug) console.log("ignored");
|
|
748
|
+
this.#clearBound();
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
break;
|
|
752
|
+
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
#onHandle = (e) => {
|
|
757
|
+
if (this.handled) {
|
|
758
|
+
e.preventDefault();
|
|
759
|
+
e.stopPropagation();
|
|
760
|
+
return false;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
#onClick = (e) => {
|
|
765
|
+
//e.preventDefault();
|
|
766
|
+
e.stopPropagation();
|
|
767
|
+
//return false;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
#onBlock = (e) => {
|
|
771
|
+
e.preventDefault();
|
|
772
|
+
e.stopPropagation();
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
setElement(element = this.element) {
|
|
777
|
+
const $responseBound = this.#$responseBound;
|
|
778
|
+
const $outerBound = this.#$outerBound;
|
|
779
|
+
if (this.#bound != null) this.release();
|
|
780
|
+
if (element instanceof jQuery) {
|
|
781
|
+
this.#$bound = element;
|
|
782
|
+
this.#bound = element[0];
|
|
783
|
+
} else {
|
|
784
|
+
this.#bound = element;
|
|
785
|
+
this.#$bound = $(element);
|
|
786
|
+
}
|
|
787
|
+
this.#data = this.#bound.dataset;
|
|
788
|
+
this.#bound.swipeHandler = this;
|
|
789
|
+
|
|
790
|
+
this.#$bound.on(this.#triggers, null, this.#onEvent);
|
|
791
|
+
//this.#$bound.on(this.#handles, null, this.#onHandle);
|
|
792
|
+
this.#$bound.on("click", null, this.#onClick);
|
|
793
|
+
this.#$bound.css("user-select", "none");
|
|
794
|
+
|
|
795
|
+
this.#$responseBound = $responseBound != null ? $responseBound : this.#$bound;
|
|
796
|
+
if ($outerBound != null) this.setOuterBound($outerBound);
|
|
797
|
+
|
|
798
|
+
const $blockTarget = this.#$bound.find(uis.blockSwipe);
|
|
799
|
+
$blockTarget.on(this.#events, this.#onBlock);
|
|
800
|
+
|
|
801
|
+
return this;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
class EstreDraggableHandler {
|
|
809
|
+
|
|
810
|
+
// enclosed property
|
|
811
|
+
#isEnabledTouch = f;
|
|
812
|
+
|
|
813
|
+
// open property
|
|
814
|
+
$bound;
|
|
815
|
+
bound;
|
|
816
|
+
|
|
817
|
+
draggableAxis = "vertical"; // "both", "horizontal", "vertical"
|
|
818
|
+
// currently supports only vertical
|
|
819
|
+
|
|
820
|
+
useTouchSupport = n; // null is auto
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
// getter and setter
|
|
824
|
+
get isTouchSupported() { return "ontouchstart" in window ||
|
|
825
|
+
navigator.maxTouchPoints > 0 ||
|
|
826
|
+
navigator.msMaxTouchPoints > 0 ||
|
|
827
|
+
window.DocumentTouch && document instanceof DocumentTouch; }
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
// instant methods
|
|
831
|
+
startTouch = _ => {};
|
|
832
|
+
getDragDistance = _ => {};
|
|
833
|
+
shouldMoveDraggingItem = _ => {};
|
|
834
|
+
performDragMove = _ => {};
|
|
835
|
+
startDragging = _ => {};
|
|
836
|
+
endDragging = _ => {};
|
|
837
|
+
clearGhost = _ => {};
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
constructor($bound, axis = "vertical", useTouchSupport = n) {
|
|
841
|
+
this.useTouchSupport = useTouchSupport;
|
|
842
|
+
if (useTouchSupport || (useTouchSupport == n && this.isTouchSupported && !isAndroid)) this.#isEnabledTouch = t;
|
|
843
|
+
this.draggableAxis = axis;
|
|
844
|
+
this.$bound = $bound;
|
|
845
|
+
this.bound = $bound[0];
|
|
846
|
+
for (const bound of $bound) bound.draggableHandler = this;
|
|
847
|
+
this.init();
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
release() {
|
|
851
|
+
$(document).off('touchstart.dragHandler');
|
|
852
|
+
this.endDragging();
|
|
853
|
+
for (const bound of this.$bound) delete bound.draggableHandler;
|
|
854
|
+
|
|
855
|
+
if (this.$blockingBound != null && this.eventBlocker != null) {
|
|
856
|
+
this.$blockingBound.off("click touchstart touchmove touchend touchcancel", this.eventBlocker);
|
|
857
|
+
this.$blockingBound = null;
|
|
858
|
+
this.eventBlocker = null;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
init() {
|
|
863
|
+
const handler = this;
|
|
864
|
+
|
|
865
|
+
const $draggables = this.$bound.find(aiv("draggable", "true"));
|
|
866
|
+
const $containers = this.$bound.find(aiv("droppable", "true"));
|
|
867
|
+
|
|
868
|
+
let $topScrollerPad = this.$bound.find(aiv("scroller-pad", "top"));
|
|
869
|
+
let $bottomScrollerPad = this.$bound.find(aiv("scroller-pad", "bottom"));
|
|
870
|
+
if (this.draggableAxis == "both" || this.draggableAxis == "vertical") {
|
|
871
|
+
if ($topScrollerPad.length < 1) {
|
|
872
|
+
const topPad = doc.ce(div, n, n, n, { "scroller-pad": "top" });
|
|
873
|
+
this.$bound.append(topPad);
|
|
874
|
+
$topScrollerPad = this.$bound.find(aiv("scroller-pad", "top"));
|
|
875
|
+
}
|
|
876
|
+
if ($bottomScrollerPad.length < 1) {
|
|
877
|
+
const bottomPad = doc.ce(div, n, n, n, { "scroller-pad": "bottom" });
|
|
878
|
+
this.$bound.append(bottomPad);
|
|
879
|
+
$bottomScrollerPad = this.$bound.find(aiv("scroller-pad", "bottom"));
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// Remove existing events
|
|
884
|
+
$draggables.off("dragstart dragend touchstart touchmove touchend touchcancel");
|
|
885
|
+
$containers.off("dragover dragleave drop touchmove touchend touchcancel");
|
|
886
|
+
$topScrollerPad.off("dragover dragleave drop touchmove touchend touchcancel");
|
|
887
|
+
$bottomScrollerPad.off("dragover dragleave drop touchmove touchend touchcancel");
|
|
888
|
+
|
|
889
|
+
const scrollDistance = 10;
|
|
890
|
+
const scrollTerminal = 16; // ~60fps
|
|
891
|
+
let topScrollInterval = n;
|
|
892
|
+
let bottomScrollInterval = n;
|
|
893
|
+
|
|
894
|
+
let draggingItem = n;
|
|
895
|
+
let isDragging = false;
|
|
896
|
+
let touchData = {
|
|
897
|
+
startX: 0,
|
|
898
|
+
startY: 0,
|
|
899
|
+
currentX: 0,
|
|
900
|
+
currentY: 0,
|
|
901
|
+
startTime: 0,
|
|
902
|
+
moved: false,
|
|
903
|
+
dragThreshold: 10 // Drag start threshold in pixels
|
|
904
|
+
};
|
|
905
|
+
let ghostElement = null;
|
|
906
|
+
let dragStartTimeout = null;
|
|
907
|
+
let lastDragPosition = { container: null, afterElement: null, timestamp: 0 };
|
|
908
|
+
let dragMoveThrottle = null;
|
|
909
|
+
|
|
910
|
+
// Helper function for touch start
|
|
911
|
+
this.startTouch = (element, touch) => {
|
|
912
|
+
touchData.startX = touch.clientX;
|
|
913
|
+
touchData.startY = touch.clientY;
|
|
914
|
+
touchData.currentX = touch.clientX;
|
|
915
|
+
touchData.currentY = touch.clientY;
|
|
916
|
+
touchData.startTime = Date.now();
|
|
917
|
+
touchData.moved = false;
|
|
918
|
+
draggingItem = element;
|
|
919
|
+
this.clearGhost();
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
// Calculate drag distance
|
|
923
|
+
this.getDragDistance = () => {
|
|
924
|
+
const deltaX = touchData.currentX - touchData.startX;
|
|
925
|
+
const deltaY = touchData.currentY - touchData.startY;
|
|
926
|
+
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
// Check if element position needs to be changed
|
|
930
|
+
this.shouldMoveDraggingItem = (targetContainer, afterElement) => {
|
|
931
|
+
const currentParent = draggingItem.parentNode;
|
|
932
|
+
const currentNext = draggingItem.nextSibling;
|
|
933
|
+
|
|
934
|
+
// Different container - always move
|
|
935
|
+
if (currentParent !== targetContainer) {
|
|
936
|
+
return true;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// Same container - check if position actually changes
|
|
940
|
+
if (afterElement === null) {
|
|
941
|
+
// Moving to end - only move if not already at end
|
|
942
|
+
return currentNext !== null;
|
|
943
|
+
} else {
|
|
944
|
+
// Moving before specific element - only move if not already before it
|
|
945
|
+
return currentNext !== afterElement;
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
// Perform DOM move with throttling to prevent excessive operations
|
|
950
|
+
this.performDragMove = (targetContainer, afterElement) => {
|
|
951
|
+
const now = Date.now();
|
|
952
|
+
|
|
953
|
+
// Check if this is the same position as last move (within 50ms)
|
|
954
|
+
if (lastDragPosition.container === targetContainer &&
|
|
955
|
+
lastDragPosition.afterElement === afterElement &&
|
|
956
|
+
(now - lastDragPosition.timestamp) < 50) {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// Check if actual move is needed
|
|
961
|
+
if (!this.shouldMoveDraggingItem(targetContainer, afterElement)) {
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// Clear any pending throttled move
|
|
966
|
+
if (dragMoveThrottle) {
|
|
967
|
+
clearTimeout(dragMoveThrottle);
|
|
968
|
+
dragMoveThrottle = null;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// Throttle the move operation
|
|
972
|
+
dragMoveThrottle = setTimeout(() => {
|
|
973
|
+
if (draggingItem && targetContainer) {
|
|
974
|
+
try {
|
|
975
|
+
if (afterElement === null) {
|
|
976
|
+
targetContainer.appendChild(draggingItem);
|
|
977
|
+
} else {
|
|
978
|
+
targetContainer.insertBefore(draggingItem, afterElement);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// Update last position
|
|
982
|
+
lastDragPosition = {
|
|
983
|
+
container: targetContainer,
|
|
984
|
+
afterElement: afterElement,
|
|
985
|
+
timestamp: Date.now()
|
|
986
|
+
};
|
|
987
|
+
} catch (error) {
|
|
988
|
+
console.warn('Drag move operation failed:', error);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
dragMoveThrottle = null;
|
|
992
|
+
}, 16); // ~60fps throttling
|
|
993
|
+
};
|
|
994
|
+
|
|
995
|
+
// Handle drag start
|
|
996
|
+
this.startDragging = (element) => {
|
|
997
|
+
if (isDragging) return;
|
|
998
|
+
|
|
999
|
+
isDragging = true;
|
|
1000
|
+
this.$bound.attr("data-dragging", t1);
|
|
1001
|
+
element.dataset.dragging = t1;
|
|
1002
|
+
|
|
1003
|
+
// Create ghost element for visual feedback
|
|
1004
|
+
ghostElement = element.cloneNode(true);
|
|
1005
|
+
ghostElement.classList.add('ghost-element');
|
|
1006
|
+
ghostElement.style.cssText = `
|
|
1007
|
+
position: fixed !important;
|
|
1008
|
+
z-index: 9999 !important;
|
|
1009
|
+
left: ${touchData.currentX - 200}px !important;
|
|
1010
|
+
top: ${touchData.currentY - 25}px !important;
|
|
1011
|
+
border-radius: 8px !important;
|
|
1012
|
+
box-shadow: 0 8px 16px var(--color-boundary-o20) !important;
|
|
1013
|
+
opacity: 0.8 !important;
|
|
1014
|
+
pointer-events: none !important;
|
|
1015
|
+
transform: rotate(5deg) scale(1.05) !important;
|
|
1016
|
+
transition-duration: 0s;
|
|
1017
|
+
`;
|
|
1018
|
+
document.body.appendChild(ghostElement);
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
// Handle drag end
|
|
1022
|
+
this.endDragging = () => {
|
|
1023
|
+
// Clear drag timeout
|
|
1024
|
+
if (dragStartTimeout) {
|
|
1025
|
+
clearTimeout(dragStartTimeout);
|
|
1026
|
+
dragStartTimeout = null;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// Clear drag move timeout
|
|
1030
|
+
if (dragMoveThrottle) {
|
|
1031
|
+
clearTimeout(dragMoveThrottle);
|
|
1032
|
+
dragMoveThrottle = null;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// Clear scroll intervals
|
|
1036
|
+
if (topScrollInterval != n) {
|
|
1037
|
+
clearInterval(topScrollInterval);
|
|
1038
|
+
topScrollInterval = n;
|
|
1039
|
+
}
|
|
1040
|
+
if (bottomScrollInterval != n) {
|
|
1041
|
+
clearInterval(bottomScrollInterval);
|
|
1042
|
+
bottomScrollInterval = n;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// Remove ghost element
|
|
1046
|
+
this.clearGhost();
|
|
1047
|
+
|
|
1048
|
+
// Remove all highlights
|
|
1049
|
+
setTimeout(_ => {
|
|
1050
|
+
$containers.removeAttr("data-highlight");
|
|
1051
|
+
}, 200);
|
|
1052
|
+
|
|
1053
|
+
if (!isDragging) return;
|
|
1054
|
+
|
|
1055
|
+
isDragging = false;
|
|
1056
|
+
this.$bound.removeAttr("data-dragging");
|
|
1057
|
+
|
|
1058
|
+
// Remove drag state
|
|
1059
|
+
if (draggingItem) {
|
|
1060
|
+
draggingItem.dataset.dragging = n;
|
|
1061
|
+
draggingItem = n;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
// Reset position tracking
|
|
1065
|
+
lastDragPosition = { container: null, afterElement: null, timestamp: 0 };
|
|
1066
|
+
};
|
|
1067
|
+
|
|
1068
|
+
this.clearGhost = () => {
|
|
1069
|
+
if (ghostElement && ghostElement.parentNode) {
|
|
1070
|
+
ghostElement.parentNode.removeChild(ghostElement);
|
|
1071
|
+
ghostElement = null;
|
|
1072
|
+
}
|
|
1073
|
+
$(doc.b).find(c.c + cls + "ghost-element").remove();
|
|
1074
|
+
};
|
|
1075
|
+
|
|
1076
|
+
// Touch start event
|
|
1077
|
+
if (this.#isEnabledTouch) $draggables.on({
|
|
1078
|
+
"touchstart": function (e) {
|
|
1079
|
+
const touch = e.originalEvent.touches[0];
|
|
1080
|
+
handler.startTouch(this, touch);
|
|
1081
|
+
|
|
1082
|
+
// Set delayed timeout for drag start
|
|
1083
|
+
dragStartTimeout = setTimeout(() => {
|
|
1084
|
+
if (draggingItem === this && !isDragging && !touchData.moved) {
|
|
1085
|
+
handler.startDragging(this);
|
|
1086
|
+
}
|
|
1087
|
+
}, 150); // Start drag mode after 150ms hold
|
|
1088
|
+
},
|
|
1089
|
+
|
|
1090
|
+
// Touch move event
|
|
1091
|
+
"touchmove": function (e) {
|
|
1092
|
+
const touch = e.originalEvent.touches[0];
|
|
1093
|
+
touchData.currentX = touch.clientX;
|
|
1094
|
+
touchData.currentY = touch.clientY;
|
|
1095
|
+
|
|
1096
|
+
// Detect movement
|
|
1097
|
+
if (!touchData.moved) {
|
|
1098
|
+
const distance = handler.getDragDistance();
|
|
1099
|
+
if (distance > touchData.dragThreshold) {
|
|
1100
|
+
if (isDragging) {
|
|
1101
|
+
touchData.moved = true;
|
|
1102
|
+
} else {
|
|
1103
|
+
handler.endDragging();
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// Do not process if not dragging
|
|
1109
|
+
if (!isDragging) return;
|
|
1110
|
+
|
|
1111
|
+
e.preventDefault();
|
|
1112
|
+
e.stopPropagation();
|
|
1113
|
+
|
|
1114
|
+
// Update ghost element position
|
|
1115
|
+
if (ghostElement) {
|
|
1116
|
+
ghostElement.style.left = (touchData.currentX - 200) + 'px';
|
|
1117
|
+
ghostElement.style.top = (touchData.currentY - 25) + 'px';
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
// Find drop target from touch position
|
|
1121
|
+
const elementBelow = document.elementFromPoint(touchData.currentX, touchData.currentY);
|
|
1122
|
+
const container = elementBelow?.closest(aiv("droppable", "true"));
|
|
1123
|
+
const topScrollPad = elementBelow?.closest(aiv("scroller-pad", "top"));
|
|
1124
|
+
const bottomScrollPad = elementBelow?.closest(aiv("scroller-pad", "bottom"));
|
|
1125
|
+
|
|
1126
|
+
// Handle auto-scrolling for touch drag
|
|
1127
|
+
if (topScrollPad) {
|
|
1128
|
+
if (topScrollInterval == n) {
|
|
1129
|
+
topScrollInterval = setInterval(() => {
|
|
1130
|
+
handler.bound.scrollTop = handler.bound.scrollTop - scrollDistance;
|
|
1131
|
+
}, scrollTerminal);
|
|
1132
|
+
}
|
|
1133
|
+
} else if (bottomScrollPad) {
|
|
1134
|
+
if (bottomScrollInterval == n) {
|
|
1135
|
+
bottomScrollInterval = setInterval(() => {
|
|
1136
|
+
handler.bound.scrollTop = handler.bound.scrollTop + scrollDistance;
|
|
1137
|
+
}, scrollTerminal);
|
|
1138
|
+
}
|
|
1139
|
+
} else {
|
|
1140
|
+
// Stop scrolling when not on scroll pads
|
|
1141
|
+
if (topScrollInterval != n) {
|
|
1142
|
+
clearInterval(topScrollInterval);
|
|
1143
|
+
topScrollInterval = n;
|
|
1144
|
+
}
|
|
1145
|
+
if (bottomScrollInterval != n) {
|
|
1146
|
+
clearInterval(bottomScrollInterval);
|
|
1147
|
+
bottomScrollInterval = n;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
if (container) {
|
|
1152
|
+
// Remove highlights from all containers
|
|
1153
|
+
$containers.removeAttr("data-highlight");
|
|
1154
|
+
|
|
1155
|
+
// Apply highlight to current container
|
|
1156
|
+
container.dataset.highlight = t1;
|
|
1157
|
+
|
|
1158
|
+
// Use improved drag move logic
|
|
1159
|
+
const afterElement = handler.getDragAfterElement(container, touchData.currentY);
|
|
1160
|
+
handler.performDragMove(container, afterElement);
|
|
1161
|
+
} else {
|
|
1162
|
+
// Remove highlight when outside containers
|
|
1163
|
+
$containers.removeAttr("data-highlight");
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
|
|
1167
|
+
// Touch end event
|
|
1168
|
+
"touchend": function (e) {
|
|
1169
|
+
// Clear scroll intervals on touch end
|
|
1170
|
+
if (topScrollInterval != n) {
|
|
1171
|
+
clearInterval(topScrollInterval);
|
|
1172
|
+
topScrollInterval = n;
|
|
1173
|
+
}
|
|
1174
|
+
if (bottomScrollInterval != n) {
|
|
1175
|
+
clearInterval(bottomScrollInterval);
|
|
1176
|
+
bottomScrollInterval = n;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
// Treat as click if touch is short and movement is minimal
|
|
1180
|
+
const touchDuration = Date.now() - touchData.startTime;
|
|
1181
|
+
const dragDistance = handler.getDragDistance();
|
|
1182
|
+
|
|
1183
|
+
if (!isDragging && touchDuration < 200 && dragDistance < touchData.dragThreshold) {
|
|
1184
|
+
// Handle as regular click - allow default behavior
|
|
1185
|
+
handler.endDragging();
|
|
1186
|
+
return;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
e.preventDefault();
|
|
1190
|
+
e.stopPropagation();
|
|
1191
|
+
|
|
1192
|
+
handler.endDragging();
|
|
1193
|
+
},
|
|
1194
|
+
|
|
1195
|
+
// Touch cancel event
|
|
1196
|
+
"touchcancel": function (e) {
|
|
1197
|
+
// Clear scroll intervals on touch cancel
|
|
1198
|
+
if (topScrollInterval != n) {
|
|
1199
|
+
clearInterval(topScrollInterval);
|
|
1200
|
+
topScrollInterval = n;
|
|
1201
|
+
}
|
|
1202
|
+
if (bottomScrollInterval != n) {
|
|
1203
|
+
clearInterval(bottomScrollInterval);
|
|
1204
|
+
bottomScrollInterval = n;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
handler.endDragging();
|
|
1208
|
+
},
|
|
1209
|
+
});
|
|
1210
|
+
|
|
1211
|
+
// Desktop drag events
|
|
1212
|
+
$draggables.on({
|
|
1213
|
+
"dragstart": function (e) {
|
|
1214
|
+
draggingItem = this;
|
|
1215
|
+
isDragging = true;
|
|
1216
|
+
handler.$bound.attr("data-dragging", t1);
|
|
1217
|
+
postQueue(_ => { this.dataset.dragging = t1; });
|
|
1218
|
+
const event = e.originalEvent;
|
|
1219
|
+
event.dataTransfer.effectAllowed = "move";
|
|
1220
|
+
event.dataTransfer.setDragImage(this, e.offsetX, e.offsetY);
|
|
1221
|
+
},
|
|
1222
|
+
|
|
1223
|
+
"dragend": function (e) {
|
|
1224
|
+
draggingItem = n;
|
|
1225
|
+
isDragging = false;
|
|
1226
|
+
handler.$bound.removeAttr("data-dragging");
|
|
1227
|
+
this.dataset.dragging = n;
|
|
1228
|
+
$containers.removeAttr("data-highlight");
|
|
1229
|
+
},
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
// Desktop container events
|
|
1233
|
+
$containers.on({
|
|
1234
|
+
"dragover": function (e) {
|
|
1235
|
+
e.preventDefault();
|
|
1236
|
+
|
|
1237
|
+
$containers.removeAttr("data-highlight");
|
|
1238
|
+
this.dataset.highlight = t1;
|
|
1239
|
+
const event = e.originalEvent;
|
|
1240
|
+
event.dataTransfer.dropEffect = "move";
|
|
1241
|
+
|
|
1242
|
+
// Use improved drag move logic
|
|
1243
|
+
const afterElement = handler.getDragAfterElement(this, e.clientY);
|
|
1244
|
+
if (handler.#isEnabledTouch) handler.performDragMove(this, afterElement);
|
|
1245
|
+
else if (afterElement === null) this.appendChild(draggingItem);
|
|
1246
|
+
else this.insertBefore(draggingItem, afterElement);
|
|
1247
|
+
|
|
1248
|
+
return false;
|
|
1249
|
+
},
|
|
1250
|
+
|
|
1251
|
+
"dragleave": function (e) {
|
|
1252
|
+
// Prevent dragleave from being triggered incorrectly by child elements
|
|
1253
|
+
const rect = this.getBoundingClientRect();
|
|
1254
|
+
const isOutside = e.clientX < rect.left || e.clientX > rect.right ||
|
|
1255
|
+
e.clientY < rect.top || e.clientY > rect.bottom;
|
|
1256
|
+
|
|
1257
|
+
if (isOutside) {
|
|
1258
|
+
delete this.dataset.highlight;
|
|
1259
|
+
}
|
|
1260
|
+
},
|
|
1261
|
+
|
|
1262
|
+
"drop": function (e) {
|
|
1263
|
+
e.preventDefault();
|
|
1264
|
+
|
|
1265
|
+
delete this.dataset.highlight;
|
|
1266
|
+
|
|
1267
|
+
return false;
|
|
1268
|
+
},
|
|
1269
|
+
});
|
|
1270
|
+
|
|
1271
|
+
|
|
1272
|
+
$topScrollerPad.on({
|
|
1273
|
+
"dragover": function (e) {
|
|
1274
|
+
e.preventDefault();
|
|
1275
|
+
|
|
1276
|
+
if (topScrollInterval == n) {
|
|
1277
|
+
topScrollInterval = setInterval(() => {
|
|
1278
|
+
handler.bound.scrollTop = handler.bound.scrollTop - scrollDistance;
|
|
1279
|
+
}, scrollTerminal);
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
return false;
|
|
1283
|
+
},
|
|
1284
|
+
|
|
1285
|
+
"dragleave": function (e) {
|
|
1286
|
+
if (topScrollInterval != n) {
|
|
1287
|
+
clearInterval(topScrollInterval);
|
|
1288
|
+
topScrollInterval = n;
|
|
1289
|
+
}
|
|
1290
|
+
},
|
|
1291
|
+
|
|
1292
|
+
"drop": function (e) {
|
|
1293
|
+
e.preventDefault();
|
|
1294
|
+
|
|
1295
|
+
if (topScrollInterval != n) {
|
|
1296
|
+
clearInterval(topScrollInterval);
|
|
1297
|
+
topScrollInterval = n;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
return false;
|
|
1301
|
+
},
|
|
1302
|
+
});
|
|
1303
|
+
$bottomScrollerPad.on({
|
|
1304
|
+
"dragover": function (e) {
|
|
1305
|
+
e.preventDefault();
|
|
1306
|
+
|
|
1307
|
+
if (bottomScrollInterval == n) {
|
|
1308
|
+
bottomScrollInterval = setInterval(() => {
|
|
1309
|
+
handler.bound.scrollTop = handler.bound.scrollTop + scrollDistance;
|
|
1310
|
+
}, scrollTerminal);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
return false;
|
|
1314
|
+
},
|
|
1315
|
+
|
|
1316
|
+
"dragleave": function (e) {
|
|
1317
|
+
if (bottomScrollInterval != n) {
|
|
1318
|
+
clearInterval(bottomScrollInterval);
|
|
1319
|
+
bottomScrollInterval = n;
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
|
|
1323
|
+
"drop": function (e) {
|
|
1324
|
+
e.preventDefault();
|
|
1325
|
+
|
|
1326
|
+
if (bottomScrollInterval != n) {
|
|
1327
|
+
clearInterval(bottomScrollInterval);
|
|
1328
|
+
bottomScrollInterval = n;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
return false;
|
|
1332
|
+
},
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
// Global touch event to handle drag end during scroll
|
|
1336
|
+
$(document).on('touchstart.dragHandler', function(e) {
|
|
1337
|
+
if (isDragging && !$(e.target).closest(aiv("draggable", "true")).length) {
|
|
1338
|
+
handler.endDragging();
|
|
1339
|
+
}
|
|
1340
|
+
});
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
getDragAfterElement(container, y) {
|
|
1344
|
+
const draggableElements = [...container.querySelectorAll(li + aiv("draggable", "true") + naiv("data-dragging", t1))];
|
|
1345
|
+
return draggableElements.reduce((closest, child) => {
|
|
1346
|
+
const box = child.getBoundingClientRect();
|
|
1347
|
+
const offset = y - box.top - box.height / 2;
|
|
1348
|
+
if (offset < 0 && offset > closest.offset) return { offset: offset, element: child };
|
|
1349
|
+
else return closest;
|
|
1350
|
+
}, { offset: Number.NEGATIVE_INFINITY }).element;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
blockEventLeaks($closestBound = this.$bound) {
|
|
1354
|
+
if (this.$blockingBound != null && this.eventBlocker != null) {
|
|
1355
|
+
this.$blockingBound.off("click touchstart touchmove touchend touchcancel", this.eventBlocker);
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
this.eventBlocker = function (e) {
|
|
1359
|
+
// e.preventDefault();
|
|
1360
|
+
e.stopPropagation();
|
|
1361
|
+
|
|
1362
|
+
// return false;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
this.$blockingBound = $closestBound;
|
|
1366
|
+
|
|
1367
|
+
$closestBound.on("click touchstart touchmove touchend touchcancel", this.eventBlocker);
|
|
1368
|
+
|
|
1369
|
+
return this;
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
// ======================================================================
|