Repository: opensheetmusicdisplay/opensheetmusicdisplay
Pull request #377 (2018-09-09 19:17:16)

fix(Cursor jumping around): Instead first staffentry the minimum is c…
…alculated and taken as x refere

#376


Patch:
diff --git a/.travis.yml b/.travis.yml
index db23d2f4..5df4f051 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,11 @@
-sudo: false
+sudo: required
+dist: trusty
 language: node_js
 node_js:
 - '6'
 - '8'
 env:
-  - timeout=4000
+  - timeout=10000
 notifications:
   email: false
   slack:
diff --git a/README.md b/README.md
index f57c0d30..038f2ae1 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
 [![Code Climate](https://codeclimate.com/github/opensheetmusicdisplay/opensheetmusicdisplay/badges/gpa.svg)](https://codeclimate.com/github/opensheetmusicdisplay/opensheetmusicdisplay)
 [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
 
-[osmd.org](https://osmd.org)
+[opensheetmusicdisplay.org](https://opensheetmusicdisplay.org/)
 
 OpenSheetMusicDisplay renders MusicXML sheet music in the browser. It is the missing link between MusicXML and VexFlow. Built upon many years of experience in both sheet music interactivity and engraving, it is the perfect solution for app developers seeking to build digital sheet music services.
 
diff --git a/demo/index.html b/demo/index.html
index 982cae59..afd26826 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -2,7 +2,8 @@
 <html lang="en">
 <head>
     <meta charset="utf-8">
-
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    
     <title><%= htmlWebpackPlugin.options.title %></title>
     <meta name="description" content="A showcase for OpenSheetMusicDisplay.">
     <meta name="author" content="OpenSheetMusicDisplay contributors">
diff --git a/karma.conf.js b/karma.conf.js
index bb45ce5e..9cf68710 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -13,24 +13,22 @@ module.exports = function (config) {
         // list of files to exclude
         exclude: [],
 
-        files: [{
-            pattern: 'src/**/*.ts',
-            included: false
-        }, {
-            pattern: 'test/**/*.ts',
-            included: true
-        }, {
-            pattern: 'test/data/*.xml',
-            included: true
-        }, {
-            pattern: 'test/data/*.mxl.base64',
-            included: true
-        }, {
-            pattern: 'test/data/*.mxl',
-            included: false,
-            watched: false,
-            served: true
-        }],
+        files: [
+            {
+                pattern: 'test/**/*.ts',
+                included: true
+            }, {
+                pattern: 'test/data/*.xml',
+                included: true
+            }, {
+                pattern: 'test/data/*.mxl.base64',
+                included: true
+            }, {
+                pattern: 'test/data/*.mxl',
+                included: false,
+                watched: false,
+                served: true
+            }],
 
         // preprocess matching files before serving them to the browser
         // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
@@ -38,7 +36,6 @@ module.exports = function (config) {
             'test/data/*.xml': ['xml2js'],
             'test/data/*.mxl.base64': ['base64-to-js'],
             // add webpack as preprocessor
-            'src/**/*.ts': ['webpack'],
             'test/**/*.ts': ['webpack']
         },
 
@@ -48,23 +45,18 @@ module.exports = function (config) {
             // webpack watches dependencies
 
             // copy parts of webpack configuration to use minimal effort here
-            devtool: process.env.CI ? false : 'cheap-module-eval-source-map',
+            devtool: process.env.CI ? false : 'inline-source-map',
             mode: process.env.CI ? 'production' : 'development',
             module: {
                 rules: common.module.rules
             },
             resolve: common.resolve
         },
-        webpackMiddleware: {
-            // webpack-dev-middleware configuration
-            // i. e.
-            noInfo: true
-        },
 
         // Required for Firefox and Chorme to work
         // see https://github.com/webpack-contrib/karma-webpack/issues/188
         mime: {
-            'text/x-typescript': ['ts', 'tsx']
+            'text/x-typescript': ['ts']
         },
 
         // test results reporter to use
@@ -75,14 +67,16 @@ module.exports = function (config) {
         // web server port
         port: 9876,
         // timeout in ms:
-        browserNoActivityTimeout: 100000,
+        browserNoActivityTimeout: 100000, // default 10000
+        browserDisconnectTimeout: 10000, // default 2000
+        browserDisconnectTolerance: 1, // default 0
         captureTimeout: 60000,
         // enable / disable colors in the output (reporters and logs)
         colors: true,
 
         // level of logging
         // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
-        logLevel: config.LOG_ERROR,
+        logLevel: config.LOG_INFO,
 
         client: {
             captureConsole: true,
@@ -95,14 +89,19 @@ module.exports = function (config) {
         autoWatch: false,
 
         // start these browsers
-        browsers: [process.env.CI ? 'ChromeHeadlessNoSandbox' : 'ChromeHeadless'],
+        browsers: ['ChromeHeadlessNoSandbox'],
 
         // For security reasons, Google Chrome is unable to provide sandboxing
         // when it is running in container-based environments (e.g. CI).
         customLaunchers: {
             ChromeHeadlessNoSandbox: {
                 base: 'ChromeHeadless',
-                flags: ['--no-sandbox']
+                flags: ['--no-sandbox',
+                    '--disable-web-security']
+            },
+            ChromeNoSecurity: {
+                base: 'Chrome',
+                flags: ['--disable-web-security']
             }
         },
 
diff --git a/package.json b/package.json
index 69098ae6..501d119d 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
     "tslint": "tslint --project tsconfig.json \"src/**/*.ts\" \"test/**/*.ts\"",
     "lint": "npm-run-all eslint tslint",
     "test": "karma start --single-run --no-auto-watch",
-    "test:watch": "karma start --no-single-run --auto-watch --browsers Chrome",
+    "test:watch": "karma start --no-single-run --auto-watch --browsers ChromeNoSecurity",
     "prepare": "npm run build",
     "build": "npm-run-all lint build:webpack",
     "build:doc": "cross-env STATIC_FILES_SUBFOLDER=sheets npm run build",
diff --git a/src/Common/Enums/TextAlignment.ts b/src/Common/Enums/TextAlignment.ts
index 27c796fd..5b87b5e3 100644
--- a/src/Common/Enums/TextAlignment.ts
+++ b/src/Common/Enums/TextAlignment.ts
@@ -1,12 +1,11 @@
 /**
- * The possible positioning of text on the sheet music
+ * The Alignment of a TextLabel.
+ * Specifically the label's position coordinates within the Bounding Box.
+ * For LeftBottom, the label's position is at the left bottom corner of its Bounding Box.
  * (used for example with title, composer, author, etc.)
- * TODO this should be split into alignment and placement, e.g. <Left, Top> for LeftTop.
- * Right now "LeftTop" means left-aligned and top-placed. This is ambiguous for center,
- * which can be alignment or placement.
- * A function like "IsLeft" would be easier with the split.
+ * (see Show Bounding Box For -> Labels in the local demo)
  */
-export enum TextAlignmentAndPlacement {
+export enum TextAlignmentEnum {
     LeftTop,
     LeftCenter,
     LeftBottom,
@@ -17,23 +16,28 @@ export enum TextAlignmentAndPlacement {
     RightCenter,
     RightBottom
 }
+/*
+ * TODO this could be split into two alignments, e.g. <Left, Top> for LeftTop.
+ * A function like IsLeft would be easier with the split.
+ * On the other hand, accessing these values will be more complex
+*/
 
 export class TextAlignment {
-    public static IsLeft(textAlignment: TextAlignmentAndPlacement): boolean {
-        return textAlignment === TextAlignmentAndPlacement.LeftTop
-            || textAlignment === TextAlignmentAndPlacement.LeftCenter
-            || textAlignment === TextAlignmentAndPlacement.LeftBottom;
+    public static IsLeft(textAlignment: TextAlignmentEnum): boolean {
+        return textAlignment === TextAlignmentEnum.LeftTop
+            || textAlignment === TextAlignmentEnum.LeftCenter
+            || textAlignment === TextAlignmentEnum.LeftBottom;
     }
 
-    public static IsCenterAligned(textAlignment: TextAlignmentAndPlacement): boolean {
-        return textAlignment === TextAlignmentAndPlacement.CenterTop
-            || textAlignment === TextAlignmentAndPlacement.CenterCenter
-            || textAlignment === TextAlignmentAndPlacement.CenterBottom;
+    public static IsCenterAligned(textAlignment: TextAlignmentEnum): boolean {
+        return textAlignment === TextAlignmentEnum.CenterTop
+            || textAlignment === TextAlignmentEnum.CenterCenter
+            || textAlignment === TextAlignmentEnum.CenterBottom;
     }
 
-    public static IsRight(textAlignment: TextAlignmentAndPlacement): boolean {
-        return textAlignment === TextAlignmentAndPlacement.RightTop
-            || textAlignment === TextAlignmentAndPlacement.RightCenter
-            || textAlignment === TextAlignmentAndPlacement.RightBottom;
+    public static IsRight(textAlignment: TextAlignmentEnum): boolean {
+        return textAlignment === TextAlignmentEnum.RightTop
+            || textAlignment === TextAlignmentEnum.RightCenter
+            || textAlignment === TextAlignmentEnum.RightBottom;
     }
 }
diff --git a/src/MusicalScore/Graphical/DrawingParameters.ts b/src/MusicalScore/Graphical/DrawingParameters.ts
index f00907a2..8a36cb6b 100644
--- a/src/MusicalScore/Graphical/DrawingParameters.ts
+++ b/src/MusicalScore/Graphical/DrawingParameters.ts
@@ -21,7 +21,7 @@ export class DrawingParameters {
         this.drawMarkedAreas = true;
     }
 
-    public setForThumbmail(): void {
+    public setForThumbnail(): void {
         this.drawHighlights = false;
         this.drawErrors = false;
         this.drawSelectionStartSymbol = false;
diff --git a/src/MusicalScore/Graphical/EngravingRules.ts b/src/MusicalScore/Graphical/EngravingRules.ts
index 5fdc5c8c..bea1136a 100644
--- a/src/MusicalScore/Graphical/EngravingRules.ts
+++ b/src/MusicalScore/Graphical/EngravingRules.ts
@@ -1,7 +1,7 @@
 import {PagePlacementEnum} from "./GraphicalMusicPage";
 //import {MusicSymbol} from "./MusicSymbol";
 import * as log from "loglevel";
-import { TextAlignmentAndPlacement } from "../../Common/Enums/TextAlignment";
+import { TextAlignmentEnum } from "../../Common/Enums/TextAlignment";
 
 export class EngravingRules {
     private static rules: EngravingRules;
@@ -88,7 +88,7 @@ export class EngravingRules {
     private repetitionEndingLabelYOffset: number;
     private repetitionEndingLineYLowerOffset: number;
     private repetitionEndingLineYUpperOffset: number;
-    private lyricsAlignmentStandard: TextAlignmentAndPlacement;
+    private lyricsAlignmentStandard: TextAlignmentEnum;
     private lyricsHeight: number;
     private lyricsYOffsetToStaffHeight: number;
     private verticalBetweenLyricsDistance: number;
@@ -274,7 +274,7 @@ export class EngravingRules {
         this.repetitionEndingLineYUpperOffset = 0.3;
 
         // Lyrics
-        this.lyricsAlignmentStandard = TextAlignmentAndPlacement.LeftBottom; // CenterBottom and LeftBottom tested, spacing-optimized
+        this.lyricsAlignmentStandard = TextAlignmentEnum.LeftBottom; // CenterBottom and LeftBottom tested, spacing-optimized
         this.lyricsHeight = 2.0; // actually size of lyrics
         this.lyricsYOffsetToStaffHeight = 3.0; // distance between lyrics and staff. could partly be even lower/dynamic
         this.verticalBetweenLyricsDistance = 0.5;
@@ -816,10 +816,10 @@ export class EngravingRules {
     public set RepetitionEndingLineYUpperOffset(value: number) {
         this.repetitionEndingLineYUpperOffset = value;
     }
-    public get LyricsAlignmentStandard(): TextAlignmentAndPlacement {
+    public get LyricsAlignmentStandard(): TextAlignmentEnum {
         return this.lyricsAlignmentStandard;
     }
-    public set LyricsAlignmentStandard(value: TextAlignmentAndPlacement) {
+    public set LyricsAlignmentStandard(value: TextAlignmentEnum) {
         this.lyricsAlignmentStandard = value;
     }
     public get LyricsHeight(): number {
diff --git a/src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts b/src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts
index 9c11ffb2..e290a096 100644
--- a/src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts
+++ b/src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts
@@ -1,4 +1,4 @@
-import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../../Common/Enums/TextAlignment";
 import {Label} from "../Label";
 import {GraphicalLabel} from "./GraphicalLabel";
 import {ChordSymbolContainer} from "../VoiceData/ChordSymbolContainer";
@@ -23,7 +23,7 @@ export class GraphicalChordSymbolContainer extends GraphicalObject {
     }
     private calculateLabel(textHeight: number, transposeHalftones: number): void {
         const text: string = ChordSymbolContainer.calculateChordText(this.chordSymbolContainer, transposeHalftones);
-        this.graphicalLabel = new GraphicalLabel(new Label(text), textHeight, TextAlignmentAndPlacement.CenterBottom, this.boundingBox);
+        this.graphicalLabel = new GraphicalLabel(new Label(text), textHeight, TextAlignmentEnum.CenterBottom, this.boundingBox);
         this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0.0, 0.0);
     }
 }
diff --git a/src/MusicalScore/Graphical/GraphicalLabel.ts b/src/MusicalScore/Graphical/GraphicalLabel.ts
index f7b47c54..604913df 100644
--- a/src/MusicalScore/Graphical/GraphicalLabel.ts
+++ b/src/MusicalScore/Graphical/GraphicalLabel.ts
@@ -1,5 +1,5 @@
 import {Label} from "../Label";
-import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../../Common/Enums/TextAlignment";
 import {Clickable} from "./Clickable";
 import {BoundingBox} from "./BoundingBox";
 import {EngravingRules} from "./EngravingRules";
@@ -18,7 +18,7 @@ export class GraphicalLabel extends Clickable {
      * @param alignment Alignement like left, right, top, ...
      * @param parent Parent Bounding Box where the label is attached to
      */
-    constructor(label: Label, textHeight: number, alignment: TextAlignmentAndPlacement, parent: BoundingBox = undefined) {
+    constructor(label: Label, textHeight: number, alignment: TextAlignmentEnum, parent: BoundingBox = undefined) {
         super();
         this.label = label;
         this.boundingBox = new BoundingBox(this, parent);
@@ -50,55 +50,55 @@ export class GraphicalLabel extends Clickable {
         const bbox: BoundingBox = this.PositionAndShape;
 
         switch (this.Label.textAlignment) {
-            case TextAlignmentAndPlacement.CenterBottom:
+            case TextAlignmentEnum.CenterBottom:
                 bbox.BorderTop = -height;
                 bbox.BorderLeft = -width / 2;
                 bbox.BorderBottom = 0;
                 bbox.BorderRight = width / 2;
                 break;
-            case TextAlignmentAndPlacement.CenterCenter:
+            case TextAlignmentEnum.CenterCenter:
                 bbox.BorderTop = -height / 2;
                 bbox.BorderLeft = -width / 2;
                 bbox.BorderBottom = height / 2;
                 bbox.BorderRight = width / 2;
                 break;
-            case TextAlignmentAndPlacement.CenterTop:
+            case TextAlignmentEnum.CenterTop:
                 bbox.BorderTop = 0;
                 bbox.BorderLeft = -width / 2;
                 bbox.BorderBottom = height;
                 bbox.BorderRight = width / 2;
                 break;
-            case TextAlignmentAndPlacement.LeftBottom:
+            case TextAlignmentEnum.LeftBottom:
                 bbox.BorderTop = -height;
-                bbox.BorderLeft = -1;
+                bbox.BorderLeft = 0;
                 bbox.BorderBottom = 0;
-                bbox.BorderRight = width - 1;
+                bbox.BorderRight = width;
                 break;
-            case TextAlignmentAndPlacement.LeftCenter:
+            case TextAlignmentEnum.LeftCenter:
                 bbox.BorderTop = -height / 2;
                 bbox.BorderLeft = 0;
                 bbox.BorderBottom = height / 2;
                 bbox.BorderRight = width;
                 break;
-            case TextAlignmentAndPlacement.LeftTop:
+            case TextAlignmentEnum.LeftTop:
                 bbox.BorderTop = 0;
                 bbox.BorderLeft = 0;
                 bbox.BorderBottom = height;
                 bbox.BorderRight = width;
                 break;
-            case TextAlignmentAndPlacement.RightBottom:
+            case TextAlignmentEnum.RightBottom:
                 bbox.BorderTop = -height;
                 bbox.BorderLeft = -width;
                 bbox.BorderBottom = 0;
                 bbox.BorderRight = 0;
                 break;
-            case TextAlignmentAndPlacement.RightCenter:
+            case TextAlignmentEnum.RightCenter:
                 bbox.BorderTop = -height / 2;
                 bbox.BorderLeft = -width;
                 bbox.BorderBottom = height / 2;
                 bbox.BorderRight = 0;
                 break;
-            case TextAlignmentAndPlacement.RightTop:
+            case TextAlignmentEnum.RightTop:
                 bbox.BorderTop = 0;
                 bbox.BorderLeft = -width;
                 bbox.BorderBottom = height;
diff --git a/src/MusicalScore/Graphical/GraphicalLyricEntry.ts b/src/MusicalScore/Graphical/GraphicalLyricEntry.ts
index 8df79bee..049cf72a 100644
--- a/src/MusicalScore/Graphical/GraphicalLyricEntry.ts
+++ b/src/MusicalScore/Graphical/GraphicalLyricEntry.ts
@@ -5,7 +5,7 @@ import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
 import {Label} from "../Label";
 import {PointF2D} from "../../Common/DataObjects/PointF2D";
 import { EngravingRules } from "./EngravingRules";
-import { TextAlignmentAndPlacement } from "../../Common/Enums/TextAlignment";
+import { TextAlignmentEnum } from "../../Common/Enums/TextAlignment";
 
 /**
  * The graphical counterpart of a [[LyricsEntry]]
@@ -19,21 +19,24 @@ export class GraphicalLyricEntry {
     constructor(lyricsEntry: LyricsEntry, graphicalStaffEntry: GraphicalStaffEntry, lyricsHeight: number, staffHeight: number) {
         this.lyricsEntry = lyricsEntry;
         this.graphicalStaffEntry = graphicalStaffEntry;
-        let lyricsTextAlignment: TextAlignmentAndPlacement = EngravingRules.Rules.LyricsAlignmentStandard;
+        const lyricsTextAlignment: TextAlignmentEnum = EngravingRules.Rules.LyricsAlignmentStandard;
         // for small notes with long text, use center alignment
         // TODO use this, fix center+left alignment combination spacing
         if (lyricsEntry.Text.length >= 4
             && lyricsEntry.Parent.Notes[0].Length.Denominator > 4
-            && lyricsTextAlignment === TextAlignmentAndPlacement.LeftBottom) {
-            lyricsTextAlignment = TextAlignmentAndPlacement.CenterBottom;
+            && lyricsTextAlignment === TextAlignmentEnum.LeftBottom) {
+            // lyricsTextAlignment = TextAlignmentAndPlacement.CenterBottom;
         }
         this.graphicalLabel = new GraphicalLabel(
             new Label(lyricsEntry.Text),
             lyricsHeight,
-            EngravingRules.Rules.LyricsAlignmentStandard,
+            lyricsTextAlignment,
             graphicalStaffEntry.PositionAndShape
         );
-        this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0, staffHeight); // TODO gets reset later
+        this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0, staffHeight);
+        if (lyricsTextAlignment === TextAlignmentEnum.LeftBottom) {
+            this.graphicalLabel.PositionAndShape.RelativePosition.x -= 1; // make lyrics optically left-aligned
+        }
     }
 
     public get LyricsEntry(): LyricsEntry {
diff --git a/src/MusicalScore/Graphical/MusicSheetCalculator.ts b/src/MusicalScore/Graphical/MusicSheetCalculator.ts
index c4005cb8..558f8041 100644
--- a/src/MusicalScore/Graphical/MusicSheetCalculator.ts
+++ b/src/MusicalScore/Graphical/MusicSheetCalculator.ts
@@ -31,7 +31,7 @@ import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
 import {BoundingBox} from "./BoundingBox";
 import {Instrument} from "../Instrument";
 import {GraphicalLabel} from "./GraphicalLabel";
-import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../../Common/Enums/TextAlignment";
 import {VerticalGraphicalStaffEntryContainer} from "./VerticalGraphicalStaffEntryContainer";
 import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
 import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
@@ -422,7 +422,7 @@ export abstract class MusicSheetCalculator {
     private calculateSingleMeasureNumberPlacement(measure: GraphicalMeasure, staffLine: StaffLine, musicSystem: MusicSystem): void {
         const labelNumber: string = measure.MeasureNumber.toString();
         const graphicalLabel: GraphicalLabel = new GraphicalLabel(new Label(labelNumber), this.rules.MeasureNumberLabelHeight,
-                                                                  TextAlignmentAndPlacement.LeftBottom);
+                                                                  TextAlignmentEnum.LeftBottom);
 
         const skyBottomLineCalculator: SkyBottomLineCalculator = staffLine.SkyBottomLineCalculator;
 
@@ -542,7 +542,8 @@ export abstract class MusicSheetCalculator {
                 if (this.leadSheet) {
                     position = 3.4 + (this.rules.VerticalBetweenLyricsDistance + this.rules.LyricsHeight) * (sortedLyricVerseNumberIndex);
                 }
-                lyricsEntryLabel.PositionAndShape.RelativePosition = new PointF2D(0, position);
+                const previousRelativeX: number = lyricsEntryLabel.PositionAndShape.RelativePosition.x;
+                lyricsEntryLabel.PositionAndShape.RelativePosition = new PointF2D(previousRelativeX, position);
                 maxPosition = Math.max(maxPosition, position);
             }
         }
@@ -550,9 +551,10 @@ export abstract class MusicSheetCalculator {
         // update BottomLine (on the whole StaffLine's length)
         if (lyricsStaffEntriesList.length > 0) {
             const endX: number = staffLine.PositionAndShape.Size.width;
-            const startX: number = lyricsStaffEntriesList[0].PositionAndShape.RelativePosition.x +
+            let startX: number = lyricsStaffEntriesList[0].PositionAndShape.RelativePosition.x +
                 lyricsStaffEntriesList[0].PositionAndShape.BorderMarginLeft +
                 lyricsStaffEntriesList[0].parentMeasure.PositionAndShape.RelativePosition.x;
+            startX = startX > endX ? endX : startX;
             skyBottomLineCalculator.updateBottomLineInRange(startX, endX, maxPosition);
         }
         return lyricsStaffEntriesList;
@@ -901,12 +903,12 @@ export abstract class MusicSheetCalculator {
         label.fontHeight = fontHeight;
 
         // TODO_RR: TextHeight from first Entry
-        const graphLabel: GraphicalLabel = new GraphicalLabel(label, fontHeight, TextAlignmentAndPlacement.CenterBottom, staffLine.PositionAndShape);
+        const graphLabel: GraphicalLabel = new GraphicalLabel(label, fontHeight, TextAlignmentEnum.CenterBottom, staffLine.PositionAndShape);
         graphLabel.Label.fontStyle = style;
         const marginFactor: number = 1.1;
 
         if (placement === PlacementEnum.Below) {
-            graphLabel.Label.textAlignment = TextAlignmentAndPlacement.LeftTop;
+            graphLabel.Label.textAlignment = TextAlignmentEnum.LeftTop;
         }
 
         graphLabel.setLabelPositionAndShapeBorders();
@@ -1167,7 +1169,7 @@ export abstract class MusicSheetCalculator {
         for (const instrument of this.graphicalMusicSheet.ParentMusicSheet.Instruments) {
             if (instrument.Voices.length > 0 && instrument.Voices[0].Visible) {
                 const graphicalLabel: GraphicalLabel = new GraphicalLabel(
-                    instrument.NameLabel, this.rules.InstrumentLabelTextHeight, TextAlignmentAndPlacement.LeftCenter);
+                    instrument.NameLabel, this.rules.InstrumentLabelTextHeight, TextAlignmentEnum.LeftCenter);
                 graphicalLabel.setLabelPositionAndShapeBorders();
                 maxLabelLength = Math.max(maxLabelLength, graphicalLabel.PositionAndShape.MarginSize.width);
             }
@@ -1178,22 +1180,22 @@ export abstract class MusicSheetCalculator {
     protected calculateSheetLabelBoundingBoxes(): void {
         const musicSheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
         if (musicSheet.Title !== undefined) {
-            const title: GraphicalLabel = new GraphicalLabel(musicSheet.Title, this.rules.SheetTitleHeight, TextAlignmentAndPlacement.CenterBottom);
+            const title: GraphicalLabel = new GraphicalLabel(musicSheet.Title, this.rules.SheetTitleHeight, TextAlignmentEnum.CenterBottom);
             this.graphicalMusicSheet.Title = title;
             title.setLabelPositionAndShapeBorders();
         }
         if (musicSheet.Subtitle !== undefined) {
-            const subtitle: GraphicalLabel = new GraphicalLabel(musicSheet.Subtitle, this.rules.SheetSubtitleHeight, TextAlignmentAndPlacement.CenterCenter);
+            const subtitle: GraphicalLabel = new GraphicalLabel(musicSheet.Subtitle, this.rules.SheetSubtitleHeight, TextAlignmentEnum.CenterCenter);
             this.graphicalMusicSheet.Subtitle = subtitle;
             subtitle.setLabelPositionAndShapeBorders();
         }
         if (musicSheet.Composer !== undefined) {
-            const composer: GraphicalLabel = new GraphicalLabel(musicSheet.Composer, this.rules.SheetComposerHeight, TextAlignmentAndPlacement.RightCenter);
+            const composer: GraphicalLabel = new GraphicalLabel(musicSheet.Composer, this.rules.SheetComposerHeight, TextAlignmentEnum.RightCenter);
             this.graphicalMusicSheet.Composer = composer;
             composer.setLabelPositionAndShapeBorders();
         }
         if (musicSheet.Lyricist !== undefined) {
-            const lyricist: GraphicalLabel = new GraphicalLabel(musicSheet.Lyricist, this.rules.SheetAuthorHeight, TextAlignmentAndPlacement.LeftCenter);
+            const lyricist: GraphicalLabel = new GraphicalLabel(musicSheet.Lyricist, this.rules.SheetAuthorHeight, TextAlignmentEnum.LeftCenter);
             this.graphicalMusicSheet.Lyricist = lyricist;
             lyricist.setLabelPositionAndShapeBorders();
         }
@@ -1895,9 +1897,12 @@ export abstract class MusicSheetCalculator {
             // start- and End margins from the text Labels
             const startX: number = startStaffEntry.parentMeasure.PositionAndShape.RelativePosition.x +
                 startStaffEntry.PositionAndShape.RelativePosition.x +
+                lyricEntry.GraphicalLabel.PositionAndShape.RelativePosition.x +
                 lyricEntry.GraphicalLabel.PositionAndShape.BorderMarginRight;
+
             const endX: number = endStaffentry.parentMeasure.PositionAndShape.RelativePosition.x +
                 endStaffentry.PositionAndShape.RelativePosition.x +
+                lyricEntry.GraphicalLabel.PositionAndShape.RelativePosition.x +
                 nextLyricEntry.GraphicalLabel.PositionAndShape.BorderMarginLeft;
             const y: number = lyricEntry.GraphicalLabel.PositionAndShape.RelativePosition.y;
             let numberOfDashes: number = 1;
@@ -1984,7 +1989,7 @@ export abstract class MusicSheetCalculator {
      * @param {number} y
      */
     private calculateSingleDashForLyricWord(staffLine: StaffLine, startX: number, endX: number, y: number): void {
-        const dash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentAndPlacement.CenterBottom);
+        const dash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom);
         dash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(dash);
         if (this.staffLinesWithLyricWords.indexOf(staffLine) === -1) {
@@ -2032,8 +2037,7 @@ export abstract class MusicSheetCalculator {
             // start- and End margins from the text Labels
             const startX: number = startStaffEntry.parentMeasure.PositionAndShape.RelativePosition.x +
                 startStaffEntry.PositionAndShape.RelativePosition.x +
-                startStaffEntry.PositionAndShape.BorderMarginRight;
-                // + lyricEntry.GraphicalLabel.PositionAndShape.BorderMarginLeft;
+                lyricEntry.GraphicalLabel.PositionAndShape.BorderMarginRight;
                 // + startStaffLine.PositionAndShape.AbsolutePosition.x; // doesn't work, done in drawer
             const endX: number = endStaffEntry.parentMeasure.PositionAndShape.RelativePosition.x +
                 endStaffEntry.PositionAndShape.RelativePosition.x +
@@ -2099,7 +2103,7 @@ export abstract class MusicSheetCalculator {
      * @returns {number}
      */
     private calculateRightAndLeftDashesForLyricWord(staffLine: StaffLine, startX: number, endX: number, y: number): number {
-        const leftDash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentAndPlacement.CenterBottom);
+        const leftDash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom);
         leftDash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(leftDash);
         if (this.staffLinesWithLyricWords.indexOf(staffLine) === -1) {
@@ -2108,7 +2112,7 @@ export abstract class MusicSheetCalculator {
         leftDash.PositionAndShape.Parent = staffLine.PositionAndShape;
         const leftDashRelative: PointF2D = new PointF2D(startX, y);
         leftDash.PositionAndShape.RelativePosition = leftDashRelative;
-        const rightDash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentAndPlacement.CenterBottom);
+        const rightDash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom);
         rightDash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(rightDash);
         rightDash.PositionAndShape.Parent = staffLine.PositionAndShape;
diff --git a/src/MusicalScore/Graphical/MusicSheetDrawer.ts b/src/MusicalScore/Graphical/MusicSheetDrawer.ts
index 420b45e6..e1244741 100644
--- a/src/MusicalScore/Graphical/MusicSheetDrawer.ts
+++ b/src/MusicalScore/Graphical/MusicSheetDrawer.ts
@@ -10,7 +10,7 @@ import {PointF2D} from "../../Common/DataObjects/PointF2D";
 import {GraphicalRectangle} from "./GraphicalRectangle";
 import {GraphicalLabel} from "./GraphicalLabel";
 import {Label} from "../Label";
-import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../../Common/Enums/TextAlignment";
 import {ArgumentOutOfRangeException} from "../Exceptions";
 import {SelectionStartSymbol} from "./SelectionStartSymbol";
 import {SelectionEndSymbol} from "./SelectionEndSymbol";
@@ -24,7 +24,6 @@ import {Instrument} from "../Instrument";
 import {MusicSymbolDrawingStyle, PhonicScoreModes} from "./DrawingMode";
 import {GraphicalObject} from "./GraphicalObject";
 import { GraphicalInstantaneousDynamicExpression } from "./GraphicalInstantaneousDynamicExpression";
-import { unitInPixels } from "./VexFlow/VexFlowMusicSheetDrawer";
 
 /**
  * Draw a [[GraphicalMusicSheet]] (through the .drawSheet method)
@@ -57,7 +56,7 @@ export abstract class MusicSheetDrawer {
         this.textMeasurer = textMeasurer;
         this.splitScreenLineColor = -1;
         if (isPreviewImageDrawer) {
-            this.drawingParameters.setForThumbmail();
+            this.drawingParameters.setForThumbnail();
         } else {
             this.drawingParameters.setForAllOn();
         }
@@ -150,36 +149,36 @@ export abstract class MusicSheetDrawer {
         const bitmapWidth: number = Math.ceil(widthInPixel);
         const bitmapHeight: number = Math.ceil(heightInPixel * 1.2);
         switch (label.textAlignment) {
-            // the following have to match the Border settings in GraphicalLabel.setLabelPositionAndShapeBorders()
-            // TODO unify alignment shifts and our label/bbox position, which does not correspond to screenposition
-            case TextAlignmentAndPlacement.LeftTop:
+            // Adjust the OSMD-calculated positions to rendering coordinates
+            // These have to match the Border settings in GraphicalLabel.setLabelPositionAndShapeBorders()
+            // TODO isn't this a Vexflow-specific transformation that should be in VexflowMusicSheetDrawer?
+            case TextAlignmentEnum.LeftTop:
                 break;
-            case TextAlignmentAndPlacement.LeftCenter:
+            case TextAlignmentEnum.LeftCenter:
                 screenPosition.y -= bitmapHeight / 2;
                 break;
-            case TextAlignmentAndPlacement.LeftBottom:
+            case TextAlignmentEnum.LeftBottom:
                 screenPosition.y -= bitmapHeight;
-                screenPosition.x -= unitInPixels; // lyrics-specific to align with notes
                 break;
-            case TextAlignmentAndPlacement.CenterTop:
+            case TextAlignmentEnum.CenterTop:
                 screenPosition.x -= bitmapWidth / 2;
                 break;
-            case TextAlignmentAndPlacement.CenterCenter:
+            case TextAlignmentEnum.CenterCenter:
                 screenPosition.x -= bitmapWidth / 2;
                 screenPosition.y -= bitmapHeight / 2;
                 break;
-            case TextAlignmentAndPlacement.CenterBottom:
+            case TextAlignmentEnum.CenterBottom:
                 screenPosition.x -= bitmapWidth / 2;
                 screenPosition.y -= bitmapHeight;
                 break;
-            case TextAlignmentAndPlacement.RightTop:
+            case TextAlignmentEnum.RightTop:
                 screenPosition.x -= bitmapWidth;
                 break;
-            case TextAlignmentAndPlacement.RightCenter:
+            case TextAlignmentEnum.RightCenter:
                 screenPosition.x -= bitmapWidth;
                 screenPosition.y -= bitmapHeight / 2;
                 break;
-            case TextAlignmentAndPlacement.RightBottom:
+            case TextAlignmentEnum.RightBottom:
                 screenPosition.x -= bitmapWidth;
                 screenPosition.y -= bitmapHeight;
                 break;
@@ -510,7 +509,7 @@ export abstract class MusicSheetDrawer {
 
             tmpRect = this.applyScreenTransformationForRect(tmpRect);
             this.renderRectangle(tmpRect, <number>GraphicalLayers.Background, layer, 0.5);
-            this.renderLabel(new GraphicalLabel(new Label(dataObjectString), 0.8, TextAlignmentAndPlacement.CenterCenter),
+            this.renderLabel(new GraphicalLabel(new Label(dataObjectString), 0.8, TextAlignmentEnum.CenterCenter),
                              layer, tmpRect.width, tmpRect.height, tmpRect.height, new PointF2D(tmpRect.x, tmpRect.y + 12));
         }
         layer++;
diff --git a/src/MusicalScore/Graphical/MusicSystem.ts b/src/MusicalScore/Graphical/MusicSystem.ts
index a7843276..7de6299f 100644
--- a/src/MusicalScore/Graphical/MusicSystem.ts
+++ b/src/MusicalScore/Graphical/MusicSystem.ts
@@ -4,7 +4,7 @@ import {BoundingBox} from "./BoundingBox";
 import {Fraction} from "../../Common/DataObjects/Fraction";
 import {SourceMeasure} from "../VoiceData/SourceMeasure";
 import {InstrumentalGroup} from "../InstrumentalGroup";
-import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../../Common/Enums/TextAlignment";
 import {GraphicalMusicPage} from "./GraphicalMusicPage";
 import {GraphicalLabel} from "./GraphicalLabel";
 import {GraphicalMeasure} from "./GraphicalMeasure";
@@ -279,7 +279,7 @@ export abstract class MusicSystem extends GraphicalObject {
             for (let idx: number = 0, len: number = instruments.length; idx < len; ++idx) {
                 const instrument: Instrument = instruments[idx];
                 const graphicalLabel: GraphicalLabel = new GraphicalLabel(
-                    instrument.NameLabel, instrumentLabelTextHeight, TextAlignmentAndPlacement.LeftCenter, this.boundingBox
+                    instrument.NameLabel, instrumentLabelTextHeight, TextAlignmentEnum.LeftCenter, this.boundingBox
                 );
                 graphicalLabel.setLabelPositionAndShapeBorders();
                 this.labels.setValue(graphicalLabel, instrument);
diff --git a/src/MusicalScore/Graphical/VexFlow/VexFlowInstantaneousDynamicExpression.ts b/src/MusicalScore/Graphical/VexFlow/VexFlowInstantaneousDynamicExpression.ts
index be2da37b..49935f1c 100644
--- a/src/MusicalScore/Graphical/VexFlow/VexFlowInstantaneousDynamicExpression.ts
+++ b/src/MusicalScore/Graphical/VexFlow/VexFlowInstantaneousDynamicExpression.ts
@@ -2,7 +2,7 @@ import { GraphicalInstantaneousDynamicExpression } from "../GraphicalInstantaneo
 import { InstantaneousDynamicExpression, DynamicEnum } from "../../VoiceData/Expressions/InstantaneousDynamicExpression";
 import { GraphicalLabel } from "../GraphicalLabel";
 import { Label } from "../../Label";
-import { TextAlignmentAndPlacement } from "../../../Common/Enums/TextAlignment";
+import { TextAlignmentEnum } from "../../../Common/Enums/TextAlignment";
 import { EngravingRules } from "../EngravingRules";
 import { FontStyles } from "../../../Common/Enums/FontStyles";
 import { StaffLine } from "../StaffLine";
@@ -16,7 +16,7 @@ export class VexFlowInstantaneousDynamicExpression extends GraphicalInstantaneou
 
         this.mLabel = new GraphicalLabel(new Label(this.Expression),
                                          EngravingRules.Rules.ContinuousDynamicTextHeight,
-                                         TextAlignmentAndPlacement.CenterTop,
+                                         TextAlignmentEnum.CenterTop,
                                          this.PositionAndShape);
 
         this.mLabel.Label.fontStyle = FontStyles.BoldItalic;
diff --git a/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts b/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts
index a99440a9..a37257d6 100644
--- a/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts
+++ b/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts
@@ -46,7 +46,7 @@ import { GraphicalInstantaneousDynamicExpression } from "../GraphicalInstantaneo
 import { SkyBottomLineCalculator } from "../SkyBottomLineCalculator";
 import { PlacementEnum } from "../../VoiceData/Expressions/AbstractExpression";
 import { Staff } from "../../VoiceData/Staff";
-import { TextAlignmentAndPlacement, TextAlignment } from "../../../Common/Enums/TextAlignment";
+import { TextAlignmentEnum, TextAlignment } from "../../../Common/Enums/TextAlignment";
 import { GraphicalSlur } from "../GraphicalSlur";
 
 export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
@@ -194,7 +194,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
         for (let j: number = 0; j < staffEntry.LyricsEntries.length; j++) {
           const lyricsEntry: GraphicalLyricEntry = staffEntry.LyricsEntries[j];
           // const lyricsEntryText = lyricsEntry.LyricsEntry.Text; // for easier debugging
-          const lyricAlignment: TextAlignmentAndPlacement = lyricsEntry.GraphicalLabel.Label.textAlignment;
+          const lyricAlignment: TextAlignmentEnum = lyricsEntry.GraphicalLabel.Label.textAlignment;
           let minLyricsSpacing: number = EngravingRules.Rules.HorizontalBetweenLyricsDistance;
           // for quarter note in Vexflow, where spacing is halfed for each smaller note duration.
 
diff --git a/src/MusicalScore/Label.ts b/src/MusicalScore/Label.ts
index 877cb20b..3fd6f8ae 100644
--- a/src/MusicalScore/Label.ts
+++ b/src/MusicalScore/Label.ts
@@ -1,4 +1,4 @@
-import {TextAlignmentAndPlacement} from "../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../Common/Enums/TextAlignment";
 import {OSMDColor} from "../Common/DataObjects/OSMDColor";
 import {Fonts} from "../Common/Enums/Fonts";
 import {FontStyles} from "../Common/Enums/FontStyles";
@@ -9,7 +9,7 @@ import {FontStyles} from "../Common/Enums/FontStyles";
  */
 export class Label {
 
-    constructor(text: string = "", alignment: TextAlignmentAndPlacement = TextAlignmentAndPlacement.LeftBottom, font: Fonts = Fonts.TimesNewRoman) {
+    constructor(text: string = "", alignment: TextAlignmentEnum = TextAlignmentEnum.LeftBottom, font: Fonts = Fonts.TimesNewRoman) {
         this.text = text;
         this.textAlignment = alignment;
         this.font = font;
@@ -20,7 +20,7 @@ export class Label {
     public font: Fonts;
     public fontStyle: FontStyles;
     public fontHeight: number;
-    public textAlignment: TextAlignmentAndPlacement;
+    public textAlignment: TextAlignmentEnum;
 
     public ToString(): string {
         return this.text;
diff --git a/src/MusicalScore/ScoreIO/MusicSymbolModules/ExpressionReader.ts b/src/MusicalScore/ScoreIO/MusicSymbolModules/ExpressionReader.ts
index 9dfb7e12..a89f9e51 100644
--- a/src/MusicalScore/ScoreIO/MusicSymbolModules/ExpressionReader.ts
+++ b/src/MusicalScore/ScoreIO/MusicSymbolModules/ExpressionReader.ts
@@ -13,7 +13,7 @@ import {InstantaneousTempoExpression} from "../../VoiceData/Expressions/Instanta
 import {MoodExpression} from "../../VoiceData/Expressions/MoodExpression";
 import {UnknownExpression} from "../../VoiceData/Expressions/UnknownExpression";
 import {PlacementEnum} from "../../VoiceData/Expressions/AbstractExpression";
-import {TextAlignmentAndPlacement} from "../../../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../../../Common/Enums/TextAlignment";
 import {ITextTranslation} from "../../Interfaces/ITextTranslation";
 import * as log from "loglevel";
 
@@ -536,7 +536,7 @@ export class ExpressionReader {
             }
         }
         const unknownExpression: UnknownExpression = new UnknownExpression(
-            stringTrimmed, this.placement, TextAlignmentAndPlacement.CenterBottom, this.staffNumber);
+            stringTrimmed, this.placement, TextAlignmentEnum.CenterBottom, this.staffNumber);
         this.getMultiExpression.addExpression(unknownExpression, prefix);
 
         return false;
diff --git a/src/MusicalScore/VoiceData/Expressions/UnknownExpression.ts b/src/MusicalScore/VoiceData/Expressions/UnknownExpression.ts
index f25abc04..d93c606a 100644
--- a/src/MusicalScore/VoiceData/Expressions/UnknownExpression.ts
+++ b/src/MusicalScore/VoiceData/Expressions/UnknownExpression.ts
@@ -1,20 +1,20 @@
 import {PlacementEnum, AbstractExpression} from "./AbstractExpression";
-import {TextAlignmentAndPlacement} from "../../../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../../../Common/Enums/TextAlignment";
 
 export class UnknownExpression extends AbstractExpression {
-    constructor(label: string, placementEnum: PlacementEnum, textAlignment: TextAlignmentAndPlacement, staffNumber: number) {
+    constructor(label: string, placementEnum: PlacementEnum, textAlignment: TextAlignmentEnum, staffNumber: number) {
         super();
         this.label = label;
         this.placement = placementEnum;
         this.staffNumber = staffNumber;
         if (textAlignment === undefined) {
-            textAlignment = TextAlignmentAndPlacement.LeftBottom;
+            textAlignment = TextAlignmentEnum.LeftBottom;
         }
         this.textAlignment = textAlignment;
     }
     private label: string;
     private placement: PlacementEnum;
-    private textAlignment: TextAlignmentAndPlacement;
+    private textAlignment: TextAlignmentEnum;
     private staffNumber: number;
 
     public get Label(): string {
@@ -32,7 +32,7 @@ export class UnknownExpression extends AbstractExpression {
     public set StaffNumber(value: number) {
         this.staffNumber = value;
     }
-    public get TextAlignment(): TextAlignmentAndPlacement {
+    public get TextAlignment(): TextAlignmentEnum {
         return this.textAlignment;
     }
 }
diff --git a/src/OpenSheetMusicDisplay/Cursor.ts b/src/OpenSheetMusicDisplay/Cursor.ts
index a4f4d0d5..5076df87 100644
--- a/src/OpenSheetMusicDisplay/Cursor.ts
+++ b/src/OpenSheetMusicDisplay/Cursor.ts
@@ -47,6 +47,12 @@ export class Cursor {
     // this.openSheetMusicDisplay.render();
   }
 
+  private getStaffEntriesFromVoiceEntry(voiceEntry: VoiceEntry): VexFlowStaffEntry {
+    const measureIndex: number = voiceEntry.ParentSourceStaffEntry.VerticalContainerParent.ParentMeasure.measureListIndex;
+    const staffIndex: number = voiceEntry.ParentSourceStaffEntry.ParentStaff.idInMusicSheet;
+    return <VexFlowStaffEntry>this.graphic.findGraphicalStaffEntryFromMeasureList(staffIndex, measureIndex, voiceEntry.ParentSourceStaffEntry);
+  }
+
   public update(): void {
     // Warning! This should NEVER call this.openSheetMusicDisplay.render()
     if (this.hidden) {
@@ -59,12 +65,11 @@ export class Cursor {
     }
     let x: number = 0, y: number = 0, height: number = 0;
 
-    const voiceEntry: VoiceEntry = iterator.CurrentVoiceEntries[0];
-    const measureIndex: number = voiceEntry.ParentSourceStaffEntry.VerticalContainerParent.ParentMeasure.measureListIndex;
-    const staffIndex: number = voiceEntry.ParentSourceStaffEntry.ParentStaff.idInMusicSheet;
+    // get all staff entries inside the current voice entry
+    const gseArr: VexFlowStaffEntry[] = iterator.CurrentVoiceEntries.map(ve => this.getStaffEntriesFromVoiceEntry(ve));
+    // sort them by x position and take the leftmost entry
     const gse: VexFlowStaffEntry =
-      <VexFlowStaffEntry>this.graphic.findGraphicalStaffEntryFromMeasureList(staffIndex, measureIndex, voiceEntry.ParentSourceStaffEntry);
-
+          gseArr.sort((a, b) => a.PositionAndShape.AbsolutePosition.x <= b.PositionAndShape.AbsolutePosition.x ? -1 : 1 )[0];
     x = gse.PositionAndShape.AbsolutePosition.x;
     const musicSystem: MusicSystem = gse.parentMeasure.parentMusicSystem;
     y = musicSystem.PositionAndShape.AbsolutePosition.y + musicSystem.StaffLines[0].PositionAndShape.RelativePosition.y;


Test patch:
diff --git a/test/Common/OSMD/OSMD_Test.ts b/test/Common/OSMD/OSMD_Test.ts
index 4a224acc..af88fc5d 100644
--- a/test/Common/OSMD/OSMD_Test.ts
+++ b/test/Common/OSMD/OSMD_Test.ts
@@ -92,10 +92,28 @@ describe("OpenSheetMusicDisplay Main Export", () => {
         );
     });
 
-    it("load MXL Document by invalid URL", (done: MochaDone) => {
+    it("load something invalid by URL", (done: MochaDone) => {
         const url: string = "https://www.google.com";
         const div: HTMLElement = TestUtils.getDivElement(document);
         const opensheetmusicdisplay: OpenSheetMusicDisplay = new OpenSheetMusicDisplay(div);
+        opensheetmusicdisplay.load(url).then(
+            (_: {}) => {
+                done(new Error("Invalid URL appears to be loaded correctly"));
+            },
+            (exc: Error) => {
+                if (exc.message.toLowerCase().match(/opensheetmusicdisplay.*invalid/)) {
+                    done();
+                } else {
+                    done(new Error("Unexpected error: " + exc.message));
+                }
+            }
+        );
+    }).timeout(5000);
+
+    it("load invalid URL", (done: MochaDone) => {
+        const url: string = "https://www.afjkhfjkauu2ui3z2uiu.com";
+        const div: HTMLElement = TestUtils.getDivElement(document);
+        const opensheetmusicdisplay: OpenSheetMusicDisplay = new OpenSheetMusicDisplay(div);
         opensheetmusicdisplay.load(url).then(
             (_: {}) => {
                 done(new Error("Invalid URL appears to be loaded correctly"));
@@ -139,8 +157,7 @@ describe("OpenSheetMusicDisplay Main Export", () => {
 
     before((): void => {
         // Create the container for the "test width" test
-        container1 = document.createElement("div");
-        document.body.appendChild(container1);
+        container1 = TestUtils.getDivElement(document);
     });
     after((): void => {
         // Destroy the container for the "test width" test