vibe-editor 0.0.4 → 0.0.5

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 (78) hide show
  1. package/package.json +65 -61
  2. package/src/scripts/js/Core.js +28 -9
  3. package/src/scripts/js/entry.js +6 -5
  4. package/src/scripts/js/gui/Annotations.js +27 -12
  5. package/src/scripts/js/gui/ScoreManipulator.js +6 -4
  6. package/src/scripts/js/gui/Tabbar.js +13 -4
  7. package/src/scripts/js/handlers/AnnotationChangeHandler.js +13 -1
  8. package/src/scripts/js/handlers/InsertModeHandler.js +3 -3
  9. package/src/scripts/js/handlers/PhantomElementHandler.js +3 -10
  10. package/src/scripts/js/handlers/WindowHandler.js +7 -7
  11. package/src/scripts/js/scripts/Core.js +932 -0
  12. package/src/scripts/js/scripts/MusicProcessor.js +810 -0
  13. package/src/scripts/js/scripts/VIBE.js +219 -0
  14. package/src/scripts/js/scripts/datastructures/MeasureMatrix.js +156 -0
  15. package/src/scripts/js/scripts/gui/Annotations.js +549 -0
  16. package/src/scripts/js/scripts/gui/Cursor.js +203 -0
  17. package/src/scripts/js/scripts/gui/PhantomElement.js +132 -0
  18. package/src/scripts/js/scripts/gui/ScoreManipulator.js +188 -0
  19. package/src/scripts/js/scripts/gui/Tabbar.js +705 -0
  20. package/src/scripts/js/{gui/Toolbar copy.js → scripts/gui/Toolbar.js} +15 -11
  21. package/src/scripts/js/scripts/handlers/AnnotationChangeHandler.js +650 -0
  22. package/src/scripts/js/scripts/handlers/ClickModeHandler.js +535 -0
  23. package/src/scripts/js/{gui → scripts/handlers}/CustomAnnotationShapeDrawer.js +34 -17
  24. package/src/scripts/js/{handlers/ModHandler.js → scripts/handlers/CustomToolbarHandler.js} +54 -66
  25. package/src/scripts/js/scripts/handlers/GlobalKeyboardHandler.js +372 -0
  26. package/src/scripts/js/scripts/handlers/Handler.js +2 -0
  27. package/src/scripts/js/{handlers/InsertModeHandler_deprecated.js → scripts/handlers/InsertModeHandler.js} +117 -164
  28. package/src/scripts/js/scripts/handlers/KeyModeHandler.js +405 -0
  29. package/src/scripts/js/scripts/handlers/LabelHandler.js +463 -0
  30. package/src/scripts/js/scripts/handlers/NoteDragHandler.js +97 -0
  31. package/src/scripts/js/scripts/handlers/PhantomElementHandler.js +168 -0
  32. package/src/scripts/js/scripts/handlers/ScoreManipulatorHandler.js +233 -0
  33. package/src/scripts/js/scripts/handlers/SidebarHandler.js +506 -0
  34. package/src/scripts/js/scripts/handlers/TooltipHandler.js +132 -0
  35. package/src/scripts/js/scripts/handlers/WindowHandler.js +278 -0
  36. package/src/scripts/js/scripts/utils/MEIOperations.js +2121 -0
  37. package/src/scripts/js/{utils/Mouse2MEI.js → scripts/utils/Mouse2SVG.js} +225 -57
  38. package/src/scripts/js/scripts/utils/SVGEditor.js +453 -0
  39. package/src/scripts/js/scripts/utils/Types.js +2 -0
  40. package/src/scripts/js/{utils/VerovioWrapper copy.js → scripts/utils/VerovioWrapper.js} +35 -21
  41. package/src/scripts/js/scripts/utils/coordinates.js +54 -0
  42. package/src/scripts/js/utils/Mouse2SVG.js +11 -4
  43. package/src/scripts/js/utils/VerovioWrapper.js +4 -4
  44. package/src/scripts/js/utils/coordinates.js +26 -2
  45. package/src/scripts/js/.DS_Store +0 -0
  46. package/src/scripts/js/MusicPlayer.js +0 -572
  47. package/src/scripts/js/datastructures/ScoreGraph copy.js +0 -432
  48. package/src/scripts/js/gui/CustomAnnotationDrawer.js +0 -114
  49. package/src/scripts/js/handlers/AnnotationDragHandler.js +0 -113
  50. package/src/scripts/js/handlers/AnnotationLineHandler.js +0 -113
  51. package/src/scripts/js/handlers/ArticulationHandler.js +0 -20
  52. package/src/scripts/js/handlers/HarmonyHandler.js +0 -282
  53. package/src/scripts/js/handlers/InsertModeHandler copy.js +0 -423
  54. package/src/scripts/js/handlers/KeyModeHandler copy.js +0 -407
  55. package/src/scripts/js/handlers/KeyModeHandler_deprecated.js +0 -411
  56. package/src/scripts/js/handlers/NoteDragHandler copy.js +0 -148
  57. package/src/scripts/js/handlers/NoteDragHandler_deprecated.js +0 -150
  58. package/src/scripts/js/handlers/SelectionHandler.js +0 -262
  59. package/src/scripts/js/utils/RectWrapper.js +0 -10
  60. package/src/scripts/js/utils/SVGFiller.js +0 -245
  61. package/src/scripts/js/utils/VerovioWrapperLocal.js +0 -156
  62. package/src/scripts/js/utils/firefoxBBoxes.js +0 -143
  63. package/src/styles/vibe.css +0 -785
  64. /package/src/scripts/js/{assets → scripts/assets}/mei_template.js +0 -0
  65. /package/src/scripts/js/{constants.js → scripts/constants.js} +0 -0
  66. /package/src/scripts/js/{datastructures → scripts/datastructures}/ScoreGraph.js +0 -0
  67. /package/src/scripts/js/{datastructures → scripts/datastructures}/ScoreGraph_deprecated.js +0 -0
  68. /package/src/scripts/js/{datastructures → scripts/datastructures}/ScoreNode.js +0 -0
  69. /package/src/scripts/js/{gui → scripts/gui}/HarmonyLabel.js +0 -0
  70. /package/src/scripts/js/{gui → scripts/gui}/Label.js +0 -0
  71. /package/src/scripts/js/{gui → scripts/gui}/TempoLabel.js +0 -0
  72. /package/src/scripts/js/{handlers → scripts/handlers}/DeleteHandler.js +0 -0
  73. /package/src/scripts/js/{utils → scripts/utils}/DOMCreator.js +0 -0
  74. /package/src/scripts/js/{utils → scripts/utils}/MEIConverter.js +0 -0
  75. /package/src/scripts/js/{utils → scripts/utils}/ReactWrapper.js +0 -0
  76. /package/src/scripts/js/{utils → scripts/utils}/convenienceQueries.js +0 -0
  77. /package/src/scripts/js/{utils → scripts/utils}/mappings.js +0 -0
  78. /package/src/scripts/js/{utils → scripts/utils}/random.js +0 -0
@@ -0,0 +1,535 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const coordinates = require("../utils/coordinates");
4
+ const cq = require("../utils/convenienceQueries");
5
+ const mappings_1 = require("../utils/mappings");
6
+ const marked = "marked";
7
+ class ClickModeHandler {
8
+ constructor() {
9
+ this.isSelecting = false;
10
+ this.selectDist = 0;
11
+ this.dragOnce = false;
12
+ this.shiftPressed = false;
13
+ this.selectEndEvent = new Event("selectEnd");
14
+ /**
15
+ * Event handler for inserting Notes
16
+ */
17
+ this.insertNoteHandler = (function insertNoteHandler(e) {
18
+ this.insertNote(e);
19
+ }).bind(this);
20
+ /**
21
+ * Hide the phantom element for the cursor.
22
+ */
23
+ this.hideCursor = function () {
24
+ if (this.interactionOverlay.querySelector(".moving"))
25
+ return;
26
+ this.container.querySelectorAll("#phantomCanvas > *").forEach(ph => {
27
+ ph.setAttribute("visibility", "hidden");
28
+ }); // make phantoms invisible
29
+ }.bind(this);
30
+ /**
31
+ * Show phantom element for cursor.
32
+ */
33
+ this.showCursor = function () {
34
+ this.container.querySelectorAll("#phantomCanvas > *").forEach(ph => ph.setAttribute("visibility", "visible")); // make phantoms invisible
35
+ }.bind(this);
36
+ /**
37
+ * Handler for {@link mouseOverChord}
38
+ */
39
+ this.mouseOverChordHandler = (function mouseOverHandler(e) {
40
+ this.mouseOverChord(e);
41
+ }).bind(this);
42
+ // SELECTION STUFF
43
+ this.clickSelectHandler = (function clickSelectHandler(e) {
44
+ this.clickSelect(e);
45
+ }).bind(this);
46
+ /**
47
+ * Initialize start coordinates of selecting rectangle.
48
+ * {@link getSelectCoordsHandler} will compute distances on dragging the mouse to decide on initialisation of selection.
49
+ */
50
+ this.selStartHandler = (function selStartHandler(e) {
51
+ this.selectStartX = this.selectStartX || e.clientX;
52
+ this.selectStartY = this.selectStartY || e.clientY;
53
+ }).bind(this);
54
+ this.selectingHandler = (function selectingHandler(e) {
55
+ this.selecting(e);
56
+ }).bind(this);
57
+ /**
58
+ * Handler for {@link selEnd}.
59
+ */
60
+ this.selEndHandler = (function selEndHandler(e) {
61
+ this.selEnd(e);
62
+ }).bind(this);
63
+ /**
64
+ * Handler for {@link getSelectCoords}
65
+ */
66
+ this.getSelectCoordsHandler = (function getSelectCoordsHandler(e) {
67
+ this.getSelectCoords(e);
68
+ }).bind(this);
69
+ /**
70
+ * Handle shift presses and set shiftPressed flag.
71
+ */
72
+ this.shiftKeyHandler = (function shiftKeyHandler(e) {
73
+ //e.preventDefault()
74
+ if (e.key === "Shift") {
75
+ if (e.type === "keydown") {
76
+ this.shiftPressed = true;
77
+ }
78
+ if (e.type === "keyup") {
79
+ this.shiftPressed = false;
80
+ }
81
+ }
82
+ }).bind(this);
83
+ }
84
+ setListeners() {
85
+ // Insert Notation Listeners
86
+ this.interactionOverlay.addEventListener("mouseup", this.insertNoteHandler);
87
+ this.interactionOverlay.addEventListener("mousemove", this.mouseOverChordHandler);
88
+ this.interactionOverlay.querySelectorAll("#scoreRects > *").forEach(sr => {
89
+ if (["clef", "meterSig", "keySig", "rest", "notehead", "harm",].some(c => sr.classList.contains(c))) {
90
+ sr.addEventListener("mouseover", this.hideCursor);
91
+ }
92
+ else {
93
+ sr.addEventListener("mouseover", this.showCursor);
94
+ }
95
+ });
96
+ //Selection Listeners
97
+ this.interactionOverlay.addEventListener("mousedown", this.selStartHandler);
98
+ this.interactionOverlay.addEventListener("mousemove", this.selectingHandler);
99
+ this.interactionOverlay.addEventListener("mousemove", this.getSelectCoordsHandler);
100
+ this.interactionOverlay.addEventListener("mouseup", this.selEndHandler);
101
+ this.interactionOverlay.querySelectorAll(".notehead, .rest").forEach(el => el.addEventListener("click", this.clickSelectHandler));
102
+ //shiftkey for special function
103
+ document.addEventListener("keydown", this.shiftKeyHandler);
104
+ document.addEventListener("keyup", this.shiftKeyHandler);
105
+ //hide or show cursor based on position
106
+ this.interactionOverlay.querySelectorAll("#manipulatorCanvas *, #annotationCanvas *").forEach(sr => {
107
+ sr.addEventListener("mouseover", this.hideCursor);
108
+ sr.addEventListener("mouseleave", this.showCursor);
109
+ });
110
+ // Listener just for staves
111
+ var staves = this.interactionOverlay.querySelectorAll(".staffLine");
112
+ Array.from(staves).forEach(element => {
113
+ element.addEventListener('mouseup', this.insertNoteHandler);
114
+ });
115
+ }
116
+ removeListeners() {
117
+ this.interactionOverlay.removeEventListener("mousedown", this.selStartHandler);
118
+ this.interactionOverlay.removeEventListener("mousemove", this.selectingHandler);
119
+ this.interactionOverlay.removeEventListener("mousemove", this.getSelectCoordsHandler);
120
+ this.interactionOverlay.removeEventListener("mouseup", this.selEndHandler);
121
+ this.interactionOverlay.querySelectorAll(".notehead, .rest").forEach(el => el.removeEventListener("click", this.clickSelectHandler));
122
+ this.interactionOverlay.removeEventListener("mouseup", this.insertNoteHandler);
123
+ this.interactionOverlay.removeEventListener("mousemove", this.mouseOverChordHandler);
124
+ if (this.annotations != undefined) {
125
+ var highLightElements = this.annotations.getAnnotationCanvas().querySelectorAll(".highlightChord");
126
+ Array.from(highLightElements).forEach(el => {
127
+ el.remove();
128
+ });
129
+ }
130
+ document.removeEventListener("keydown", this.shiftKeyHandler);
131
+ document.removeEventListener("keyup", this.shiftKeyHandler);
132
+ this.container.querySelectorAll(".highlighted").forEach((c) => {
133
+ c.classList.remove("highlighted");
134
+ });
135
+ this.interactionOverlay.querySelectorAll("#scoreRects > *").forEach(sr => {
136
+ if (["clef", "meterSig", "keySig", "rest", "notehead", "harm"].some(c => sr.classList.contains(c))) {
137
+ sr.removeEventListener("mouseover", this.hideCursor);
138
+ }
139
+ else {
140
+ sr.removeEventListener("mouseover", this.showCursor);
141
+ }
142
+ });
143
+ // Listener just for staves
144
+ var staves = this.interactionOverlay.querySelectorAll(".staffLine");
145
+ Array.from(staves).forEach(element => {
146
+ element.removeEventListener('mouseup', this.insertNoteHandler);
147
+ });
148
+ }
149
+ resetListeners() {
150
+ this.removeListeners();
151
+ this.setListeners();
152
+ }
153
+ /**
154
+ * Insert a note when mouseup is fires based on mouse position.
155
+ * @param e
156
+ * @returns
157
+ */
158
+ insertNote(e) {
159
+ var _a;
160
+ // when mouseup is fired, selEndHandler and insertNotehandler are alled.
161
+ // The isSelecting flag is set to true as soon as a selection startet, only after that an insertion of a note should be possible
162
+ if (this.isSelecting) {
163
+ this.isSelecting = false;
164
+ return;
165
+ }
166
+ var t = e.target;
167
+ if (cq.getContainer(this.containerId).querySelectorAll(`.${marked}`).length > 1 && !this.shiftPressed) {
168
+ cq.getContainer(this.containerId).querySelectorAll(`.${marked}`).forEach(m => m.classList.remove(marked));
169
+ return; // when more than one element is marked is likely to remove marked status of all notes
170
+ }
171
+ if (cq.getContainer(this.containerId).classList.contains("annotMode"))
172
+ return; // prevent selecting when resizing annotation objects
173
+ if (cq.getContainer(this.containerId).querySelector("#phantomNote").getAttribute("visibility") === "hidden")
174
+ return; //the cursor is possibly somewhere where no note input is possible
175
+ if (cq.getContainer(this.containerId).querySelector("[contenteditable=true]"))
176
+ return;
177
+ e.preventDefault();
178
+ // when mouse is over other interactable elements discard this event
179
+ if (["clef", "meterSig", "keySig", "rest", "notehead", "manipulator"].some(c => {
180
+ let parentCondition = t.parentElement.classList.contains(c);
181
+ let layerCondition = false;
182
+ if (!t.closest(".activeLayer")) {
183
+ layerCondition = true;
184
+ }
185
+ return parentCondition && layerCondition;
186
+ })) {
187
+ this.hideCursor();
188
+ return;
189
+ }
190
+ if (!this.phantomElementHandler.getIsTrackingMouse()) {
191
+ return;
192
+ }
193
+ if (this.musicPlayer.getIsPlaying() === true) {
194
+ return;
195
+ } // getIsPlaying could also be undefined
196
+ // Define position of mouse and which note to set
197
+ var pospt = coordinates.transformToDOMMatrixCoordinates(e.clientX, e.clientY, this.vrvSVG);
198
+ var posx = pospt.x;
199
+ var posy = pospt.y;
200
+ var target = e.target;
201
+ var options = {};
202
+ if (target.classList.contains("staffLine")) {
203
+ options["staffLineId"] = target.id;
204
+ }
205
+ if ((_a = this.interactionOverlay.querySelector("#phantomNote")) === null || _a === void 0 ? void 0 : _a.classList.contains("onChord")) {
206
+ options["targetChord"] = this.findScoreTarget(posx, posy);
207
+ }
208
+ //this.m2s.defineNote(e.pageX, e.pageY, options);
209
+ this.m2s.defineNote(posx, posy, options);
210
+ var newNote = this.m2s.getNewNote();
211
+ if (newNote == undefined)
212
+ return; //Eingabemaske in Chrome: zusätzliche Notenlinien in Noteneditor #10
213
+ var meiDoc = this.m2s.getCurrentMei();
214
+ var pitchExists = false;
215
+ // do not insert same note more than once in chord
216
+ if (newNote.chordElement) {
217
+ var chordEl = meiDoc.getElementById(newNote.chordElement.id);
218
+ if (chordEl.getAttribute("pname") === newNote.pname && chordEl.getAttribute("oct") === newNote.oct) {
219
+ pitchExists = true;
220
+ }
221
+ else {
222
+ for (let c of chordEl.children) {
223
+ if (c.getAttribute("pname") === newNote.pname && c.getAttribute("oct") === newNote.oct) {
224
+ pitchExists = true;
225
+ break;
226
+ }
227
+ }
228
+ }
229
+ }
230
+ if (!pitchExists) {
231
+ var replace = true; //(this.container.querySelector("#insertToggle") as HTMLInputElement).checked && newNote.chordElement == undefined
232
+ this.insertCallback(this.m2s.getNewNote(), replace).then(() => {
233
+ this.musicPlayer.generateTone(this.m2s.getNewNote());
234
+ }).catch(() => {
235
+ //alert("Your bar is to small")
236
+ });
237
+ }
238
+ }
239
+ /**
240
+ * Check if mouse is over a chord to snap cursor and define new note within a chord elemnt
241
+ */
242
+ mouseOverChord(e) {
243
+ var _a;
244
+ if (!this.phantomElementHandler.getIsTrackingMouse()) {
245
+ return;
246
+ }
247
+ var coords = coordinates.transformToDOMMatrixCoordinates(e.clientX, e.clientY, this.interactionOverlay);
248
+ var posx = coords.x;
249
+ var posy = coords.y;
250
+ var elementToHighlight = this.findScoreTarget(posx, posy);
251
+ if (elementToHighlight == undefined || elementToHighlight.closest(".mRest") !== null || elementToHighlight.closest(".rest") !== null) {
252
+ return;
253
+ }
254
+ //if (this.currentElementToHighlight !== elementToHighlight) {
255
+ //update focussed layer if element and layer do not match
256
+ if (elementToHighlight.closest(".layer").id !== ((_a = this.m2s.getMouseEnterElementByName("layer")) === null || _a === void 0 ? void 0 : _a.id) && this.m2s.getMouseEnterElementByName("layer") !== null) {
257
+ this.m2s.setMouseEnterElements(elementToHighlight);
258
+ }
259
+ //snap note to closest Chord
260
+ var phantom = this.interactionOverlay.querySelector("#phantomNote");
261
+ var cx = parseFloat(phantom.getAttribute("cx"));
262
+ var bboxElement = this.interactionOverlay.querySelector("[refId=" + elementToHighlight.id + "]");
263
+ var ptLeft = new DOMPoint(bboxElement.getBoundingClientRect().left, 0);
264
+ var ptRight = new DOMPoint(bboxElement.getBoundingClientRect().right, 0);
265
+ var vrvSVG = this.interactionOverlay;
266
+ var left = ptLeft.matrixTransform(vrvSVG.getScreenCTM().inverse()).x;
267
+ var right = ptRight.matrixTransform(vrvSVG.getScreenCTM().inverse()).x;
268
+ //snap only when within boundaries of target Chord
269
+ if (cx > left && cx < right) {
270
+ var snapTarget;
271
+ var snapTargetBBox;
272
+ var phantomSnapX;
273
+ var targetwidth;
274
+ var snapCoord;
275
+ snapTarget = bboxElement;
276
+ snapTargetBBox = snapTarget.getBoundingClientRect();
277
+ snapCoord = snapTargetBBox.x + snapTargetBBox.width / 2;
278
+ let snappt = new DOMPoint(snapCoord, 0);
279
+ phantomSnapX = snappt.matrixTransform(vrvSVG.getScreenCTM().inverse()).x;
280
+ // if (elementToHighlight.querySelector(".chord") !== null) {
281
+ // console.log(phantomSnapX)
282
+ // }
283
+ phantom.setAttribute("cx", phantomSnapX.toString());
284
+ if (!phantom.classList.contains("onChord")) {
285
+ phantom.classList.add("onChord");
286
+ phantom.classList.add("l" + elementToHighlight.closest(".layer").getAttribute("n"));
287
+ if (!elementToHighlight.classList.contains("chord")) {
288
+ elementToHighlight.classList.add("highlighted");
289
+ }
290
+ else {
291
+ elementToHighlight.querySelectorAll(".note").forEach((c) => {
292
+ c.classList.add("highlighted");
293
+ });
294
+ }
295
+ }
296
+ }
297
+ else {
298
+ for (const [key, value] of phantom.classList.entries()) {
299
+ if (value.indexOf("l") === 0) {
300
+ phantom.classList.remove(value);
301
+ }
302
+ }
303
+ phantom.classList.remove("onChord");
304
+ phantom.setAttribute("fill", "black");
305
+ this.container.querySelectorAll(".highlighted").forEach(h => {
306
+ h.classList.remove("highlighted");
307
+ });
308
+ }
309
+ this.currentElementToHighlight = elementToHighlight;
310
+ //}
311
+ }
312
+ /**
313
+ * Find Score Element nearest to given Position (e.g. Mouse)
314
+ * @param posx client position
315
+ * @param posy client position
316
+ * @returns
317
+ */
318
+ findScoreTarget(posx, posy) {
319
+ var _a;
320
+ const nextNote = this.m2s.findScoreTarget(posx, posy);
321
+ if (nextNote) {
322
+ var el = ((_a = this.vrvSVG.querySelector("#" + nextNote.id)) === null || _a === void 0 ? void 0 : _a.closest(".chord")) || this.vrvSVG.querySelector("#" + nextNote.id);
323
+ if (el.classList.contains("notehead")) {
324
+ el = el.parentElement;
325
+ }
326
+ return el;
327
+ }
328
+ return;
329
+ }
330
+ clickSelect(e) {
331
+ if (!this.shiftPressed) {
332
+ cq.getVrvSVG(this.containerId).querySelectorAll(".marked").forEach(m => m.classList.remove(marked));
333
+ }
334
+ const t = e.target;
335
+ const notehead = cq.getVrvSVG(this.containerId).querySelector(`#${t.parentElement.getAttribute("refId")}`);
336
+ notehead === null || notehead === void 0 ? void 0 : notehead.classList.add(marked);
337
+ const note = notehead.closest(".note");
338
+ if (note) {
339
+ note.classList.add(marked);
340
+ this.scoreGraph.setCurrentNodeById(note.id);
341
+ }
342
+ }
343
+ selStart(e) {
344
+ e.preventDefault();
345
+ if (!this.isSelecting)
346
+ return;
347
+ if (cq.getContainer(this.containerId).classList.contains("annotMode")) {
348
+ this.selEnd(e);
349
+ return;
350
+ }
351
+ //var pt = coordinates.transformToDOMMatrixCoordinates(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY, cq.getInteractOverlay(this.containerId))
352
+ var pt = coordinates.transformToDOMMatrixCoordinates(e.clientX, e.clientY, cq.getInteractOverlay(this.containerId));
353
+ this.initialSelectX = pt.x; //d3.event.x
354
+ this.initialSelectY = pt.y; //d3.event.y
355
+ if (!document.getElementById(this.containerId).classList.contains("harmonyMode") && !this.shiftPressed) { //!this.harmonyHandler.getGlobal()){
356
+ this.m2s.getNoteBBoxes().forEach(bb => {
357
+ let note = this.vrvSVG.querySelector("#" + bb.id);
358
+ note.classList.remove(marked);
359
+ });
360
+ }
361
+ this.initRect(this.initialSelectX, this.initialSelectY);
362
+ this.isSelecting = true;
363
+ }
364
+ selecting(e) {
365
+ e.preventDefault();
366
+ if (document.getElementById(this.containerId).classList.contains("annotMode"))
367
+ return; // prevent selecting when resizing annotation objects
368
+ if (!this.isSelecting)
369
+ return;
370
+ const pt = coordinates.transformToDOMMatrixCoordinates(e.clientX, e.clientY, cq.getInteractOverlay(this.containerId));
371
+ const curX = pt.x;
372
+ const curY = pt.y;
373
+ const newX = curX < this.initialSelectX ? curX : this.initialSelectX;
374
+ const newY = curY < this.initialSelectY ? curY : this.initialSelectY;
375
+ const width = curX < this.initialSelectX ? this.initialSelectX - curX : curX - this.initialSelectX;
376
+ const height = curY < this.initialSelectY ? this.initialSelectY - curY : curY - this.initialSelectY;
377
+ this.updateRect(newX, newY, width, height);
378
+ const rect = this.interactionOverlay.querySelector("#selectRect");
379
+ const rectpt = coordinates.getDOMMatrixCoordinates(rect, this.vrvSVG);
380
+ const rectHeightpt = rectpt.height;
381
+ const rectWidthpt = rectpt.width;
382
+ const rx = rectpt.x;
383
+ const ry = rectpt.y;
384
+ const noteBBoxes = this.m2s.getNoteBBoxes();
385
+ noteBBoxes.forEach(bb => {
386
+ const note = cq.getVrvSVG(this.containerId).querySelector("#" + bb.id);
387
+ const stem = note.querySelector(".stem");
388
+ const accid = note.querySelector(".accid");
389
+ if (bb.x >= rx &&
390
+ //bb.x <= rx + rectBBox.width &&
391
+ bb.x <= rx + rectWidthpt &&
392
+ bb.y >= ry &&
393
+ //bb.y <= ry + rectBBox.height
394
+ bb.y <= ry + rectHeightpt) {
395
+ note.classList.add(marked);
396
+ if (stem !== null)
397
+ stem.classList.add(marked);
398
+ const chord = note.closest(".chord");
399
+ if (chord !== null) {
400
+ //if(!chord.classList.contains(marked))
401
+ const noteArr = Array.from(chord.querySelectorAll(".note"));
402
+ if (noteArr.every(c => c.classList.contains(marked)) && noteArr.length > 0) {
403
+ chord.classList.add(marked);
404
+ }
405
+ }
406
+ }
407
+ else if (!this.shiftPressed) {
408
+ note.classList.remove(marked);
409
+ stem === null || stem === void 0 ? void 0 : stem.classList.remove(marked);
410
+ accid === null || accid === void 0 ? void 0 : accid.classList.remove(marked);
411
+ const chord = note.closest(".chord");
412
+ chord === null || chord === void 0 ? void 0 : chord.classList.remove(marked);
413
+ }
414
+ });
415
+ }
416
+ /**
417
+ * Ends selection. Resets all flags and delets selectRect
418
+ * @param e
419
+ * @returns
420
+ */
421
+ selEnd(e) {
422
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
423
+ e.preventDefault();
424
+ this.dragOnce = false;
425
+ this.selectStartX = undefined;
426
+ this.selectStartY = undefined;
427
+ this.selectDist = 0;
428
+ this.isSelecting = false;
429
+ if (document.getElementById(this.containerId).classList.contains("annotMode"))
430
+ return; // prevent selecting when resizing annotation objects
431
+ var selectRect = cq.getInteractOverlay(this.containerId).querySelector("#selectRect");
432
+ if (selectRect !== null && (selectRect === null || selectRect === void 0 ? void 0 : selectRect.getAttribute("width")) !== "0" && (selectRect === null || selectRect === void 0 ? void 0 : selectRect.getAttribute("height")) !== "0") {
433
+ document.dispatchEvent(this.selectEndEvent);
434
+ }
435
+ selectRect === null || selectRect === void 0 ? void 0 : selectRect.remove();
436
+ var firstMarkedNote = (_a = this.vrvSVG.querySelector(".chord.marked, .note.marked, .rest.marked")) === null || _a === void 0 ? void 0 : _a.id;
437
+ var meiNote = this.m2s.getCurrentMei().getElementById(firstMarkedNote);
438
+ (_c = (_b = document.getElementById(this.containerId)) === null || _b === void 0 ? void 0 : _b.querySelectorAll(".lastAdded")) === null || _c === void 0 ? void 0 : _c.forEach(la => la.classList.remove("lastAdded"));
439
+ if ((firstMarkedNote === null || firstMarkedNote === void 0 ? void 0 : firstMarkedNote.length) > 0) {
440
+ (_d = document.getElementById(this.containerId)) === null || _d === void 0 ? void 0 : _d.querySelectorAll("#noteGroup *, #dotGroup *, #modGroup *, #articGroup *").forEach(b => b.classList.remove("selected"));
441
+ //select buttons for given note state
442
+ var modBtnId = this.container.querySelector("#customToolbar #articGroup") !== null ? "artic" : "accid";
443
+ (_f = (_e = document.getElementById(this.containerId)) === null || _e === void 0 ? void 0 : _e.querySelector("#" + mappings_1.attrToAccidButtonId.get(meiNote === null || meiNote === void 0 ? void 0 : meiNote.getAttribute(modBtnId)))) === null || _f === void 0 ? void 0 : _f.classList.add("selected");
444
+ if ((meiNote === null || meiNote === void 0 ? void 0 : meiNote.closest("chord")) !== null) {
445
+ meiNote = meiNote.closest("chord");
446
+ }
447
+ (_h = (_g = document.getElementById(this.containerId)) === null || _g === void 0 ? void 0 : _g.querySelector("#" + mappings_1.numToNoteButtonId.get(meiNote === null || meiNote === void 0 ? void 0 : meiNote.getAttribute("dur")))) === null || _h === void 0 ? void 0 : _h.classList.add("selected");
448
+ (_k = (_j = document.getElementById(this.containerId)) === null || _j === void 0 ? void 0 : _j.querySelector("#" + mappings_1.numToDotButtonId.get(meiNote === null || meiNote === void 0 ? void 0 : meiNote.getAttribute("dots")))) === null || _k === void 0 ? void 0 : _k.classList.add("selected");
449
+ }
450
+ }
451
+ /**
452
+ * Initialize selectRect.
453
+ * @param x start x
454
+ * @param y start y
455
+ */
456
+ initRect(x, y) {
457
+ const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
458
+ rect.setAttribute("x", x.toString());
459
+ rect.setAttribute("y", y.toString());
460
+ rect.setAttribute("width", "0");
461
+ rect.setAttribute("height", "0");
462
+ rect.setAttribute("id", "selectRect");
463
+ rect.setAttribute("stroke", "black");
464
+ rect.setAttribute("stroke-width", "1px");
465
+ rect.setAttribute("fill", "none");
466
+ this.interactionOverlay.appendChild(rect);
467
+ }
468
+ /**
469
+ * Update size of selectRect.
470
+ * @param newX x posiiton of mouse cursor
471
+ * @param newY y position of mouse cursor
472
+ * @param currentWidth
473
+ * @param currentHeight
474
+ */
475
+ updateRect(newX, newY, currentWidth, currentHeight) {
476
+ const rect = this.interactionOverlay.querySelector("#selectRect");
477
+ rect.setAttribute("x", newX.toString());
478
+ rect.setAttribute("y", newY.toString());
479
+ rect.setAttribute("width", currentWidth.toString());
480
+ rect.setAttribute("height", currentHeight.toString());
481
+ }
482
+ /**
483
+ * Compute coordinates to determine if a selection should be initialized.
484
+ * Starts selection once if distance > 10.
485
+ * This is important to distinguish between inserting a note, drawing the selectRect and selecting one element by click.
486
+ * @param e MouseEvent
487
+ */
488
+ getSelectCoords(e) {
489
+ this.selectDist = Math.sqrt(Math.abs(e.clientX - this.selectStartX) ** 2 + Math.abs(e.clientY - this.selectStartY) ** 2);
490
+ if (this.selectDist > 10) {
491
+ this.isSelecting = true;
492
+ if (!this.dragOnce) {
493
+ this.dragOnce = true;
494
+ this.selStart(e);
495
+ }
496
+ }
497
+ }
498
+ ///// GETTER / SETTER////////////////
499
+ setm2s(m2s) {
500
+ this.m2s = m2s;
501
+ return this;
502
+ }
503
+ setMusicProcessor(musicPlayer) {
504
+ this.musicPlayer = musicPlayer;
505
+ return this;
506
+ }
507
+ setScoreGraph(sg) {
508
+ this.scoreGraph = sg;
509
+ return this;
510
+ }
511
+ setContainerId(id) {
512
+ this.containerId = id;
513
+ this.vrvSVG = cq.getVrvSVG(id);
514
+ this.interactionOverlay = cq.getInteractOverlay(id);
515
+ this.container = document.getElementById(id);
516
+ return this;
517
+ }
518
+ setAnnotations(annotations) {
519
+ this.annotations = annotations;
520
+ return this;
521
+ }
522
+ setInsertCallback(insertCallback) {
523
+ this.insertCallback = insertCallback;
524
+ return this;
525
+ }
526
+ setDeleteCallback(deleteCallback) {
527
+ this.deleteCallback = deleteCallback;
528
+ return this;
529
+ }
530
+ setPhantomCursor(peh) {
531
+ this.phantomElementHandler = peh;
532
+ return this;
533
+ }
534
+ }
535
+ exports.default = ClickModeHandler;
@@ -2,22 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const d3 = require("d3");
4
4
  const random_1 = require("../utils/random");
5
- const constants_1 = require("../constants");
6
- class CustomAnnotationDrawer {
7
- constructor() {
5
+ const coordinates = require("../utils/coordinates");
6
+ const cq = require("../utils/convenienceQueries");
7
+ class CustomAnnotationShapeDrawer {
8
+ constructor(containerId) {
9
+ this.setContainerId(containerId);
8
10
  this.shapes = new Array();
9
11
  this.shapeID = "";
10
12
  this.dragged = false;
11
- this.canvas = d3.select(constants_1.constants._ROOTSVGID_WITH_IDSELECTOR_); // draw directly in svg
13
+ this.canvas = d3.select("#" + this.containerId + " #interactionOverlay"); // draw directly in svg
12
14
  this.dragBehaviour = d3.drag()
13
15
  .on('start', drawStart)
14
16
  .on('drag', this.drawing.bind(this))
15
17
  .on('end', this.drawEnd.bind(this));
16
18
  var that = this;
17
19
  function drawStart() {
18
- that.initialX = d3.event.x;
19
- that.initialY = d3.event.y;
20
- if (d3.event.sourceEvent.srcElement.id === constants_1.constants._ROOTSVGID_) {
20
+ var pt = coordinates.transformToDOMMatrixCoordinates(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY, that.interactionOverlay);
21
+ that.initialX = pt.x; //d3.event.x
22
+ that.initialY = pt.y; //d3.event.y
23
+ if (d3.event.sourceEvent.srcElement.id === that.interactionOverlay.id) {
21
24
  that.initRect(that.initialX, that.initialY);
22
25
  //that.initCircle(that.initialX, that.initialY)
23
26
  }
@@ -25,10 +28,10 @@ class CustomAnnotationDrawer {
25
28
  this.setListeners();
26
29
  }
27
30
  drawing() {
28
- //const currentPt =
29
- const curX = d3.event.x;
30
- const curY = d3.event.y;
31
- if (typeof this.shape === "undefined") {
31
+ var pt = coordinates.transformToDOMMatrixCoordinates(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY, this.interactionOverlay);
32
+ const curX = pt.x; //d3.event.x
33
+ const curY = pt.y; //d3.event.y
34
+ if (this.shape == undefined) {
32
35
  return;
33
36
  }
34
37
  if (Math.abs(curX - this.initialX) > 20 || Math.abs(curY - this.initialY) > 20) {
@@ -42,14 +45,22 @@ class CustomAnnotationDrawer {
42
45
  }
43
46
  }
44
47
  drawEnd() {
48
+ if (this.shapeID === "")
49
+ return;
45
50
  if (!this.dragged) {
46
- var elToRemove = document.getElementById(this.shapeID);
51
+ var elToRemove = this.interactionOverlay.querySelector("#" + this.shapeID);
47
52
  if (elToRemove !== null) {
48
53
  elToRemove.remove();
49
54
  }
50
55
  }
51
56
  else {
52
- document.getElementById("annotationCanvas").appendChild(this.shape);
57
+ var annotCanvas = this.interactionOverlay.querySelector("#annotationCanvas");
58
+ var pt = coordinates.getDOMMatrixCoordinates(this.shape, annotCanvas);
59
+ this.interactionOverlay.querySelector("#annotationCanvas").appendChild(this.shape);
60
+ this.shape.setAttribute("x", pt.left.toString());
61
+ this.shape.setAttribute("y", pt.top.toString());
62
+ this.shape.setAttribute("width", pt.width.toString());
63
+ this.shape.setAttribute("height", pt.height.toString());
53
64
  this.shapes.push(this.shape.cloneNode(true));
54
65
  }
55
66
  this.shape = undefined;
@@ -90,7 +101,7 @@ class CustomAnnotationDrawer {
90
101
  this.shape.setAttribute('ry', currentHeight.toString());
91
102
  }
92
103
  removeListeners() {
93
- d3.select(constants_1.constants._ROOTSVGID_WITH_IDSELECTOR_).on('mousedown.drag', null);
104
+ d3.select("#" + this.containerId + " #interactionOverlay").on('mousedown.drag', null);
94
105
  }
95
106
  setListeners() {
96
107
  this.canvas.call(this.dragBehaviour);
@@ -100,8 +111,14 @@ class CustomAnnotationDrawer {
100
111
  this.setListeners();
101
112
  }
102
113
  ///////// GETTER/ SETTER ////////
103
- setM2M(m2m) {
104
- this.m2m = m2m;
114
+ setm2s(m2s) {
115
+ this.m2s = m2s;
116
+ }
117
+ setContainerId(id) {
118
+ this.containerId = id;
119
+ this.container = document.getElementById(id);
120
+ this.interactionOverlay = cq.getInteractOverlay(id);
121
+ this.vrvSVG = cq.getVrvSVG(id);
105
122
  }
106
123
  getShapes() {
107
124
  return this.shapes;
@@ -111,4 +128,4 @@ class CustomAnnotationDrawer {
111
128
  this.updateCallback = updateCallback;
112
129
  }
113
130
  }
114
- exports.default = CustomAnnotationDrawer;
131
+ exports.default = CustomAnnotationShapeDrawer;