diff options
author | Hsieh Chin Fan <pham@topo.tw> | 2024-09-20 23:51:20 +0800 |
---|---|---|
committer | Hsieh Chin Fan <pham@topo.tw> | 2024-09-21 10:58:47 +0800 |
commit | f48923d9421af46f0ca7ad5127d6f11f103df951 (patch) | |
tree | 143166ca447fd449434dd583d60971828fbac600 /src/dumbymap.mjs | |
parent | 9d579e00faefe50047c869f494cd2c1ba4d2780d (diff) |
refactor: setting draggable block in one place
Diffstat (limited to 'src/dumbymap.mjs')
-rw-r--r-- | src/dumbymap.mjs | 79 |
1 files changed, 44 insertions, 35 deletions
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index d6ed1d3..d18fab8 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -206,35 +206,56 @@ export const generateMaps = async (container, callback) => { | |||
206 | // Add draggable part for blocks | 206 | // Add draggable part for blocks |
207 | 207 | ||
208 | const dumbyBlocks = Array.from(htmlHolder.querySelectorAll('.dumby-block')) | 208 | const dumbyBlocks = Array.from(htmlHolder.querySelectorAll('.dumby-block')) |
209 | const intoDraggableContainer = (block) => { | 209 | const moveIntoDraggable = (block) => { |
210 | // Create draggable block | 210 | // Create draggable block |
211 | const draggableContainer = document.createElement('div') | 211 | const draggableBlock = document.createElement('div') |
212 | draggableContainer.classList.add('draggable-block') | 212 | draggableBlock.classList.add('draggable-block') |
213 | 213 | ||
214 | // Add draggable part | 214 | // Add draggable part |
215 | const draggablePart = document.createElement('div'); | 215 | const draggablePart = document.createElement('div'); |
216 | draggablePart.classList.add('draggable') | 216 | draggablePart.classList.add('draggable') |
217 | draggablePart.textContent = '☰' | 217 | draggablePart.textContent = '☰' |
218 | draggablePart.title = 'Use middle-click to remove block' | 218 | draggablePart.title = 'Use middle-click to remove block' |
219 | // Hide block with middle click | ||
220 | draggablePart.onmouseup = (e) => { | 219 | draggablePart.onmouseup = (e) => { |
221 | if (e.button === 1) { | 220 | if (e.button === 1) { |
222 | draggableContainer.style.display = "none"; | 221 | // Hide block with middle click |
222 | draggableBlock.style.display = "none"; | ||
223 | } | 223 | } |
224 | } | 224 | } |
225 | draggableContainer.appendChild(draggablePart) | ||
226 | 225 | ||
227 | draggableContainer.appendChild(block) | 226 | // Set elements |
228 | htmlHolder.appendChild(draggableContainer) | 227 | draggableBlock.appendChild(draggablePart) |
229 | return draggableContainer | 228 | draggableBlock.appendChild(block) |
229 | htmlHolder.appendChild(draggableBlock) | ||
230 | |||
231 | // Add draggable instance | ||
232 | const draggableInstance = new PlainDraggable(draggableBlock, { | ||
233 | handle: draggablePart, | ||
234 | snap: { x: { step: 20 }, y: { step: 20 } }, | ||
235 | }) | ||
236 | |||
237 | // Reposition draggable instance when resized | ||
238 | new ResizeObserver(() => { | ||
239 | try { | ||
240 | draggableInstance.position(); | ||
241 | } catch (_) { | ||
242 | null | ||
243 | } | ||
244 | }).observe(draggableBlock); | ||
245 | |||
246 | // Callback for remove | ||
247 | onRemove(draggableBlock, () => { | ||
248 | draggableInstance.remove() | ||
249 | }) | ||
250 | |||
251 | return draggableInstance | ||
230 | } | 252 | } |
231 | 253 | ||
232 | const resumeFromDraggableContainer = (block) => { | 254 | const resumeFromDraggable = (block) => { |
233 | const draggableContainer = block.closest('.draggable-block') | 255 | const draggableContainer = block.closest('.draggable-block') |
234 | if (!draggableContainer) return | 256 | if (!draggableContainer) return |
235 | htmlHolder.appendChild(block) | 257 | htmlHolder.appendChild(block) |
236 | block.removeAttribute('style') | 258 | block.removeAttribute('style') |
237 | draggableContainer.draggableInstance.remove() | ||
238 | draggableContainer.remove() | 259 | draggableContainer.remove() |
239 | } | 260 | } |
240 | // }}} | 261 | // }}} |
@@ -362,32 +383,20 @@ export const generateMaps = async (container, callback) => { | |||
362 | }) | 383 | }) |
363 | 384 | ||
364 | if (layout === 'overlay') { | 385 | if (layout === 'overlay') { |
365 | const draggableContainers = dumbyBlocks.map(intoDraggableContainer) | 386 | let [x, y] = [0, 0] |
366 | 387 | dumbyBlocks.map(moveIntoDraggable) | |
367 | // Set initial position side by side | 388 | .forEach(draggable => { |
368 | let [x, y] = [0, 0]; | 389 | draggable.left = x |
369 | draggableContainers.forEach((c) => { | 390 | draggable.top = y |
370 | 391 | const rect = draggable.element.getBoundingClientRect() | |
371 | // Add draggable instance | 392 | x += rect.width + 30 |
372 | c.draggableInstance = new PlainDraggable(c, { | 393 | if (x > window.innerWidth) { |
373 | handle: c.querySelector('.draggable') ?? c, | 394 | y += 200 |
374 | snap: { x: { step: 20 }, y: { step: 20 } }, | 395 | x = x % window.innerWidth |
375 | left: x, | 396 | } |
376 | top: y, | ||
377 | }) | 397 | }) |
378 | x += parseInt(window.getComputedStyle(c).width) + 30 | ||
379 | if (x > window.innerWidth) { | ||
380 | y += 200 | ||
381 | x = x % window.innerWidth | ||
382 | } | ||
383 | |||
384 | const resizeObserver = new ResizeObserver(() => { | ||
385 | c.draggableInstance.position(); | ||
386 | }).observe(c); | ||
387 | onRemove(c, () => resizeObserver.disconnect()) | ||
388 | }) | ||
389 | } else { | 398 | } else { |
390 | dumbyBlocks.forEach(resumeFromDraggableContainer) | 399 | dumbyBlocks.forEach(resumeFromDraggable) |
391 | } | 400 | } |
392 | }); | 401 | }); |
393 | layoutObserver.observe(container, { | 402 | layoutObserver.observe(container, { |