vibe-editor 0.0.0

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.
Files changed (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -0
  3. package/package.json +56 -0
  4. package/src/fonts/bravura/FONTLOG.txt +243 -0
  5. package/src/fonts/bravura/OFL-FAQ.txt +369 -0
  6. package/src/fonts/bravura/OFL.txt +94 -0
  7. package/src/fonts/bravura/bravura-text.md +153 -0
  8. package/src/fonts/bravura/bravura_metadata.json +34718 -0
  9. package/src/fonts/bravura/eot/Bravura.eot +0 -0
  10. package/src/fonts/bravura/eot/BravuraText.eot +0 -0
  11. package/src/fonts/bravura/otf/Bravura.otf +0 -0
  12. package/src/fonts/bravura/otf/BravuraText.otf +0 -0
  13. package/src/fonts/bravura/svg/Bravura.svg +3517 -0
  14. package/src/fonts/bravura/svg/BravuraText.svg +18879 -0
  15. package/src/fonts/bravura/woff/Bravura.woff +0 -0
  16. package/src/fonts/bravura/woff/BravuraText.woff +0 -0
  17. package/src/fonts/colaborate/ColabBol-webfont.eot +0 -0
  18. package/src/fonts/colaborate/ColabBol-webfont.svg +976 -0
  19. package/src/fonts/colaborate/ColabBol-webfont.ttf +0 -0
  20. package/src/fonts/colaborate/ColabBol-webfont.woff +0 -0
  21. package/src/fonts/colaborate/ColabLig-webfont.eot +0 -0
  22. package/src/fonts/colaborate/ColabLig-webfont.svg +976 -0
  23. package/src/fonts/colaborate/ColabLig-webfont.ttf +0 -0
  24. package/src/fonts/colaborate/ColabLig-webfont.woff +0 -0
  25. package/src/fonts/colaborate/ColabMed-webfont.eot +0 -0
  26. package/src/fonts/colaborate/ColabMed-webfont.svg +976 -0
  27. package/src/fonts/colaborate/ColabMed-webfont.ttf +0 -0
  28. package/src/fonts/colaborate/ColabMed-webfont.woff +0 -0
  29. package/src/fonts/colaborate/ColabReg-webfont.eot +0 -0
  30. package/src/fonts/colaborate/ColabReg-webfont.svg +976 -0
  31. package/src/fonts/colaborate/ColabReg-webfont.ttf +0 -0
  32. package/src/fonts/colaborate/ColabReg-webfont.woff +0 -0
  33. package/src/fonts/colaborate/ColabThi-webfont.eot +0 -0
  34. package/src/fonts/colaborate/ColabThi-webfont.svg +970 -0
  35. package/src/fonts/colaborate/ColabThi-webfont.ttf +0 -0
  36. package/src/fonts/colaborate/ColabThi-webfont.woff +0 -0
  37. package/src/images/GUI/.DS_Store +0 -0
  38. package/src/images/GUI/backward-fast-solid.svg +1 -0
  39. package/src/images/GUI/bars-solid.svg +1 -0
  40. package/src/images/GUI/caret-left-solid.svg +1 -0
  41. package/src/images/GUI/caret-right-solid.svg +1 -0
  42. package/src/images/GUI/edit-solid.svg +1 -0
  43. package/src/images/GUI/pause-solid.svg +1 -0
  44. package/src/images/GUI/play-solid.svg +1 -0
  45. package/src/images/GUI/triplet.svg +21 -0
  46. package/src/images/GUI/zoomin.svg +1 -0
  47. package/src/images/GUI/zoomout.svg +1 -0
  48. package/src/images/bravura_notes/.DS_Store +0 -0
  49. package/src/images/bravura_notes/16th.svg +1 -0
  50. package/src/images/bravura_notes/32th.svg +1 -0
  51. package/src/images/bravura_notes/alterDDown.svg +1 -0
  52. package/src/images/bravura_notes/alterDUp.svg +1 -0
  53. package/src/images/bravura_notes/alterDown.svg +1 -0
  54. package/src/images/bravura_notes/alterNeutral.svg +1 -0
  55. package/src/images/bravura_notes/alterUp.svg +1 -0
  56. package/src/images/bravura_notes/beams.svg +1 -0
  57. package/src/images/bravura_notes/eigth.svg +1 -0
  58. package/src/images/bravura_notes/full.svg +1 -0
  59. package/src/images/bravura_notes/half.svg +1 -0
  60. package/src/images/bravura_notes/oneDot.svg +1 -0
  61. package/src/images/bravura_notes/pauseNote.svg +1 -0
  62. package/src/images/bravura_notes/quarter.svg +1 -0
  63. package/src/images/bravura_notes/tie.svg +1 -0
  64. package/src/images/bravura_notes/twoDot.svg +1 -0
  65. package/src/scripts/js/.DS_Store +0 -0
  66. package/src/scripts/js/Core.js +887 -0
  67. package/src/scripts/js/MusicPlayer.js +572 -0
  68. package/src/scripts/js/MusicProcessor.js +652 -0
  69. package/src/scripts/js/VerovioScoreEditor.js +183 -0
  70. package/src/scripts/js/assets/mei_template.js +161 -0
  71. package/src/scripts/js/constants.js +20 -0
  72. package/src/scripts/js/datastructures/MeasureMatrix.js +235 -0
  73. package/src/scripts/js/datastructures/ScoreGraph.js +432 -0
  74. package/src/scripts/js/datastructures/ScoreNode.js +78 -0
  75. package/src/scripts/js/entry.js +4 -0
  76. package/src/scripts/js/gui/Annotations.js +456 -0
  77. package/src/scripts/js/gui/Cursor.js +203 -0
  78. package/src/scripts/js/gui/CustomAnnotationDrawer.js +114 -0
  79. package/src/scripts/js/gui/CustomAnnotationShapeDrawer.js +114 -0
  80. package/src/scripts/js/gui/HarmonyLabel.js +104 -0
  81. package/src/scripts/js/gui/Label.js +2 -0
  82. package/src/scripts/js/gui/PhantomElement.js +132 -0
  83. package/src/scripts/js/gui/ScoreManipulator.js +156 -0
  84. package/src/scripts/js/gui/Tabbar.js +675 -0
  85. package/src/scripts/js/gui/TempoLabel.js +60 -0
  86. package/src/scripts/js/gui/Toolbar copy.js +614 -0
  87. package/src/scripts/js/gui/Toolbar.js +618 -0
  88. package/src/scripts/js/handlers/AnnotationChangeHandler.js +567 -0
  89. package/src/scripts/js/handlers/AnnotationDragHandler.js +113 -0
  90. package/src/scripts/js/handlers/AnnotationLineHandler.js +113 -0
  91. package/src/scripts/js/handlers/ArticulationHandler.js +20 -0
  92. package/src/scripts/js/handlers/ClickModeHandler.js +265 -0
  93. package/src/scripts/js/handlers/CustomAnnotationShapeDrawer.js +131 -0
  94. package/src/scripts/js/handlers/CustomToolbarHandler.js +297 -0
  95. package/src/scripts/js/handlers/DeleteHandler.js +102 -0
  96. package/src/scripts/js/handlers/GlobalKeyboardHandler.js +367 -0
  97. package/src/scripts/js/handlers/Handler.js +2 -0
  98. package/src/scripts/js/handlers/HarmonyHandler.js +282 -0
  99. package/src/scripts/js/handlers/InsertModeHandler copy.js +423 -0
  100. package/src/scripts/js/handlers/InsertModeHandler.js +380 -0
  101. package/src/scripts/js/handlers/InsertModeHandler_deprecated.js +424 -0
  102. package/src/scripts/js/handlers/KeyModeHandler copy.js +407 -0
  103. package/src/scripts/js/handlers/KeyModeHandler.js +456 -0
  104. package/src/scripts/js/handlers/KeyModeHandler_deprecated.js +411 -0
  105. package/src/scripts/js/handlers/LabelHandler.js +461 -0
  106. package/src/scripts/js/handlers/ModHandler.js +311 -0
  107. package/src/scripts/js/handlers/NoteDragHandler copy.js +148 -0
  108. package/src/scripts/js/handlers/NoteDragHandler.js +97 -0
  109. package/src/scripts/js/handlers/NoteDragHandler_deprecated.js +150 -0
  110. package/src/scripts/js/handlers/PhantomElementHandler.js +168 -0
  111. package/src/scripts/js/handlers/ScoreManipulatorHandler.js +135 -0
  112. package/src/scripts/js/handlers/SelectionHandler.js +218 -0
  113. package/src/scripts/js/handlers/SideBarHandler.js +499 -0
  114. package/src/scripts/js/handlers/TooltipHandler.js +132 -0
  115. package/src/scripts/js/handlers/WindowHandler.js +257 -0
  116. package/src/scripts/js/utils/DOMCreator.js +174 -0
  117. package/src/scripts/js/utils/MEIConverter.js +64 -0
  118. package/src/scripts/js/utils/MEIOperations.js +2112 -0
  119. package/src/scripts/js/utils/Mouse2MEI.js +735 -0
  120. package/src/scripts/js/utils/Mouse2SVG.js +737 -0
  121. package/src/scripts/js/utils/SVGEditor.js +352 -0
  122. package/src/scripts/js/utils/SVGFiller.js +245 -0
  123. package/src/scripts/js/utils/Types.js +2 -0
  124. package/src/scripts/js/utils/VerovioWrapper copy.js +156 -0
  125. package/src/scripts/js/utils/VerovioWrapper.js +165 -0
  126. package/src/scripts/js/utils/VerovioWrapperLocal.js +156 -0
  127. package/src/scripts/js/utils/convenienceQueries.js +37 -0
  128. package/src/scripts/js/utils/coordinates.js +54 -0
  129. package/src/scripts/js/utils/firefoxBBoxes.js +143 -0
  130. package/src/scripts/js/utils/mappings.js +332 -0
  131. package/src/scripts/js/utils/random.js +45 -0
  132. package/src/styles/VerovioScoreEditor.css +694 -0
@@ -0,0 +1,367 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const meiOperation = require("../utils/MEIOperations");
4
+ const meiConverter = require("../utils/MEIConverter");
5
+ const cq = require("../utils/convenienceQueries");
6
+ const marked = "marked";
7
+ const lastAdded = "lastAdded";
8
+ const editStates = [marked, lastAdded];
9
+ const editStateSelector = "." + editStates.join(",.");
10
+ const noteEditStateSelector = editStateSelector.replace(".", ".note.");
11
+ class GlobalKeyboardHandler {
12
+ constructor(containerId) {
13
+ this.preventScroll = function (e) {
14
+ if (this.hasEditableOpen())
15
+ return;
16
+ if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].indexOf(e.code) > -1) {
17
+ e.preventDefault();
18
+ }
19
+ }.bind(this);
20
+ this.keydownHandler = (function keydownHandler(e) {
21
+ if (e.code === "Space")
22
+ return;
23
+ if (this.hasContainerFocus()) {
24
+ if (e.key == undefined) {
25
+ return;
26
+ }
27
+ if (this.hasEditableOpen())
28
+ return;
29
+ var that = this;
30
+ var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
31
+ var ctrl = e.ctrlKey;
32
+ if (isMac) {
33
+ ctrl = e.metaKey;
34
+ }
35
+ if (ctrl) {
36
+ if (e.key === "z") {
37
+ this.undoHandler(e);
38
+ }
39
+ if (e.key === "y") {
40
+ this.redoHandler(e);
41
+ }
42
+ if (e.key === "a") {
43
+ this.selectAllHandler(e);
44
+ }
45
+ if (e.key === "c") {
46
+ this.copyHandler(e);
47
+ }
48
+ if (e.key === "v") {
49
+ this.pasteHandler(e);
50
+ }
51
+ // if(e.key === "k" && Array.from(document.querySelectorAll(".note, .chord, .rest, .mrest")).some(el => el.classList.contains(marked))){
52
+ // this.handleHarmony(e)
53
+ // }
54
+ }
55
+ else if (e.key.includes("Arrow")) {
56
+ //document.removeEventListener("keydown", this.keydownHandler)
57
+ this.transposeHandler(e);
58
+ }
59
+ else if (e.key === "Escape") {
60
+ this.resetHandler(e);
61
+ }
62
+ else if (e.key.match(/F\d/) !== null) { // interact with F-Keys
63
+ this.changeTab(e.key);
64
+ }
65
+ else if (e.key.match(/^\d+$/) !== null) { // interaction with numbers
66
+ this.changeCustomBtn(e.key);
67
+ }
68
+ else if (e.shiftKey) {
69
+ if (e.key !== "Shift" && cq.getContainer(this.containerId).classList.contains("clickMode")) { // may only be used during Notation Tab is open
70
+ // wait for a double keydown and cache input information
71
+ if (this.tempKey == undefined) {
72
+ this.tempKey = e.key;
73
+ }
74
+ else {
75
+ this.tempKey += e.key;
76
+ }
77
+ if (this.keyTimeOuts == undefined)
78
+ this.keyTimeOuts = new Array();
79
+ this.keyTimeOuts.forEach(to => {
80
+ clearTimeout(to);
81
+ });
82
+ var to = setTimeout(function () {
83
+ if (["B", "BB", "'", "''", "N", "T", "_"].some(k => that.tempKey === k)) {
84
+ that.changeCustomBtn(that.tempKey);
85
+ }
86
+ that.tempKey = undefined;
87
+ that.keyTimeOuts.forEach(to => {
88
+ clearTimeout(to);
89
+ });
90
+ that.keyTimeOuts = undefined;
91
+ }, 100);
92
+ this.keyTimeOuts.push(to);
93
+ }
94
+ }
95
+ }
96
+ }).bind(this);
97
+ this.prolongHandler = (function prolongHandler(e) {
98
+ if (this.hasContainerFocus()) {
99
+ if (e.code === "Semicolon") { // Deutsch: Ä
100
+ this.reduceDur();
101
+ }
102
+ else if (e.code === "Quote") { // Deutsch: Ö
103
+ this.prolongDur();
104
+ }
105
+ }
106
+ }).bind(this);
107
+ this.containerId = containerId;
108
+ this.container = document.getElementById(containerId);
109
+ this.setListeners();
110
+ }
111
+ setListeners() {
112
+ document.addEventListener("keydown", this.keydownHandler);
113
+ //document.addEventListener("keydown", this.prolongHandler)
114
+ window.addEventListener("keydown", this.preventScroll, false);
115
+ }
116
+ removeListeners() {
117
+ document.removeEventListener("keydown", this.keydownHandler);
118
+ //document.removeEventListener("keydown", this.prolongHandler)
119
+ window.removeEventListener("keydown", this.preventScroll, false);
120
+ }
121
+ undoHandler(e) {
122
+ e.preventDefault();
123
+ if (!this.hasContainerFocus())
124
+ return;
125
+ e.stopImmediatePropagation();
126
+ this.undoCallback();
127
+ //document.removeEventListener("keydown", this.keydownHandler)
128
+ }
129
+ redoHandler(e) {
130
+ e.preventDefault();
131
+ if (!this.hasContainerFocus())
132
+ return;
133
+ e.stopImmediatePropagation();
134
+ this.redoCallback();
135
+ //document.removeEventListener("keydown", this.keydownHandler)
136
+ }
137
+ selectAllHandler(e) {
138
+ if (!this.hasContainerFocus())
139
+ return;
140
+ e.preventDefault();
141
+ cq.getVrvSVG(this.containerId).querySelectorAll(".note").forEach(note => {
142
+ let stem = note.querySelector(".stem");
143
+ note.classList.add(marked);
144
+ if (stem !== null) {
145
+ stem.classList.add(marked);
146
+ }
147
+ var chord = note.closest(".chord");
148
+ if (chord !== null) {
149
+ if (!chord.classList.contains(marked))
150
+ chord.classList.add(marked);
151
+ }
152
+ });
153
+ }
154
+ /**
155
+ * Copy marked Elements
156
+ * @param e
157
+ */
158
+ copyHandler(e) {
159
+ if (!this.hasContainerFocus())
160
+ return;
161
+ e.preventDefault();
162
+ this.copiedIds = new Array();
163
+ document.querySelectorAll(".marked").forEach(m => {
164
+ this.copiedIds.push(m.id);
165
+ });
166
+ this.copiedIds.filter(n => n); //undefined and null Elements will be excluded
167
+ }
168
+ /**
169
+ * paste marked Elements
170
+ * @param e
171
+ */
172
+ pasteHandler(e) {
173
+ var _a, _b;
174
+ //if(!this.hasContainerFocus()) return
175
+ //e.preventDefault()
176
+ var pastePosition = ((_a = this.container.querySelector(".chord.marked, .note.marked, .rest.marked, .mRest.marked")) === null || _a === void 0 ? void 0 : _a.id) || ((_b = this.container.querySelector("#cursor")) === null || _b === void 0 ? void 0 : _b.getAttribute("refId"));
177
+ if (this.copiedIds != undefined && pastePosition != undefined) {
178
+ var lastId = meiOperation.paste(this.copiedIds, pastePosition, this.currentMEI);
179
+ var mei = meiConverter.restoreXmlIdTags(this.currentMEI);
180
+ this.loadDataCallback("", mei, false).then(mei => {
181
+ //Tell everyone that a past just occured to readjust certain elements e.g.
182
+ var pastedEvent = new CustomEvent("pasted", { detail: lastId });
183
+ document.dispatchEvent(pastedEvent);
184
+ });
185
+ }
186
+ }
187
+ resetHandler(e) {
188
+ if (!this.hasContainerFocus())
189
+ return;
190
+ e.preventDefault();
191
+ this.container.querySelectorAll(editStateSelector).forEach(el => {
192
+ editStates.forEach(es => {
193
+ el.classList.remove(es);
194
+ });
195
+ });
196
+ this.musicPlayer.rewindMidi();
197
+ this.resetLastInsertedNoteId();
198
+ this.container.querySelectorAll("#modGroup *").forEach(mg => mg.classList.remove("selected"));
199
+ }
200
+ transposeHandler(e) {
201
+ if (!this.hasContainerFocus())
202
+ return;
203
+ if (["annotMode", "harmonyMode"].some(cn => this.container.classList.contains(cn)))
204
+ return;
205
+ //e.preventDefault()
206
+ if (document.querySelectorAll(noteEditStateSelector).length === 0) {
207
+ return;
208
+ }
209
+ var mei;
210
+ switch (e.key) {
211
+ case "ArrowUp":
212
+ mei = meiOperation.transposeByStep(this.currentMEI, "up");
213
+ break;
214
+ case "ArrowDown":
215
+ mei = meiOperation.transposeByStep(this.currentMEI, "down");
216
+ break;
217
+ default:
218
+ //console.log(this, "Sorry, wrong turn")
219
+ }
220
+ if (mei != undefined) {
221
+ if (cq.getContainer(this.containerId).querySelector(".marked") !== null)
222
+ this.resetLastInsertedNoteId();
223
+ mei = meiConverter.restoreXmlIdTags(mei);
224
+ this.loadDataCallback("", mei, false);
225
+ }
226
+ }
227
+ /**
228
+ * Change tab according to F-Key. The mapping is based on the displayed order
229
+ * @param fkey
230
+ */
231
+ changeTab(fkey) {
232
+ var cont = cq.getContainer(this.containerId);
233
+ var target;
234
+ switch (fkey) {
235
+ case "F1":
236
+ target = "notationTabBtn";
237
+ break;
238
+ case "F2":
239
+ target = "annotationTabBtn";
240
+ break;
241
+ case "F3":
242
+ target = "articulationTabBtn";
243
+ break;
244
+ default:
245
+ console.log("There is no Tab to be selected for KEY " + fkey);
246
+ }
247
+ try {
248
+ cont.querySelector("#" + target).dispatchEvent(new MouseEvent("click"));
249
+ }
250
+ catch (error) {
251
+ console.log(this.constructor.name, " has no implementation for " + target);
252
+ }
253
+ }
254
+ /**
255
+ * Change to the button in custom tool bar based on the key input.
256
+ * In the case of numbers: mapping is based on the displayed order. Everything else is mapped by key combinations
257
+ * @param key
258
+ */
259
+ changeCustomBtn(key) {
260
+ var _a, _b;
261
+ if (key.match(/^\d+$/) !== null) {
262
+ var i = parseInt(key);
263
+ i = i === 0 ? 9 : i - 1;
264
+ var btn = cq.getContainer(this.containerId).querySelectorAll("#customToolbar button.btn");
265
+ (_a = btn[i]) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new MouseEvent("click"));
266
+ }
267
+ else {
268
+ var id = "";
269
+ switch (key) {
270
+ case "B": //b
271
+ id = "alterDown";
272
+ break;
273
+ case "'": //#
274
+ id = "alterUp";
275
+ break;
276
+ case "BB": //bb
277
+ id = "alterDDown";
278
+ break;
279
+ case "''": //x
280
+ id = "alterDUp";
281
+ break;
282
+ case "N": //neutral
283
+ id = "alterNeutral";
284
+ break;
285
+ case "T": //tie /slur
286
+ id = "tieNotes";
287
+ break;
288
+ case "_": //beam
289
+ id = "organizeBeams";
290
+ break;
291
+ }
292
+ (_b = cq.getContainer(this.containerId).querySelector("#" + id)) === null || _b === void 0 ? void 0 : _b.dispatchEvent(new MouseEvent("click"));
293
+ }
294
+ }
295
+ handleHarmony(e) {
296
+ if (!this.hasContainerFocus())
297
+ return;
298
+ this.harmonyHandlerCallback(e);
299
+ }
300
+ // Helpers
301
+ reduceDur() {
302
+ var additionalElements = new Array();
303
+ additionalElements.push(document.getElementById(this.scoreGraph.nextRight().getId()));
304
+ //meiOperation.changeDuration(this.currentMEI, "reduce", additionalElements)
305
+ meiOperation.changeDurationsInLayer(this.currentMEI, additionalElements);
306
+ var mei = meiConverter.restoreXmlIdTags(this.currentMEI);
307
+ this.loadDataCallback("", mei, false);
308
+ }
309
+ prolongDur() {
310
+ var additionalElements = new Array();
311
+ additionalElements.push(document.getElementById(this.scoreGraph.nextRight().getId()));
312
+ //meiOperation.changeDuration(this.currentMEI, "prolong", additionalElements)
313
+ meiOperation.changeDurationsInLayer(this.currentMEI, additionalElements);
314
+ var mei = meiConverter.restoreXmlIdTags(this.currentMEI);
315
+ this.loadDataCallback("", mei, false);
316
+ }
317
+ resetListeners() {
318
+ this.removeListeners();
319
+ this.setListeners();
320
+ return this;
321
+ }
322
+ hasContainerFocus() {
323
+ return this.container.classList.contains("activeContainer");
324
+ }
325
+ hasEditableOpen() {
326
+ return document.getElementById(this.containerId).querySelector(".canvas *[contenteditable=true]") !== null;
327
+ }
328
+ /////// GETTER/ SETTER ///////
329
+ setUndoCallback(undoCallback) {
330
+ this.undoCallback = undoCallback;
331
+ return this;
332
+ }
333
+ setRedoCallback(redoCallback) {
334
+ this.redoCallback = redoCallback;
335
+ return this;
336
+ }
337
+ setCurrentMei(mei) {
338
+ this.currentMEI = mei;
339
+ return this;
340
+ }
341
+ setMusicProcessor(musicPlayer) {
342
+ this.musicPlayer = musicPlayer;
343
+ return this;
344
+ }
345
+ setScoreGraph(scoreGraph) {
346
+ this.scoreGraph = scoreGraph;
347
+ return this;
348
+ }
349
+ resetLastInsertedNoteId() { }
350
+ setHarmonyHandlerCallback(harmonyHandlerCallback) {
351
+ this.harmonyHandlerCallback = harmonyHandlerCallback;
352
+ return this;
353
+ }
354
+ setLoadDataCallback(loadDataCallback) {
355
+ this.loadDataCallback = loadDataCallback;
356
+ return this;
357
+ }
358
+ setContainerId(containerId) {
359
+ this.containerId = containerId;
360
+ return this;
361
+ }
362
+ resetLastInsertedNoteCallback(resetLastInsertedNoteId) {
363
+ this.resetLastInsertedNoteId = resetLastInsertedNoteId;
364
+ return this;
365
+ }
366
+ }
367
+ exports.default = GlobalKeyboardHandler;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,282 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const meiConverter = require("../utils/MEIConverter");
4
+ const constants_1 = require("../constants");
5
+ const random_1 = require("../utils/random");
6
+ const HarmonyLabel_1 = require("../gui/HarmonyLabel");
7
+ const coordinates = require("../utils/coordinates");
8
+ class HarmonyHandler {
9
+ constructor() {
10
+ this.setHarmonyLabelHandlerClick = (function setHarmonyLabelHandler(e) {
11
+ if (document.body.classList.contains("harmonyMode")) {
12
+ this.harmonyLabelHandler(e);
13
+ }
14
+ }).bind(this);
15
+ this.setHarmonyLabelHandlerKey = (function setHarmonyLabelHandler(e) {
16
+ if (e.ctrlKey || e.metaKey) {
17
+ if (e.key === "k" && Array.from(document.querySelectorAll(".note, .chord, .rest, .mrest")).some(el => el.classList.contains("marked"))) {
18
+ e.preventDefault();
19
+ this.harmonyLabelHandler(e);
20
+ }
21
+ }
22
+ }).bind(this);
23
+ this.activateHarmonyHighlight = (function highlightNextHarmonyHandler(e) {
24
+ if (e.type === "mouseleave" && !this.isGlobal) {
25
+ document.getElementById(constants_1.constants._ROOTSVGID_).addEventListener("mousemove", this.activateHarmonyHighlight);
26
+ }
27
+ if (!this.isGlobal) {
28
+ this.highlightNextHarmony(e);
29
+ }
30
+ }).bind(this);
31
+ this.deactivateHarmonyHighlight = (function deactivateHighlight(e) {
32
+ // document.querySelectorAll(".marked").forEach(m => {
33
+ // m.classList.remove("marked")
34
+ // })
35
+ document.getElementById(constants_1.constants._ROOTSVGID_).removeEventListener("mousemove", this.activateHarmonyHighlight);
36
+ }).bind(this);
37
+ this.modifyLabelHandler = (function modifyLabelHandler(e) {
38
+ document.querySelectorAll(".marked").forEach(m => {
39
+ m.classList.remove("marked");
40
+ });
41
+ this.modifyLabel(e);
42
+ }).bind(this);
43
+ this.submitLabelHandler = (function submitHandler(e) {
44
+ if (e.key === "Enter" && this.harmonyCanvas.hasChildNodes()) {
45
+ this.submitLabel();
46
+ }
47
+ }).bind(this);
48
+ this.closeModifyWindowHandler = (function closeModifyWindow(e) {
49
+ if (e.key === "Escape") {
50
+ this.closeModifyWindow();
51
+ }
52
+ }).bind(this);
53
+ this.addCanvas();
54
+ this.harmonyElements = new Map();
55
+ }
56
+ addCanvas() {
57
+ if (typeof this.harmonyCanvas === "undefined") {
58
+ this.harmonyCanvas = document.createElementNS(constants_1.constants._SVGNS_, "svg");
59
+ this.harmonyCanvas.setAttribute("id", "harmonyCanvas");
60
+ }
61
+ this.root = document.getElementById(constants_1.constants._ROOTSVGID_);
62
+ this.root.insertBefore(this.harmonyCanvas, this.root.firstChild);
63
+ }
64
+ setListeners() {
65
+ document.querySelectorAll(".sylTextRect").forEach(s => {
66
+ s.remove();
67
+ });
68
+ if (!this.isGlobal) {
69
+ document.getElementById(constants_1.constants._ROOTSVGID_).addEventListener("click", this.setHarmonyLabelHandlerClick, true);
70
+ document.getElementById(constants_1.constants._ROOTSVGID_).addEventListener("mousemove", this.activateHarmonyHighlight);
71
+ document.getElementById(constants_1.constants._ROOTSVGID_).addEventListener("keydown", this.closeModifyWindowHandler, true);
72
+ }
73
+ document.addEventListener("keydown", this.setHarmonyLabelHandlerKey);
74
+ document.querySelectorAll(".harm").forEach(h => {
75
+ h.addEventListener("mouseover", this.deactivateHarmonyHighlight);
76
+ h.addEventListener("mouseleave", this.activateHarmonyHighlight);
77
+ h.addEventListener("dblclick", this.modifyLabelHandler);
78
+ });
79
+ return this;
80
+ }
81
+ removeListeners() {
82
+ document.getElementById(constants_1.constants._ROOTSVGID_).removeEventListener("click", this.setHarmonyLabelHandlerClick);
83
+ document.removeEventListener("keydown", this.setHarmonyLabelHandlerKey);
84
+ document.getElementById(constants_1.constants._ROOTSVGID_).removeEventListener("mousemove", this.activateHarmonyHighlight);
85
+ document.getElementById(constants_1.constants._ROOTSVGID_).removeEventListener("keydown", this.closeModifyWindowHandler);
86
+ document.querySelectorAll(".harm").forEach(h => {
87
+ h.removeEventListener("mouseenter", this.deactivateHarmonyHighlight);
88
+ h.removeEventListener("mouseleave", this.activateHarmonyHighlight);
89
+ h.removeEventListener("dblclick", this.modifyLabelHandler);
90
+ });
91
+ return this;
92
+ }
93
+ /**
94
+ * Open Inputbox for (first) selected Note
95
+ */
96
+ harmonyLabelHandler(e) {
97
+ var root = document.getElementById(constants_1.constants._ROOTSVGID_);
98
+ var rootBBox = root.getBoundingClientRect();
99
+ var nextNote = document.querySelector(".note.marked, .chord.marked");
100
+ if (nextNote === null) {
101
+ return;
102
+ }
103
+ var nextNoteBBox = nextNote.getBoundingClientRect();
104
+ var staffBBox = nextNote.closest(".staff").getBoundingClientRect();
105
+ var posx = nextNoteBBox.left - nextNoteBBox.width / 2 - window.scrollX - rootBBox.x - root.scrollLeft;
106
+ var posy = staffBBox.bottom - window.scrollY - rootBBox.y - root.scrollLeft;
107
+ if (this.currentMEI.querySelector("harm[startid=\"" + nextNote.id + "\"]") === null && !this.harmonyCanvas.hasChildNodes()) {
108
+ this.createInputBox(posx, posy, nextNote.id);
109
+ }
110
+ else if (this.harmonyCanvas.hasChildNodes()) {
111
+ this.closeModifyWindow();
112
+ }
113
+ }
114
+ setHarmonyLabel(label, bboxId) {
115
+ var harmonyLabel = new HarmonyLabel_1.default(label, bboxId, this.currentMEI); // TODO: Make Dynamically
116
+ this.harmonyElements.set(harmonyLabel.getHarmElement().id, harmonyLabel);
117
+ var measure = this.currentMEI.getElementById(bboxId).closest("measure");
118
+ measure.appendChild(harmonyLabel.getHarmElement());
119
+ var mei = meiConverter.restoreXmlIdTags(this.currentMEI);
120
+ this.loadDataCallback("", mei, false, constants_1.constants._TARGETDIVID_).then(() => {
121
+ this.reset();
122
+ });
123
+ return harmonyLabel;
124
+ }
125
+ highlightNextHarmony(e, active = true) {
126
+ if (!active) {
127
+ return;
128
+ }
129
+ var posx = coordinates.adjustToPage(e.pageX, "x");
130
+ var posy = coordinates.adjustToPage(e.pageY, "y");
131
+ var nextNoteBBox = this.m2m.findScoreTarget(posx, posy);
132
+ var el = document.getElementById(nextNoteBBox.id);
133
+ if (el.closest(".chord") !== null) {
134
+ el = el.closest(".chord");
135
+ }
136
+ if (!el.classList.contains("marked")) {
137
+ document.querySelectorAll(".marked").forEach(m => {
138
+ m.classList.remove("marked");
139
+ });
140
+ el.classList.add("marked");
141
+ }
142
+ }
143
+ modifyLabel(e) {
144
+ var target = e.target;
145
+ target = target.closest(".harm");
146
+ target.setAttribute("visibility", "hidden");
147
+ this.harmId = target.id;
148
+ var targetBBox = target.getBoundingClientRect();
149
+ var root = document.getElementById(constants_1.constants._ROOTSVGID_);
150
+ var rootBBox = root.getBoundingClientRect();
151
+ var posx = targetBBox.x - window.scrollX - rootBBox.left - root.scrollLeft; //coordinates.adjustToPage(e.pageX, "x")
152
+ var posy = targetBBox.y - window.scrollY - rootBBox.top - root.scrollTop; //coordinates.adjustToPage(e.pageY, "y")
153
+ if (document.querySelector("*[refHarmId=\"" + target.id + "\"]") !== null) {
154
+ return;
155
+ }
156
+ this.createInputBox(posx, posy, target.id);
157
+ }
158
+ closeModifyWindow() {
159
+ Array.from(this.harmonyCanvas.children).forEach(c => {
160
+ c.remove();
161
+ });
162
+ // clean MEI from empty harm Elements
163
+ this.currentMEI.querySelectorAll("harm").forEach(h => {
164
+ var _a;
165
+ (_a = document.getElementById(h.id)) === null || _a === void 0 ? void 0 : _a.setAttribute("visibility", "visible");
166
+ if (h.childElementCount > 0) {
167
+ if (h.firstElementChild.childElementCount === 0) {
168
+ h.remove();
169
+ }
170
+ }
171
+ else if (h.textContent.length === 0) {
172
+ h.remove();
173
+ }
174
+ });
175
+ }
176
+ submitLabel() {
177
+ var harmonyDiv = this.harmonyCanvas.getElementsByClassName("harmonyDiv")[0];
178
+ var text = harmonyDiv.textContent;
179
+ var harmLabel = this.harmonyElements.get(harmonyDiv.closest("g").getAttribute("refHarmId"));
180
+ if (typeof harmLabel !== "undefined") {
181
+ harmLabel.modifyLabel(text);
182
+ var currentHarm = this.currentMEI.getElementById(harmLabel.getHarmElement().id);
183
+ currentHarm.parentElement.replaceChild(harmLabel.getHarmElement(), currentHarm);
184
+ }
185
+ else {
186
+ harmLabel = this.setHarmonyLabel(harmonyDiv.textContent, harmonyDiv.closest("g").getAttribute("refHarmId"));
187
+ var oldLabel = this.currentMEI.getElementById(this.harmId);
188
+ harmLabel.getHarmElement().setAttribute("tstamp", oldLabel.getAttribute("tstamp"));
189
+ harmLabel.getHarmElement().setAttribute("startid", oldLabel.getAttribute("startid"));
190
+ oldLabel.remove();
191
+ }
192
+ this.closeModifyWindow();
193
+ var mei = meiConverter.restoreXmlIdTags(this.currentMEI);
194
+ this.loadDataCallback("", mei, false, constants_1.constants._TARGETDIVID_).then(() => {
195
+ this.reset();
196
+ });
197
+ }
198
+ createInputBox(posx, posy, targetId) {
199
+ var textGroup = document.createElementNS(constants_1.constants._SVGNS_, "g");
200
+ textGroup.setAttribute("id", random_1.uuidv4());
201
+ textGroup.setAttribute("refHarmId", targetId);
202
+ var text = document.createElementNS(constants_1.constants._SVGNS_, "svg");
203
+ text.classList.add("harmonyText");
204
+ var textForeignObject = document.createElementNS(constants_1.constants._SVGNS_, "foreignObject");
205
+ textForeignObject.classList.add("harmonyFO");
206
+ var textDiv = document.createElement("div");
207
+ textDiv.setAttribute("contenteditable", "true");
208
+ textDiv.textContent = typeof this.harmonyElements.get(targetId) !== "undefined" ? this.harmonyElements.get(targetId).getInputString() : "";
209
+ textDiv.classList.add("harmonyDiv");
210
+ text.append(textForeignObject);
211
+ document.body.appendChild(textDiv);
212
+ var rectPadding = 5;
213
+ text.setAttribute("x", (posx + rectPadding).toString());
214
+ text.setAttribute("y", (posy).toString());
215
+ textForeignObject.setAttribute("x", "0");
216
+ textForeignObject.setAttribute("y", "0");
217
+ textForeignObject.setAttribute("height", (textDiv.clientHeight + 2 * rectPadding).toString());
218
+ textForeignObject.setAttribute("width", (100 + 2 * rectPadding).toString());
219
+ this.harmonyCanvas.appendChild(textGroup);
220
+ textGroup.appendChild(text);
221
+ textForeignObject.appendChild(textDiv);
222
+ // Special Listeners while Editing Harmonies
223
+ var that = this;
224
+ textDiv.addEventListener("focus", function () {
225
+ that.removeListeners();
226
+ that.musicPlayer.removePlayListener();
227
+ });
228
+ textDiv.addEventListener("blur", function () {
229
+ that.setListeners();
230
+ that.musicPlayer.setPlayListener();
231
+ });
232
+ textDiv.addEventListener("keydown", this.submitLabelHandler);
233
+ textDiv.focus();
234
+ }
235
+ getTimestamp(note) {
236
+ var layer = note.closest("layer");
237
+ var elements = Array.from(layer.querySelectorAll("*[dur]"));
238
+ elements = elements.filter((v, i) => i <= elements.indexOf(note));
239
+ var tstamp;
240
+ elements.forEach(e => {
241
+ var dur = parseInt(e.getAttribute("dur"));
242
+ tstamp += 4 / dur;
243
+ var dots = e.getAttribute("dots");
244
+ var add = dur;
245
+ if (dots !== null) {
246
+ for (var i = 0; i < parseInt(dots); i++) {
247
+ add = add / 2;
248
+ tstamp += add;
249
+ }
250
+ }
251
+ });
252
+ return tstamp;
253
+ }
254
+ reset() {
255
+ this.setListeners();
256
+ this.addCanvas();
257
+ }
258
+ setM2M(m2m) {
259
+ this.m2m = m2m;
260
+ return this;
261
+ }
262
+ setCurrentMEI(mei) {
263
+ this.currentMEI = mei;
264
+ return this;
265
+ }
266
+ setMusicPlayer(musicPlayer) {
267
+ this.musicPlayer = musicPlayer;
268
+ return this;
269
+ }
270
+ setGlobal(global) {
271
+ this.isGlobal = global;
272
+ return this;
273
+ }
274
+ getGlobal() {
275
+ return this.isGlobal;
276
+ }
277
+ setLoadDataCallback(loadDataCallback) {
278
+ this.loadDataCallback = loadDataCallback;
279
+ return this;
280
+ }
281
+ }
282
+ exports.default = HarmonyHandler;