diff options
Diffstat (limited to 'src/editor.mjs')
-rw-r--r-- | src/editor.mjs | 96 |
1 files changed, 7 insertions, 89 deletions
diff --git a/src/editor.mjs b/src/editor.mjs index a8e3e0d..df6e3bf 100644 --- a/src/editor.mjs +++ b/src/editor.mjs | |||
@@ -4,7 +4,6 @@ import { defaultAliases, parseConfigsFromYaml } from 'mapclay' | |||
4 | import * as menuItem from './MenuItem' | 4 | import * as menuItem from './MenuItem' |
5 | import { addAnchorByPoint, createGeoLink } from './dumbyUtils.mjs' | 5 | import { addAnchorByPoint, createGeoLink } from './dumbyUtils.mjs' |
6 | import { shiftByWindow } from './utils.mjs' | 6 | import { shiftByWindow } from './utils.mjs' |
7 | import LeaderLine from 'leader-line' | ||
8 | import * as tutorial from './tutorial' | 7 | import * as tutorial from './tutorial' |
9 | 8 | ||
10 | /** | 9 | /** |
@@ -27,9 +26,11 @@ const context = document.querySelector('[data-mode]') | |||
27 | const textArea = document.querySelector('.editor textarea') | 26 | const textArea = document.querySelector('.editor textarea') |
28 | const dumbyContainer = document.querySelector('.DumbyMap') | 27 | const dumbyContainer = document.querySelector('.DumbyMap') |
29 | dumbyContainer.dataset.scrollLine = '' | 28 | dumbyContainer.dataset.scrollLine = '' |
30 | /** Watch: Layout of DumbyMap */ | 29 | /** Watch: DumbyMap */ |
31 | new window.MutationObserver(mutaions => { | 30 | new window.MutationObserver(mutations => { |
32 | const mutation = mutaions.at(-1) | 31 | const mutation = mutations.at(-1) |
32 | |||
33 | /** Handle layout change */ | ||
33 | const layout = dumbyContainer.dataset.layout | 34 | const layout = dumbyContainer.dataset.layout |
34 | if (layout !== 'normal' || mutation.oldValue === 'normal') { | 35 | if (layout !== 'normal' || mutation.oldValue === 'normal') { |
35 | context.dataset.mode = '' | 36 | context.dataset.mode = '' |
@@ -38,6 +39,8 @@ new window.MutationObserver(mutaions => { | |||
38 | attributes: true, | 39 | attributes: true, |
39 | attributeFilter: ['data-layout'], | 40 | attributeFilter: ['data-layout'], |
40 | attributeOldValue: true, | 41 | attributeOldValue: true, |
42 | childList: true, | ||
43 | subtree: true, | ||
41 | }) | 44 | }) |
42 | let dumbymap | 45 | let dumbymap |
43 | 46 | ||
@@ -1070,88 +1073,3 @@ document.addEventListener('selectionchange', () => { | |||
1070 | cm.scrollIntoView(focus) | 1073 | cm.scrollIntoView(focus) |
1071 | } | 1074 | } |
1072 | }) | 1075 | }) |
1073 | |||
1074 | /** Drag/Drop on map for new reference style link */ | ||
1075 | dumbyContainer.onmousedown = (e) => { | ||
1076 | // Check should start drag event for GeoLink | ||
1077 | if (e.which !== 1) return | ||
1078 | const selection = document.getSelection() | ||
1079 | if (cm.getSelection() === '' || selection.type !== 'Range') return | ||
1080 | const range = selection.getRangeAt(0) | ||
1081 | const rect = range.getBoundingClientRect() | ||
1082 | const mouseInRange = e.x < rect.right && e.x > rect.left && e.y < rect.bottom && e.y > rect.top | ||
1083 | if (!mouseInRange) return | ||
1084 | |||
1085 | const geoLink = document.createElement('a') | ||
1086 | geoLink.textContent = range.toString() | ||
1087 | geoLink.classList.add('with-leader-line', 'geolink', 'drag') | ||
1088 | const originContent = range.cloneContents() | ||
1089 | range.deleteContents() | ||
1090 | range.insertNode(geoLink) | ||
1091 | |||
1092 | const lineEnd = document.createElement('div') | ||
1093 | lineEnd.style.cssText = `position: absolute; left: ${e.clientX}px; top: ${e.clientY}px;` | ||
1094 | document.body.appendChild(lineEnd) | ||
1095 | |||
1096 | const line = new LeaderLine({ | ||
1097 | start: geoLink, | ||
1098 | end: lineEnd, | ||
1099 | path: 'magnet', | ||
1100 | }) | ||
1101 | |||
1102 | function onMouseMove (event) { | ||
1103 | lineEnd.style.left = event.clientX + 'px' | ||
1104 | lineEnd.style.top = event.clientY + 'px' | ||
1105 | line.position() | ||
1106 | |||
1107 | // TODO Scroll dumbymap.htmlHolder when cursor is at upper/lower side | ||
1108 | } | ||
1109 | |||
1110 | context.classList.add('dragging-geolink') | ||
1111 | dumbyContainer.onmousemove = onMouseMove | ||
1112 | dumbymap.utils.renderedMaps().forEach(map => { map.style.cursor = 'crosshair' }) | ||
1113 | dumbyContainer.onmouseup = function (e) { | ||
1114 | context.classList.remove('dragging-geolink') | ||
1115 | dumbyContainer.onmousemove = null | ||
1116 | dumbyContainer.onmouseup = null | ||
1117 | line?.remove() | ||
1118 | lineEnd.remove() | ||
1119 | dumbymap.utils.renderedMaps().forEach(map => map.style.removeProperty('cursor')) | ||
1120 | const resumeContent = () => { | ||
1121 | range.deleteContents() | ||
1122 | range.insertNode(originContent) | ||
1123 | } | ||
1124 | |||
1125 | const map = document.elementFromPoint(e.clientX, e.clientY) | ||
1126 | .closest('.mapclay[data-render="fulfilled"]') | ||
1127 | const selection = cm.getSelection() | ||
1128 | if (!map || !selection) { | ||
1129 | resumeContent('map/selection') | ||
1130 | return | ||
1131 | } | ||
1132 | |||
1133 | const refLink = addAnchorByPoint({ | ||
1134 | defaultName: geoLink.textContent, | ||
1135 | point: e, | ||
1136 | map, | ||
1137 | validateAnchorName, | ||
1138 | }) | ||
1139 | if (!refLink) { | ||
1140 | resumeContent('reflink') | ||
1141 | return | ||
1142 | } | ||
1143 | |||
1144 | const scrollTop = dumbymap.htmlHolder.scrollTop | ||
1145 | geoLink.href = refLink.link | ||
1146 | createGeoLink(geoLink) | ||
1147 | appendRefLink(cm, refLink) | ||
1148 | if (selection === refLink.ref) { | ||
1149 | cm.replaceSelection(`[${selection}]`) | ||
1150 | } else { | ||
1151 | cm.replaceSelection(`[${selection}][${refLink.ref}]`) | ||
1152 | } | ||
1153 | dumbymap.htmlHolder.scrollBy(0, scrollTop) | ||
1154 | } | ||
1155 | } | ||
1156 | |||
1157 | dumbyContainer.ondragstart = () => false | ||