aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Layout.mjs
diff options
context:
space:
mode:
authorHsieh Chin Fan <pham@topo.tw>2024-09-21 16:40:22 +0800
committerHsieh Chin Fan <pham@topo.tw>2024-09-21 17:08:05 +0800
commitcbe40ac1128eedcda30812285cbec003acb8adc1 (patch)
tree0b1765b9cceaee4c7532282cf733cb5f95ecb18a /src/Layout.mjs
parente015aeb2c13903871da306d3aa840c25c7a3597f (diff)
refactor: layout class
* put class Layout and OverlayLayout together * apply extend on OverlayLayout * rename layouts: "none" -> "normal", "side" -> "side-by-side"
Diffstat (limited to 'src/Layout.mjs')
-rw-r--r--src/Layout.mjs117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/Layout.mjs b/src/Layout.mjs
new file mode 100644
index 0000000..20e8a23
--- /dev/null
+++ b/src/Layout.mjs
@@ -0,0 +1,117 @@
1import PlainDraggable from 'plain-draggable'
2import { onRemove } from './utils'
3
4export class Layout {
5 constructor(options = {}) {
6 if (!options.name) throw Error("Layout name is not given")
7 this.name = options.name
8 this.enterHandler = options.enterHandler
9 this.leaveHandler = options.leaveHandler
10 }
11 valueOf = () => this.name
12}
13
14export class OverlayLayout extends Layout {
15 name = "overlay"
16
17 enterHandler = (dumbymap) => {
18 const container = dumbymap.htmlHolder
19 const moveIntoDraggable = (block) => {
20 // Create draggable block
21 const draggableBlock = document.createElement('div')
22 draggableBlock.classList.add('draggable-block')
23 draggableBlock.innerHTML = `
24 <div class="draggable">
25 <div class="handle">\u2630</div>
26 </div>
27 <div class="utils">
28 <div id="plus-font-size" ">\u2795</div>
29 <div id="minus-font-size">\u2796</div>
30 </div>
31 `
32
33 // Add draggable part
34 const draggablePart = draggableBlock.querySelector('.draggable')
35 draggablePart.title = 'Use middle-click to remove block'
36 draggablePart.onmouseup = (e) => {
37 if (e.button === 1) {
38 // Hide block with middle click
39 draggableBlock.style.display = "none";
40 }
41 }
42
43 // Set elements
44 draggableBlock.appendChild(draggablePart)
45 draggableBlock.appendChild(block)
46 container.appendChild(draggableBlock)
47
48 // Add draggable instance
49 const draggableInstance = new PlainDraggable(draggableBlock, {
50 handle: draggablePart,
51 snap: { x: { step: 20 }, y: { step: 20 } },
52 })
53
54 // Plus/Minus font-size of content
55 const plusButton = draggableBlock.querySelector('#plus-font-size')
56 plusButton.onclick = () => {
57 const fontSize = parseFloat(getComputedStyle(block).fontSize) / 16
58 block.style.fontSize = `${fontSize + 0.1}rem`
59 }
60 const minusButton = draggableBlock.querySelector('#minus-font-size')
61 minusButton.onclick = () => {
62 const fontSize = parseFloat(getComputedStyle(block).fontSize) / 16
63 block.style.fontSize = `${fontSize - 0.1}rem`
64 }
65 draggableInstance.onDragStart = () => {
66 plusButton.style.opacity = '0'
67 minusButton.style.opacity = '0'
68 }
69 draggableInstance.onDragEnd = () => {
70 plusButton.style = ''
71 minusButton.style = ''
72 }
73
74 // Reposition draggable instance when resized
75 new ResizeObserver(() => {
76 try {
77 draggableInstance.position();
78 } catch (_) {
79 null
80 }
81 }).observe(draggableBlock);
82
83 // Callback for remove
84 onRemove(draggableBlock, () => {
85 draggableInstance.remove()
86 })
87
88 return draggableInstance
89 }
90
91 // Create draggable blocks and set each position by previous one
92 let [x, y] = [0, 0]
93 dumbymap.blocks.map(moveIntoDraggable)
94 .forEach(draggable => {
95 draggable.left = x
96 draggable.top = y
97 const rect = draggable.element.getBoundingClientRect()
98 x += rect.width + 30
99 if (x > window.innerWidth) {
100 y += 200
101 x = x % window.innerWidth
102 }
103 })
104 }
105 leaveHandler = (dumbymap) => {
106 const container = dumbymap.htmlHolder
107 const resumeFromDraggable = (block) => {
108 const draggableContainer = block.closest('.draggable-block')
109 if (!draggableContainer) return
110 container.appendChild(block)
111 block.removeAttribute('style')
112 draggableContainer.remove()
113 }
114 dumbymap.blocks.forEach(resumeFromDraggable)
115 }
116}
117