@svgedit/svgcanvas 7.2.2 → 7.2.4
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 +7 -0
- package/core/coords.js +203 -99
- package/core/draw.js +288 -205
- package/core/event.js +6 -3
- package/core/json.js +1 -1
- package/core/math.js +138 -154
- package/core/recalculate.js +232 -613
- package/core/sanitize.js +3 -3
- package/core/selected-elem.js +1 -1
- package/core/selection.js +1 -1
- package/core/svg-exec.js +163 -140
- package/core/text-actions.js +160 -129
- package/dist/svgcanvas.js +20445 -19585
- package/dist/svgcanvas.js.map +1 -1
- package/package.json +1 -1
- package/rollup.config.mjs +1 -0
- package/svgcanvas.js +18 -1
package/core/draw.js
CHANGED
|
@@ -9,15 +9,14 @@ import Layer from './layer.js'
|
|
|
9
9
|
import HistoryRecordingService from './historyrecording.js'
|
|
10
10
|
|
|
11
11
|
import { NS } from './namespaces.js'
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
} from './utilities.js'
|
|
15
|
-
import {
|
|
16
|
-
copyElem as utilCopyElem
|
|
17
|
-
} from './copy-elem.js'
|
|
12
|
+
import { toXml, getElement } from './utilities.js'
|
|
13
|
+
import { copyElem as utilCopyElem } from './copy-elem.js'
|
|
18
14
|
import { getParentsUntil } from '../common/util.js'
|
|
19
15
|
|
|
20
|
-
const visElems =
|
|
16
|
+
const visElems =
|
|
17
|
+
'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(
|
|
18
|
+
','
|
|
19
|
+
)
|
|
21
20
|
|
|
22
21
|
const RandomizeModes = {
|
|
23
22
|
LET_DOCUMENT_DECIDE: 0,
|
|
@@ -47,6 +46,16 @@ function findLayerNameInGroup (group) {
|
|
|
47
46
|
return sel ? sel.textContent : ''
|
|
48
47
|
}
|
|
49
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Verify the classList of the given element : if the classList contains 'layer', return true, then return false
|
|
51
|
+
*
|
|
52
|
+
* @param {Element} element - The given element
|
|
53
|
+
* @returns {boolean} Return true if the classList contains 'layer' then return false
|
|
54
|
+
*/
|
|
55
|
+
function isLayerElement (element) {
|
|
56
|
+
return element.classList.contains('layer')
|
|
57
|
+
}
|
|
58
|
+
|
|
50
59
|
/**
|
|
51
60
|
* Given a set of names, return a new unique name.
|
|
52
61
|
* @param {string[]} existingLayerNames - Existing layer names.
|
|
@@ -54,9 +63,10 @@ function findLayerNameInGroup (group) {
|
|
|
54
63
|
*/
|
|
55
64
|
function getNewLayerName (existingLayerNames) {
|
|
56
65
|
let i = 1
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
while (existingLayerNames.includes(`Layer ${i}`)) {
|
|
67
|
+
i++
|
|
68
|
+
}
|
|
69
|
+
return `Layer ${i}`
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
/**
|
|
@@ -64,70 +74,77 @@ function getNewLayerName (existingLayerNames) {
|
|
|
64
74
|
*/
|
|
65
75
|
export class Drawing {
|
|
66
76
|
/**
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
* @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object
|
|
78
|
+
* encapsulates. If the svgElem has a se:nonce attribute on it, then
|
|
79
|
+
* IDs will use the nonce as they are generated.
|
|
80
|
+
* @param {string} [optIdPrefix=svg_] - The ID prefix to use.
|
|
81
|
+
* @throws {Error} If not initialized with an SVG element
|
|
82
|
+
*/
|
|
73
83
|
constructor (svgElem, optIdPrefix) {
|
|
74
|
-
if (
|
|
75
|
-
svgElem
|
|
76
|
-
|
|
84
|
+
if (
|
|
85
|
+
!svgElem ||
|
|
86
|
+
!svgElem.tagName ||
|
|
87
|
+
!svgElem.namespaceURI ||
|
|
88
|
+
svgElem.tagName !== 'svg' ||
|
|
89
|
+
svgElem.namespaceURI !== NS.SVG
|
|
90
|
+
) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
'Error: svgedit.draw.Drawing instance initialized without a <svg> element'
|
|
93
|
+
)
|
|
77
94
|
}
|
|
78
95
|
|
|
79
96
|
/**
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
97
|
+
* The SVG DOM Element that represents this drawing.
|
|
98
|
+
* @type {SVGSVGElement}
|
|
99
|
+
*/
|
|
83
100
|
this.svgElem_ = svgElem
|
|
84
101
|
|
|
85
102
|
/**
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
103
|
+
* The latest object number used in this drawing.
|
|
104
|
+
* @type {Integer}
|
|
105
|
+
*/
|
|
89
106
|
this.obj_num = 0
|
|
90
107
|
|
|
91
108
|
/**
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
109
|
+
* The prefix to prepend to each element id in the drawing.
|
|
110
|
+
* @type {string}
|
|
111
|
+
*/
|
|
95
112
|
this.idPrefix = optIdPrefix || 'svg_'
|
|
96
113
|
|
|
97
114
|
/**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
* An array of released element ids to immediately reuse.
|
|
116
|
+
* @type {Integer[]}
|
|
117
|
+
*/
|
|
101
118
|
this.releasedNums = []
|
|
102
119
|
|
|
103
120
|
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
121
|
+
* The z-ordered array of Layer objects. Each layer has a name
|
|
122
|
+
* and group element.
|
|
123
|
+
* The first layer is the one at the bottom of the rendering.
|
|
124
|
+
* @type {Layer[]}
|
|
125
|
+
*/
|
|
109
126
|
this.all_layers = []
|
|
110
127
|
|
|
111
128
|
/**
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
129
|
+
* Map of all_layers by name.
|
|
130
|
+
*
|
|
131
|
+
* Note: Layers are ordered, but referenced externally by name; so, we need both container
|
|
132
|
+
* types depending on which function is called (i.e. all_layers and layer_map).
|
|
133
|
+
*
|
|
134
|
+
* @type {PlainObject<string, Layer>}
|
|
135
|
+
*/
|
|
119
136
|
this.layer_map = {}
|
|
120
137
|
|
|
121
138
|
/**
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
139
|
+
* The current layer being used.
|
|
140
|
+
* @type {Layer}
|
|
141
|
+
*/
|
|
125
142
|
this.current_layer = null
|
|
126
143
|
|
|
127
144
|
/**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
145
|
+
* The nonce to use to uniquely identify elements across drawings.
|
|
146
|
+
* @type {!string}
|
|
147
|
+
*/
|
|
131
148
|
this.nonce_ = ''
|
|
132
149
|
const n = this.svgElem_.getAttributeNS(NS.SE, 'nonce')
|
|
133
150
|
// If already set in the DOM, use the nonce throughout the document
|
|
@@ -142,7 +159,7 @@ export class Drawing {
|
|
|
142
159
|
/**
|
|
143
160
|
* @param {string} id Element ID to retrieve
|
|
144
161
|
* @returns {Element} SVG element within the root SVGSVGElement
|
|
145
|
-
|
|
162
|
+
*/
|
|
146
163
|
getElem_ (id) {
|
|
147
164
|
if (this.svgElem_.querySelector) {
|
|
148
165
|
// querySelector lookup
|
|
@@ -238,7 +255,7 @@ export class Drawing {
|
|
|
238
255
|
* that client code will do this.
|
|
239
256
|
* @param {string} id - The id to release.
|
|
240
257
|
* @returns {boolean} True if the id was valid to be released, false otherwise.
|
|
241
|
-
|
|
258
|
+
*/
|
|
242
259
|
releaseId (id) {
|
|
243
260
|
// confirm if this is a valid id for this Document, else return false
|
|
244
261
|
const front = this.idPrefix + (this.nonce_ ? this.nonce_ + '_' : '')
|
|
@@ -250,7 +267,11 @@ export class Drawing {
|
|
|
250
267
|
|
|
251
268
|
// if we didn't get a positive number or we already released this number
|
|
252
269
|
// then return false.
|
|
253
|
-
if (
|
|
270
|
+
if (
|
|
271
|
+
typeof num !== 'number' ||
|
|
272
|
+
num <= 0 ||
|
|
273
|
+
this.releasedNums.includes(num)
|
|
274
|
+
) {
|
|
254
275
|
return false
|
|
255
276
|
}
|
|
256
277
|
|
|
@@ -263,7 +284,7 @@ export class Drawing {
|
|
|
263
284
|
/**
|
|
264
285
|
* Returns the number of layers in the current drawing.
|
|
265
286
|
* @returns {Integer} The number of layers in the current drawing.
|
|
266
|
-
|
|
287
|
+
*/
|
|
267
288
|
getNumLayers () {
|
|
268
289
|
return this.all_layers.length
|
|
269
290
|
}
|
|
@@ -272,7 +293,7 @@ export class Drawing {
|
|
|
272
293
|
* Check if layer with given name already exists.
|
|
273
294
|
* @param {string} name - The layer name to check
|
|
274
295
|
* @returns {boolean}
|
|
275
|
-
|
|
296
|
+
*/
|
|
276
297
|
hasLayer (name) {
|
|
277
298
|
return this.layer_map[name] !== undefined
|
|
278
299
|
}
|
|
@@ -281,7 +302,7 @@ export class Drawing {
|
|
|
281
302
|
* Returns the name of the ith layer. If the index is out of range, an empty string is returned.
|
|
282
303
|
* @param {Integer} i - The zero-based index of the layer you are querying.
|
|
283
304
|
* @returns {string} The name of the ith layer (or the empty string if none found)
|
|
284
|
-
|
|
305
|
+
*/
|
|
285
306
|
getLayerName (i) {
|
|
286
307
|
return i >= 0 && i < this.getNumLayers() ? this.all_layers[i].getName() : ''
|
|
287
308
|
}
|
|
@@ -307,7 +328,7 @@ export class Drawing {
|
|
|
307
328
|
* Returns the name of the currently selected layer. If an error occurs, an empty string
|
|
308
329
|
* is returned.
|
|
309
330
|
* @returns {string} The name of the currently active layer (or the empty string if none found).
|
|
310
|
-
|
|
331
|
+
*/
|
|
311
332
|
getCurrentLayerName () {
|
|
312
333
|
return this.current_layer ? this.current_layer.getName() : ''
|
|
313
334
|
}
|
|
@@ -343,7 +364,9 @@ export class Drawing {
|
|
|
343
364
|
}
|
|
344
365
|
|
|
345
366
|
const oldpos = this.indexCurrentLayer()
|
|
346
|
-
if (
|
|
367
|
+
if (oldpos === -1 || oldpos === newpos) {
|
|
368
|
+
return null
|
|
369
|
+
}
|
|
347
370
|
|
|
348
371
|
// if our new position is below us, we need to insert before the node after newpos
|
|
349
372
|
const currentGroup = this.current_layer.getGroup()
|
|
@@ -370,13 +393,15 @@ export class Drawing {
|
|
|
370
393
|
}
|
|
371
394
|
|
|
372
395
|
/**
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
396
|
+
* @param {module:history.HistoryRecordingService} hrService
|
|
397
|
+
* @returns {void}
|
|
398
|
+
*/
|
|
376
399
|
mergeLayer (hrService) {
|
|
377
400
|
const currentGroup = this.current_layer.getGroup()
|
|
378
401
|
const prevGroup = currentGroup.previousElementSibling
|
|
379
|
-
if (!prevGroup) {
|
|
402
|
+
if (!prevGroup) {
|
|
403
|
+
return
|
|
404
|
+
}
|
|
380
405
|
|
|
381
406
|
hrService.startBatchCommand('Merge Layer')
|
|
382
407
|
|
|
@@ -410,9 +435,9 @@ export class Drawing {
|
|
|
410
435
|
}
|
|
411
436
|
|
|
412
437
|
/**
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
438
|
+
* @param {module:history.HistoryRecordingService} hrService
|
|
439
|
+
* @returns {void}
|
|
440
|
+
*/
|
|
416
441
|
mergeAllLayers (hrService) {
|
|
417
442
|
// Set the current layer to the last layer.
|
|
418
443
|
this.current_layer = this.all_layers[this.all_layers.length - 1]
|
|
@@ -474,13 +499,14 @@ export class Drawing {
|
|
|
474
499
|
* Updates layer system and sets the current layer to the
|
|
475
500
|
* top-most layer (last `<g>` child of this drawing).
|
|
476
501
|
* @returns {void}
|
|
477
|
-
|
|
502
|
+
*/
|
|
478
503
|
identifyLayers () {
|
|
479
504
|
this.all_layers = []
|
|
480
505
|
this.layer_map = {}
|
|
481
506
|
const numchildren = this.svgElem_.childNodes.length
|
|
482
507
|
// loop through all children of SVG element
|
|
483
|
-
const orphans = []
|
|
508
|
+
const orphans = []
|
|
509
|
+
const layernames = []
|
|
484
510
|
let layer = null
|
|
485
511
|
let childgroups = false
|
|
486
512
|
for (let i = 0; i < numchildren; ++i) {
|
|
@@ -489,8 +515,8 @@ export class Drawing {
|
|
|
489
515
|
if (child?.nodeType === 1) {
|
|
490
516
|
if (child.tagName === 'g') {
|
|
491
517
|
childgroups = true
|
|
492
|
-
|
|
493
|
-
|
|
518
|
+
if (isLayerElement(child)) {
|
|
519
|
+
const name = findLayerNameInGroup(child)
|
|
494
520
|
layernames.push(name)
|
|
495
521
|
layer = new Layer(name, child)
|
|
496
522
|
this.all_layers.push(layer)
|
|
@@ -508,7 +534,8 @@ export class Drawing {
|
|
|
508
534
|
|
|
509
535
|
// If orphans or no layers found, create a new layer and add all the orphans to it
|
|
510
536
|
if (orphans.length > 0 || !childgroups) {
|
|
511
|
-
|
|
537
|
+
const name = getNewLayerName(layernames)
|
|
538
|
+
layer = new Layer(name, null, this.svgElem_)
|
|
512
539
|
layer.appendChildren(orphans)
|
|
513
540
|
this.all_layers.push(layer)
|
|
514
541
|
this.layer_map[name] = layer
|
|
@@ -525,13 +552,18 @@ export class Drawing {
|
|
|
525
552
|
* @param {module:history.HistoryRecordingService} hrService - History recording service
|
|
526
553
|
* @returns {SVGGElement} The SVGGElement of the new layer, which is
|
|
527
554
|
* also the current layer of this drawing.
|
|
528
|
-
|
|
555
|
+
*/
|
|
529
556
|
createLayer (name, hrService) {
|
|
530
557
|
if (this.current_layer) {
|
|
531
558
|
this.current_layer.deactivate()
|
|
532
559
|
}
|
|
533
560
|
// Check for duplicate name.
|
|
534
|
-
if (
|
|
561
|
+
if (
|
|
562
|
+
name === undefined ||
|
|
563
|
+
name === null ||
|
|
564
|
+
name === '' ||
|
|
565
|
+
this.layer_map[name]
|
|
566
|
+
) {
|
|
535
567
|
name = getNewLayerName(Object.keys(this.layer_map))
|
|
536
568
|
}
|
|
537
569
|
|
|
@@ -556,12 +588,19 @@ export class Drawing {
|
|
|
556
588
|
* @param {module:history.HistoryRecordingService} hrService - History recording service
|
|
557
589
|
* @returns {SVGGElement} The SVGGElement of the new layer, which is
|
|
558
590
|
* also the current layer of this drawing.
|
|
559
|
-
|
|
591
|
+
*/
|
|
560
592
|
cloneLayer (name, hrService) {
|
|
561
|
-
if (!this.current_layer) {
|
|
593
|
+
if (!this.current_layer) {
|
|
594
|
+
return null
|
|
595
|
+
}
|
|
562
596
|
this.current_layer.deactivate()
|
|
563
597
|
// Check for duplicate name.
|
|
564
|
-
if (
|
|
598
|
+
if (
|
|
599
|
+
name === undefined ||
|
|
600
|
+
name === null ||
|
|
601
|
+
name === '' ||
|
|
602
|
+
this.layer_map[name]
|
|
603
|
+
) {
|
|
565
604
|
name = getNewLayerName(Object.keys(this.layer_map))
|
|
566
605
|
}
|
|
567
606
|
|
|
@@ -572,8 +611,10 @@ export class Drawing {
|
|
|
572
611
|
|
|
573
612
|
// Clone children
|
|
574
613
|
const children = [...currentGroup.childNodes]
|
|
575
|
-
children.forEach(
|
|
576
|
-
if (child.localName === 'title') {
|
|
614
|
+
children.forEach(child => {
|
|
615
|
+
if (child.localName === 'title') {
|
|
616
|
+
return
|
|
617
|
+
}
|
|
577
618
|
group.append(this.copyElem(child))
|
|
578
619
|
})
|
|
579
620
|
|
|
@@ -600,7 +641,7 @@ export class Drawing {
|
|
|
600
641
|
* then this function returns `false`.
|
|
601
642
|
* @param {string} layerName - The name of the layer which you want to query.
|
|
602
643
|
* @returns {boolean} The visibility state of the layer, or `false` if the layer name was invalid.
|
|
603
|
-
|
|
644
|
+
*/
|
|
604
645
|
getLayerVisibility (layerName) {
|
|
605
646
|
const layer = this.layer_map[layerName]
|
|
606
647
|
return layer ? layer.isVisible() : false
|
|
@@ -614,13 +655,15 @@ export class Drawing {
|
|
|
614
655
|
* @param {boolean} bVisible - Whether the layer should be visible
|
|
615
656
|
* @returns {?SVGGElement} The SVGGElement representing the layer if the
|
|
616
657
|
* `layerName` was valid, otherwise `null`.
|
|
617
|
-
|
|
658
|
+
*/
|
|
618
659
|
setLayerVisibility (layerName, bVisible) {
|
|
619
660
|
if (typeof bVisible !== 'boolean') {
|
|
620
661
|
return null
|
|
621
662
|
}
|
|
622
663
|
const layer = this.layer_map[layerName]
|
|
623
|
-
if (!layer) {
|
|
664
|
+
if (!layer) {
|
|
665
|
+
return null
|
|
666
|
+
}
|
|
624
667
|
layer.setVisible(bVisible)
|
|
625
668
|
return layer.getGroup()
|
|
626
669
|
}
|
|
@@ -630,10 +673,12 @@ export class Drawing {
|
|
|
630
673
|
* @param {string} layerName - name of the layer on which to get the opacity
|
|
631
674
|
* @returns {?Float} The opacity value of the given layer. This will be a value between 0.0 and 1.0, or `null`
|
|
632
675
|
* if `layerName` is not a valid layer
|
|
633
|
-
|
|
676
|
+
*/
|
|
634
677
|
getLayerOpacity (layerName) {
|
|
635
678
|
const layer = this.layer_map[layerName]
|
|
636
|
-
if (!layer) {
|
|
679
|
+
if (!layer) {
|
|
680
|
+
return null
|
|
681
|
+
}
|
|
637
682
|
return layer.getOpacity()
|
|
638
683
|
}
|
|
639
684
|
|
|
@@ -648,7 +693,7 @@ export class Drawing {
|
|
|
648
693
|
* @param {string} layerName - Name of the layer on which to set the opacity
|
|
649
694
|
* @param {Float} opacity - A float value in the range 0.0-1.0
|
|
650
695
|
* @returns {void}
|
|
651
|
-
|
|
696
|
+
*/
|
|
652
697
|
setLayerOpacity (layerName, opacity) {
|
|
653
698
|
if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) {
|
|
654
699
|
return
|
|
@@ -666,7 +711,9 @@ export class Drawing {
|
|
|
666
711
|
*/
|
|
667
712
|
copyElem (el) {
|
|
668
713
|
const that = this
|
|
669
|
-
const getNextIdClosure = function () {
|
|
714
|
+
const getNextIdClosure = function () {
|
|
715
|
+
return that.getNextId()
|
|
716
|
+
}
|
|
670
717
|
return utilCopyElem(el, getNextIdClosure)
|
|
671
718
|
}
|
|
672
719
|
}
|
|
@@ -680,13 +727,20 @@ export class Drawing {
|
|
|
680
727
|
* @returns {void}
|
|
681
728
|
*/
|
|
682
729
|
export const randomizeIds = function (enableRandomization, currentDrawing) {
|
|
683
|
-
randIds =
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
730
|
+
randIds =
|
|
731
|
+
enableRandomization === false
|
|
732
|
+
? RandomizeModes.NEVER_RANDOMIZE
|
|
733
|
+
: RandomizeModes.ALWAYS_RANDOMIZE
|
|
734
|
+
|
|
735
|
+
if (
|
|
736
|
+
randIds === RandomizeModes.ALWAYS_RANDOMIZE &&
|
|
737
|
+
!currentDrawing.getNonce()
|
|
738
|
+
) {
|
|
688
739
|
currentDrawing.setNonce(Math.floor(Math.random() * 100001))
|
|
689
|
-
} else if (
|
|
740
|
+
} else if (
|
|
741
|
+
randIds === RandomizeModes.NEVER_RANDOMIZE &&
|
|
742
|
+
currentDrawing.getNonce()
|
|
743
|
+
) {
|
|
690
744
|
currentDrawing.clearNonce()
|
|
691
745
|
}
|
|
692
746
|
}
|
|
@@ -694,8 +748,8 @@ export const randomizeIds = function (enableRandomization, currentDrawing) {
|
|
|
694
748
|
// Layer API Functions
|
|
695
749
|
|
|
696
750
|
/**
|
|
697
|
-
* Group: Layers.
|
|
698
|
-
*/
|
|
751
|
+
* Group: Layers.
|
|
752
|
+
*/
|
|
699
753
|
|
|
700
754
|
/**
|
|
701
755
|
* @see {@link https://api.jquery.com/jQuery.data/}
|
|
@@ -715,11 +769,11 @@ export const randomizeIds = function (enableRandomization, currentDrawing) {
|
|
|
715
769
|
* @function module:draw.DrawCanvasInit#setCurrentGroup
|
|
716
770
|
* @param {Element} cg
|
|
717
771
|
* @returns {void}
|
|
718
|
-
*/
|
|
772
|
+
*/
|
|
719
773
|
/**
|
|
720
774
|
* @function module:draw.DrawCanvasInit#getSelectedElements
|
|
721
775
|
* @returns {Element[]} the array with selected DOM elements
|
|
722
|
-
*/
|
|
776
|
+
*/
|
|
723
777
|
/**
|
|
724
778
|
* @function module:draw.DrawCanvasInit#getSvgContent
|
|
725
779
|
* @returns {SVGSVGElement}
|
|
@@ -732,7 +786,7 @@ export const randomizeIds = function (enableRandomization, currentDrawing) {
|
|
|
732
786
|
* @function module:draw.DrawCanvasInit#clearSelection
|
|
733
787
|
* @param {boolean} [noCall] - When `true`, does not call the "selected" handler
|
|
734
788
|
* @returns {void}
|
|
735
|
-
*/
|
|
789
|
+
*/
|
|
736
790
|
/**
|
|
737
791
|
* Run the callback function associated with the given event.
|
|
738
792
|
* @function module:draw.DrawCanvasInit#call
|
|
@@ -746,7 +800,7 @@ export const randomizeIds = function (enableRandomization, currentDrawing) {
|
|
|
746
800
|
* @function module:draw.DrawCanvasInit#addCommandToHistory
|
|
747
801
|
* @param {Command} cmd
|
|
748
802
|
* @returns {void}
|
|
749
|
-
*/
|
|
803
|
+
*/
|
|
750
804
|
/**
|
|
751
805
|
* @function module:draw.DrawCanvasInit#changeSvgContent
|
|
752
806
|
* @returns {void}
|
|
@@ -754,48 +808,47 @@ export const randomizeIds = function (enableRandomization, currentDrawing) {
|
|
|
754
808
|
|
|
755
809
|
let svgCanvas
|
|
756
810
|
/**
|
|
757
|
-
* @function module:draw.init
|
|
758
|
-
* @param {module:draw.DrawCanvasInit} canvas
|
|
759
|
-
* @returns {void}
|
|
760
|
-
*/
|
|
761
|
-
export const init =
|
|
811
|
+
* @function module:draw.init
|
|
812
|
+
* @param {module:draw.DrawCanvasInit} canvas
|
|
813
|
+
* @returns {void}
|
|
814
|
+
*/
|
|
815
|
+
export const init = canvas => {
|
|
762
816
|
svgCanvas = canvas
|
|
763
817
|
}
|
|
764
818
|
|
|
765
819
|
/**
|
|
766
|
-
* Updates layer system.
|
|
767
|
-
* @function module:draw.identifyLayers
|
|
768
|
-
* @returns {void}
|
|
769
|
-
*/
|
|
820
|
+
* Updates layer system.
|
|
821
|
+
* @function module:draw.identifyLayers
|
|
822
|
+
* @returns {void}
|
|
823
|
+
*/
|
|
770
824
|
export const identifyLayers = () => {
|
|
771
825
|
leaveContext()
|
|
772
826
|
svgCanvas.getCurrentDrawing().identifyLayers()
|
|
773
827
|
}
|
|
774
828
|
|
|
775
829
|
/**
|
|
776
|
-
* get current index
|
|
777
|
-
* @function module:draw.identifyLayers
|
|
778
|
-
* @returns {void}
|
|
779
|
-
*/
|
|
830
|
+
* get current index
|
|
831
|
+
* @function module:draw.identifyLayers
|
|
832
|
+
* @returns {void}
|
|
833
|
+
*/
|
|
780
834
|
export const indexCurrentLayer = () => {
|
|
781
835
|
return svgCanvas.getCurrentDrawing().indexCurrentLayer()
|
|
782
836
|
}
|
|
783
837
|
|
|
784
838
|
/**
|
|
785
|
-
* Creates a new top-level layer in the drawing with the given name, sets the current layer
|
|
786
|
-
* to it, and then clears the selection. This function then calls the 'changed' handler.
|
|
787
|
-
* This is an undoable action.
|
|
788
|
-
* @function module:draw.createLayer
|
|
789
|
-
* @param {string} name - The given name
|
|
790
|
-
* @param {module:history.HistoryRecordingService} hrService
|
|
791
|
-
* @fires module:svgcanvas.SvgCanvas#event:changed
|
|
792
|
-
* @returns {void}
|
|
793
|
-
*/
|
|
839
|
+
* Creates a new top-level layer in the drawing with the given name, sets the current layer
|
|
840
|
+
* to it, and then clears the selection. This function then calls the 'changed' handler.
|
|
841
|
+
* This is an undoable action.
|
|
842
|
+
* @function module:draw.createLayer
|
|
843
|
+
* @param {string} name - The given name
|
|
844
|
+
* @param {module:history.HistoryRecordingService} hrService
|
|
845
|
+
* @fires module:svgcanvas.SvgCanvas#event:changed
|
|
846
|
+
* @returns {void}
|
|
847
|
+
*/
|
|
794
848
|
export const createLayer = (name, hrService) => {
|
|
795
|
-
const newLayer = svgCanvas
|
|
796
|
-
|
|
797
|
-
historyRecordingService(hrService)
|
|
798
|
-
)
|
|
849
|
+
const newLayer = svgCanvas
|
|
850
|
+
.getCurrentDrawing()
|
|
851
|
+
.createLayer(name, historyRecordingService(hrService))
|
|
799
852
|
svgCanvas.clearSelection()
|
|
800
853
|
svgCanvas.call('changed', [newLayer])
|
|
801
854
|
}
|
|
@@ -812,7 +865,9 @@ export const createLayer = (name, hrService) => {
|
|
|
812
865
|
*/
|
|
813
866
|
export const cloneLayer = (name, hrService) => {
|
|
814
867
|
// Clone the current layer and make the cloned layer the new current layer
|
|
815
|
-
const newLayer = svgCanvas
|
|
868
|
+
const newLayer = svgCanvas
|
|
869
|
+
.getCurrentDrawing()
|
|
870
|
+
.cloneLayer(name, historyRecordingService(hrService))
|
|
816
871
|
|
|
817
872
|
svgCanvas.clearSelection()
|
|
818
873
|
leaveContext()
|
|
@@ -820,12 +875,12 @@ export const cloneLayer = (name, hrService) => {
|
|
|
820
875
|
}
|
|
821
876
|
|
|
822
877
|
/**
|
|
823
|
-
* Deletes the current layer from the drawing and then clears the selection. This function
|
|
824
|
-
* then calls the 'changed' handler. This is an undoable action.
|
|
825
|
-
* @function module:draw.deleteCurrentLayer
|
|
826
|
-
* @fires module:svgcanvas.SvgCanvas#event:changed
|
|
827
|
-
* @returns {boolean} `true` if an old layer group was found to delete
|
|
828
|
-
*/
|
|
878
|
+
* Deletes the current layer from the drawing and then clears the selection. This function
|
|
879
|
+
* then calls the 'changed' handler. This is an undoable action.
|
|
880
|
+
* @function module:draw.deleteCurrentLayer
|
|
881
|
+
* @fires module:svgcanvas.SvgCanvas#event:changed
|
|
882
|
+
* @returns {boolean} `true` if an old layer group was found to delete
|
|
883
|
+
*/
|
|
829
884
|
export const deleteCurrentLayer = () => {
|
|
830
885
|
const { BatchCommand, RemoveElementCommand } = svgCanvas.history
|
|
831
886
|
let currentLayer = svgCanvas.getCurrentDrawing().getCurrentLayer()
|
|
@@ -835,7 +890,9 @@ export const deleteCurrentLayer = () => {
|
|
|
835
890
|
if (currentLayer) {
|
|
836
891
|
const batchCmd = new BatchCommand('Delete Layer')
|
|
837
892
|
// store in our Undo History
|
|
838
|
-
batchCmd.addSubCommand(
|
|
893
|
+
batchCmd.addSubCommand(
|
|
894
|
+
new RemoveElementCommand(currentLayer, nextSibling, parent)
|
|
895
|
+
)
|
|
839
896
|
svgCanvas.addCommandToHistory(batchCmd)
|
|
840
897
|
svgCanvas.clearSelection()
|
|
841
898
|
svgCanvas.call('changed', [parent])
|
|
@@ -845,13 +902,13 @@ export const deleteCurrentLayer = () => {
|
|
|
845
902
|
}
|
|
846
903
|
|
|
847
904
|
/**
|
|
848
|
-
* Sets the current layer. If the name is not a valid layer name, then this function returns
|
|
849
|
-
* false. Otherwise it returns true. This is not an undo-able action.
|
|
850
|
-
* @function module:draw.setCurrentLayer
|
|
851
|
-
* @param {string} name - The name of the layer you want to switch to.
|
|
852
|
-
* @returns {boolean} true if the current layer was switched, otherwise false
|
|
853
|
-
*/
|
|
854
|
-
export const setCurrentLayer =
|
|
905
|
+
* Sets the current layer. If the name is not a valid layer name, then this function returns
|
|
906
|
+
* false. Otherwise it returns true. This is not an undo-able action.
|
|
907
|
+
* @function module:draw.setCurrentLayer
|
|
908
|
+
* @param {string} name - The name of the layer you want to switch to.
|
|
909
|
+
* @returns {boolean} true if the current layer was switched, otherwise false
|
|
910
|
+
*/
|
|
911
|
+
export const setCurrentLayer = name => {
|
|
855
912
|
const result = svgCanvas.getCurrentDrawing().setCurrentLayer(toXml(name))
|
|
856
913
|
if (result) {
|
|
857
914
|
svgCanvas.clearSelection()
|
|
@@ -860,19 +917,22 @@ export const setCurrentLayer = (name) => {
|
|
|
860
917
|
}
|
|
861
918
|
|
|
862
919
|
/**
|
|
863
|
-
* Renames the current layer. If the layer name is not valid (i.e. unique), then this function
|
|
864
|
-
* does nothing and returns `false`, otherwise it returns `true`. This is an undo-able action.
|
|
865
|
-
* @function module:draw.renameCurrentLayer
|
|
866
|
-
* @param {string} newName - the new name you want to give the current layer. This name must
|
|
867
|
-
* be unique among all layer names.
|
|
868
|
-
* @fires module:svgcanvas.SvgCanvas#event:changed
|
|
869
|
-
* @returns {boolean} Whether the rename succeeded
|
|
870
|
-
*/
|
|
871
|
-
export const renameCurrentLayer =
|
|
920
|
+
* Renames the current layer. If the layer name is not valid (i.e. unique), then this function
|
|
921
|
+
* does nothing and returns `false`, otherwise it returns `true`. This is an undo-able action.
|
|
922
|
+
* @function module:draw.renameCurrentLayer
|
|
923
|
+
* @param {string} newName - the new name you want to give the current layer. This name must
|
|
924
|
+
* be unique among all layer names.
|
|
925
|
+
* @fires module:svgcanvas.SvgCanvas#event:changed
|
|
926
|
+
* @returns {boolean} Whether the rename succeeded
|
|
927
|
+
*/
|
|
928
|
+
export const renameCurrentLayer = newName => {
|
|
872
929
|
const drawing = svgCanvas.getCurrentDrawing()
|
|
873
930
|
const layer = drawing.getCurrentLayer()
|
|
874
931
|
if (layer) {
|
|
875
|
-
const result = drawing.setCurrentLayerName(
|
|
932
|
+
const result = drawing.setCurrentLayerName(
|
|
933
|
+
newName,
|
|
934
|
+
historyRecordingService()
|
|
935
|
+
)
|
|
876
936
|
if (result) {
|
|
877
937
|
svgCanvas.call('changed', [layer])
|
|
878
938
|
return true
|
|
@@ -882,33 +942,39 @@ export const renameCurrentLayer = (newName) => {
|
|
|
882
942
|
}
|
|
883
943
|
|
|
884
944
|
/**
|
|
885
|
-
* Changes the position of the current layer to the new value. If the new index is not valid,
|
|
886
|
-
* this function does nothing and returns false, otherwise it returns true. This is an
|
|
887
|
-
* undo-able action.
|
|
888
|
-
* @function module:draw.setCurrentLayerPosition
|
|
889
|
-
* @param {Integer} newPos - The zero-based index of the new position of the layer. This should be between
|
|
890
|
-
* 0 and (number of layers - 1)
|
|
891
|
-
* @returns {boolean} `true` if the current layer position was changed, `false` otherwise.
|
|
892
|
-
*/
|
|
893
|
-
export const setCurrentLayerPosition =
|
|
945
|
+
* Changes the position of the current layer to the new value. If the new index is not valid,
|
|
946
|
+
* this function does nothing and returns false, otherwise it returns true. This is an
|
|
947
|
+
* undo-able action.
|
|
948
|
+
* @function module:draw.setCurrentLayerPosition
|
|
949
|
+
* @param {Integer} newPos - The zero-based index of the new position of the layer. This should be between
|
|
950
|
+
* 0 and (number of layers - 1)
|
|
951
|
+
* @returns {boolean} `true` if the current layer position was changed, `false` otherwise.
|
|
952
|
+
*/
|
|
953
|
+
export const setCurrentLayerPosition = newPos => {
|
|
894
954
|
const { MoveElementCommand } = svgCanvas.history
|
|
895
955
|
const drawing = svgCanvas.getCurrentDrawing()
|
|
896
956
|
const result = drawing.setCurrentLayerPosition(newPos)
|
|
897
957
|
if (result) {
|
|
898
|
-
svgCanvas.addCommandToHistory(
|
|
958
|
+
svgCanvas.addCommandToHistory(
|
|
959
|
+
new MoveElementCommand(
|
|
960
|
+
result.currentGroup,
|
|
961
|
+
result.oldNextSibling,
|
|
962
|
+
svgCanvas.getSvgContent()
|
|
963
|
+
)
|
|
964
|
+
)
|
|
899
965
|
return true
|
|
900
966
|
}
|
|
901
967
|
return false
|
|
902
968
|
}
|
|
903
969
|
|
|
904
970
|
/**
|
|
905
|
-
* Sets the visibility of the layer. If the layer name is not valid, this function return
|
|
906
|
-
* `false`, otherwise it returns `true`. This is an undo-able action.
|
|
907
|
-
* @function module:draw.setLayerVisibility
|
|
908
|
-
* @param {string} layerName - The name of the layer to change the visibility
|
|
909
|
-
* @param {boolean} bVisible - Whether the layer should be visible
|
|
910
|
-
* @returns {boolean} true if the layer's visibility was set, false otherwise
|
|
911
|
-
*/
|
|
971
|
+
* Sets the visibility of the layer. If the layer name is not valid, this function return
|
|
972
|
+
* `false`, otherwise it returns `true`. This is an undo-able action.
|
|
973
|
+
* @function module:draw.setLayerVisibility
|
|
974
|
+
* @param {string} layerName - The name of the layer to change the visibility
|
|
975
|
+
* @param {boolean} bVisible - Whether the layer should be visible
|
|
976
|
+
* @returns {boolean} true if the layer's visibility was set, false otherwise
|
|
977
|
+
*/
|
|
912
978
|
export const setLayerVisibility = (layerName, bVisible) => {
|
|
913
979
|
const { ChangeElementCommand } = svgCanvas.history
|
|
914
980
|
const drawing = svgCanvas.getCurrentDrawing()
|
|
@@ -916,7 +982,13 @@ export const setLayerVisibility = (layerName, bVisible) => {
|
|
|
916
982
|
const layer = drawing.setLayerVisibility(layerName, bVisible)
|
|
917
983
|
if (layer) {
|
|
918
984
|
const oldDisplay = prevVisibility ? 'inline' : 'none'
|
|
919
|
-
svgCanvas.addCommandToHistory(
|
|
985
|
+
svgCanvas.addCommandToHistory(
|
|
986
|
+
new ChangeElementCommand(
|
|
987
|
+
layer,
|
|
988
|
+
{ display: oldDisplay },
|
|
989
|
+
'Layer Visibility'
|
|
990
|
+
)
|
|
991
|
+
)
|
|
920
992
|
} else {
|
|
921
993
|
return false
|
|
922
994
|
}
|
|
@@ -930,18 +1002,20 @@ export const setLayerVisibility = (layerName, bVisible) => {
|
|
|
930
1002
|
}
|
|
931
1003
|
|
|
932
1004
|
/**
|
|
933
|
-
* Moves the selected elements to layerName. If the name is not a valid layer name, then `false`
|
|
934
|
-
* is returned. Otherwise it returns `true`. This is an undo-able action.
|
|
935
|
-
* @function module:draw.moveSelectedToLayer
|
|
936
|
-
* @param {string} layerName - The name of the layer you want to which you want to move the selected elements
|
|
937
|
-
* @returns {boolean} Whether the selected elements were moved to the layer.
|
|
938
|
-
*/
|
|
939
|
-
export const moveSelectedToLayer =
|
|
1005
|
+
* Moves the selected elements to layerName. If the name is not a valid layer name, then `false`
|
|
1006
|
+
* is returned. Otherwise it returns `true`. This is an undo-able action.
|
|
1007
|
+
* @function module:draw.moveSelectedToLayer
|
|
1008
|
+
* @param {string} layerName - The name of the layer you want to which you want to move the selected elements
|
|
1009
|
+
* @returns {boolean} Whether the selected elements were moved to the layer.
|
|
1010
|
+
*/
|
|
1011
|
+
export const moveSelectedToLayer = layerName => {
|
|
940
1012
|
const { BatchCommand, MoveElementCommand } = svgCanvas.history
|
|
941
1013
|
// find the layer
|
|
942
1014
|
const drawing = svgCanvas.getCurrentDrawing()
|
|
943
1015
|
const layer = drawing.getLayerByName(layerName)
|
|
944
|
-
if (!layer) {
|
|
1016
|
+
if (!layer) {
|
|
1017
|
+
return false
|
|
1018
|
+
}
|
|
945
1019
|
|
|
946
1020
|
const batchCmd = new BatchCommand('Move Elements to Layer')
|
|
947
1021
|
|
|
@@ -950,12 +1024,16 @@ export const moveSelectedToLayer = (layerName) => {
|
|
|
950
1024
|
let i = selElems.length
|
|
951
1025
|
while (i--) {
|
|
952
1026
|
const elem = selElems[i]
|
|
953
|
-
if (!elem) {
|
|
1027
|
+
if (!elem) {
|
|
1028
|
+
continue
|
|
1029
|
+
}
|
|
954
1030
|
const oldNextSibling = elem.nextSibling
|
|
955
1031
|
// TODO: this is pretty brittle!
|
|
956
1032
|
const oldLayer = elem.parentNode
|
|
957
1033
|
layer.append(elem)
|
|
958
|
-
batchCmd.addSubCommand(
|
|
1034
|
+
batchCmd.addSubCommand(
|
|
1035
|
+
new MoveElementCommand(elem, oldNextSibling, oldLayer)
|
|
1036
|
+
)
|
|
959
1037
|
}
|
|
960
1038
|
|
|
961
1039
|
svgCanvas.addCommandToHistory(batchCmd)
|
|
@@ -964,11 +1042,11 @@ export const moveSelectedToLayer = (layerName) => {
|
|
|
964
1042
|
}
|
|
965
1043
|
|
|
966
1044
|
/**
|
|
967
|
-
* @function module:draw.mergeLayer
|
|
968
|
-
* @param {module:history.HistoryRecordingService} hrService
|
|
969
|
-
* @returns {void}
|
|
970
|
-
*/
|
|
971
|
-
export const mergeLayer =
|
|
1045
|
+
* @function module:draw.mergeLayer
|
|
1046
|
+
* @param {module:history.HistoryRecordingService} hrService
|
|
1047
|
+
* @returns {void}
|
|
1048
|
+
*/
|
|
1049
|
+
export const mergeLayer = hrService => {
|
|
972
1050
|
svgCanvas.getCurrentDrawing().mergeLayer(historyRecordingService(hrService))
|
|
973
1051
|
svgCanvas.clearSelection()
|
|
974
1052
|
leaveContext()
|
|
@@ -976,24 +1054,26 @@ export const mergeLayer = (hrService) => {
|
|
|
976
1054
|
}
|
|
977
1055
|
|
|
978
1056
|
/**
|
|
979
|
-
* @function module:draw.mergeAllLayers
|
|
980
|
-
* @param {module:history.HistoryRecordingService} hrService
|
|
981
|
-
* @returns {void}
|
|
982
|
-
*/
|
|
983
|
-
export const mergeAllLayers =
|
|
984
|
-
svgCanvas
|
|
1057
|
+
* @function module:draw.mergeAllLayers
|
|
1058
|
+
* @param {module:history.HistoryRecordingService} hrService
|
|
1059
|
+
* @returns {void}
|
|
1060
|
+
*/
|
|
1061
|
+
export const mergeAllLayers = hrService => {
|
|
1062
|
+
svgCanvas
|
|
1063
|
+
.getCurrentDrawing()
|
|
1064
|
+
.mergeAllLayers(historyRecordingService(hrService))
|
|
985
1065
|
svgCanvas.clearSelection()
|
|
986
1066
|
leaveContext()
|
|
987
1067
|
svgCanvas.changeSvgContent()
|
|
988
1068
|
}
|
|
989
1069
|
|
|
990
1070
|
/**
|
|
991
|
-
* Return from a group context to the regular kind, make any previously
|
|
992
|
-
* disabled elements enabled again.
|
|
993
|
-
* @function module:draw.leaveContext
|
|
994
|
-
* @fires module:svgcanvas.SvgCanvas#event:contextset
|
|
995
|
-
* @returns {void}
|
|
996
|
-
*/
|
|
1071
|
+
* Return from a group context to the regular kind, make any previously
|
|
1072
|
+
* disabled elements enabled again.
|
|
1073
|
+
* @function module:draw.leaveContext
|
|
1074
|
+
* @fires module:svgcanvas.SvgCanvas#event:contextset
|
|
1075
|
+
* @returns {void}
|
|
1076
|
+
*/
|
|
997
1077
|
export const leaveContext = () => {
|
|
998
1078
|
const len = disabledElems.length
|
|
999
1079
|
const dataStorage = svgCanvas.getDataStorage()
|
|
@@ -1016,13 +1096,13 @@ export const leaveContext = () => {
|
|
|
1016
1096
|
}
|
|
1017
1097
|
|
|
1018
1098
|
/**
|
|
1019
|
-
* Set the current context (for in-group editing).
|
|
1020
|
-
* @function module:draw.setContext
|
|
1021
|
-
* @param {Element} elem
|
|
1022
|
-
* @fires module:svgcanvas.SvgCanvas#event:contextset
|
|
1023
|
-
* @returns {void}
|
|
1024
|
-
*/
|
|
1025
|
-
export const setContext =
|
|
1099
|
+
* Set the current context (for in-group editing).
|
|
1100
|
+
* @function module:draw.setContext
|
|
1101
|
+
* @param {Element} elem
|
|
1102
|
+
* @fires module:svgcanvas.SvgCanvas#event:contextset
|
|
1103
|
+
* @returns {void}
|
|
1104
|
+
*/
|
|
1105
|
+
export const setContext = elem => {
|
|
1026
1106
|
const dataStorage = svgCanvas.getDataStorage()
|
|
1027
1107
|
leaveContext()
|
|
1028
1108
|
if (typeof elem === 'string') {
|
|
@@ -1036,9 +1116,12 @@ export const setContext = (elem) => {
|
|
|
1036
1116
|
const parentsUntil = getParentsUntil(elem, '#svgcontent')
|
|
1037
1117
|
const siblings = []
|
|
1038
1118
|
parentsUntil.forEach(function (parent) {
|
|
1039
|
-
const elements = Array.prototype.filter.call(
|
|
1040
|
-
|
|
1041
|
-
|
|
1119
|
+
const elements = Array.prototype.filter.call(
|
|
1120
|
+
parent.parentNode.children,
|
|
1121
|
+
function (child) {
|
|
1122
|
+
return child !== parent
|
|
1123
|
+
}
|
|
1124
|
+
)
|
|
1042
1125
|
elements.forEach(function (element) {
|
|
1043
1126
|
siblings.push(element)
|
|
1044
1127
|
})
|
|
@@ -1057,8 +1140,8 @@ export const setContext = (elem) => {
|
|
|
1057
1140
|
}
|
|
1058
1141
|
|
|
1059
1142
|
/**
|
|
1060
|
-
* @memberof module:draw
|
|
1061
|
-
* @class Layer
|
|
1062
|
-
* @see {@link module:layer.Layer}
|
|
1063
|
-
*/
|
|
1143
|
+
* @memberof module:draw
|
|
1144
|
+
* @class Layer
|
|
1145
|
+
* @see {@link module:layer.Layer}
|
|
1146
|
+
*/
|
|
1064
1147
|
export { Layer }
|