abcjs 6.0.0-beta.8 → 6.0.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/.github/workflows/tests.yml +29 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/CONTRIBUTING.md +1 -0
- package/LICENSE.md +1 -1
- package/README.md +92 -3
- package/RELEASE.md +959 -1
- package/abcjs-audio.css +14 -5
- package/dist/.gitignore +1 -2
- package/dist/abcjs-basic-min.js +3 -0
- package/dist/abcjs-basic-min.js.LICENSE +23 -0
- package/dist/abcjs-basic.js +28232 -0
- package/dist/abcjs-basic.js.map +1 -0
- package/dist/abcjs-plugin-min.js +3 -0
- package/dist/abcjs-plugin-min.js.LICENSE +23 -0
- package/dist/report-basic.html +37 -0
- package/dist/report-before-glyph-compress.html +37 -0
- package/dist/report-brown-ts-target-es5.html +37 -0
- package/dist/report-dev-orig-no-babel.html +37 -0
- package/dist/report-synth.html +37 -0
- package/docker-build.sh +1 -0
- package/glyphs.json +1 -0
- package/index.js +27 -2
- package/{static-wrappers/license.js → license.js} +1 -1
- package/package.json +26 -29
- package/{src/plugin/abc_plugin.js → plugin.js} +31 -19
- package/src/api/abc_animation.js +1 -17
- package/src/api/abc_tablatures.js +144 -0
- package/src/api/abc_timing_callbacks.js +239 -116
- package/src/api/abc_tunebook.js +18 -67
- package/src/api/abc_tunebook_svg.js +38 -46
- package/src/data/abc_tune.js +232 -972
- package/src/data/deline-tune.js +199 -0
- package/src/edit/abc_editarea.js +112 -0
- package/src/edit/abc_editor.js +95 -221
- package/src/midi/abc_midi_create.js +48 -50
- package/src/parse/abc_common.js +0 -14
- package/src/parse/abc_parse.js +167 -1321
- package/src/parse/abc_parse_book.js +62 -0
- package/src/parse/abc_parse_directive.js +164 -41
- package/src/parse/abc_parse_header.js +116 -145
- package/src/parse/abc_parse_key_voice.js +26 -20
- package/src/parse/abc_parse_music.js +1337 -0
- package/src/parse/abc_tokenizer.js +21 -15
- package/src/parse/abc_transpose.js +3 -15
- package/src/parse/tune-builder.js +896 -0
- package/src/parse/wrap_lines.js +205 -453
- package/src/synth/abc_midi_flattener.js +1292 -0
- package/src/{midi → synth}/abc_midi_renderer.js +44 -17
- package/src/synth/abc_midi_sequencer.js +648 -0
- package/src/synth/active-audio-context.js +3 -14
- package/src/synth/cents-to-factor.js +10 -0
- package/src/synth/create-note-map.js +21 -32
- package/src/synth/create-synth-control.js +20 -103
- package/src/synth/create-synth.js +185 -77
- package/src/synth/download-buffer.js +7 -21
- package/src/synth/get-midi-file.js +13 -20
- package/src/synth/images/{loading.svg → loading.svg.js} +4 -0
- package/src/synth/images/loop.svg.js +65 -0
- package/src/synth/images/pause.svg.js +10 -0
- package/src/synth/images/play.svg.js +9 -0
- package/src/synth/images/{reset.svg → reset.svg.js} +5 -1
- package/src/synth/instrument-index-to-name.js +1 -16
- package/src/synth/load-note.js +37 -76
- package/src/synth/pitch-to-note-name.js +0 -15
- package/src/synth/pitches-to-perc.js +64 -0
- package/src/synth/place-note.js +78 -68
- package/src/synth/play-event.js +17 -18
- package/src/synth/register-audio-context.js +11 -23
- package/src/synth/sounds-cache.js +0 -15
- package/src/synth/supports-audio.js +9 -23
- package/src/synth/synth-controller.js +80 -49
- package/src/synth/synth-sequence.js +20 -34
- package/src/tablatures/instruments/guitar/guitar-fonts.js +19 -0
- package/src/tablatures/instruments/guitar/guitar-patterns.js +23 -0
- package/src/tablatures/instruments/guitar/tab-guitar.js +50 -0
- package/src/tablatures/instruments/string-patterns.js +277 -0
- package/src/tablatures/instruments/string-tablature.js +56 -0
- package/src/tablatures/instruments/tab-note.js +282 -0
- package/src/tablatures/instruments/tab-notes.js +41 -0
- package/src/tablatures/instruments/violin/tab-violin.js +47 -0
- package/src/tablatures/instruments/violin/violin-fonts.js +19 -0
- package/src/tablatures/instruments/violin/violin-patterns.js +23 -0
- package/src/tablatures/tab-absolute-elements.js +310 -0
- package/src/tablatures/tab-common.js +29 -0
- package/src/tablatures/tab-renderer.js +243 -0
- package/src/tablatures/transposer.js +110 -0
- package/src/test/abc_midi_lint.js +5 -22
- package/src/test/abc_midi_sequencer_lint.js +11 -14
- package/src/test/abc_parser_lint.js +136 -32
- package/src/test/abc_vertical_lint.js +94 -32
- package/src/test/rendering-lint.js +38 -5
- package/src/write/abc_absolute_element.js +112 -120
- package/src/write/abc_abstract_engraver.js +102 -253
- package/src/write/abc_beam_element.js +30 -290
- package/src/write/abc_brace_element.js +12 -121
- package/src/write/abc_create_clef.js +21 -32
- package/src/write/abc_create_key_signature.js +8 -26
- package/src/write/abc_create_note_head.js +107 -0
- package/src/write/abc_create_time_signature.js +2 -21
- package/src/write/abc_crescendo_element.js +3 -50
- package/src/write/abc_decoration.js +7 -30
- package/src/write/abc_dynamic_decoration.js +3 -37
- package/src/write/abc_ending_element.js +1 -57
- package/src/write/abc_engraver_controller.js +111 -234
- package/src/write/abc_glyphs.js +8 -18
- package/src/write/abc_relative_element.js +57 -97
- package/src/write/abc_renderer.js +10 -832
- package/src/write/abc_spacing.js +0 -15
- package/src/write/abc_staff_group_element.js +14 -349
- package/src/write/abc_tempo_element.js +9 -117
- package/src/write/abc_tie_element.js +5 -68
- package/src/write/abc_triplet_element.js +6 -124
- package/src/write/abc_voice_element.js +7 -222
- package/src/write/add-chord.js +103 -0
- package/src/write/add-text-if.js +33 -0
- package/src/write/bottom-text.js +79 -0
- package/src/write/calcHeight.js +17 -0
- package/src/write/classes.js +100 -0
- package/src/write/draw/absolute.js +68 -0
- package/src/write/draw/beam.js +56 -0
- package/src/write/draw/brace.js +106 -0
- package/src/write/draw/crescendo.js +38 -0
- package/src/write/draw/debug-box.js +8 -0
- package/src/write/draw/draw.js +56 -0
- package/src/write/draw/dynamics.js +20 -0
- package/src/write/draw/ending.js +46 -0
- package/src/write/draw/group-elements.js +66 -0
- package/src/write/draw/horizontal-line.js +25 -0
- package/src/write/draw/non-music.js +50 -0
- package/src/write/draw/print-line.js +24 -0
- package/src/write/draw/print-path.js +7 -0
- package/src/write/draw/print-stem.js +30 -0
- package/src/write/draw/print-symbol.js +59 -0
- package/src/write/draw/print-vertical-line.js +18 -0
- package/src/write/draw/relative.js +77 -0
- package/src/write/draw/round-number.js +5 -0
- package/src/write/draw/selectables.js +59 -0
- package/src/write/draw/separator.js +16 -0
- package/src/write/draw/set-paper-size.js +45 -0
- package/src/write/{sprintf.js → draw/sprintf.js} +0 -0
- package/src/write/draw/staff-group.js +226 -0
- package/src/write/draw/staff-line.js +9 -0
- package/src/write/draw/staff.js +33 -0
- package/src/write/draw/tab-line.js +40 -0
- package/src/write/draw/tempo.js +45 -0
- package/src/write/draw/text.js +71 -0
- package/src/write/draw/tie.js +97 -0
- package/src/write/draw/triplet.js +46 -0
- package/src/write/draw/voice.js +102 -0
- package/src/write/format-jazz-chord.js +15 -0
- package/src/write/free-text.js +41 -0
- package/src/write/get-font-and-attr.js +37 -0
- package/src/write/get-text-size.js +56 -0
- package/src/write/highlight.js +11 -0
- package/src/write/layout/VoiceElements.js +121 -0
- package/src/write/layout/beam.js +213 -0
- package/src/write/layout/get-left-edge-of-staff.js +56 -0
- package/src/write/layout/getBarYAt.js +6 -0
- package/src/write/layout/layout.js +94 -0
- package/src/write/layout/setUpperAndLowerElements.js +232 -0
- package/src/write/layout/staffGroup.js +146 -0
- package/src/write/layout/triplet.js +75 -0
- package/src/write/layout/voice.js +137 -0
- package/src/write/selection.js +188 -70
- package/src/write/separator.js +10 -0
- package/src/write/set-class.js +21 -0
- package/src/write/subtitle.js +12 -0
- package/src/write/svg.js +95 -43
- package/src/write/top-text.js +54 -0
- package/src/write/unhighlight.js +11 -0
- package/temp.txt +15256 -0
- package/test.js +27 -64
- package/types/index.d.ts +1095 -0
- package/version.js +1 -1
- package/.babelrc +0 -5
- package/.eslintrc +0 -3
- package/.gitmodules +0 -3
- package/abcjs-midi.css +0 -166
- package/build-utils/loadPresets.js +0 -14
- package/build-utils/presets/webpack.analyze.js +0 -6
- package/build-utils/presets/webpack.optimize.js +0 -30
- package/build-utils/webpack.development.js +0 -14
- package/build-utils/webpack.production.js +0 -35
- package/deploy-docs.sh +0 -25
- package/docs/README.md +0 -33
- package/fix-versions.sh +0 -23
- package/mei.js +0 -43
- package/midi.js +0 -62
- package/src/api/abc_tunebook_midi.js +0 -116
- package/src/midi/abc_midi_controls.js +0 -701
- package/src/midi/abc_midi_flattener.js +0 -1119
- package/src/midi/abc_midi_js_preparer.js +0 -243
- package/src/midi/abc_midi_sequencer.js +0 -401
- package/src/midi/abc_midi_ui_generator.js +0 -86
- package/src/plugin/abc_plugin_midi.js +0 -220
- package/src/synth/images/loop.svg +0 -61
- package/src/synth/images/pause.svg +0 -6
- package/src/synth/images/play.svg +0 -5
- package/src/transform/abc2abc_write.js +0 -395
- package/static-wrappers/basic.js +0 -2
- package/static-wrappers/midi.js +0 -2
- package/static-wrappers/plugin-midi.js +0 -6
- package/static-wrappers/plugin.js +0 -6
- package/webpack.config.js +0 -29
package/src/write/selection.js
CHANGED
|
@@ -1,26 +1,11 @@
|
|
|
1
|
-
// Copyright (C) 2020 Paul Rosen (paul at paulrosen dot net)
|
|
2
|
-
//
|
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
4
|
-
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
5
|
-
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
6
|
-
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
7
|
-
//
|
|
8
|
-
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
9
|
-
//
|
|
10
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
|
11
|
-
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
12
|
-
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
13
|
-
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
14
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
15
|
-
|
|
16
1
|
var spacing = require('./abc_spacing');
|
|
17
2
|
|
|
18
3
|
function setupSelection(engraver) {
|
|
19
4
|
engraver.rangeHighlight = rangeHighlight;
|
|
20
5
|
if (engraver.dragging) {
|
|
21
|
-
for (var h = 0; h < engraver.
|
|
22
|
-
var hist = engraver.
|
|
23
|
-
if (hist.selectable) {
|
|
6
|
+
for (var h = 0; h < engraver.selectables.length; h++) {
|
|
7
|
+
var hist = engraver.selectables[h];
|
|
8
|
+
if (hist.svgEl.getAttribute("selectable") === "true") {
|
|
24
9
|
hist.svgEl.setAttribute("tabindex", 0);
|
|
25
10
|
hist.svgEl.setAttribute("data-index", h);
|
|
26
11
|
hist.svgEl.addEventListener("keydown", keyboardDown.bind(engraver));
|
|
@@ -34,26 +19,42 @@ function setupSelection(engraver) {
|
|
|
34
19
|
engraver.renderer.paper.svg.addEventListener('mouseup', mouseUp.bind(engraver));
|
|
35
20
|
}
|
|
36
21
|
|
|
37
|
-
function getCoord(ev) {
|
|
38
|
-
var
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
22
|
+
function getCoord(ev, svg) {
|
|
23
|
+
var scaleX = 1;
|
|
24
|
+
var scaleY = 1;
|
|
25
|
+
|
|
26
|
+
// when renderer.options.responsive === 'resize' the click coords are in relation to the HTML
|
|
27
|
+
// element, we need to convert to the SVG viewBox coords
|
|
28
|
+
if (svg.viewBox.baseVal) { // Firefox passes null to this when no viewBox is given
|
|
29
|
+
// Chrome makes these values null when no viewBox is given.
|
|
30
|
+
if (svg.viewBox.baseVal.width !== 0)
|
|
31
|
+
scaleX = svg.viewBox.baseVal.width / svg.clientWidth
|
|
32
|
+
if (svg.viewBox.baseVal.height !== 0)
|
|
33
|
+
scaleY = svg.viewBox.baseVal.height / svg.clientHeight
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var svgClicked = ev.target.tagName === "svg";
|
|
37
|
+
var x;
|
|
38
|
+
var y;
|
|
39
|
+
if (svgClicked) {
|
|
40
|
+
x = ev.offsetX;
|
|
41
|
+
y = ev.offsetY;
|
|
42
|
+
} else {
|
|
43
|
+
x = ev.layerX;
|
|
44
|
+
y = ev.layerY;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
x = x * scaleX;
|
|
48
|
+
y = y * scaleY;
|
|
49
|
+
//console.log(x, y)
|
|
50
|
+
|
|
51
|
+
return [x, y];
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
function elementFocused(ev) {
|
|
54
55
|
// If there had been another element focused and is being dragged, then report that before setting the new element up.
|
|
55
56
|
if (this.dragMechanism === "keyboard" && this.dragYStep !== 0 && this.dragTarget)
|
|
56
|
-
notifySelect.bind(this)(this.dragTarget, this.dragYStep, this.
|
|
57
|
+
notifySelect.bind(this)(this.dragTarget, this.dragYStep, this.selectables.length, this.dragIndex, ev);
|
|
57
58
|
|
|
58
59
|
this.dragYStep = 0;
|
|
59
60
|
}
|
|
@@ -75,14 +76,14 @@ function keyboardSelection(ev) {
|
|
|
75
76
|
case 13:
|
|
76
77
|
case 32:
|
|
77
78
|
handled = true;
|
|
78
|
-
this.dragTarget = this.
|
|
79
|
+
this.dragTarget = this.selectables[index];
|
|
79
80
|
this.dragIndex = index;
|
|
80
81
|
this.dragMechanism = "keyboard";
|
|
81
|
-
mouseUp.bind(this)();
|
|
82
|
+
mouseUp.bind(this)(ev);
|
|
82
83
|
break;
|
|
83
84
|
case 38: // arrow up
|
|
84
85
|
handled = true;
|
|
85
|
-
this.dragTarget = this.
|
|
86
|
+
this.dragTarget = this.selectables[index];
|
|
86
87
|
this.dragIndex = index;
|
|
87
88
|
if (this.dragTarget.isDraggable) {
|
|
88
89
|
if (this.dragging && this.dragTarget.isDraggable)
|
|
@@ -93,7 +94,7 @@ function keyboardSelection(ev) {
|
|
|
93
94
|
break;
|
|
94
95
|
case 40: // arrow down
|
|
95
96
|
handled = true;
|
|
96
|
-
this.dragTarget = this.
|
|
97
|
+
this.dragTarget = this.selectables[index];
|
|
97
98
|
this.dragIndex = index;
|
|
98
99
|
this.dragMechanism = "keyboard";
|
|
99
100
|
if (this.dragTarget.isDraggable) {
|
|
@@ -106,7 +107,7 @@ function keyboardSelection(ev) {
|
|
|
106
107
|
case 9: // tab
|
|
107
108
|
// This is losing focus - if there had been dragging, then do the callback
|
|
108
109
|
if (this.dragYStep !== 0) {
|
|
109
|
-
mouseUp.bind(this)();
|
|
110
|
+
mouseUp.bind(this)(ev);
|
|
110
111
|
}
|
|
111
112
|
break;
|
|
112
113
|
default:
|
|
@@ -117,22 +118,21 @@ function keyboardSelection(ev) {
|
|
|
117
118
|
ev.preventDefault();
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
function
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
function findElementInHistory(selectables, el) {
|
|
122
|
+
for (var i = 0; i < selectables.length; i++) {
|
|
123
|
+
if (el === selectables[i].svgEl)
|
|
124
|
+
return i;
|
|
125
|
+
}
|
|
126
|
+
return -1;
|
|
127
|
+
}
|
|
126
128
|
|
|
129
|
+
function findElementByCoord(self, x, y) {
|
|
127
130
|
var minDistance = 9999999;
|
|
128
131
|
var closestIndex = -1;
|
|
129
|
-
var
|
|
130
|
-
|
|
131
|
-
var el = this.history[i];
|
|
132
|
-
if (!el.selectable)
|
|
133
|
-
continue;
|
|
132
|
+
for (var i = 0; i < self.selectables.length && minDistance > 0; i++) {
|
|
133
|
+
var el = self.selectables[i];
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
self.getDim(el);
|
|
136
136
|
if (el.dim.left < x && el.dim.right > x && el.dim.top < y && el.dim.bottom > y) {
|
|
137
137
|
// See if it is a direct hit on an element - if so, definitely take it (there are no overlapping elements)
|
|
138
138
|
closestIndex = i;
|
|
@@ -162,13 +162,82 @@ function mouseDown(ev) {
|
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
return (closestIndex >= 0 && minDistance <= 12) ? closestIndex : -1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function getBestMatchCoordinates(dim, ev, scale) {
|
|
169
|
+
// Different browsers have conflicting meanings for the coordinates that are returned.
|
|
170
|
+
// If the item we want is clicked on directly, then we will just see what is the best match.
|
|
171
|
+
// This seems like less of a hack than browser sniffing.
|
|
172
|
+
if (dim.x <= ev.offsetX && dim.x+dim.width >= ev.offsetX &&
|
|
173
|
+
dim.y <= ev.offsetY && dim.y+dim.height >= ev.offsetY)
|
|
174
|
+
return [ ev.offsetX, ev.offsetY];
|
|
175
|
+
// Firefox returns a weird value for offset, but layer is correct.
|
|
176
|
+
// Safari and Chrome return the correct value for offset, but layer is multiplied by the scale (that is, if it were rendered with { scale: 2 })
|
|
177
|
+
// For instance (if scale is 2):
|
|
178
|
+
// Firefox: { offsetY: 5, layerY: 335 }
|
|
179
|
+
// Others: {offsetY: 335, layerY: 670} (there could be a little rounding, so the number might not be exactly 2x)
|
|
180
|
+
// So, if layerY/scale is approx. offsetY, then use offsetY, otherwise use layerY
|
|
181
|
+
var epsilon = Math.abs(ev.layerY/scale - ev.offsetY);
|
|
182
|
+
if (epsilon < 3)
|
|
183
|
+
return [ ev.offsetX, ev.offsetY];
|
|
184
|
+
else
|
|
185
|
+
return [ ev.layerX, ev.layerY];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function getTarget(target) {
|
|
189
|
+
// This searches up the dom for the first item containing the attribute "selectable", or stopping at the SVG.
|
|
190
|
+
if (target.tagName === "svg")
|
|
191
|
+
return target;
|
|
192
|
+
|
|
193
|
+
var found = target.getAttribute("selectable");
|
|
194
|
+
while (!found) {
|
|
195
|
+
target = target.parentElement;
|
|
196
|
+
if (target.tagName === "svg")
|
|
197
|
+
found = true;
|
|
198
|
+
else
|
|
199
|
+
found = target.getAttribute("selectable");
|
|
200
|
+
}
|
|
201
|
+
return target;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function getMousePosition(self, ev) {
|
|
205
|
+
// if the user clicked exactly on an element that we're interested in, then we already have the answer.
|
|
206
|
+
// This is more reliable than the calculations because firefox returns different coords for offsetX, offsetY
|
|
207
|
+
var x;
|
|
208
|
+
var y;
|
|
209
|
+
var box;
|
|
210
|
+
var clickedOn = findElementInHistory(self.selectables, getTarget(ev.target));
|
|
211
|
+
if (clickedOn >= 0) {
|
|
212
|
+
// There was a direct hit on an element.
|
|
213
|
+
box = getBestMatchCoordinates(self.selectables[clickedOn].svgEl.getBBox(), ev, self.scale);
|
|
214
|
+
x = box[0];
|
|
215
|
+
y = box[1];
|
|
216
|
+
//console.log("clicked on", clickedOn, x, y, self.selectables[clickedOn].svgEl.getBBox(), ev.target.getBBox());
|
|
217
|
+
} else {
|
|
218
|
+
// See if they clicked close to an element.
|
|
219
|
+
box = getCoord(ev, self.renderer.paper.svg);
|
|
220
|
+
x = box[0];
|
|
221
|
+
y = box[1];
|
|
222
|
+
clickedOn = findElementByCoord(self, x, y);
|
|
223
|
+
//console.log("clicked near", clickedOn, x, y, printEl(ev.target));
|
|
224
|
+
}
|
|
225
|
+
return { x: x, y: y, clickedOn: clickedOn };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function mouseDown(ev) {
|
|
229
|
+
// "this" is the EngraverController because of the bind(this) when setting the event listener.
|
|
230
|
+
|
|
231
|
+
var positioning = getMousePosition(this, ev);
|
|
232
|
+
|
|
233
|
+
// Only start dragging if the user clicked close enough to an element and clicked with the main mouse button.
|
|
234
|
+
if (positioning.clickedOn >= 0 && ev.button === 0) {
|
|
235
|
+
this.dragTarget = this.selectables[positioning.clickedOn];
|
|
236
|
+
this.dragIndex = positioning.clickedOn;
|
|
168
237
|
this.dragMechanism = "mouse";
|
|
169
|
-
this.dragMouseStart = { x: x, y: y };
|
|
238
|
+
this.dragMouseStart = { x: positioning.x, y: positioning.y };
|
|
170
239
|
if (this.dragging && this.dragTarget.isDraggable) {
|
|
171
|
-
this.renderer.
|
|
240
|
+
addGlobalClass(this.renderer.paper, "abcjs-dragging-in-progress");
|
|
172
241
|
this.dragTarget.absEl.highlight(undefined, this.dragColor);
|
|
173
242
|
}
|
|
174
243
|
}
|
|
@@ -180,11 +249,9 @@ function mouseMove(ev) {
|
|
|
180
249
|
if (!this.dragTarget || !this.dragging || !this.dragTarget.isDraggable || this.dragMechanism !== 'mouse')
|
|
181
250
|
return;
|
|
182
251
|
|
|
183
|
-
var
|
|
184
|
-
var x = box[0];
|
|
185
|
-
var y = box[1];
|
|
252
|
+
var positioning = getMousePosition(this, ev);
|
|
186
253
|
|
|
187
|
-
var yDist = Math.round((y - this.dragMouseStart.y)/spacing.STEP);
|
|
254
|
+
var yDist = Math.round((positioning.y - this.dragMouseStart.y)/spacing.STEP);
|
|
188
255
|
if (yDist !== this.dragYStep) {
|
|
189
256
|
this.dragYStep = yDist;
|
|
190
257
|
this.dragTarget.svgEl.setAttribute("transform", "translate(0," + (yDist * spacing.STEP) + ")");
|
|
@@ -203,23 +270,25 @@ function mouseUp(ev) {
|
|
|
203
270
|
this.dragTarget.absEl.highlight(undefined, this.selectionColor);
|
|
204
271
|
}
|
|
205
272
|
|
|
206
|
-
notifySelect.bind(this)(this.dragTarget, this.dragYStep, this.
|
|
207
|
-
this.dragTarget.svgEl.focus
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
273
|
+
notifySelect.bind(this)(this.dragTarget, this.dragYStep, this.selectables.length, this.dragIndex, ev);
|
|
274
|
+
if (this.dragTarget.svgEl && this.dragTarget.svgEl.focus) {
|
|
275
|
+
this.dragTarget.svgEl.focus();
|
|
276
|
+
this.dragTarget = null;
|
|
277
|
+
this.dragIndex = -1;
|
|
278
|
+
}
|
|
279
|
+
removeGlobalClass(this.renderer.svg, "abcjs-dragging-in-progress");
|
|
211
280
|
}
|
|
212
281
|
|
|
213
282
|
function setSelection(dragIndex) {
|
|
214
|
-
if (dragIndex >= 0 && dragIndex < this.
|
|
215
|
-
this.dragTarget = this.
|
|
283
|
+
if (dragIndex >= 0 && dragIndex < this.selectables.length) {
|
|
284
|
+
this.dragTarget = this.selectables[dragIndex];
|
|
216
285
|
this.dragIndex = dragIndex;
|
|
217
286
|
this.dragMechanism = "keyboard";
|
|
218
|
-
mouseUp.bind(this)();
|
|
287
|
+
mouseUp.bind(this)({target: this.dragTarget.svgEl});
|
|
219
288
|
}
|
|
220
289
|
}
|
|
221
290
|
|
|
222
|
-
function notifySelect(target, dragStep, dragMax, dragIndex) {
|
|
291
|
+
function notifySelect(target, dragStep, dragMax, dragIndex, ev) {
|
|
223
292
|
var classes = [];
|
|
224
293
|
if (target.absEl.elemset) {
|
|
225
294
|
var classObj = {};
|
|
@@ -240,9 +309,22 @@ function notifySelect(target, dragStep, dragMax, dragIndex) {
|
|
|
240
309
|
findNumber(classes[ii], "abcjs-l", analysis, "line");
|
|
241
310
|
findNumber(classes[ii], "abcjs-m", analysis, "measure");
|
|
242
311
|
}
|
|
312
|
+
if (target.staffPos)
|
|
313
|
+
analysis.staffPos = target.staffPos;
|
|
314
|
+
var closest = ev.target;
|
|
315
|
+
while (!closest.dataset.name && closest.tagName.toLowerCase() !== 'svg')
|
|
316
|
+
closest = closest.parentNode;
|
|
317
|
+
var parent = ev.target;
|
|
318
|
+
while (!parent.dataset.index && parent.tagName.toLowerCase() !== 'svg')
|
|
319
|
+
parent = parent.parentNode;
|
|
320
|
+
analysis.name = parent.dataset.name;
|
|
321
|
+
analysis.clickedName = closest.dataset.name;
|
|
322
|
+
analysis.parentClasses = parent.classList;
|
|
323
|
+
analysis.clickedClasses = closest.classList;
|
|
324
|
+
analysis.selectableElement = target.svgEl;
|
|
243
325
|
|
|
244
326
|
for (var i=0; i<this.listeners.length;i++) {
|
|
245
|
-
this.listeners[i](target.absEl.abcelem, target.absEl.tuneNumber, classes.join(' '), analysis, { step: dragStep, max: dragMax, index: dragIndex, setSelection: setSelection.bind(this)});
|
|
327
|
+
this.listeners[i](target.absEl.abcelem, target.absEl.tuneNumber, classes.join(' '), analysis, { step: dragStep, max: dragMax, index: dragIndex, setSelection: setSelection.bind(this)}, ev);
|
|
246
328
|
}
|
|
247
329
|
}
|
|
248
330
|
|
|
@@ -257,7 +339,7 @@ function findNumber(klass, match, target, name) {
|
|
|
257
339
|
|
|
258
340
|
function clearSelection() {
|
|
259
341
|
for (var i=0;i<this.selected.length;i++) {
|
|
260
|
-
this.selected[i].unhighlight();
|
|
342
|
+
this.selected[i].unhighlight(undefined, this.renderer.foregroundColor);
|
|
261
343
|
}
|
|
262
344
|
this.selected = [];
|
|
263
345
|
}
|
|
@@ -283,4 +365,40 @@ function rangeHighlight(start,end) {
|
|
|
283
365
|
}
|
|
284
366
|
}
|
|
285
367
|
|
|
368
|
+
function getClassSet(el) {
|
|
369
|
+
var oldClass = el.getAttribute('class');
|
|
370
|
+
if (!oldClass)
|
|
371
|
+
oldClass = "";
|
|
372
|
+
var klasses = oldClass.split(" ");
|
|
373
|
+
var obj = {};
|
|
374
|
+
for (var i = 0; i < klasses.length; i++)
|
|
375
|
+
obj[klasses[i]] = true;
|
|
376
|
+
return obj;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function setClassSet(el, klassSet) {
|
|
380
|
+
var klasses = [];
|
|
381
|
+
for (var key in klassSet) {
|
|
382
|
+
if (klassSet.hasOwnProperty(key))
|
|
383
|
+
klasses.push(key);
|
|
384
|
+
}
|
|
385
|
+
el.setAttribute('class', klasses.join(' '));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function addGlobalClass(svg, klass) {
|
|
389
|
+
if (svg) {
|
|
390
|
+
var obj = getClassSet(svg.svg);
|
|
391
|
+
obj[klass] = true;
|
|
392
|
+
setClassSet(svg.svg, obj);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function removeGlobalClass(svg, klass) {
|
|
397
|
+
if (svg) {
|
|
398
|
+
var obj = getClassSet(svg.svg);
|
|
399
|
+
delete obj[klass];
|
|
400
|
+
setClassSet(svg.svg, obj);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
286
404
|
module.exports = setupSelection;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function Separator(spaceAbove, lineLength, spaceBelow) {
|
|
2
|
+
this.rows = [];
|
|
3
|
+
if (spaceAbove)
|
|
4
|
+
this.rows.push({move: spaceAbove});
|
|
5
|
+
this.rows.push({ separator: lineLength, absElemType: "separator" });
|
|
6
|
+
if (spaceBelow)
|
|
7
|
+
this.rows.push({move: spaceBelow});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = Separator;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var setClass = function (elemset, addClass, removeClass, color) {
|
|
2
|
+
if (!elemset)
|
|
3
|
+
return;
|
|
4
|
+
for (var i = 0; i < elemset.length; i++) {
|
|
5
|
+
var el = elemset[i];
|
|
6
|
+
var attr = el.getAttribute("highlight");
|
|
7
|
+
if (!attr) attr = "fill";
|
|
8
|
+
el.setAttribute(attr, color);
|
|
9
|
+
var kls = el.getAttribute("class");
|
|
10
|
+
if (!kls) kls = "";
|
|
11
|
+
kls = kls.replace(removeClass, "");
|
|
12
|
+
kls = kls.replace(addClass, "");
|
|
13
|
+
if (addClass.length > 0) {
|
|
14
|
+
if (kls.length > 0 && kls.charAt(kls.length - 1) !== ' ') kls += " ";
|
|
15
|
+
kls += addClass;
|
|
16
|
+
}
|
|
17
|
+
el.setAttribute("class", kls);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
module.exports = setClass;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
function Subtitle(spaceAbove, formatting, info, center, paddingLeft, getTextSize) {
|
|
2
|
+
this.rows = [];
|
|
3
|
+
if (spaceAbove)
|
|
4
|
+
this.rows.push({move: spaceAbove});
|
|
5
|
+
var tAnchor = formatting.titleleft ? 'start' : 'middle';
|
|
6
|
+
var tLeft = formatting.titleleft ? paddingLeft : center;
|
|
7
|
+
this.rows.push({left: tLeft, text: info.text, font: 'subtitlefont', klass: 'text subtitle', anchor: tAnchor, startChar: info.startChar, endChar: info.endChar, absElemType: "subtitle", name: "subtitle"});
|
|
8
|
+
var size = getTextSize.calc(info.text, 'subtitlefont', 'text subtitle');
|
|
9
|
+
this.rows.push({move: size.height});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = Subtitle;
|
package/src/write/svg.js
CHANGED
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
// abc_voice_element.js: Definition of the VoiceElement class.
|
|
2
|
-
// Copyright (C) 2010-2020 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
|
|
3
|
-
//
|
|
4
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
5
|
-
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
6
|
-
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
7
|
-
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
-
//
|
|
9
|
-
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
-
//
|
|
11
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
|
12
|
-
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
13
|
-
// NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
14
|
-
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
15
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
16
2
|
|
|
17
3
|
/*global module */
|
|
18
4
|
|
|
@@ -20,6 +6,7 @@ var svgNS = "http://www.w3.org/2000/svg";
|
|
|
20
6
|
|
|
21
7
|
function Svg(wrapper) {
|
|
22
8
|
this.svg = createSvg();
|
|
9
|
+
this.currentGroup = [];
|
|
23
10
|
wrapper.appendChild(this.svg);
|
|
24
11
|
}
|
|
25
12
|
|
|
@@ -27,6 +14,7 @@ Svg.prototype.clear = function() {
|
|
|
27
14
|
if (this.svg) {
|
|
28
15
|
var wrapper = this.svg.parentNode;
|
|
29
16
|
this.svg = createSvg();
|
|
17
|
+
this.currentGroup = [];
|
|
30
18
|
if (wrapper) {
|
|
31
19
|
// TODO-PER: If the wrapper is not present, then the underlying div was pulled out from under this instance. It's possible that is still useful (for creating the music off page?)
|
|
32
20
|
wrapper.innerHTML = "";
|
|
@@ -74,14 +62,10 @@ Svg.prototype.setResponsiveWidth = function(w, h) {
|
|
|
74
62
|
Svg.prototype.setSize = function(w, h) {
|
|
75
63
|
this.svg.setAttribute('width', w);
|
|
76
64
|
this.svg.setAttribute('height', h);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
// this.paper.canvas.parentNode.style.width = w + "px";
|
|
82
|
-
// this.paper.canvas.parentNode.style.height = "" + h + "px";
|
|
83
|
-
// } else
|
|
84
|
-
// this.paper.canvas.parentNode.setAttribute("style", "width:" + w + "px");
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
Svg.prototype.setAttribute = function(attr, value) {
|
|
68
|
+
this.svg.setAttribute(attr, value);
|
|
85
69
|
};
|
|
86
70
|
|
|
87
71
|
Svg.prototype.setScale = function(scale) {
|
|
@@ -126,15 +110,19 @@ Svg.prototype.setParentStyles = function(attr) {
|
|
|
126
110
|
};
|
|
127
111
|
|
|
128
112
|
function constructHLine(x1, y1, x2) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"
|
|
113
|
+
var len = x2 - x1;
|
|
114
|
+
return "M " + x1 + " " + y1 +
|
|
115
|
+
" l " + len + ' ' + 0 +
|
|
116
|
+
" l " + 0 + " " + 1 + " " +
|
|
117
|
+
" l " + (-len) + " " + 0 + " " + " z ";
|
|
132
118
|
}
|
|
133
119
|
|
|
134
120
|
function constructVLine(x1, y1, y2) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
"
|
|
121
|
+
var len = y2 - y1;
|
|
122
|
+
return "M " + x1 + " " + y1 +
|
|
123
|
+
" l " + 0 + ' ' + len +
|
|
124
|
+
" l " + 1 + " " + 0 + " " +
|
|
125
|
+
" l " + 0 + " " + (-len) + " " + " z ";
|
|
138
126
|
}
|
|
139
127
|
|
|
140
128
|
Svg.prototype.rect = function(attr) {
|
|
@@ -146,14 +134,43 @@ Svg.prototype.rect = function(attr) {
|
|
|
146
134
|
var y2 = attr.y + attr.height;
|
|
147
135
|
lines.push(constructHLine(x1, y1, x2));
|
|
148
136
|
lines.push(constructHLine(x1, y2, x2));
|
|
149
|
-
lines.push(constructVLine(x1, y1, y2));
|
|
150
137
|
lines.push(constructVLine(x2, y1, y2));
|
|
138
|
+
lines.push(constructVLine(x1, y2, y1));
|
|
139
|
+
|
|
140
|
+
return this.path({ path: lines.join(" "), stroke: "none", "data-name": attr["data-name"] });
|
|
141
|
+
};
|
|
151
142
|
|
|
152
|
-
|
|
143
|
+
Svg.prototype.dottedLine = function(attr) {
|
|
144
|
+
var el = document.createElementNS(svgNS, 'line');
|
|
145
|
+
el.setAttribute("x1", attr.x1);
|
|
146
|
+
el.setAttribute("x2", attr.x2);
|
|
147
|
+
el.setAttribute("y1", attr.y1);
|
|
148
|
+
el.setAttribute("y2", attr.y2);
|
|
149
|
+
el.setAttribute("stroke", attr.stroke);
|
|
150
|
+
el.setAttribute("stroke-dasharray", "5,5");
|
|
151
|
+
this.svg.insertBefore(el, this.svg.firstChild);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
Svg.prototype.rectBeneath = function(attr) {
|
|
155
|
+
var el = document.createElementNS(svgNS, 'rect');
|
|
156
|
+
el.setAttribute("x", attr.x);
|
|
157
|
+
el.setAttribute("width", attr.width);
|
|
158
|
+
el.setAttribute("y", attr.y);
|
|
159
|
+
el.setAttribute("height", attr.height);
|
|
160
|
+
if (attr.stroke)
|
|
161
|
+
el.setAttribute("stroke", attr.stroke);
|
|
162
|
+
if (attr['stroke-opacity'])
|
|
163
|
+
el.setAttribute("stroke-opacity", attr['stroke-opacity']);
|
|
164
|
+
if (attr.fill)
|
|
165
|
+
el.setAttribute("fill", attr.fill);
|
|
166
|
+
if (attr['fill-opacity'])
|
|
167
|
+
el.setAttribute("fill-opacity", attr['fill-opacity']);
|
|
168
|
+
this.svg.insertBefore(el, this.svg.firstChild);
|
|
153
169
|
};
|
|
154
170
|
|
|
155
171
|
Svg.prototype.text = function(text, attr, target) {
|
|
156
172
|
var el = document.createElementNS(svgNS, 'text');
|
|
173
|
+
el.setAttribute("stroke", "none");
|
|
157
174
|
for (var key in attr) {
|
|
158
175
|
if (attr.hasOwnProperty(key)) {
|
|
159
176
|
el.setAttribute(key, attr[key]);
|
|
@@ -162,10 +179,29 @@ Svg.prototype.text = function(text, attr, target) {
|
|
|
162
179
|
var lines = (""+text).split("\n");
|
|
163
180
|
for (var i = 0; i < lines.length; i++) {
|
|
164
181
|
var line = document.createElementNS(svgNS, 'tspan');
|
|
165
|
-
line.textContent = lines[i];
|
|
166
182
|
line.setAttribute("x", attr.x ? attr.x : 0);
|
|
167
183
|
if (i !== 0)
|
|
168
184
|
line.setAttribute("dy", "1.2em");
|
|
185
|
+
if (lines[i].indexOf("\x03") !== -1) {
|
|
186
|
+
var parts = lines[i].split('\x03')
|
|
187
|
+
line.textContent = parts[0];
|
|
188
|
+
if (parts[1]) {
|
|
189
|
+
var ts2 = document.createElementNS(svgNS, 'tspan');
|
|
190
|
+
ts2.setAttribute("dy", "-0.3em");
|
|
191
|
+
ts2.setAttribute("style", "font-size:0.7em");
|
|
192
|
+
ts2.textContent = parts[1];
|
|
193
|
+
line.appendChild(ts2);
|
|
194
|
+
}
|
|
195
|
+
if (parts[2]) {
|
|
196
|
+
var dist = parts[1] ? "0.4em" : "0.1em";
|
|
197
|
+
var ts3 = document.createElementNS(svgNS, 'tspan');
|
|
198
|
+
ts3.setAttribute("dy", dist);
|
|
199
|
+
ts3.setAttribute("style", "font-size:0.7em");
|
|
200
|
+
ts3.textContent = parts[2];
|
|
201
|
+
line.appendChild(ts3);
|
|
202
|
+
}
|
|
203
|
+
} else
|
|
204
|
+
line.textContent = lines[i];
|
|
169
205
|
el.appendChild(line);
|
|
170
206
|
}
|
|
171
207
|
if (target)
|
|
@@ -237,8 +273,8 @@ Svg.prototype.getTextSize = function(text, attr, el) {
|
|
|
237
273
|
size = this.guessWidth(text, attr);
|
|
238
274
|
}
|
|
239
275
|
if (removeLater) {
|
|
240
|
-
if (this.currentGroup)
|
|
241
|
-
this.currentGroup.removeChild(el);
|
|
276
|
+
if (this.currentGroup.length > 0)
|
|
277
|
+
this.currentGroup[0].removeChild(el);
|
|
242
278
|
else
|
|
243
279
|
this.svg.removeChild(el);
|
|
244
280
|
}
|
|
@@ -256,18 +292,24 @@ Svg.prototype.openGroup = function(options) {
|
|
|
256
292
|
el.setAttribute("fill", options.fill);
|
|
257
293
|
if (options.stroke)
|
|
258
294
|
el.setAttribute("stroke", options.stroke);
|
|
295
|
+
if (options['data-name'])
|
|
296
|
+
el.setAttribute("data-name", options['data-name']);
|
|
259
297
|
|
|
260
298
|
if (options.prepend)
|
|
261
|
-
this.
|
|
299
|
+
this.prepend(el);
|
|
262
300
|
else
|
|
263
|
-
this.
|
|
264
|
-
this.currentGroup
|
|
301
|
+
this.append(el);
|
|
302
|
+
this.currentGroup.unshift(el);
|
|
265
303
|
return el;
|
|
266
304
|
};
|
|
267
305
|
|
|
268
306
|
Svg.prototype.closeGroup = function() {
|
|
269
|
-
var g = this.currentGroup;
|
|
270
|
-
|
|
307
|
+
var g = this.currentGroup.shift();
|
|
308
|
+
if (g && g.children.length === 0) {
|
|
309
|
+
// If nothing was added to the group it is because all the elements were invisible. We don't need the group, then.
|
|
310
|
+
this.svg.removeChild(g);
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
271
313
|
return g;
|
|
272
314
|
};
|
|
273
315
|
|
|
@@ -277,7 +319,9 @@ Svg.prototype.path = function(attr) {
|
|
|
277
319
|
if (attr.hasOwnProperty(key)) {
|
|
278
320
|
if (key === 'path')
|
|
279
321
|
el.setAttributeNS(null, 'd', attr.path);
|
|
280
|
-
else
|
|
322
|
+
else if (key === 'klass')
|
|
323
|
+
el.setAttributeNS(null, "class", attr[key]);
|
|
324
|
+
else if (attr[key] !== undefined)
|
|
281
325
|
el.setAttributeNS(null, key, attr[key]);
|
|
282
326
|
}
|
|
283
327
|
}
|
|
@@ -291,6 +335,8 @@ Svg.prototype.pathToBack = function(attr) {
|
|
|
291
335
|
if (attr.hasOwnProperty(key)) {
|
|
292
336
|
if (key === 'path')
|
|
293
337
|
el.setAttributeNS(null, 'd', attr.path);
|
|
338
|
+
else if (key === 'klass')
|
|
339
|
+
el.setAttributeNS(null, "class", attr[key]);
|
|
294
340
|
else
|
|
295
341
|
el.setAttributeNS(null, key, attr[key]);
|
|
296
342
|
}
|
|
@@ -300,16 +346,16 @@ Svg.prototype.pathToBack = function(attr) {
|
|
|
300
346
|
};
|
|
301
347
|
|
|
302
348
|
Svg.prototype.append = function(el) {
|
|
303
|
-
if (this.currentGroup)
|
|
304
|
-
this.currentGroup.appendChild(el);
|
|
349
|
+
if (this.currentGroup.length > 0)
|
|
350
|
+
this.currentGroup[0].appendChild(el);
|
|
305
351
|
else
|
|
306
352
|
this.svg.appendChild(el);
|
|
307
353
|
};
|
|
308
354
|
|
|
309
355
|
Svg.prototype.prepend = function(el) {
|
|
310
356
|
// The entire group is prepended, so don't prepend the individual elements.
|
|
311
|
-
if (this.currentGroup)
|
|
312
|
-
this.currentGroup.appendChild(el);
|
|
357
|
+
if (this.currentGroup.length > 0)
|
|
358
|
+
this.currentGroup[0].appendChild(el);
|
|
313
359
|
else
|
|
314
360
|
this.svg.insertBefore(el, this.svg.firstChild);
|
|
315
361
|
};
|
|
@@ -322,10 +368,16 @@ Svg.prototype.setAttributeOnElement = function(el, attr) {
|
|
|
322
368
|
}
|
|
323
369
|
};
|
|
324
370
|
|
|
371
|
+
Svg.prototype.moveElementToChild = function(parent, child) {
|
|
372
|
+
parent.appendChild(child);
|
|
373
|
+
};
|
|
374
|
+
|
|
325
375
|
function createSvg() {
|
|
326
376
|
var svg = document.createElementNS(svgNS, "svg");
|
|
327
377
|
svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
|
|
328
378
|
svg.setAttribute('role', 'img'); // for accessibility
|
|
379
|
+
svg.setAttribute('fill', 'currentColor'); // for automatically picking up dark mode and high contrast
|
|
380
|
+
svg.setAttribute('stroke', 'currentColor'); // for automatically picking up dark mode and high contrast
|
|
329
381
|
return svg;
|
|
330
382
|
}
|
|
331
383
|
|