vibe-editor 0.0.0 → 0.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/LICENSE +1 -1
- package/README.md +12 -9
- package/package.json +11 -5
- package/src/scripts/js/Core.js +212 -186
- package/src/scripts/js/MusicProcessor.js +286 -128
- package/src/scripts/js/{VerovioScoreEditor.js → VIBE.js} +62 -28
- package/src/scripts/js/assets/mei_template.js +5 -1
- package/src/scripts/js/datastructures/MeasureMatrix.js +6 -85
- package/src/scripts/js/datastructures/ScoreGraph.js +1 -1
- package/src/scripts/js/entry.js +3 -2
- package/src/scripts/js/gui/Annotations.js +188 -111
- package/src/scripts/js/gui/HarmonyLabel.js +26 -2
- package/src/scripts/js/gui/ScoreManipulator.js +61 -31
- package/src/scripts/js/gui/Tabbar.js +41 -21
- package/src/scripts/js/gui/Toolbar.js +4 -4
- package/src/scripts/js/handlers/AnnotationChangeHandler.js +131 -60
- package/src/scripts/js/handlers/ClickModeHandler.js +406 -143
- package/src/scripts/js/handlers/CustomToolbarHandler.js +26 -24
- package/src/scripts/js/handlers/GlobalKeyboardHandler.js +12 -7
- package/src/scripts/js/handlers/InsertModeHandler.js +26 -32
- package/src/scripts/js/handlers/KeyModeHandler.js +12 -86
- package/src/scripts/js/handlers/LabelHandler.js +3 -2
- package/src/scripts/js/handlers/PhantomElementHandler.js +1 -1
- package/src/scripts/js/handlers/ScoreManipulatorHandler.js +101 -14
- package/src/scripts/js/handlers/SelectionHandler.js +80 -36
- package/src/scripts/js/handlers/SideBarHandler.js +10 -3
- package/src/scripts/js/handlers/WindowHandler.js +25 -4
- package/src/scripts/js/utils/DOMCreator.js +1 -1
- package/src/scripts/js/utils/MEIConverter.js +13 -1
- package/src/scripts/js/utils/MEIOperations.js +180 -187
- package/src/scripts/js/utils/Mouse2SVG.js +200 -43
- package/src/scripts/js/utils/ReactWrapper.js +46 -0
- package/src/scripts/js/utils/RectWrapper.js +10 -0
- package/src/scripts/js/utils/SVGEditor.js +94 -3
- package/src/scripts/js/utils/VerovioWrapper.js +6 -1
- package/src/scripts/js/utils/convenienceQueries.js +2 -0
- package/src/scripts/js/utils/mappings.js +322 -56
- package/src/styles/VerovioScoreEditor.css +0 -694
@@ -1,20 +1,22 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.setArticulation = exports.getTimestamp = exports.getElementTimestampById = exports.insertTempo = exports.insertMeter = exports.replaceMeterInScoreDef = exports.insertKey = exports.replaceKeyInScoreDef = exports.insertClef = exports.replaceClefinScoreDef = exports.paste = exports.createTuplet = exports.removeStaff = exports.addStaff = exports.removeMeasure = exports.addMeasure = exports.cleanUp = exports.elementIsOverfilling = exports.changeDur = exports.changeDurationsInLayer = exports.fillLayerWithRests = exports.fillWithRests = exports.disableFeatures = exports.changeMeter = exports.transposeByStep = exports.mergeArticToParent = exports.mergeSectionScoreDefToLayer = exports.adjustAccids = exports.extrapolateMeter = exports.getAbsoluteRatio = exports.connectNotes = exports.addToMEI = exports.getMeterRatioLocal = exports.removeFromMEI = void 0;
|
3
|
+
exports.setArticulation = exports.getTimestamp = exports.getElementTimestampById = exports.insertTempo = exports.insertMeter = exports.replaceMeterInScoreDef = exports.insertKey = exports.replaceKeyInScoreDef = exports.insertClef = exports.replaceClefinScoreDef = exports.paste = exports.createTuplet = exports.addLayerForStaff = exports.removeStaff = exports.addStaff = exports.removeMeasure = exports.addMeasure = exports.cleanUp = exports.elementIsOverfilling = exports.changeDur = exports.changeDurationsInLayer = exports.fillLayerWithRests = exports.fillWithRests = exports.disableFeatures = exports.changeMeter = exports.transposeByStep = exports.mergeArticToParent = exports.mergeSectionScoreDefToLayer = exports.adjustAccids = exports.extrapolateMeter = exports.getAbsoluteRatio = exports.connectNotes = exports.addToMEI = exports.getMeterRatioLocal = exports.removeFromMEI = void 0;
|
4
4
|
const meiConverter = require("./MEIConverter");
|
5
5
|
const random_1 = require("./random");
|
6
6
|
const constants_1 = require("../constants");
|
7
7
|
const mappings_1 = require("./mappings");
|
8
8
|
const mei_template_1 = require("../assets/mei_template");
|
9
9
|
const MeasureMatrix_1 = require("../datastructures/MeasureMatrix");
|
10
|
+
/**
|
11
|
+
* This script is a collection of functions which help to manipulate the underlying MEI, so that it can be renderd anew.
|
12
|
+
* E.g.: Add and remove notes, process beams and slurs, cleanup empty elements, etc.
|
13
|
+
*
|
14
|
+
* Some extract features from the MEI which are not apparent in the MEI itself, like processing ratios and relationsships between notes.
|
15
|
+
*
|
16
|
+
*/
|
10
17
|
const countableNoteUnitSelector = ":scope > *[dur]:not([grace])";
|
11
18
|
const overfillMeasure = false;
|
12
19
|
const siblingNames = ["note", "chord", "clef", "beam"];
|
13
|
-
// ":scope > note:not([grace])," +
|
14
|
-
// ":scope > chord," +
|
15
|
-
// ":scope > beam > chord," +
|
16
|
-
// ":scope > beam > note:not([grace])," +
|
17
|
-
// ":scope > rest"
|
18
20
|
////// DELETE //////
|
19
21
|
/**
|
20
22
|
* Remove Elements from MEI.
|
@@ -67,14 +69,7 @@ function removeFromMEI(scoreElements, currentMEI) {
|
|
67
69
|
}
|
68
70
|
}
|
69
71
|
});
|
70
|
-
//removeEmptyElements(currentMEI)
|
71
|
-
// For now: No Shifts (22.07.2021)
|
72
|
-
// if($(".measure").length > 1){
|
73
|
-
// checkDeleteShifts(currentMEI);
|
74
|
-
// }
|
75
72
|
cleanUp(currentMEI);
|
76
|
-
//fillWithRests(currentMEI)
|
77
|
-
// Warum ist das ein Problem?
|
78
73
|
currentMEI = meiConverter.restoreXmlIdTags(currentMEI);
|
79
74
|
resolve(currentMEI);
|
80
75
|
});
|
@@ -161,12 +156,14 @@ exports.getMeterRatioLocal = getMeterRatioLocal;
|
|
161
156
|
* @returns mei
|
162
157
|
*/
|
163
158
|
function addToMEI(newSound, currentMEI, replace = false, scoreGraph = null) {
|
164
|
-
var _a
|
159
|
+
var _a;
|
165
160
|
//return new Promise<Document>((resolve): void => {
|
166
161
|
var currMeiClone = currentMEI.cloneNode(true);
|
167
162
|
var newElem;
|
168
163
|
var nearestNoteIsSameDurRest = false;
|
169
164
|
if (newSound.hasOwnProperty("pname")) {
|
165
|
+
if (!newSound.nearestNoteId)
|
166
|
+
return currentMEI;
|
170
167
|
var newNote = newSound;
|
171
168
|
if (newNote.rest) {
|
172
169
|
newElem = currentMEI.createElement("rest");
|
@@ -264,7 +261,7 @@ function addToMEI(newSound, currentMEI, replace = false, scoreGraph = null) {
|
|
264
261
|
}
|
265
262
|
}
|
266
263
|
if (replace) {
|
267
|
-
let ms = Array.from(trueSibling.parentElement.querySelectorAll("note:not(chord note), chord, rest, mRest"));
|
264
|
+
let ms = Array.from(trueSibling.parentElement.querySelectorAll("note:not(chord note), chord, rest, mRest"));
|
268
265
|
if (newNote.relPosX === "left") {
|
269
266
|
var measureSiblings = ms.filter((_, i) => i >= ms.indexOf(trueSibling));
|
270
267
|
trueSibling.parentElement.insertBefore(newElem, trueSibling);
|
@@ -300,8 +297,40 @@ function addToMEI(newSound, currentMEI, replace = false, scoreGraph = null) {
|
|
300
297
|
var newChord = newSound;
|
301
298
|
newElem = convertToElement(newChord, currentMEI);
|
302
299
|
var nearestElem = currentMEI.getElementById(newChord.nearestNoteId);
|
303
|
-
if (
|
304
|
-
|
300
|
+
// if (nearestElem?.tagName === "layer") {
|
301
|
+
// nearestElem.insertBefore(newElem, nearestElem.firstChild)
|
302
|
+
var sibling = currentMEI.getElementById(newChord.nearestNoteId);
|
303
|
+
if (!sibling)
|
304
|
+
return;
|
305
|
+
var parentLayer = sibling.closest("layer");
|
306
|
+
var trueParent = sibling.parentElement;
|
307
|
+
var isTrueSibling = parentLayer == trueParent;
|
308
|
+
var trueSibling = sibling;
|
309
|
+
if (!isTrueSibling) {
|
310
|
+
var currParent = trueParent;
|
311
|
+
while (!isTrueSibling) {
|
312
|
+
trueSibling = currParent;
|
313
|
+
currParent = currParent === null || currParent === void 0 ? void 0 : currParent.parentElement;
|
314
|
+
isTrueSibling = currParent.tagName === "layer";
|
315
|
+
}
|
316
|
+
}
|
317
|
+
if (replace) {
|
318
|
+
let ms = Array.from(trueSibling.parentElement.querySelectorAll("note:not(chord note), chord, rest, mRest"));
|
319
|
+
if (newChord.relPosX === "left") {
|
320
|
+
var measureSiblings = ms.filter((_, i) => i >= ms.indexOf(trueSibling));
|
321
|
+
trueSibling.parentElement.insertBefore(newElem, trueSibling);
|
322
|
+
changeDurationsInLayer(currentMEI, measureSiblings, newElem);
|
323
|
+
}
|
324
|
+
else {
|
325
|
+
if (["clef"].every(el => { var _a; return ((_a = trueSibling.nextElementSibling) === null || _a === void 0 ? void 0 : _a.tagName) !== el; }) && trueSibling.nextElementSibling !== null) {
|
326
|
+
var measureSiblings = ms.filter((_, i) => i >= ms.indexOf(trueSibling.nextElementSibling));
|
327
|
+
trueSibling.parentElement.insertBefore(newElem, trueSibling.nextElementSibling);
|
328
|
+
changeDurationsInLayer(currentMEI, measureSiblings, newElem);
|
329
|
+
}
|
330
|
+
else {
|
331
|
+
trueSibling.parentElement.insertBefore(newElem, trueSibling.nextElementSibling);
|
332
|
+
}
|
333
|
+
}
|
305
334
|
}
|
306
335
|
else if (newChord.relPosX === "left") {
|
307
336
|
nearestElem.parentElement.insertBefore(newElem, currentMEI.getElementById(newChord.nearestNoteId));
|
@@ -312,11 +341,61 @@ function addToMEI(newSound, currentMEI, replace = false, scoreGraph = null) {
|
|
312
341
|
}
|
313
342
|
// if measure overfills tie note to next measure
|
314
343
|
var currentLayer = newElem.closest("layer");
|
344
|
+
currentMEI = tieToNextMeasure(currentMEI, newElem, currMeiClone, replace, newSound);
|
345
|
+
newElem = currentMEI.querySelector("#" + newElem.id);
|
346
|
+
fillLayerWithRests(currentLayer, currentMEI);
|
347
|
+
//reestablish beams
|
348
|
+
beams === null || beams === void 0 ? void 0 : beams.forEach(b => {
|
349
|
+
var first;
|
350
|
+
var last;
|
351
|
+
Array.from(b.children).forEach(bc => {
|
352
|
+
var existingChild = currentMEI.querySelector("#" + bc.id);
|
353
|
+
if (existingChild !== null) {
|
354
|
+
if (first == undefined) {
|
355
|
+
first = bc;
|
356
|
+
}
|
357
|
+
else {
|
358
|
+
last = bc;
|
359
|
+
}
|
360
|
+
}
|
361
|
+
else if (!first) {
|
362
|
+
first = newElem;
|
363
|
+
}
|
364
|
+
});
|
365
|
+
if (!last) {
|
366
|
+
last = newElem;
|
367
|
+
}
|
368
|
+
if (first && last) {
|
369
|
+
var newBeam = currentMEI.createElement("beam");
|
370
|
+
newBeam.id = b.id;
|
371
|
+
var beamElements = currentMEI.querySelectorAll("#" + first.id + ", #" + first.id + "~ *:not(#" + last.id + "~ *)"); // all elements in between first and last
|
372
|
+
beamElements[0].insertAdjacentElement("beforebegin", newBeam);
|
373
|
+
beamElements.forEach(be => {
|
374
|
+
newBeam.append(be);
|
375
|
+
});
|
376
|
+
}
|
377
|
+
});
|
378
|
+
cleanUp(currentMEI);
|
379
|
+
adjustAccids(currentMEI);
|
380
|
+
currentMEI = meiConverter.restoreXmlIdTags(currentMEI);
|
381
|
+
return currentMEI;
|
382
|
+
}
|
383
|
+
exports.addToMEI = addToMEI;
|
384
|
+
/**
|
385
|
+
*
|
386
|
+
* @param currentMEI MEI to be changed
|
387
|
+
* @param newElem Element to tie to next measure
|
388
|
+
* @param currMeiClone clone of the original MEI to compute ratios before anything was changed
|
389
|
+
* @param replace replace flag, if addToMEI must be called again
|
390
|
+
* @param newSound change parameters of newSound if it has to be shifted to the right
|
391
|
+
*/
|
392
|
+
function tieToNextMeasure(currentMEI, newElem, currMeiClone, replace, newSound) {
|
393
|
+
var _a;
|
394
|
+
var currentLayer = newElem.closest("layer");
|
315
395
|
if (!overfillMeasure) {
|
316
396
|
var newMeasureRatio = getAbsoluteRatio(newElem.closest("layer"));
|
317
397
|
var measureRatio = getMeterRatioLocal(currMeiClone, newElem);
|
318
398
|
if (newMeasureRatio > measureRatio) {
|
319
|
-
//currentMEI = currMeiClone as Document
|
320
399
|
// Decide if next measure should be created and what should be added
|
321
400
|
var lastElement = Array.from(currentLayer.querySelectorAll(":scope > :is(note, chord)")).reverse()[0];
|
322
401
|
var lastElementRatio = getAbsoluteRatio(lastElement);
|
@@ -345,54 +424,19 @@ function addToMEI(newSound, currentMEI, replace = false, scoreGraph = null) {
|
|
345
424
|
if (currentLayer.closest("measure").nextElementSibling === null) { // add measure if there is none to extend into
|
346
425
|
addMeasure(currentMEI);
|
347
426
|
}
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
427
|
+
if (newSound) {
|
428
|
+
var cl = currentMEI.getElementById(currentLayer.id);
|
429
|
+
newSound.nearestNoteId = (_a = cl.closest("measure").nextElementSibling.querySelector("staff[n='" + cl.closest("staff").getAttribute("n") + "'] layer[n='" + cl.getAttribute("n") + "'] :is(chord, note, rest, mRest)")) === null || _a === void 0 ? void 0 : _a.id;
|
430
|
+
newSound.relPosX = "left";
|
431
|
+
if (newSound.nearestNoteId !== null) {
|
432
|
+
currentMEI = addToMEI(newSound, currentMEI, replace);
|
433
|
+
}
|
353
434
|
}
|
354
435
|
}
|
355
436
|
}
|
356
437
|
}
|
357
|
-
newElem = currentMEI.querySelector("#" + newElem.id);
|
358
|
-
fillLayerWithRests(currentLayer, currentMEI);
|
359
|
-
//reestablish beams
|
360
|
-
beams.forEach(b => {
|
361
|
-
var first;
|
362
|
-
var last;
|
363
|
-
Array.from(b.children).forEach(bc => {
|
364
|
-
var existingChild = currentMEI.querySelector("#" + bc.id);
|
365
|
-
if (existingChild !== null) {
|
366
|
-
if (first == undefined) {
|
367
|
-
first = bc;
|
368
|
-
}
|
369
|
-
else {
|
370
|
-
last = bc;
|
371
|
-
}
|
372
|
-
}
|
373
|
-
else if (first == undefined) {
|
374
|
-
first = newElem;
|
375
|
-
}
|
376
|
-
});
|
377
|
-
if (last == undefined) {
|
378
|
-
last = newElem;
|
379
|
-
}
|
380
|
-
if (first != undefined && last != undefined) {
|
381
|
-
var newBeam = currentMEI.createElement("beam");
|
382
|
-
newBeam.id = b.id;
|
383
|
-
var beamElements = currentMEI.querySelectorAll("#" + first.id + ", #" + first.id + "~ *:not(#" + last.id + "~ *)"); // all elements in between first and last
|
384
|
-
beamElements[0].insertAdjacentElement("beforebegin", newBeam);
|
385
|
-
beamElements.forEach(be => {
|
386
|
-
newBeam.append(be);
|
387
|
-
});
|
388
|
-
}
|
389
|
-
});
|
390
|
-
cleanUp(currentMEI);
|
391
|
-
adjustAccids(currentMEI);
|
392
|
-
currentMEI = meiConverter.restoreXmlIdTags(currentMEI);
|
393
438
|
return currentMEI;
|
394
439
|
}
|
395
|
-
exports.addToMEI = addToMEI;
|
396
440
|
/**
|
397
441
|
* Check if notes have to be shifted after insertion
|
398
442
|
* @param currentMEI
|
@@ -1155,105 +1199,6 @@ function replaceWithRest(element, currentMEI) {
|
|
1155
1199
|
elmei.parentElement.insertBefore(newRest, elmei);
|
1156
1200
|
elmei.remove();
|
1157
1201
|
}
|
1158
|
-
/**
|
1159
|
-
* @deprecated
|
1160
|
-
* Change duration of the following sound events. Elements to change duration are determined by the class to be "marked".
|
1161
|
-
* @param currentMEI Current MEI as Document
|
1162
|
-
* @param additionalElements Elements to be considered to be changed.
|
1163
|
-
* @param refElement Reference Element after which all determined elements (.marked and additionElements) will be changed (e.g. replacing duration during a note insert).
|
1164
|
-
* If no refElement is given, filter the additionalElements to exclude the refElement
|
1165
|
-
* @param marked Consider marked elements
|
1166
|
-
* @returns
|
1167
|
-
*/
|
1168
|
-
function _changeDuration(currentMEI, additionalElements = new Array(), refElement = null) {
|
1169
|
-
var currMeiClone = currentMEI.cloneNode(true);
|
1170
|
-
var changedFlag = "changed";
|
1171
|
-
var multiplier;
|
1172
|
-
var elmei;
|
1173
|
-
var i = refElement === null ? 1 : 0;
|
1174
|
-
for (i; i < additionalElements.length; i++) {
|
1175
|
-
elmei = currentMEI.getElementById(additionalElements[i].id);
|
1176
|
-
var elmeiRatio = getAbsoluteRatio(elmei);
|
1177
|
-
var chord = elmei.closest("chord");
|
1178
|
-
//Dur is attribute of chord and all notes will be changed accordingly
|
1179
|
-
if (chord !== null) {
|
1180
|
-
if (chord.classList.contains(changedFlag)) {
|
1181
|
-
return;
|
1182
|
-
}
|
1183
|
-
else {
|
1184
|
-
elmei = chord;
|
1185
|
-
elmei.classList.add(changedFlag);
|
1186
|
-
}
|
1187
|
-
}
|
1188
|
-
var dur = parseInt(elmei.getAttribute("dur"));
|
1189
|
-
var dots = parseInt(elmei.getAttribute("dots")); // is NaN if elmei has no dots
|
1190
|
-
if (dur > 0) {
|
1191
|
-
var layerRatio = getAbsoluteRatio(elmei.closest("layer")); // current ratio of layer with already inserted new sound event
|
1192
|
-
var localRatio = getMeterRatioLocal(currentMEI, elmei); //getMeterRatioGlobal(currentMEI )
|
1193
|
-
var danglingRatio = layerRatio - localRatio;
|
1194
|
-
if (danglingRatio > 0) {
|
1195
|
-
var nextElementRatio = getAbsoluteRatio(elmei);
|
1196
|
-
var neNewRatio = nextElementRatio - danglingRatio;
|
1197
|
-
if (neNewRatio > 0) {
|
1198
|
-
var durArr = ratioToDur(neNewRatio);
|
1199
|
-
elmei.setAttribute("dur", durArr[0].toString());
|
1200
|
-
if (durArr[1] > 0) {
|
1201
|
-
elmei.setAttribute("dots", durArr[1].toString());
|
1202
|
-
}
|
1203
|
-
else {
|
1204
|
-
elmei.removeAttribute("dots");
|
1205
|
-
}
|
1206
|
-
}
|
1207
|
-
else {
|
1208
|
-
elmei.remove();
|
1209
|
-
}
|
1210
|
-
}
|
1211
|
-
if ((layerRatio <= localRatio && refElement === null) || (layerRatio < localRatio && refElement !== null)) {
|
1212
|
-
var nextElementRatio = getAbsoluteRatio(elmei);
|
1213
|
-
var neNewRatio;
|
1214
|
-
if (refElement !== null) {
|
1215
|
-
neNewRatio = nextElementRatio - getAbsoluteRatio(refElement);
|
1216
|
-
}
|
1217
|
-
else {
|
1218
|
-
var addRatios = (function (elements) {
|
1219
|
-
var r = 0;
|
1220
|
-
elements.forEach((v, i) => {
|
1221
|
-
if (i > 0) {
|
1222
|
-
r += getAbsoluteRatio(v);
|
1223
|
-
}
|
1224
|
-
});
|
1225
|
-
return r;
|
1226
|
-
});
|
1227
|
-
neNewRatio = nextElementRatio - (layerRatio - addRatios(additionalElements) - getAbsoluteRatio(additionalElements[0]));
|
1228
|
-
}
|
1229
|
-
if (neNewRatio > 0) {
|
1230
|
-
var durArr = ratioToDur(neNewRatio);
|
1231
|
-
elmei.setAttribute("dur", durArr[0].toString());
|
1232
|
-
if (durArr[1] > 0) {
|
1233
|
-
elmei.setAttribute("dots", durArr[1].toString());
|
1234
|
-
}
|
1235
|
-
else {
|
1236
|
-
elmei.removeAttribute("dots");
|
1237
|
-
}
|
1238
|
-
}
|
1239
|
-
else {
|
1240
|
-
elmei.remove();
|
1241
|
-
}
|
1242
|
-
}
|
1243
|
-
}
|
1244
|
-
}
|
1245
|
-
if (!overfillMeasure && elmei != undefined && (elmei === null || elmei === void 0 ? void 0 : elmei.closest("layer")) !== null) {
|
1246
|
-
var newMeasureRatio = getAbsoluteRatio(elmei.closest("layer"));
|
1247
|
-
var localRatio = getMeterRatioLocal(currentMEI, elmei);
|
1248
|
-
if (newMeasureRatio > localRatio) { //getMeterRatioGlobal(currentMEI )){
|
1249
|
-
currentMEI = currMeiClone;
|
1250
|
-
}
|
1251
|
-
}
|
1252
|
-
//clean up after changing durations
|
1253
|
-
currentMEI.querySelectorAll(".changed").forEach(c => c.classList.remove(changedFlag));
|
1254
|
-
cleanUp(currentMEI);
|
1255
|
-
return currentMEI;
|
1256
|
-
}
|
1257
1202
|
function addRatios(elements) {
|
1258
1203
|
var r = 0;
|
1259
1204
|
elements.forEach((v, i) => {
|
@@ -1291,11 +1236,6 @@ function changeDurationsInLayer(currentMEI, additionalElements = new Array(), re
|
|
1291
1236
|
if (remainRatio < nnRatio) {
|
1292
1237
|
var diffRatio = nnRatio - remainRatio;
|
1293
1238
|
var nextNoteMEI = currentMEI.getElementById(nextNote.id);
|
1294
|
-
//var dur = ratioToDur(diffRatio)
|
1295
|
-
// currentMEI.getElementById(nextNote.id).setAttribute("dur", dur.shift().toString())
|
1296
|
-
// if (dur.length > 0) {
|
1297
|
-
// currentMEI.getElementById(nextNote.id).setAttribute("dots", dur.shift().toString())
|
1298
|
-
// }
|
1299
1239
|
changeDur(nextNoteMEI, diffRatio);
|
1300
1240
|
harm = currentMEI.querySelector('harm[startid="' + nextNote.id + '"]');
|
1301
1241
|
if (harm !== null) {
|
@@ -1323,6 +1263,9 @@ function changeDurationsInLayer(currentMEI, additionalElements = new Array(), re
|
|
1323
1263
|
changeDurationsInLayer(currentMEI, additionalElements, refElement, remainRatio, meiCopy);
|
1324
1264
|
}
|
1325
1265
|
}
|
1266
|
+
else {
|
1267
|
+
currentMEI = tieToNextMeasure(currentMEI, refElement, currentMEI.cloneNode(true), true, null);
|
1268
|
+
}
|
1326
1269
|
cleanUp(currentMEI);
|
1327
1270
|
return currentMEI;
|
1328
1271
|
}
|
@@ -1369,6 +1312,7 @@ function cleanUp(currentMEI) {
|
|
1369
1312
|
removeEmptyElements(currentMEI);
|
1370
1313
|
adjustRests(currentMEI);
|
1371
1314
|
redistributeHarms(currentMEI);
|
1315
|
+
reformatBreve(currentMEI);
|
1372
1316
|
}
|
1373
1317
|
exports.cleanUp = cleanUp;
|
1374
1318
|
/**
|
@@ -1591,6 +1535,9 @@ function removeTiesFromDoc(currentMEI) {
|
|
1591
1535
|
}
|
1592
1536
|
});
|
1593
1537
|
}
|
1538
|
+
function reformatBreve(currentMEI) {
|
1539
|
+
currentMEI.querySelectorAll("[dur='0.5']").forEach(d => d.setAttribute("dur", "breve"));
|
1540
|
+
}
|
1594
1541
|
function addMeasure(currentMEI) {
|
1595
1542
|
var lastMeasure = Array.from(currentMEI.querySelectorAll("measure")).reverse()[0];
|
1596
1543
|
var staffCounts = Array.from(lastMeasure.querySelectorAll("staff")).map(s => { return parseInt(s.getAttribute("n")); });
|
@@ -1633,6 +1580,7 @@ function addStaff(currentMEI, referenceStaff, relPos) {
|
|
1633
1580
|
var refElement;
|
1634
1581
|
currentMEI.querySelectorAll("staff[n=\"" + staffNum + "\"]").forEach(s => {
|
1635
1582
|
var _a;
|
1583
|
+
var layers = s.querySelectorAll("layer");
|
1636
1584
|
var newStaff = new mei_template_1.default().createStaff(1, 1);
|
1637
1585
|
switch (relPos) {
|
1638
1586
|
case "above":
|
@@ -1653,7 +1601,7 @@ function addStaff(currentMEI, referenceStaff, relPos) {
|
|
1653
1601
|
//copy elements from the current Staff that have to appear in new staff
|
1654
1602
|
var newLayer = newStaff.querySelector("layer");
|
1655
1603
|
var copyMeter = (_a = s.querySelector("meterSig")) === null || _a === void 0 ? void 0 : _a.cloneNode(true);
|
1656
|
-
if (copyMeter
|
1604
|
+
if (copyMeter) {
|
1657
1605
|
newLayer.insertBefore(copyMeter, newLayer.firstChild);
|
1658
1606
|
}
|
1659
1607
|
refn = (refElement === null || refElement === void 0 ? void 0 : refElement.getAttribute("n")) || staffNum; // s.getAttribute("n")
|
@@ -1714,6 +1662,12 @@ function removeStaff(currentMEI, referenceStaff, relPos) {
|
|
1714
1662
|
cleanUp(currentMEI);
|
1715
1663
|
}
|
1716
1664
|
exports.removeStaff = removeStaff;
|
1665
|
+
function addLayerForStaff(currentMEI, staffN, layerN) {
|
1666
|
+
currentMEI.querySelectorAll(`staff[n='${staffN}']`).forEach(staff => {
|
1667
|
+
staff.append(new mei_template_1.default().createLayer(layerN));
|
1668
|
+
});
|
1669
|
+
}
|
1670
|
+
exports.addLayerForStaff = addLayerForStaff;
|
1717
1671
|
/**
|
1718
1672
|
* Create a tuplet out of given Elements.
|
1719
1673
|
* Tuplet duration and kind will be derived from number and attributes of the given notes.
|
@@ -1765,10 +1719,10 @@ exports.createTuplet = createTuplet;
|
|
1765
1719
|
* Paste copied ids. First position to which the Elements are copied is the Element according to the refId (= RefElement).
|
1766
1720
|
* If multiple staffs are copied, overhanging staffs will be pasted to the staffs below the staff of the RefElement, if definedstaffs exist.
|
1767
1721
|
* Else these copiedId will be not pasted.
|
1768
|
-
* @param ids
|
1769
|
-
* @param
|
1722
|
+
* @param ids Array of Element IDs to be pasted
|
1723
|
+
* @param pastePosition
|
1770
1724
|
*/
|
1771
|
-
function paste(ids,
|
1725
|
+
function paste(ids, pastePosition, currentMEI) {
|
1772
1726
|
var _a;
|
1773
1727
|
//ordered by staff
|
1774
1728
|
var meiElements = new Array();
|
@@ -1788,36 +1742,36 @@ function paste(ids, refId, currentMEI) {
|
|
1788
1742
|
}
|
1789
1743
|
}
|
1790
1744
|
});
|
1791
|
-
var refElement = currentMEI.getElementById(
|
1745
|
+
var refElement = currentMEI.getElementById(pastePosition);
|
1792
1746
|
refElement = (refElement === null || refElement === void 0 ? void 0 : refElement.closest("chord")) || refElement;
|
1793
1747
|
var refStaff = refElement === null || refElement === void 0 ? void 0 : refElement.closest("staff");
|
1794
1748
|
var refLayer = refElement === null || refElement === void 0 ? void 0 : refElement.closest("layer");
|
1795
1749
|
var refMeasure = refElement === null || refElement === void 0 ? void 0 : refElement.closest("measure");
|
1796
1750
|
var currentMeasure;
|
1797
|
-
|
1751
|
+
var anyNew;
|
1798
1752
|
//console.log(...meiElements)
|
1799
1753
|
meiElements.forEach((staff, staffIdx) => {
|
1800
1754
|
var _a, _b, _c, _d, _e, _f, _g;
|
1801
|
-
if (refElement
|
1755
|
+
if (!refElement)
|
1802
1756
|
return;
|
1803
1757
|
currentMeasure = refElement.closest("measure");
|
1804
1758
|
staff.forEach((element, elementIdx) => {
|
1805
1759
|
var _a, _b;
|
1806
1760
|
if (["NOTE", "REST"].includes(element.tagName.toUpperCase())) {
|
1807
|
-
|
1761
|
+
const newNote = convertToNewNote(element);
|
1808
1762
|
newNote.nearestNoteId = refElement.id;
|
1809
|
-
newNote.relPosX = "right";
|
1763
|
+
newNote.relPosX = elementIdx === 0 ? "left" : "right"; // make sure to replace the element on the pasteposition
|
1810
1764
|
anyNew = newNote;
|
1811
1765
|
}
|
1812
1766
|
else if (element.tagName.toUpperCase() === "CHORD") {
|
1813
|
-
|
1767
|
+
const newChord = convertToNewChord(element);
|
1814
1768
|
newChord.nearestNoteId = refElement.id;
|
1815
|
-
newChord.relPosX = "right";
|
1769
|
+
newChord.relPosX = elementIdx === 0 ? "left" : "right"; // make sure to replace the element on the pasteposition
|
1816
1770
|
anyNew = newChord;
|
1817
1771
|
var elementArr = Array.from(element.querySelectorAll("note"));
|
1818
1772
|
}
|
1819
|
-
|
1820
|
-
addToMEI(anyNew, currentMEI, replace);
|
1773
|
+
const replace = ((_b = (_a = document.querySelector(".activeContainer")) === null || _a === void 0 ? void 0 : _a.querySelector("#insertToggle")) === null || _b === void 0 ? void 0 : _b.checked) || true;
|
1774
|
+
currentMEI = addToMEI(anyNew, meiConverter.cleanIdAttr(currentMEI), replace);
|
1821
1775
|
refElement = convertToElement(anyNew, currentMEI); //element
|
1822
1776
|
});
|
1823
1777
|
//when changing next staff, refElement musst be staff + 1
|
@@ -1827,10 +1781,10 @@ function paste(ids, refId, currentMEI) {
|
|
1827
1781
|
refElement = currentMEI.querySelector("measure[n=\"" + refMeasureN + "\"] > staff[n=\"" + targetStaffN + "\"] > layer[n=\"" + refLayerN + "\"]");
|
1828
1782
|
});
|
1829
1783
|
//Element gets replaced in all other modes except keymode/textmode
|
1830
|
-
if (!document.querySelector(".activeContainer").classList.contains("textmode") && ((_a = currentMEI.getElementById(
|
1831
|
-
removeFromMEI([currentMEI.getElementById(
|
1784
|
+
if (!document.querySelector(".activeContainer").classList.contains("textmode") && ((_a = currentMEI.getElementById(pastePosition)) === null || _a === void 0 ? void 0 : _a.tagName) !== "LAYER") {
|
1785
|
+
removeFromMEI([currentMEI.getElementById(pastePosition)], currentMEI);
|
1832
1786
|
}
|
1833
|
-
return anyNew === null || anyNew === void 0 ? void 0 : anyNew.id;
|
1787
|
+
return [currentMEI, anyNew === null || anyNew === void 0 ? void 0 : anyNew.id];
|
1834
1788
|
}
|
1835
1789
|
exports.paste = paste;
|
1836
1790
|
/**
|
@@ -1841,10 +1795,39 @@ exports.paste = paste;
|
|
1841
1795
|
* @returns
|
1842
1796
|
*/
|
1843
1797
|
function replaceClefinScoreDef(target, newClef, currentMEI) {
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1798
|
+
const staffN = document.querySelector(".activeContainer #vrvSVG #" + target.id).closest(".staff").getAttribute("n");
|
1799
|
+
const staffDefClef = currentMEI.querySelector("staffDef[n=\"" + staffN + "\"] > clef");
|
1800
|
+
const shape = newClef.charAt(0);
|
1801
|
+
var line = mappings_1.clefToLine.get(newClef.charAt(0));
|
1802
|
+
if (shape === "C") { // get line depending on id of the cclef
|
1803
|
+
line = mappings_1.clefToLine.get(newClef.match(/CClef(.*)/)[1]);
|
1804
|
+
}
|
1805
|
+
const disPlace = newClef.includes("OctDown") ? "below" : newClef.includes("OctUp") ? "above" : null;
|
1806
|
+
if (staffDefClef) {
|
1807
|
+
staffDefClef.setAttribute("shape", shape);
|
1808
|
+
staffDefClef.setAttribute("line", line);
|
1809
|
+
if (disPlace) {
|
1810
|
+
staffDefClef.setAttribute("dis", "8");
|
1811
|
+
staffDefClef.setAttribute("dis.place", disPlace);
|
1812
|
+
}
|
1813
|
+
else {
|
1814
|
+
staffDefClef.removeAttribute("dis");
|
1815
|
+
staffDefClef.removeAttribute("dis.place");
|
1816
|
+
}
|
1817
|
+
}
|
1818
|
+
else {
|
1819
|
+
const staffDef = currentMEI.querySelector("staffDef[n=\"" + staffN + "\"]");
|
1820
|
+
staffDef === null || staffDef === void 0 ? void 0 : staffDef.setAttribute("clef.shape", shape);
|
1821
|
+
staffDef === null || staffDef === void 0 ? void 0 : staffDef.setAttribute("clef.line", line);
|
1822
|
+
if (disPlace) {
|
1823
|
+
staffDef === null || staffDef === void 0 ? void 0 : staffDef.setAttribute("clef.dis", "8");
|
1824
|
+
staffDef === null || staffDef === void 0 ? void 0 : staffDef.setAttribute("clef.dis.place", disPlace);
|
1825
|
+
}
|
1826
|
+
else {
|
1827
|
+
staffDef === null || staffDef === void 0 ? void 0 : staffDef.removeAttribute("clef.dis");
|
1828
|
+
staffDef === null || staffDef === void 0 ? void 0 : staffDef.removeAttribute("clef.dis.place");
|
1829
|
+
}
|
1830
|
+
}
|
1848
1831
|
cleanUp(currentMEI);
|
1849
1832
|
currentMEI = meiConverter.restoreXmlIdTags(currentMEI);
|
1850
1833
|
return currentMEI;
|
@@ -1860,10 +1843,20 @@ function insertClef(target, newClef, currentMEI) {
|
|
1860
1843
|
var targetStaffId = ((_a = target.closest(".measure").querySelector(".staff[n=\"" + target.getAttribute("n") + "\"]")) === null || _a === void 0 ? void 0 : _a.id) || ((_b = target.closest(".staff")) === null || _b === void 0 ? void 0 : _b.id);
|
1861
1844
|
var targetLayerId = currentMEI.getElementById(targetStaffId).querySelector("layer").id;
|
1862
1845
|
currentMEI.getElementById(targetLayerId).querySelectorAll("clef").forEach(c => c.remove());
|
1846
|
+
const shape = newClef.charAt(0);
|
1847
|
+
var line = mappings_1.clefToLine.get(newClef.charAt(0));
|
1848
|
+
if (shape === "C") { // get line depending on id of the cclef
|
1849
|
+
line = mappings_1.clefToLine.get(newClef.match(/CClef(.*)/)[1]);
|
1850
|
+
}
|
1851
|
+
var disPlace = newClef.includes("OctDown") ? "below" : newClef.includes("OctUp") ? "above" : null;
|
1863
1852
|
var clefElement = currentMEI.createElement("clef");
|
1864
1853
|
clefElement.setAttribute("id", random_1.uuidv4());
|
1865
|
-
clefElement.setAttribute("shape",
|
1866
|
-
clefElement.setAttribute("line",
|
1854
|
+
clefElement.setAttribute("shape", shape);
|
1855
|
+
clefElement.setAttribute("line", line);
|
1856
|
+
if (disPlace) {
|
1857
|
+
clefElement.setAttribute("dis", "8");
|
1858
|
+
clefElement.setAttribute("dis.place", disPlace);
|
1859
|
+
}
|
1867
1860
|
currentMEI.getElementById(targetLayerId).append(clefElement);
|
1868
1861
|
cleanUp(currentMEI);
|
1869
1862
|
currentMEI = meiConverter.restoreXmlIdTags(currentMEI);
|
@@ -2019,7 +2012,7 @@ function getTimestamp(note) {
|
|
2019
2012
|
var layer = note.closest("layer");
|
2020
2013
|
var elements = Array.from(layer.querySelectorAll("*[dur]"));
|
2021
2014
|
elements = elements.filter((v, i) => i <= elements.indexOf(note));
|
2022
|
-
var tstamp;
|
2015
|
+
var tstamp = 0;
|
2023
2016
|
elements.forEach(e => {
|
2024
2017
|
var dur = parseInt(e.getAttribute("dur"));
|
2025
2018
|
tstamp += 4 / dur;
|