diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dumbymap.mjs | 144 | ||||
| -rw-r--r-- | src/editor.mjs | 8 |
2 files changed, 93 insertions, 59 deletions
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index d05e7c4..d512136 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
| @@ -37,9 +37,7 @@ const mapCache = {} | |||
| 37 | */ | 37 | */ |
| 38 | export const markdown2HTML = (container, mdContent) => { | 38 | export const markdown2HTML = (container, mdContent) => { |
| 39 | /** Prepare Elements for Container */ | 39 | /** Prepare Elements for Container */ |
| 40 | container.replaceChildren() | 40 | container.querySelector('.SemanticHtml')?.remove() |
| 41 | container.innerHTML = '<div class="SemanticHtml"></div>' | ||
| 42 | const htmlHolder = container.querySelector('.SemanticHtml') | ||
| 43 | 41 | ||
| 44 | /** Prepare MarkdownIt Instance */ | 42 | /** Prepare MarkdownIt Instance */ |
| 45 | const md = MarkdownIt({ | 43 | const md = MarkdownIt({ |
| @@ -80,7 +78,10 @@ export const markdown2HTML = (container, mdContent) => { | |||
| 80 | }) | 78 | }) |
| 81 | 79 | ||
| 82 | /** Render HTML */ | 80 | /** Render HTML */ |
| 81 | const htmlHolder = document.createElement('div') | ||
| 82 | htmlHolder.className = 'SemanticHtml' | ||
| 83 | htmlHolder.innerHTML = md.render(mdContent) | 83 | htmlHolder.innerHTML = md.render(mdContent) |
| 84 | container.appendChild(htmlHolder) | ||
| 84 | 85 | ||
| 85 | return container | 86 | return container |
| 86 | } | 87 | } |
| @@ -160,6 +161,47 @@ export const generateMaps = (container, { | |||
| 160 | container.appendChild(showcase) | 161 | container.appendChild(showcase) |
| 161 | showcase.classList.add('Showcase') | 162 | showcase.classList.add('Showcase') |
| 162 | 163 | ||
| 164 | /** Prepare Other Variables */ | ||
| 165 | const modalContent = document.createElement('div') | ||
| 166 | container.appendChild(modalContent) | ||
| 167 | const modal = new PlainModal(modalContent) | ||
| 168 | |||
| 169 | /** Define dumbymap Object */ | ||
| 170 | const dumbymap = { | ||
| 171 | layouts: [...defaultLayouts, ...layouts.map(l => typeof l === 'object' ? l : { name: l })], | ||
| 172 | container, | ||
| 173 | get htmlHolder () { return container.querySelector('.SemanticHtml') }, | ||
| 174 | get showcase () { return container.querySelector('.Showcase') }, | ||
| 175 | get blocks () { return Array.from(container.querySelectorAll('.dumby-block')) }, | ||
| 176 | modal, | ||
| 177 | modalContent, | ||
| 178 | utils: { | ||
| 179 | ...utils, | ||
| 180 | renderedMaps: () => | ||
| 181 | Array.from( | ||
| 182 | container.querySelectorAll('.mapclay[data-render=fulfilled]'), | ||
| 183 | ).sort((a, b) => a.style.order > b.style.order), | ||
| 184 | setContextMenu: (menuCallback) => { | ||
| 185 | const originalCallback = container.oncontextmenu | ||
| 186 | container.oncontextmenu = (e) => { | ||
| 187 | const menu = originalCallback(e) | ||
| 188 | if (!menu) return | ||
| 189 | |||
| 190 | menuCallback(e, menu) | ||
| 191 | menu.style.transform = '' | ||
| 192 | shiftByWindow(menu) | ||
| 193 | } | ||
| 194 | }, | ||
| 195 | focusNextMap: throttle(utils.focusNextMap, utils.focusDelay), | ||
| 196 | switchToNextLayout: throttle(utils.switchToNextLayout, 300), | ||
| 197 | }, | ||
| 198 | } | ||
| 199 | Object.entries(dumbymap.utils).forEach(([util, value]) => { | ||
| 200 | if (typeof value === 'function') { | ||
| 201 | dumbymap.utils[util] = value.bind(dumbymap) | ||
| 202 | } | ||
| 203 | }) | ||
| 204 | |||
| 163 | /** WATCH: text content of Semantic HTML */ | 205 | /** WATCH: text content of Semantic HTML */ |
| 164 | new window.MutationObserver((mutations) => { | 206 | new window.MutationObserver((mutations) => { |
| 165 | for (const mutation of mutations) { | 207 | for (const mutation of mutations) { |
| @@ -180,7 +222,6 @@ export const generateMaps = (container, { | |||
| 180 | subtree: true, | 222 | subtree: true, |
| 181 | }) | 223 | }) |
| 182 | 224 | ||
| 183 | const counter = 0 | ||
| 184 | /** WATCH: children of Semantic HTML */ | 225 | /** WATCH: children of Semantic HTML */ |
| 185 | new window.MutationObserver((mutations) => { | 226 | new window.MutationObserver((mutations) => { |
| 186 | for (const mutation of mutations) { | 227 | for (const mutation of mutations) { |
| @@ -223,52 +264,46 @@ export const generateMaps = (container, { | |||
| 223 | } | 264 | } |
| 224 | }).observe(container, { | 265 | }).observe(container, { |
| 225 | attributes: true, | 266 | attributes: true, |
| 226 | attributesFilter: ['data-init-dumby'], | 267 | attributeFilter: ['data-init-dumby'], |
| 227 | childList: true, | 268 | childList: true, |
| 228 | subtree: true, | 269 | subtree: true, |
| 229 | }) | 270 | }) |
| 230 | 271 | ||
| 231 | container.dataset.initDumby = 'true' | 272 | container.dataset.initDumby = 'true' |
| 232 | 273 | ||
| 233 | /** Prepare Other Variables */ | 274 | /** WATCH: Layout changes */ |
| 234 | const modalContent = document.createElement('div') | 275 | new window.MutationObserver(mutations => { |
| 235 | container.appendChild(modalContent) | 276 | const mutation = mutations.at(-1) |
| 236 | const modal = new PlainModal(modalContent) | 277 | const oldLayout = mutation.oldValue |
| 278 | const newLayout = container.dataset.layout | ||
| 279 | |||
| 280 | // Apply handler for leaving/entering layouts | ||
| 281 | if (oldLayout) { | ||
| 282 | dumbymap.layouts | ||
| 283 | .find(l => l.name === oldLayout) | ||
| 284 | ?.leaveHandler?.call(this, dumbymap) | ||
| 285 | } | ||
| 237 | 286 | ||
| 238 | /** Define dumbymap Object */ | 287 | Object.values(dumbymap) |
| 239 | const dumbymap = { | 288 | .filter(ele => ele instanceof window.HTMLElement) |
| 240 | layouts: [...defaultLayouts, ...layouts.map(l => typeof l === 'object' ? l : { name: l })], | 289 | .forEach(ele => { ele.style.cssText = '' }) |
| 241 | container, | ||
| 242 | htmlHolder, | ||
| 243 | showcase, | ||
| 244 | get blocks () { return Array.from(container.querySelectorAll('.dumby-block')) }, | ||
| 245 | modal, | ||
| 246 | modalContent, | ||
| 247 | utils: { | ||
| 248 | ...utils, | ||
| 249 | renderedMaps: () => | ||
| 250 | Array.from( | ||
| 251 | container.querySelectorAll('.mapclay[data-render=fulfilled]'), | ||
| 252 | ).sort((a, b) => a.style.order > b.style.order), | ||
| 253 | setContextMenu: (menuCallback) => { | ||
| 254 | const originalCallback = container.oncontextmenu | ||
| 255 | container.oncontextmenu = (e) => { | ||
| 256 | const menu = originalCallback(e) | ||
| 257 | if (!menu) return | ||
| 258 | 290 | ||
| 259 | menuCallback(e, menu) | 291 | if (newLayout) { |
| 260 | menu.style.transform = '' | 292 | dumbymap.layouts |
| 261 | shiftByWindow(menu) | 293 | .find(l => l.name === newLayout) |
| 262 | } | 294 | ?.enterHandler?.call(this, dumbymap) |
| 263 | }, | ||
| 264 | focusNextMap: throttle(utils.focusNextMap, utils.focusDelay), | ||
| 265 | switchToNextLayout: throttle(utils.switchToNextLayout, 300), | ||
| 266 | }, | ||
| 267 | } | ||
| 268 | Object.entries(dumbymap.utils).forEach(([util, value]) => { | ||
| 269 | if (typeof value === 'function') { | ||
| 270 | dumbymap.utils[util] = value.bind(dumbymap) | ||
| 271 | } | 295 | } |
| 296 | |||
| 297 | // Since layout change may show/hide showcase, the current focused map may need to go into/outside showcase | ||
| 298 | // Reset attribute triggers MutationObserver which is observing it | ||
| 299 | const focusMap = | ||
| 300 | container.querySelector('.mapclay.focus') ?? | ||
| 301 | container.querySelector('.mapclay') | ||
| 302 | focusMap?.classList?.add('focus') | ||
| 303 | }).observe(container, { | ||
| 304 | attributes: true, | ||
| 305 | attributeFilter: ['data-layout'], | ||
| 306 | attributeOldValue: true, | ||
| 272 | }) | 307 | }) |
| 273 | 308 | ||
| 274 | /** | 309 | /** |
| @@ -473,17 +508,19 @@ export const generateMaps = (container, { | |||
| 473 | } | 508 | } |
| 474 | 509 | ||
| 475 | if (!target.renderMap) { | 510 | if (!target.renderMap) { |
| 476 | target.renderMap = debounce(() => { | 511 | target.renderMap = debounce( |
| 477 | // Render maps | 512 | () => { |
| 478 | render(target, configList).forEach(renderPromise => { | 513 | // Render maps |
| 479 | renderPromise.then(afterMapRendered) | 514 | render(target, configList).forEach(renderPromise => { |
| 480 | }) | 515 | renderPromise.then(afterMapRendered) |
| 481 | Array.from(target.children).forEach(e => { | 516 | }) |
| 482 | if (e.dataset.render === 'fulfilled') { | 517 | Array.from(target.children).forEach(e => { |
| 483 | afterMapRendered(e.renderer) | 518 | if (e.dataset.render === 'fulfilled') { |
| 484 | } | 519 | afterMapRendered(e.renderer) |
| 485 | }), mapDelay | 520 | } |
| 486 | }) | 521 | }) |
| 522 | }, mapDelay, | ||
| 523 | ) | ||
| 487 | } | 524 | } |
| 488 | target.renderMap() | 525 | target.renderMap() |
| 489 | } | 526 | } |
| @@ -498,7 +535,8 @@ export const generateMaps = (container, { | |||
| 498 | 535 | ||
| 499 | menu.style.display = 'none' | 536 | menu.style.display = 'none' |
| 500 | } | 537 | } |
| 501 | document.body.appendChild(menu) | 538 | container.appendChild(menu) |
| 539 | window.menu = menu | ||
| 502 | 540 | ||
| 503 | /** MENU: Menu Items for Context Menu */ | 541 | /** MENU: Menu Items for Context Menu */ |
| 504 | container.oncontextmenu = e => { | 542 | container.oncontextmenu = e => { |
diff --git a/src/editor.mjs b/src/editor.mjs index 430353a..3f8f27d 100644 --- a/src/editor.mjs +++ b/src/editor.mjs | |||
| @@ -476,13 +476,9 @@ function menuForEditor (event, menu) { | |||
| 476 | */ | 476 | */ |
| 477 | const updateDumbyMap = (callback = null) => { | 477 | const updateDumbyMap = (callback = null) => { |
| 478 | markdown2HTML(dumbyContainer, editor.value()) | 478 | markdown2HTML(dumbyContainer, editor.value()) |
| 479 | // debounceForMap(dumbyContainer, afterMapRendered) | ||
| 480 | // dumbymap = generateMaps(dumbyContainer, { | ||
| 481 | // crs, | ||
| 482 | // }) | ||
| 483 | // Set onscroll callback | 479 | // Set onscroll callback |
| 484 | // const htmlHolder = dumbymap.htmlHolder | 480 | const htmlHolder = dumbymap.htmlHolder |
| 485 | // htmlHolder.onscroll = updateScrollLine(htmlHolder) | 481 | dumbymap.htmlHolder.onscroll = updateScrollLine(htmlHolder) |
| 486 | 482 | ||
| 487 | callback?.(dumbymap) | 483 | callback?.(dumbymap) |
| 488 | } | 484 | } |