From 5072cf2805e7815524c9320ddd7970dd9625f024 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Tue, 1 Oct 2024 12:27:59 +0800 Subject: refactor: menu-item only call methods from dumbymap.utils --- src/MenuItem.mjs | 87 ++++++++++++++++++++++-------------------------------- src/dumbyUtils.mjs | 69 +++++++++++++++++++++++++++++++++++++++++++ src/dumbymap.mjs | 77 +++-------------------------------------------- 3 files changed, 108 insertions(+), 125 deletions(-) (limited to 'src') diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index b4d4650..1ab7d5f 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs @@ -1,6 +1,3 @@ -import { createGeoLink } from './dumbymap'; -import { scrollToBlock } from './dumbyUtils'; - class Item extends HTMLDivElement { constructor({ text, innerHTML, onclick }) { super(); @@ -35,10 +32,10 @@ class Folder extends HTMLDivElement { } window.customElements.define('menu-folder', Folder, { extends: 'div' }); -export const pickMapItem = dumbymap => +export const pickMapItem = ({ utils }) => new Folder({ innerHTML: 'Maps(Tab)', - items: dumbymap.utils.renderedMaps().map( + items: utils.renderedMaps().map( map => new Item({ text: map.id, @@ -50,10 +47,10 @@ export const pickMapItem = dumbymap => ), }); -export const pickBlockItem = dumbymap => +export const pickBlockItem = ({ blocks, utils }) => new Folder({ innerHTML: 'Blocks(n/p)', - items: dumbymap.blocks.map( + items: blocks.map( (block, index) => new Item({ text: @@ -64,67 +61,54 @@ export const pickBlockItem = dumbymap => .concat(' ...'), onclick: () => { block.classList.add('focus'); - scrollToBlock(block); + utils.scrollToBlock(block); }, }), ), }); -export const pickLayoutItem = dumbymap => +export const pickLayoutItem = ({ container, layouts }) => new Folder({ innerHTML: 'Layouts(x)', items: [ new Item({ text: 'EDIT', onclick: () => - dumbymap.container - .closest('[data-mode]') - .setAttribute('data-mode', 'editing'), + container.closest('[data-mode]').setAttribute('data-mode', 'editing'), }), - ...dumbymap.layouts.map( + ...layouts.map( layout => new Item({ text: layout.name, - onclick: () => - dumbymap.container.setAttribute('data-layout', layout.name), + onclick: () => container.setAttribute('data-layout', layout.name), }), ), ], }); -export class GeoLink { - constructor({ range }) { - this.range = range; - } - - createElement = () => { - const element = document.createElement('div'); - element.className = 'menu-item'; - element.innerText = 'Add GeoLink'; - element.onclick = this.addGeoLinkbyRange; - - return element; - }; - - addGeoLinkbyRange = () => { - const range = this.range; - const content = range.toString(); - // FIXME Apply geolink only on matching sub-range - const match = content.match(/(^\D*[\d.]+)\D+([\d.]+)\D*$/); - if (!match) return false; - - const [x, y] = match.slice(1); - const anchor = document.createElement('a'); - anchor.textContent = content; - // FIXME apply WGS84 - anchor.href = `geo:${y},${x}?xy=${x},${y}`; +export const addGeoLink = ({ utils }, range) => + new Item({ + text: 'Add GeoLink', + onclick: () => { + const content = range.toString(); + // FIXME Apply geolink only on matching sub-range + const match = content.match(/(^\D*[\d.]+)\D+([\d.]+)\D*$/); + if (!match) return false; + + const [x, y] = match.slice(1); + const anchor = document.createElement('a'); + anchor.textContent = content; + // FIXME apply WGS84 + anchor.href = `geo:${y},${x}?xy=${x},${y}`; + + // FIXME + if (utils.createGeoLink(anchor)) { + range.deleteContents(); + range.insertNode(anchor); + } + }, + }); - if (createGeoLink(anchor)) { - range.deleteContents(); - range.insertNode(anchor); - } - }; -} export class Suggestion { constructor({ text, replace }) { this.text = text; @@ -161,11 +145,10 @@ export class Suggestion { } } -export const renderResults = (dumbymap, map) => +export const renderResults = ({ modal, modalContent }, map) => new Item({ text: 'Render Results', - onclick: e => { - const modal = dumbymap.modal; + onclick: () => { modal.open(); modal.overlayBlur = 3; modal.closeByEscKey = false; @@ -175,7 +158,7 @@ export const renderResults = (dumbymap, map) => map.renderer.results.forEach(result => printObject( result, - dumbymap.modalContent, + modalContent, `${result.func.name} (${result.state})`, ), ); @@ -195,7 +178,7 @@ function printObject(obj, parentElement, name) { if (typeof value === 'object') { printObject(value, detailsEle, key); } else { - let valueString = + const valueString = typeof value === 'function' ? `
${value}
` : value ?? typeof value; diff --git a/src/dumbyUtils.mjs b/src/dumbyUtils.mjs index e7edee3..71dc290 100644 --- a/src/dumbyUtils.mjs +++ b/src/dumbyUtils.mjs @@ -1,3 +1,5 @@ +import LeaderLine from 'leader-line'; + export function focusNextMap(reverse = false) { const renderedList = this.utils.renderedMaps(); const index = renderedList.findIndex(e => e.classList.contains('focus')); @@ -56,3 +58,70 @@ export function switchToNextLayout(reverse = false) { export function removeBlockFocus() { this.blocks.forEach(b => b.classList.remove('focus')); } + +/** + * Create geolinks, which points to map by geo schema and id + * + * @param {HTMLElement} Elements contains anchor elements for doclinks + * @returns {Boolean} ture is link is created, false if coordinates are invalid + */ +export const createGeoLink = (link, callback = null) => { + const url = new URL(link.href); + const xyInParams = url.searchParams.get('xy'); + const xy = xyInParams + ? xyInParams.split(',')?.map(Number) + : url?.href + ?.match(/^geo:([0-9.,]+)/) + ?.at(1) + ?.split(',') + ?.reverse() + ?.map(Number); + + if (!xy || isNaN(xy[0]) || isNaN(xy[1])) return false; + + // Geo information in link + link.url = url; + link.xy = xy; + link.classList.add('with-leader-line', 'geolink'); + link.targets = link.url.searchParams.get('id')?.split(',') ?? null; + + // LeaderLine + link.lines = []; + callback?.call(this, link); + + return true; +}; + +/** + * CreateDocLink. + * + * @param {HTMLElement} Elements contains anchor elements for doclinks + */ +export const createDocLink = link => { + link.classList.add('with-leader-line', 'doclink'); + link.lines = []; + + link.onmouseover = () => { + const label = decodeURIComponent(link.href.split('#')[1]); + const selector = link.title.split('=>')[1] ?? '#' + label; + const target = document.querySelector(selector); + if (!target?.checkVisibility()) return; + + const line = new LeaderLine({ + start: link, + end: target, + middleLabel: LeaderLine.pathLabel({ + text: label, + fontWeight: 'bold', + }), + hide: true, + path: 'magnet', + }); + link.lines.push(line); + line.show('draw', { duration: 300 }); + }; + link.onmouseout = () => { + link.lines.forEach(line => line.remove()); + link.lines.length = 0; + }; +}; diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index c7bdc92..72936ec 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -21,76 +21,6 @@ const layouts = [ ]; const mapCache = {}; -// FUNCTION: Get DocLinks from special anchor element {{{ -/** - * CreateDocLink. - * - * @param {HTMLElement} Elements contains anchor elements for doclinks - */ -export const createDocLink = link => { - link.classList.add('with-leader-line', 'doclink'); - link.lines = []; - - link.onmouseover = () => { - const label = decodeURIComponent(link.href.split('#')[1]); - const selector = link.title.split('=>')[1] ?? '#' + label; - const target = document.querySelector(selector); - if (!target?.checkVisibility()) return; - - const line = new LeaderLine({ - start: link, - end: target, - middleLabel: LeaderLine.pathLabel({ - text: label, - fontWeight: 'bold', - }), - hide: true, - path: 'magnet', - }); - link.lines.push(line); - line.show('draw', { duration: 300 }); - }; - link.onmouseout = () => { - link.lines.forEach(line => line.remove()); - link.lines.length = 0; - }; -}; -// }}} -// FUNCTION: Get GeoLinks from special anchor element {{{ -/** - * Create geolinks, which points to map by geo schema and id - * - * @param {HTMLElement} Elements contains anchor elements for doclinks - * @returns {Boolean} ture is link is created, false if coordinates are invalid - */ -export const createGeoLink = (link, callback = null) => { - const url = new URL(link.href); - const xyInParams = url.searchParams.get('xy'); - const xy = xyInParams - ? xyInParams.split(',')?.map(Number) - : url?.href - ?.match(/^geo:([0-9.,]+)/) - ?.at(1) - ?.split(',') - ?.reverse() - ?.map(Number); - - if (!xy || isNaN(xy[0]) || isNaN(xy[1])) return false; - - // Geo information in link - link.url = url; - link.xy = xy; - link.classList.add('with-leader-line', 'geolink'); - link.targets = link.url.searchParams.get('id')?.split(',') ?? null; - - // LeaderLine - link.lines = []; - callback?.call(this, link); - - return true; -}; -// }}} - export const markdown2HTML = (container, mdContent) => { // Render: Markdown -> HTML {{{ container.replaceChildren(); @@ -184,7 +114,9 @@ export const generateMaps = (container, { delay, mapCallback }) => { // LeaderLine {{{ - Array.from(container.querySelectorAll(docLinkSelector)).filter(createDocLink); + Array.from(container.querySelectorAll(docLinkSelector)).filter( + utils.createDocLink, + ); // Get anchors with "geo:" scheme htmlHolder.anchors = []; @@ -202,7 +134,7 @@ export const generateMaps = (container, { delay, mapCallback }) => { }; const geoLinks = Array.from( container.querySelectorAll(geoLinkSelector), - ).filter(l => createGeoLink(l, geoLinkCallback)); + ).filter(l => utils.createGeoLink(l, geoLinkCallback)); const isAnchorPointedBy = link => anchor => { const mapContainer = anchor.closest('.mapclay'); @@ -527,7 +459,6 @@ export const generateMaps = (container, { delay, mapCallback }) => { }); }); // }}} - // Menu {{{ const menu = document.createElement('div'); menu.className = 'menu'; -- cgit v1.2.3-70-g09d2