@svgedit/svgcanvas 7.2.6 → 7.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.md +6 -0
- package/common/browser.js +104 -37
- package/common/logger.js +151 -0
- package/common/util.js +96 -155
- package/core/blur-event.js +106 -42
- package/core/clear.js +13 -3
- package/core/coords.js +214 -90
- package/core/copy-elem.js +27 -13
- package/core/dataStorage.js +84 -21
- package/core/draw.js +80 -40
- package/core/elem-get-set.js +161 -77
- package/core/event.js +143 -28
- package/core/history.js +51 -31
- package/core/historyrecording.js +4 -2
- package/core/json.js +54 -12
- package/core/layer.js +11 -17
- package/core/math.js +102 -23
- package/core/namespaces.js +5 -5
- package/core/paint.js +100 -23
- package/core/paste-elem.js +58 -19
- package/core/path-actions.js +812 -791
- package/core/path-method.js +236 -37
- package/core/path.js +45 -10
- package/core/recalculate.js +438 -24
- package/core/sanitize.js +71 -34
- package/core/select.js +44 -20
- package/core/selected-elem.js +146 -31
- package/core/selection.js +16 -6
- package/core/svg-exec.js +103 -29
- package/core/svgroot.js +1 -1
- package/core/text-actions.js +327 -306
- package/core/undo.js +20 -5
- package/core/units.js +8 -6
- package/core/utilities.js +316 -203
- package/dist/svgcanvas.js +31616 -53281
- package/dist/svgcanvas.js.map +1 -1
- package/package.json +55 -54
- package/publish.md +1 -6
- package/svgcanvas.d.ts +225 -0
- package/svgcanvas.js +9 -9
- package/vite.config.mjs +20 -0
- package/rollup.config.mjs +0 -38
package/core/copy-elem.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { preventClickDefault } from './utilities.js'
|
|
2
|
+
import dataStorage from './dataStorage.js'
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Create a clone of an element, updating its ID and its children's IDs when needed.
|
|
@@ -7,37 +8,50 @@ import { preventClickDefault } from './utilities.js'
|
|
|
7
8
|
* @param {module:utilities.GetNextID} getNextId - The getter of the next unique ID.
|
|
8
9
|
* @returns {Element} The cloned element
|
|
9
10
|
*/
|
|
10
|
-
export const copyElem =
|
|
11
|
+
export const copyElem = (el, getNextId) => {
|
|
12
|
+
const ownerDocument = el?.ownerDocument || document
|
|
11
13
|
// manually create a copy of the element
|
|
12
|
-
const newEl =
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
const newEl = ownerDocument.createElementNS(el.namespaceURI, el.nodeName)
|
|
15
|
+
Array.from(el.attributes).forEach((attr) => {
|
|
16
|
+
if (attr.namespaceURI) {
|
|
17
|
+
newEl.setAttributeNS(attr.namespaceURI, attr.name, attr.value)
|
|
18
|
+
} else {
|
|
19
|
+
newEl.setAttribute(attr.name, attr.value)
|
|
20
|
+
}
|
|
15
21
|
})
|
|
16
22
|
// set the copied element's new id
|
|
17
23
|
newEl.removeAttribute('id')
|
|
18
24
|
newEl.id = getNextId()
|
|
19
25
|
|
|
20
26
|
// now create copies of all children
|
|
21
|
-
el.childNodes.forEach(
|
|
27
|
+
el.childNodes.forEach((child) => {
|
|
22
28
|
switch (child.nodeType) {
|
|
23
29
|
case 1: // element node
|
|
24
30
|
newEl.append(copyElem(child, getNextId))
|
|
25
31
|
break
|
|
26
32
|
case 3: // text node
|
|
27
|
-
|
|
33
|
+
case 4: // cdata section node
|
|
34
|
+
newEl.append(ownerDocument.createTextNode(child.nodeValue ?? ''))
|
|
28
35
|
break
|
|
29
36
|
default:
|
|
30
37
|
break
|
|
31
38
|
}
|
|
32
39
|
})
|
|
33
40
|
|
|
34
|
-
if (el
|
|
35
|
-
newEl.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
if (dataStorage.has(el, 'gsvg')) {
|
|
42
|
+
const firstChild = newEl.firstElementChild || newEl.firstChild
|
|
43
|
+
if (firstChild) {
|
|
44
|
+
dataStorage.put(newEl, 'gsvg', firstChild)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (dataStorage.has(el, 'symbol')) {
|
|
48
|
+
dataStorage.put(newEl, 'symbol', dataStorage.get(el, 'symbol'))
|
|
49
|
+
}
|
|
50
|
+
if (dataStorage.has(el, 'ref')) {
|
|
51
|
+
dataStorage.put(newEl, 'ref', dataStorage.get(el, 'ref'))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (newEl.tagName === 'image') {
|
|
41
55
|
preventClickDefault(newEl)
|
|
42
56
|
}
|
|
43
57
|
|
package/core/dataStorage.js
CHANGED
|
@@ -1,28 +1,91 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
/**
|
|
2
|
+
* A storage solution aimed at replacing jQuery's data function.
|
|
3
|
+
* Implementation Note: Elements are stored in a [WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap).
|
|
4
|
+
* This makes sure the data is garbage collected when the node is removed.
|
|
5
|
+
*
|
|
6
|
+
* @module dataStorage
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
class DataStorage {
|
|
10
|
+
#storage = new WeakMap()
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Checks if the provided element is a valid WeakMap key.
|
|
14
|
+
* @param {any} element - The element to validate
|
|
15
|
+
* @returns {boolean} True if the element can be used as a WeakMap key
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
#isValidKey = (element) => {
|
|
19
|
+
return element !== null && (typeof element === 'object' || typeof element === 'function')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Stores data associated with an element.
|
|
24
|
+
* @param {Object|Function} element - The element to store data for
|
|
25
|
+
* @param {string} key - The key to store the data under
|
|
26
|
+
* @param {any} obj - The data to store
|
|
27
|
+
* @returns {void}
|
|
28
|
+
*/
|
|
29
|
+
put (element, key, obj) {
|
|
30
|
+
if (!this.#isValidKey(element)) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
let elementMap = this.#storage.get(element)
|
|
34
|
+
if (!elementMap) {
|
|
35
|
+
elementMap = new Map()
|
|
36
|
+
this.#storage.set(element, elementMap)
|
|
37
|
+
}
|
|
38
|
+
elementMap.set(key, obj)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Retrieves data associated with an element.
|
|
43
|
+
* @param {Object|Function} element - The element to retrieve data for
|
|
44
|
+
* @param {string} key - The key the data was stored under
|
|
45
|
+
* @returns {any|undefined} The stored data, or undefined if not found
|
|
46
|
+
*/
|
|
47
|
+
get (element, key) {
|
|
48
|
+
if (!this.#isValidKey(element)) {
|
|
49
|
+
return undefined
|
|
50
|
+
}
|
|
51
|
+
return this.#storage.get(element)?.get(key)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Checks if an element has data stored under a specific key.
|
|
56
|
+
* @param {Object|Function} element - The element to check
|
|
57
|
+
* @param {string} key - The key to check for
|
|
58
|
+
* @returns {boolean} True if the element has data stored under the key
|
|
59
|
+
*/
|
|
60
|
+
has (element, key) {
|
|
61
|
+
if (!this.#isValidKey(element)) {
|
|
62
|
+
return false
|
|
63
|
+
}
|
|
64
|
+
return this.#storage.get(element)?.has(key) === true
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Removes data associated with an element.
|
|
69
|
+
* @param {Object|Function} element - The element to remove data from
|
|
70
|
+
* @param {string} key - The key the data was stored under
|
|
71
|
+
* @returns {boolean} True if the data was removed, false otherwise
|
|
72
|
+
*/
|
|
73
|
+
remove (element, key) {
|
|
74
|
+
if (!this.#isValidKey(element)) {
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
const elementMap = this.#storage.get(element)
|
|
78
|
+
if (!elementMap) {
|
|
79
|
+
return false
|
|
10
80
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return this._storage.get(element)?.get(key)
|
|
15
|
-
},
|
|
16
|
-
has: function (element, key) {
|
|
17
|
-
return this._storage.has(element) && this._storage.get(element).has(key)
|
|
18
|
-
},
|
|
19
|
-
remove: function (element, key) {
|
|
20
|
-
const ret = this._storage.get(element).delete(key)
|
|
21
|
-
if (this._storage.get(element).size === 0) {
|
|
22
|
-
this._storage.delete(element)
|
|
81
|
+
const ret = elementMap.delete(key)
|
|
82
|
+
if (elementMap.size === 0) {
|
|
83
|
+
this.#storage.delete(element)
|
|
23
84
|
}
|
|
24
85
|
return ret
|
|
25
86
|
}
|
|
26
87
|
}
|
|
27
88
|
|
|
89
|
+
// Export singleton instance for backward compatibility
|
|
90
|
+
const dataStorage = new DataStorage()
|
|
28
91
|
export default dataStorage
|
package/core/draw.js
CHANGED
|
@@ -12,6 +12,7 @@ import { NS } from './namespaces.js'
|
|
|
12
12
|
import { toXml, getElement } from './utilities.js'
|
|
13
13
|
import { copyElem as utilCopyElem } from './copy-elem.js'
|
|
14
14
|
import { getParentsUntil } from '../common/util.js'
|
|
15
|
+
import { warn } from '../common/logger.js'
|
|
15
16
|
|
|
16
17
|
const visElems =
|
|
17
18
|
'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(
|
|
@@ -32,7 +33,7 @@ let disabledElems = []
|
|
|
32
33
|
* @param {module:history.HistoryRecordingService} [hrService] - if exists, return it instead of creating a new service.
|
|
33
34
|
* @returns {module:history.HistoryRecordingService}
|
|
34
35
|
*/
|
|
35
|
-
|
|
36
|
+
const historyRecordingService = (hrService) => {
|
|
36
37
|
return hrService || new HistoryRecordingService(svgCanvas.undoMgr)
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -41,18 +42,18 @@ function historyRecordingService (hrService) {
|
|
|
41
42
|
* @param {Element} group The group element to search in.
|
|
42
43
|
* @returns {string} The layer name or empty string.
|
|
43
44
|
*/
|
|
44
|
-
|
|
45
|
+
const findLayerNameInGroup = (group) => {
|
|
45
46
|
const sel = group.querySelector('title')
|
|
46
47
|
return sel ? sel.textContent : ''
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
|
-
*
|
|
51
|
+
* Checks if the given element's classList contains 'layer'.
|
|
51
52
|
*
|
|
52
53
|
* @param {Element} element - The given element
|
|
53
|
-
* @returns {boolean}
|
|
54
|
+
* @returns {boolean} True if the classList contains 'layer', false otherwise
|
|
54
55
|
*/
|
|
55
|
-
|
|
56
|
+
const isLayerElement = (element) => {
|
|
56
57
|
return element.classList.contains('layer')
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -61,7 +62,7 @@ function isLayerElement (element) {
|
|
|
61
62
|
* @param {string[]} existingLayerNames - Existing layer names.
|
|
62
63
|
* @returns {string} - The new name.
|
|
63
64
|
*/
|
|
64
|
-
|
|
65
|
+
const getNewLayerName = (existingLayerNames) => {
|
|
65
66
|
let i = 1
|
|
66
67
|
while (existingLayerNames.includes(`Layer ${i}`)) {
|
|
67
68
|
i++
|
|
@@ -163,10 +164,10 @@ export class Drawing {
|
|
|
163
164
|
getElem_ (id) {
|
|
164
165
|
if (this.svgElem_.querySelector) {
|
|
165
166
|
// querySelector lookup
|
|
166
|
-
return this.svgElem_.querySelector(
|
|
167
|
+
return this.svgElem_.querySelector(`#${id}`)
|
|
167
168
|
}
|
|
168
169
|
// jQuery lookup: twice as slow as xpath in FF
|
|
169
|
-
return this.svgElem_.querySelector(
|
|
170
|
+
return this.svgElem_.querySelector(`[id=${id}]`)
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
/**
|
|
@@ -209,7 +210,7 @@ export class Drawing {
|
|
|
209
210
|
*/
|
|
210
211
|
getId () {
|
|
211
212
|
return this.nonce_
|
|
212
|
-
? this.idPrefix
|
|
213
|
+
? `${this.idPrefix}${this.nonce_}_${this.obj_num}`
|
|
213
214
|
: this.idPrefix + this.obj_num
|
|
214
215
|
}
|
|
215
216
|
|
|
@@ -258,12 +259,16 @@ export class Drawing {
|
|
|
258
259
|
*/
|
|
259
260
|
releaseId (id) {
|
|
260
261
|
// confirm if this is a valid id for this Document, else return false
|
|
261
|
-
const front = this.idPrefix
|
|
262
|
+
const front = `${this.idPrefix}${this.nonce_ ? `${this.nonce_}_` : ''}`
|
|
262
263
|
if (typeof id !== 'string' || !id.startsWith(front)) {
|
|
263
264
|
return false
|
|
264
265
|
}
|
|
265
266
|
// extract the obj_num of this id
|
|
266
|
-
const
|
|
267
|
+
const suffix = id.slice(front.length)
|
|
268
|
+
if (!/^[0-9]+$/.test(suffix)) {
|
|
269
|
+
return false
|
|
270
|
+
}
|
|
271
|
+
const num = Number.parseInt(suffix)
|
|
267
272
|
|
|
268
273
|
// if we didn't get a positive number or we already released this number
|
|
269
274
|
// then return false.
|
|
@@ -612,6 +617,10 @@ export class Drawing {
|
|
|
612
617
|
// Clone children
|
|
613
618
|
const children = [...currentGroup.childNodes]
|
|
614
619
|
children.forEach(child => {
|
|
620
|
+
if (child.nodeType !== 1) {
|
|
621
|
+
group.append(child.cloneNode(true))
|
|
622
|
+
return
|
|
623
|
+
}
|
|
615
624
|
if (child.localName === 'title') {
|
|
616
625
|
return
|
|
617
626
|
}
|
|
@@ -710,10 +719,7 @@ export class Drawing {
|
|
|
710
719
|
* @returns {Element}
|
|
711
720
|
*/
|
|
712
721
|
copyElem (el) {
|
|
713
|
-
const
|
|
714
|
-
const getNextIdClosure = function () {
|
|
715
|
-
return that.getNextId()
|
|
716
|
-
}
|
|
722
|
+
const getNextIdClosure = () => this.getNextId()
|
|
717
723
|
return utilCopyElem(el, getNextIdClosure)
|
|
718
724
|
}
|
|
719
725
|
}
|
|
@@ -726,7 +732,7 @@ export class Drawing {
|
|
|
726
732
|
* @param {draw.Drawing} currentDrawing
|
|
727
733
|
* @returns {void}
|
|
728
734
|
*/
|
|
729
|
-
export const randomizeIds =
|
|
735
|
+
export const randomizeIds = (enableRandomization, currentDrawing) => {
|
|
730
736
|
randIds =
|
|
731
737
|
enableRandomization === false
|
|
732
738
|
? RandomizeModes.NEVER_RANDOMIZE
|
|
@@ -868,6 +874,10 @@ export const cloneLayer = (name, hrService) => {
|
|
|
868
874
|
const newLayer = svgCanvas
|
|
869
875
|
.getCurrentDrawing()
|
|
870
876
|
.cloneLayer(name, historyRecordingService(hrService))
|
|
877
|
+
if (!newLayer) {
|
|
878
|
+
warn('cloneLayer: no layer returned', null, 'draw')
|
|
879
|
+
return
|
|
880
|
+
}
|
|
871
881
|
|
|
872
882
|
svgCanvas.clearSelection()
|
|
873
883
|
leaveContext()
|
|
@@ -883,15 +893,19 @@ export const cloneLayer = (name, hrService) => {
|
|
|
883
893
|
*/
|
|
884
894
|
export const deleteCurrentLayer = () => {
|
|
885
895
|
const { BatchCommand, RemoveElementCommand } = svgCanvas.history
|
|
886
|
-
|
|
896
|
+
const currentLayer = svgCanvas.getCurrentDrawing().getCurrentLayer()
|
|
897
|
+
if (!currentLayer) {
|
|
898
|
+
warn('deleteCurrentLayer: no current layer', null, 'draw')
|
|
899
|
+
return false
|
|
900
|
+
}
|
|
887
901
|
const { nextSibling } = currentLayer
|
|
888
902
|
const parent = currentLayer.parentNode
|
|
889
|
-
|
|
890
|
-
if (
|
|
903
|
+
const removedLayer = svgCanvas.getCurrentDrawing().deleteCurrentLayer()
|
|
904
|
+
if (removedLayer && parent) {
|
|
891
905
|
const batchCmd = new BatchCommand('Delete Layer')
|
|
892
906
|
// store in our Undo History
|
|
893
907
|
batchCmd.addSubCommand(
|
|
894
|
-
new RemoveElementCommand(
|
|
908
|
+
new RemoveElementCommand(removedLayer, nextSibling, parent)
|
|
895
909
|
)
|
|
896
910
|
svgCanvas.addCommandToHistory(batchCmd)
|
|
897
911
|
svgCanvas.clearSelection()
|
|
@@ -978,20 +992,19 @@ export const setCurrentLayerPosition = newPos => {
|
|
|
978
992
|
export const setLayerVisibility = (layerName, bVisible) => {
|
|
979
993
|
const { ChangeElementCommand } = svgCanvas.history
|
|
980
994
|
const drawing = svgCanvas.getCurrentDrawing()
|
|
981
|
-
const
|
|
995
|
+
const layerGroup = drawing.getLayerByName(layerName)
|
|
996
|
+
if (!layerGroup) {
|
|
997
|
+
warn('setLayerVisibility: layer not found', layerName, 'draw')
|
|
998
|
+
return false
|
|
999
|
+
}
|
|
1000
|
+
const oldDisplay = layerGroup.getAttribute('display')
|
|
982
1001
|
const layer = drawing.setLayerVisibility(layerName, bVisible)
|
|
983
|
-
if (layer) {
|
|
984
|
-
const oldDisplay = prevVisibility ? 'inline' : 'none'
|
|
985
|
-
svgCanvas.addCommandToHistory(
|
|
986
|
-
new ChangeElementCommand(
|
|
987
|
-
layer,
|
|
988
|
-
{ display: oldDisplay },
|
|
989
|
-
'Layer Visibility'
|
|
990
|
-
)
|
|
991
|
-
)
|
|
992
|
-
} else {
|
|
1002
|
+
if (!layer) {
|
|
993
1003
|
return false
|
|
994
1004
|
}
|
|
1005
|
+
svgCanvas.addCommandToHistory(
|
|
1006
|
+
new ChangeElementCommand(layer, { display: oldDisplay }, 'Layer Visibility')
|
|
1007
|
+
)
|
|
995
1008
|
|
|
996
1009
|
if (layer === drawing.getCurrentLayer()) {
|
|
997
1010
|
svgCanvas.clearSelection()
|
|
@@ -1024,18 +1037,21 @@ export const moveSelectedToLayer = layerName => {
|
|
|
1024
1037
|
let i = selElems.length
|
|
1025
1038
|
while (i--) {
|
|
1026
1039
|
const elem = selElems[i]
|
|
1027
|
-
|
|
1040
|
+
const oldLayer = elem?.parentNode
|
|
1041
|
+
if (!elem || !oldLayer || oldLayer === layer) {
|
|
1028
1042
|
continue
|
|
1029
1043
|
}
|
|
1030
1044
|
const oldNextSibling = elem.nextSibling
|
|
1031
|
-
// TODO: this is pretty brittle!
|
|
1032
|
-
const oldLayer = elem.parentNode
|
|
1033
1045
|
layer.append(elem)
|
|
1034
1046
|
batchCmd.addSubCommand(
|
|
1035
1047
|
new MoveElementCommand(elem, oldNextSibling, oldLayer)
|
|
1036
1048
|
)
|
|
1037
1049
|
}
|
|
1038
1050
|
|
|
1051
|
+
if (batchCmd.isEmpty()) {
|
|
1052
|
+
warn('moveSelectedToLayer: no elements moved', null, 'draw')
|
|
1053
|
+
return false
|
|
1054
|
+
}
|
|
1039
1055
|
svgCanvas.addCommandToHistory(batchCmd)
|
|
1040
1056
|
|
|
1041
1057
|
return true
|
|
@@ -1081,12 +1097,13 @@ export const leaveContext = () => {
|
|
|
1081
1097
|
for (let i = 0; i < len; i++) {
|
|
1082
1098
|
const elem = disabledElems[i]
|
|
1083
1099
|
const orig = dataStorage.get(elem, 'orig_opac')
|
|
1084
|
-
if (orig
|
|
1085
|
-
elem.setAttribute('opacity', orig)
|
|
1086
|
-
} else {
|
|
1100
|
+
if (orig === null || orig === undefined) {
|
|
1087
1101
|
elem.removeAttribute('opacity')
|
|
1102
|
+
} else {
|
|
1103
|
+
elem.setAttribute('opacity', orig)
|
|
1088
1104
|
}
|
|
1089
1105
|
elem.setAttribute('style', 'pointer-events: inherit')
|
|
1106
|
+
dataStorage.remove(elem, 'orig_opac')
|
|
1090
1107
|
}
|
|
1091
1108
|
disabledElems = []
|
|
1092
1109
|
svgCanvas.clearSelection(true)
|
|
@@ -1106,7 +1123,22 @@ export const setContext = elem => {
|
|
|
1106
1123
|
const dataStorage = svgCanvas.getDataStorage()
|
|
1107
1124
|
leaveContext()
|
|
1108
1125
|
if (typeof elem === 'string') {
|
|
1109
|
-
|
|
1126
|
+
const id = elem
|
|
1127
|
+
try {
|
|
1128
|
+
elem = getElement(id)
|
|
1129
|
+
} catch (e) {
|
|
1130
|
+
elem = null
|
|
1131
|
+
}
|
|
1132
|
+
if (!elem && typeof document !== 'undefined') {
|
|
1133
|
+
const candidate = document.getElementById(id)
|
|
1134
|
+
const svgContent = svgCanvas.getSvgContent?.()
|
|
1135
|
+
elem = candidate && (svgContent ? svgContent.contains(candidate) : true)
|
|
1136
|
+
? candidate
|
|
1137
|
+
: null
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
if (!elem) {
|
|
1141
|
+
return
|
|
1110
1142
|
}
|
|
1111
1143
|
|
|
1112
1144
|
// Edit inside this group
|
|
@@ -1114,8 +1146,14 @@ export const setContext = elem => {
|
|
|
1114
1146
|
|
|
1115
1147
|
// Disable other elements
|
|
1116
1148
|
const parentsUntil = getParentsUntil(elem, '#svgcontent')
|
|
1149
|
+
if (!parentsUntil) {
|
|
1150
|
+
return
|
|
1151
|
+
}
|
|
1117
1152
|
const siblings = []
|
|
1118
1153
|
parentsUntil.forEach(function (parent) {
|
|
1154
|
+
if (!parent?.parentNode) {
|
|
1155
|
+
return
|
|
1156
|
+
}
|
|
1119
1157
|
const elements = Array.prototype.filter.call(
|
|
1120
1158
|
parent.parentNode.children,
|
|
1121
1159
|
function (child) {
|
|
@@ -1128,9 +1166,11 @@ export const setContext = elem => {
|
|
|
1128
1166
|
})
|
|
1129
1167
|
|
|
1130
1168
|
siblings.forEach(function (curthis) {
|
|
1131
|
-
const opac = curthis.getAttribute('opacity') || 1
|
|
1132
1169
|
// Store the original's opacity
|
|
1133
|
-
|
|
1170
|
+
const origOpacity = curthis.getAttribute('opacity')
|
|
1171
|
+
dataStorage.put(curthis, 'orig_opac', origOpacity)
|
|
1172
|
+
const parsedOpacity = Number.parseFloat(origOpacity)
|
|
1173
|
+
const opac = Number.isFinite(parsedOpacity) ? parsedOpacity : 1
|
|
1134
1174
|
curthis.setAttribute('opacity', opac * 0.33)
|
|
1135
1175
|
curthis.setAttribute('style', 'pointer-events: none')
|
|
1136
1176
|
disabledElems.push(curthis)
|