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 | |
| parent | 9d579e00faefe50047c869f494cd2c1ba4d2780d (diff) | |
refactor: setting draggable block in one place
Diffstat (limited to 'src')
| -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, { |