@fc3/mmcadi 0.1.56 → 0.1.57
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/dist/.last-compile-time +1 -1
- package/dist/.last-publish-time +1 -1
- package/dist/client.js +125 -72
- package/dist/src/client/helper/interaction.d.ts +10 -8
- package/dist/src/client/helper/interaction.js +128 -75
- package/dist/src/client/helper/interaction.js.map +1 -1
- package/dist/src/server/serializer/base.js +28 -0
- package/dist/src/server/serializer/base.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/.last-compile-time
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
1767736645
|
package/dist/.last-publish-time
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
1767736776
|
package/dist/client.js
CHANGED
|
@@ -2283,17 +2283,21 @@
|
|
|
2283
2283
|
this.drag_delay_timer = null;
|
|
2284
2284
|
}
|
|
2285
2285
|
attach() {
|
|
2286
|
-
|
|
2287
|
-
|
|
2286
|
+
if (!this.isTouchDevice()) {
|
|
2287
|
+
return;
|
|
2288
|
+
}
|
|
2289
|
+
this.applyNonInteractiveClasses();
|
|
2290
|
+
document.addEventListener("touchstart", (event) => {
|
|
2291
|
+
this.handleTouchStart(event);
|
|
2288
2292
|
}, { capture: true });
|
|
2289
|
-
document.addEventListener("
|
|
2290
|
-
this.
|
|
2293
|
+
document.addEventListener("touchmove", (event) => {
|
|
2294
|
+
this.handleTouchMove(event);
|
|
2291
2295
|
}, { capture: true, passive: false });
|
|
2292
|
-
document.addEventListener("
|
|
2293
|
-
this.
|
|
2296
|
+
document.addEventListener("touchend", (event) => {
|
|
2297
|
+
this.handleTouchEnd(event);
|
|
2294
2298
|
}, { capture: true });
|
|
2295
|
-
document.addEventListener("
|
|
2296
|
-
this.
|
|
2299
|
+
document.addEventListener("click", (event) => {
|
|
2300
|
+
this.handleGenericClick(event);
|
|
2297
2301
|
}, { capture: true });
|
|
2298
2302
|
document.addEventListener("dragstart", (event) => {
|
|
2299
2303
|
this.handleNativeDragStart(event);
|
|
@@ -2303,14 +2307,29 @@
|
|
|
2303
2307
|
const elements = Array.from(document.querySelectorAll(".dragging"));
|
|
2304
2308
|
return elements.length > 0;
|
|
2305
2309
|
}
|
|
2306
|
-
|
|
2310
|
+
applyNonInteractiveClasses() {
|
|
2311
|
+
const raw_elements = document.querySelectorAll("section.block");
|
|
2312
|
+
const elements = Array.from(raw_elements);
|
|
2313
|
+
elements.forEach((element) => {
|
|
2314
|
+
element.classList.add("no-interaction");
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2317
|
+
isTouchDevice() {
|
|
2318
|
+
if (Math.random() > 0) {
|
|
2319
|
+
return true;
|
|
2320
|
+
}
|
|
2321
|
+
const pointer_matches = window.matchMedia("(pointer: coarse)").matches;
|
|
2322
|
+
const hover_none_matches = window.matchMedia("(hover: none)").matches;
|
|
2323
|
+
return pointer_matches && hover_none_matches;
|
|
2324
|
+
}
|
|
2325
|
+
handleTouchStart(event) {
|
|
2307
2326
|
const { target } = event;
|
|
2308
2327
|
if (target === null) {
|
|
2309
2328
|
return;
|
|
2310
2329
|
}
|
|
2311
2330
|
const target_element = target;
|
|
2312
2331
|
let current_element = target_element;
|
|
2313
|
-
while (current_element) {
|
|
2332
|
+
while (current_element instanceof HTMLElement) {
|
|
2314
2333
|
const attribute = current_element.getAttribute("data-role");
|
|
2315
2334
|
if (attribute === "block_activation") {
|
|
2316
2335
|
break;
|
|
@@ -2319,15 +2338,12 @@
|
|
|
2319
2338
|
return;
|
|
2320
2339
|
}
|
|
2321
2340
|
current_element = current_element.parentNode;
|
|
2322
|
-
if (!(current_element instanceof HTMLElement)) {
|
|
2323
|
-
break;
|
|
2324
|
-
}
|
|
2325
2341
|
}
|
|
2326
2342
|
const block = target_element.closest("section.block");
|
|
2327
2343
|
if (block === null) {
|
|
2328
2344
|
return;
|
|
2329
2345
|
}
|
|
2330
|
-
if (target_element.closest("
|
|
2346
|
+
if (target_element.closest("input, textarea, select, label, form")) {
|
|
2331
2347
|
return;
|
|
2332
2348
|
}
|
|
2333
2349
|
const coordinate = this.getEventCoordinate(event);
|
|
@@ -2337,6 +2353,7 @@
|
|
|
2337
2353
|
this.drag_start_coordinate = coordinate;
|
|
2338
2354
|
block.classList.add("drag-candidate");
|
|
2339
2355
|
this.scheduleDelayedDrag();
|
|
2356
|
+
event.preventDefault();
|
|
2340
2357
|
}
|
|
2341
2358
|
scheduleDelayedDrag() {
|
|
2342
2359
|
this.cancelDelayedDrag();
|
|
@@ -2348,7 +2365,8 @@
|
|
|
2348
2365
|
clearTimeout(this.drag_delay_timer);
|
|
2349
2366
|
}
|
|
2350
2367
|
}
|
|
2351
|
-
|
|
2368
|
+
demoteAllDragCandidates() {
|
|
2369
|
+
const class_name = "drag-candidate";
|
|
2352
2370
|
const raw_elements = document.querySelectorAll(`.${class_name}`);
|
|
2353
2371
|
const elements = Array.from(raw_elements);
|
|
2354
2372
|
elements.forEach((element) => {
|
|
@@ -2356,7 +2374,22 @@
|
|
|
2356
2374
|
});
|
|
2357
2375
|
return elements;
|
|
2358
2376
|
}
|
|
2377
|
+
createDragMask() {
|
|
2378
|
+
const mask = document.createElement("div");
|
|
2379
|
+
mask.classList.add("drag-mask");
|
|
2380
|
+
document.body.appendChild(mask);
|
|
2381
|
+
document.body.style.overflow = "hidden";
|
|
2382
|
+
}
|
|
2383
|
+
hideDragMask() {
|
|
2384
|
+
const raw_elements = document.querySelectorAll(".drag-mask");
|
|
2385
|
+
const elements = Array.from(raw_elements);
|
|
2386
|
+
elements.forEach((element) => {
|
|
2387
|
+
document.body.removeChild(element);
|
|
2388
|
+
});
|
|
2389
|
+
document.body.style.overflow = "auto";
|
|
2390
|
+
}
|
|
2359
2391
|
beginDelayedDrag() {
|
|
2392
|
+
this.createDragMask();
|
|
2360
2393
|
const raw_candidates = document.querySelectorAll(".drag-candidate");
|
|
2361
2394
|
const candidates = Array.from(raw_candidates);
|
|
2362
2395
|
candidates.forEach((candidate) => {
|
|
@@ -2380,6 +2413,7 @@
|
|
|
2380
2413
|
});
|
|
2381
2414
|
candidate.setAttribute("data-drag-start-x", rect.left.toString());
|
|
2382
2415
|
candidate.setAttribute("data-drag-start-y", rect.top.toString());
|
|
2416
|
+
candidate.setAttribute("data-dragging", "true");
|
|
2383
2417
|
candidate.classList.add("dragging");
|
|
2384
2418
|
parentNode.insertBefore(ghost, candidate);
|
|
2385
2419
|
});
|
|
@@ -2394,28 +2428,13 @@
|
|
|
2394
2428
|
event.preventDefault();
|
|
2395
2429
|
}
|
|
2396
2430
|
}
|
|
2397
|
-
|
|
2431
|
+
handleTouchMove(event) {
|
|
2398
2432
|
const current_coordinate = this.getEventCoordinate(event);
|
|
2399
2433
|
const start_coordinate = this.getDragStartCoordinate();
|
|
2400
2434
|
if (start_coordinate === null || current_coordinate === null) {
|
|
2401
2435
|
return;
|
|
2402
2436
|
}
|
|
2403
|
-
|
|
2404
|
-
if (target !== null) {
|
|
2405
|
-
const target_element = target;
|
|
2406
|
-
const block = target_element.closest("section.block");
|
|
2407
|
-
if (block) {
|
|
2408
|
-
if (!block.classList.contains("dragging")) {
|
|
2409
|
-
block.classList.add("drag-candidate");
|
|
2410
|
-
}
|
|
2411
|
-
}
|
|
2412
|
-
}
|
|
2413
|
-
const { x: start_x, y: start_y } = start_coordinate;
|
|
2414
|
-
const { x: current_x, y: current_y } = current_coordinate;
|
|
2415
|
-
const distance = Math.hypot(current_x - start_x, current_y - start_y);
|
|
2416
|
-
if (distance > 25) {
|
|
2417
|
-
this.removeClassFromAllElements("drag-candidate");
|
|
2418
|
-
}
|
|
2437
|
+
this.demoteAllDragCandidates();
|
|
2419
2438
|
this.scheduleDelayedDrag();
|
|
2420
2439
|
const raw_targets = document.querySelectorAll(".dragging");
|
|
2421
2440
|
const drag_target_blocks = Array.from(raw_targets);
|
|
@@ -2547,26 +2566,36 @@
|
|
|
2547
2566
|
}
|
|
2548
2567
|
return null;
|
|
2549
2568
|
}
|
|
2550
|
-
|
|
2569
|
+
handleTouchEnd(event) {
|
|
2551
2570
|
this.stopDragging();
|
|
2552
2571
|
}
|
|
2553
|
-
|
|
2554
|
-
|
|
2572
|
+
handleGenericClick(event) {
|
|
2573
|
+
const { target } = event;
|
|
2574
|
+
if (target === null) {
|
|
2575
|
+
return;
|
|
2576
|
+
}
|
|
2577
|
+
const target_element = target;
|
|
2578
|
+
const block = target_element.closest("section.block");
|
|
2579
|
+
if (block === null) {
|
|
2580
|
+
return;
|
|
2581
|
+
}
|
|
2582
|
+
const attribute = block.getAttribute("data-dragging");
|
|
2583
|
+
if (attribute === "true") {
|
|
2584
|
+
block.removeAttribute("data-dragging");
|
|
2585
|
+
event.preventDefault();
|
|
2586
|
+
event.stopPropagation();
|
|
2587
|
+
}
|
|
2555
2588
|
}
|
|
2556
2589
|
stopDragging() {
|
|
2557
|
-
this.showFullscreenBlockingOverlay();
|
|
2558
2590
|
this.stopDraggingAsync().then(() => {
|
|
2559
|
-
this.
|
|
2591
|
+
this.hideDragMask();
|
|
2560
2592
|
});
|
|
2561
2593
|
}
|
|
2562
|
-
showFullscreenBlockingOverlay() {
|
|
2563
|
-
}
|
|
2564
|
-
hideFullscreenBlockingOverlay() {
|
|
2565
|
-
}
|
|
2566
2594
|
async stopDraggingAsync() {
|
|
2567
2595
|
this.cancelDelayedDrag();
|
|
2568
|
-
this.
|
|
2569
|
-
const
|
|
2596
|
+
this.demoteAllDragCandidates();
|
|
2597
|
+
const raw_elements = document.querySelectorAll(".dragging");
|
|
2598
|
+
const dragging_elements = Array.from(raw_elements);
|
|
2570
2599
|
let index = 0;
|
|
2571
2600
|
while (index < dragging_elements.length) {
|
|
2572
2601
|
const element = dragging_elements[index++];
|
|
@@ -2574,8 +2603,8 @@
|
|
|
2574
2603
|
const source_index_path = get_index_path_for_element_default(element);
|
|
2575
2604
|
const target_index_path = this.getIndexPathForGhost(ghost);
|
|
2576
2605
|
await this.submitReposition(source_index_path, target_index_path);
|
|
2577
|
-
ghost.replaceWith(element);
|
|
2578
2606
|
Object.assign(element.style, {
|
|
2607
|
+
opacity: "0",
|
|
2579
2608
|
left: "",
|
|
2580
2609
|
top: "",
|
|
2581
2610
|
right: "",
|
|
@@ -2583,39 +2612,55 @@
|
|
|
2583
2612
|
width: "",
|
|
2584
2613
|
height: ""
|
|
2585
2614
|
});
|
|
2615
|
+
element.classList.remove("dragging");
|
|
2616
|
+
ghost.replaceWith(element);
|
|
2617
|
+
element.style.opacity = "1";
|
|
2586
2618
|
}
|
|
2619
|
+
this.recomputeIndexPaths();
|
|
2587
2620
|
}
|
|
2588
|
-
|
|
2589
|
-
const
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2621
|
+
recomputeIndexPaths() {
|
|
2622
|
+
const raw_blocks = document.querySelectorAll("section.block");
|
|
2623
|
+
const blocks = Array.from(raw_blocks);
|
|
2624
|
+
let index = 0;
|
|
2625
|
+
blocks.forEach((block) => {
|
|
2626
|
+
const block_parent = block.parentNode;
|
|
2627
|
+
if (block_parent === null) {
|
|
2628
|
+
throw new import_errors8.InvariantViolation(`
|
|
2629
|
+
Tried to read block parent element, but it was not set
|
|
2630
|
+
`);
|
|
2631
|
+
}
|
|
2632
|
+
const multicolumn_ancestor = block_parent.closest("section.block.multi_column");
|
|
2633
|
+
if (multicolumn_ancestor === null) {
|
|
2634
|
+
const index_path = index.toString();
|
|
2635
|
+
block.setAttribute("data-index-path", index_path);
|
|
2636
|
+
index++;
|
|
2637
|
+
}
|
|
2638
|
+
});
|
|
2598
2639
|
}
|
|
2599
2640
|
getIndexPathForGhost(ghost) {
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
}
|
|
2606
|
-
current_child = current_child.nextElementSibling;
|
|
2641
|
+
const parent_element = ghost.parentNode;
|
|
2642
|
+
if (parent_element === null) {
|
|
2643
|
+
throw new import_errors8.InvariantViolation(`
|
|
2644
|
+
Tried to read parent element for ghost, but it was not set
|
|
2645
|
+
`);
|
|
2607
2646
|
}
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2647
|
+
const siblings = Array.from(parent_element.children);
|
|
2648
|
+
let index = 0;
|
|
2649
|
+
let effective_index = 0;
|
|
2650
|
+
while (index < siblings.length) {
|
|
2651
|
+
const sibling = siblings[index++];
|
|
2652
|
+
if (!sibling.classList.contains("block")) {
|
|
2653
|
+
continue;
|
|
2615
2654
|
}
|
|
2616
|
-
|
|
2655
|
+
if (sibling.classList.contains("dragging")) {
|
|
2656
|
+
continue;
|
|
2657
|
+
}
|
|
2658
|
+
if (sibling === ghost) {
|
|
2659
|
+
break;
|
|
2660
|
+
}
|
|
2661
|
+
effective_index++;
|
|
2617
2662
|
}
|
|
2618
|
-
return
|
|
2663
|
+
return effective_index.toString();
|
|
2619
2664
|
}
|
|
2620
2665
|
async submitReposition(source_index_path, target_index_path) {
|
|
2621
2666
|
const form = new FormData();
|
|
@@ -2637,9 +2682,17 @@
|
|
|
2637
2682
|
}
|
|
2638
2683
|
}
|
|
2639
2684
|
getEventCoordinate(event) {
|
|
2685
|
+
const { touches } = event;
|
|
2686
|
+
if (touches === void 0) {
|
|
2687
|
+
return null;
|
|
2688
|
+
}
|
|
2689
|
+
const touch = touches[0];
|
|
2690
|
+
if (touch === void 0) {
|
|
2691
|
+
return null;
|
|
2692
|
+
}
|
|
2640
2693
|
return {
|
|
2641
|
-
x:
|
|
2642
|
-
y:
|
|
2694
|
+
x: touch.clientX,
|
|
2695
|
+
y: touch.clientY
|
|
2643
2696
|
};
|
|
2644
2697
|
}
|
|
2645
2698
|
getDragStartCoordinate() {
|
|
@@ -4,24 +4,26 @@ declare class InteractionHelper {
|
|
|
4
4
|
constructor();
|
|
5
5
|
attach(): void;
|
|
6
6
|
isDragging(): boolean;
|
|
7
|
-
private
|
|
7
|
+
private applyNonInteractiveClasses;
|
|
8
|
+
private isTouchDevice;
|
|
9
|
+
private handleTouchStart;
|
|
8
10
|
private scheduleDelayedDrag;
|
|
9
11
|
private cancelDelayedDrag;
|
|
10
|
-
private
|
|
12
|
+
private demoteAllDragCandidates;
|
|
13
|
+
private createDragMask;
|
|
14
|
+
private hideDragMask;
|
|
11
15
|
private beginDelayedDrag;
|
|
12
16
|
private handleNativeDragStart;
|
|
13
|
-
private
|
|
17
|
+
private handleTouchMove;
|
|
14
18
|
private translateDragTargetBlock;
|
|
15
19
|
private getGhostForBlock;
|
|
16
20
|
private getPreviousBlock;
|
|
17
21
|
private getNextBlock;
|
|
18
|
-
private
|
|
19
|
-
private
|
|
22
|
+
private handleTouchEnd;
|
|
23
|
+
private handleGenericClick;
|
|
20
24
|
private stopDragging;
|
|
21
|
-
private showFullscreenBlockingOverlay;
|
|
22
|
-
private hideFullscreenBlockingOverlay;
|
|
23
25
|
private stopDraggingAsync;
|
|
24
|
-
private
|
|
26
|
+
private recomputeIndexPaths;
|
|
25
27
|
private getIndexPathForGhost;
|
|
26
28
|
private submitReposition;
|
|
27
29
|
private getEventCoordinate;
|
|
@@ -13,17 +13,21 @@ class InteractionHelper {
|
|
|
13
13
|
this.drag_delay_timer = null;
|
|
14
14
|
}
|
|
15
15
|
attach() {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
if (!this.isTouchDevice()) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
this.applyNonInteractiveClasses();
|
|
20
|
+
document.addEventListener('touchstart', (event) => {
|
|
21
|
+
this.handleTouchStart(event);
|
|
18
22
|
}, { capture: true });
|
|
19
|
-
document.addEventListener('
|
|
20
|
-
this.
|
|
23
|
+
document.addEventListener('touchmove', (event) => {
|
|
24
|
+
this.handleTouchMove(event);
|
|
21
25
|
}, { capture: true, passive: false });
|
|
22
|
-
document.addEventListener('
|
|
23
|
-
this.
|
|
26
|
+
document.addEventListener('touchend', (event) => {
|
|
27
|
+
this.handleTouchEnd(event);
|
|
24
28
|
}, { capture: true });
|
|
25
|
-
document.addEventListener('
|
|
26
|
-
this.
|
|
29
|
+
document.addEventListener('click', (event) => {
|
|
30
|
+
this.handleGenericClick(event);
|
|
27
31
|
}, { capture: true });
|
|
28
32
|
document.addEventListener('dragstart', (event) => {
|
|
29
33
|
this.handleNativeDragStart(event);
|
|
@@ -33,33 +37,47 @@ class InteractionHelper {
|
|
|
33
37
|
const elements = Array.from(document.querySelectorAll('.dragging'));
|
|
34
38
|
return elements.length > 0;
|
|
35
39
|
}
|
|
36
|
-
|
|
40
|
+
applyNonInteractiveClasses() {
|
|
41
|
+
const raw_elements = document.querySelectorAll('section.block');
|
|
42
|
+
const elements = Array.from(raw_elements);
|
|
43
|
+
elements.forEach((element) => {
|
|
44
|
+
element.classList.add('no-interaction');
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
isTouchDevice() {
|
|
48
|
+
if (Math.random() > 0) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
const pointer_matches = window.matchMedia('(pointer: coarse)').matches;
|
|
52
|
+
const hover_none_matches = window.matchMedia('(hover: none)').matches;
|
|
53
|
+
return pointer_matches && hover_none_matches;
|
|
54
|
+
}
|
|
55
|
+
handleTouchStart(event) {
|
|
37
56
|
const { target } = event;
|
|
38
57
|
if (target === null) {
|
|
39
58
|
return;
|
|
40
59
|
}
|
|
41
60
|
const target_element = target;
|
|
42
61
|
let current_element = target_element;
|
|
43
|
-
while (current_element) {
|
|
62
|
+
while (current_element instanceof HTMLElement) {
|
|
44
63
|
const attribute = current_element.getAttribute('data-role');
|
|
45
64
|
if (attribute === 'block_activation') {
|
|
46
65
|
break;
|
|
47
66
|
}
|
|
48
67
|
// Tricky. Bail out early if we detect an anchor element in the event
|
|
49
|
-
// ancestry that is NOT an all-block-encompassing link (eg, a folder block)
|
|
68
|
+
// ancestry that is NOT an all-block-encompassing link (eg, a folder block)
|
|
69
|
+
// the existence of which was ruled out by checking its data-role
|
|
70
|
+
// attribute above (folder and link blocks both have "block_activation")
|
|
50
71
|
if (current_element instanceof HTMLAnchorElement) {
|
|
51
72
|
return;
|
|
52
73
|
}
|
|
53
74
|
current_element = current_element.parentNode;
|
|
54
|
-
if (!(current_element instanceof HTMLElement)) {
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
75
|
}
|
|
58
76
|
const block = target_element.closest('section.block');
|
|
59
77
|
if (block === null) {
|
|
60
78
|
return;
|
|
61
79
|
}
|
|
62
|
-
if (target_element.closest('
|
|
80
|
+
if (target_element.closest('input, textarea, select, label, form')) {
|
|
63
81
|
return;
|
|
64
82
|
}
|
|
65
83
|
const coordinate = this.getEventCoordinate(event);
|
|
@@ -69,6 +87,7 @@ class InteractionHelper {
|
|
|
69
87
|
this.drag_start_coordinate = coordinate;
|
|
70
88
|
block.classList.add('drag-candidate');
|
|
71
89
|
this.scheduleDelayedDrag();
|
|
90
|
+
event.preventDefault();
|
|
72
91
|
}
|
|
73
92
|
scheduleDelayedDrag() {
|
|
74
93
|
this.cancelDelayedDrag();
|
|
@@ -80,7 +99,8 @@ class InteractionHelper {
|
|
|
80
99
|
clearTimeout(this.drag_delay_timer);
|
|
81
100
|
}
|
|
82
101
|
}
|
|
83
|
-
|
|
102
|
+
demoteAllDragCandidates() {
|
|
103
|
+
const class_name = 'drag-candidate';
|
|
84
104
|
const raw_elements = document.querySelectorAll(`.${class_name}`);
|
|
85
105
|
const elements = Array.from(raw_elements);
|
|
86
106
|
elements.forEach((element) => {
|
|
@@ -88,7 +108,22 @@ class InteractionHelper {
|
|
|
88
108
|
});
|
|
89
109
|
return elements;
|
|
90
110
|
}
|
|
111
|
+
createDragMask() {
|
|
112
|
+
const mask = document.createElement('div');
|
|
113
|
+
mask.classList.add('drag-mask');
|
|
114
|
+
document.body.appendChild(mask);
|
|
115
|
+
document.body.style.overflow = 'hidden';
|
|
116
|
+
}
|
|
117
|
+
hideDragMask() {
|
|
118
|
+
const raw_elements = document.querySelectorAll('.drag-mask');
|
|
119
|
+
const elements = Array.from(raw_elements);
|
|
120
|
+
elements.forEach((element) => {
|
|
121
|
+
document.body.removeChild(element);
|
|
122
|
+
});
|
|
123
|
+
document.body.style.overflow = 'auto';
|
|
124
|
+
}
|
|
91
125
|
beginDelayedDrag() {
|
|
126
|
+
this.createDragMask();
|
|
92
127
|
const raw_candidates = document.querySelectorAll('.drag-candidate');
|
|
93
128
|
const candidates = Array.from(raw_candidates);
|
|
94
129
|
candidates.forEach((candidate) => {
|
|
@@ -112,6 +147,7 @@ class InteractionHelper {
|
|
|
112
147
|
});
|
|
113
148
|
candidate.setAttribute('data-drag-start-x', rect.left.toString());
|
|
114
149
|
candidate.setAttribute('data-drag-start-y', rect.top.toString());
|
|
150
|
+
candidate.setAttribute('data-dragging', 'true');
|
|
115
151
|
candidate.classList.add('dragging');
|
|
116
152
|
parentNode.insertBefore(ghost, candidate);
|
|
117
153
|
});
|
|
@@ -126,28 +162,13 @@ class InteractionHelper {
|
|
|
126
162
|
event.preventDefault();
|
|
127
163
|
}
|
|
128
164
|
}
|
|
129
|
-
|
|
165
|
+
handleTouchMove(event) {
|
|
130
166
|
const current_coordinate = this.getEventCoordinate(event);
|
|
131
167
|
const start_coordinate = this.getDragStartCoordinate();
|
|
132
168
|
if (start_coordinate === null || current_coordinate === null) {
|
|
133
169
|
return;
|
|
134
170
|
}
|
|
135
|
-
|
|
136
|
-
if (target !== null) {
|
|
137
|
-
const target_element = target;
|
|
138
|
-
const block = target_element.closest('section.block');
|
|
139
|
-
if (block) {
|
|
140
|
-
if (!block.classList.contains('dragging')) {
|
|
141
|
-
block.classList.add('drag-candidate');
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
const { x: start_x, y: start_y } = start_coordinate;
|
|
146
|
-
const { x: current_x, y: current_y } = current_coordinate;
|
|
147
|
-
const distance = Math.hypot(current_x - start_x, current_y - start_y);
|
|
148
|
-
if (distance > 25) {
|
|
149
|
-
this.removeClassFromAllElements('drag-candidate');
|
|
150
|
-
}
|
|
171
|
+
this.demoteAllDragCandidates();
|
|
151
172
|
this.scheduleDelayedDrag();
|
|
152
173
|
const raw_targets = document.querySelectorAll('.dragging');
|
|
153
174
|
const drag_target_blocks = Array.from(raw_targets);
|
|
@@ -279,26 +300,36 @@ class InteractionHelper {
|
|
|
279
300
|
}
|
|
280
301
|
return null;
|
|
281
302
|
}
|
|
282
|
-
|
|
303
|
+
handleTouchEnd(event) {
|
|
283
304
|
this.stopDragging();
|
|
284
305
|
}
|
|
285
|
-
|
|
286
|
-
|
|
306
|
+
handleGenericClick(event) {
|
|
307
|
+
const { target } = event;
|
|
308
|
+
if (target === null) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const target_element = target;
|
|
312
|
+
const block = target_element.closest('section.block');
|
|
313
|
+
if (block === null) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const attribute = block.getAttribute('data-dragging');
|
|
317
|
+
if (attribute === 'true') {
|
|
318
|
+
block.removeAttribute('data-dragging');
|
|
319
|
+
event.preventDefault();
|
|
320
|
+
event.stopPropagation();
|
|
321
|
+
}
|
|
287
322
|
}
|
|
288
323
|
stopDragging() {
|
|
289
|
-
this.showFullscreenBlockingOverlay();
|
|
290
324
|
this.stopDraggingAsync().then(() => {
|
|
291
|
-
this.
|
|
325
|
+
this.hideDragMask();
|
|
292
326
|
});
|
|
293
327
|
}
|
|
294
|
-
showFullscreenBlockingOverlay() {
|
|
295
|
-
}
|
|
296
|
-
hideFullscreenBlockingOverlay() {
|
|
297
|
-
}
|
|
298
328
|
async stopDraggingAsync() {
|
|
299
329
|
this.cancelDelayedDrag();
|
|
300
|
-
this.
|
|
301
|
-
const
|
|
330
|
+
this.demoteAllDragCandidates();
|
|
331
|
+
const raw_elements = document.querySelectorAll('.dragging');
|
|
332
|
+
const dragging_elements = Array.from(raw_elements);
|
|
302
333
|
let index = 0;
|
|
303
334
|
while (index < dragging_elements.length) {
|
|
304
335
|
const element = dragging_elements[index++];
|
|
@@ -306,8 +337,8 @@ class InteractionHelper {
|
|
|
306
337
|
const source_index_path = (0, get_index_path_for_element_1.default)(element);
|
|
307
338
|
const target_index_path = this.getIndexPathForGhost(ghost);
|
|
308
339
|
await this.submitReposition(source_index_path, target_index_path);
|
|
309
|
-
ghost.replaceWith(element);
|
|
310
340
|
Object.assign(element.style, {
|
|
341
|
+
opacity: '0',
|
|
311
342
|
left: '',
|
|
312
343
|
top: '',
|
|
313
344
|
right: '',
|
|
@@ -315,41 +346,55 @@ class InteractionHelper {
|
|
|
315
346
|
width: '',
|
|
316
347
|
height: ''
|
|
317
348
|
});
|
|
349
|
+
element.classList.remove('dragging');
|
|
350
|
+
ghost.replaceWith(element);
|
|
351
|
+
element.style.opacity = '1';
|
|
318
352
|
}
|
|
353
|
+
this.recomputeIndexPaths();
|
|
319
354
|
}
|
|
320
|
-
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
355
|
+
recomputeIndexPaths() {
|
|
356
|
+
const raw_blocks = document.querySelectorAll('section.block');
|
|
357
|
+
const blocks = Array.from(raw_blocks);
|
|
358
|
+
let index = 0;
|
|
359
|
+
blocks.forEach((block) => {
|
|
360
|
+
const block_parent = block.parentNode;
|
|
361
|
+
if (block_parent === null) {
|
|
362
|
+
throw new errors_1.InvariantViolation(`
|
|
363
|
+
Tried to read block parent element, but it was not set
|
|
364
|
+
`);
|
|
365
|
+
}
|
|
366
|
+
const multicolumn_ancestor = block_parent.closest('section.block.multi_column');
|
|
367
|
+
if (multicolumn_ancestor === null) {
|
|
368
|
+
const index_path = index.toString();
|
|
369
|
+
block.setAttribute('data-index-path', index_path);
|
|
370
|
+
index++;
|
|
371
|
+
}
|
|
372
|
+
});
|
|
330
373
|
}
|
|
331
374
|
getIndexPathForGhost(ghost) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
375
|
+
const parent_element = ghost.parentNode;
|
|
376
|
+
if (parent_element === null) {
|
|
377
|
+
throw new errors_1.InvariantViolation(`
|
|
378
|
+
Tried to read parent element for ghost, but it was not set
|
|
379
|
+
`);
|
|
380
|
+
}
|
|
381
|
+
const siblings = Array.from(parent_element.children);
|
|
382
|
+
let index = 0;
|
|
383
|
+
let effective_index = 0;
|
|
384
|
+
while (index < siblings.length) {
|
|
385
|
+
const sibling = siblings[index++];
|
|
386
|
+
if (!sibling.classList.contains('block')) {
|
|
387
|
+
continue;
|
|
337
388
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if (index_path !== null) {
|
|
344
|
-
// TODO: This will need to change when I implement drag-reordering of
|
|
345
|
-
// multicolumn layouts.
|
|
346
|
-
const index_major_version = parseInt(index_path);
|
|
347
|
-
const next_version = index_major_version + 1;
|
|
348
|
-
return next_version.toString();
|
|
389
|
+
if (sibling.classList.contains('dragging')) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
if (sibling === ghost) {
|
|
393
|
+
break;
|
|
349
394
|
}
|
|
350
|
-
|
|
395
|
+
effective_index++;
|
|
351
396
|
}
|
|
352
|
-
return
|
|
397
|
+
return effective_index.toString();
|
|
353
398
|
}
|
|
354
399
|
async submitReposition(source_index_path, target_index_path) {
|
|
355
400
|
const form = new FormData();
|
|
@@ -372,9 +417,17 @@ class InteractionHelper {
|
|
|
372
417
|
}
|
|
373
418
|
}
|
|
374
419
|
getEventCoordinate(event) {
|
|
420
|
+
const { touches } = event;
|
|
421
|
+
if (touches === undefined) {
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
const touch = touches[0];
|
|
425
|
+
if (touch === undefined) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
375
428
|
return {
|
|
376
|
-
x:
|
|
377
|
-
y:
|
|
429
|
+
x: touch.clientX,
|
|
430
|
+
y: touch.clientY
|
|
378
431
|
};
|
|
379
432
|
}
|
|
380
433
|
getDragStartCoordinate() {
|