JointJS - Dashed Line Between Vertices (Data Binding)

by Roman Bruckner

HTML

<html>
<head>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.5.5/joint.css" />
</head>
<body>
      <!-- content -->
      <div id="paper"></div>         

      <!-- dependencies -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.0/backbone.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.5.5/joint.js"></script>
    
    </body>
</html>

CSS

.joint-paper {
  display: inline-block;
  border: 1px solid gray;
}

JavaScript

class Link extends joint.dia.Link {

    defaults() {
        return {
            ...super.defaults,
            type: 'Link',
            attrs: {
                line: {
                    connection: true,
                    stroke: '#333333',
                    strokeWidth: 2,
                    strokeLinejoin: 'round',
                    targetMarker: {
                        'type': 'path',
                        'd': 'M 10 -5 0 0 10 5 z'
                    }
                },
                dashedLine: {
                    stroke: '#FFFFFF',
                    strokeWidth: 2,
                    strokeDasharray: '5 5',
                    strokeLinejoin: 'round',
                },
                wrapper: {
                    connection: true,
                    strokeWidth: 10,
                    strokeLinejoin: 'round'
                }
            }
        };
    }

    preinitialize() {
        this.markup = [{
            tagName: 'path',
            selector: 'wrapper',
            attributes: {
                'fill': 'none',
                'cursor': 'pointer',
                'stroke': 'transparent',
                'stroke-linecap': 'round'
            }
        }, {
            tagName: 'path',
            selector: 'line',
            attributes: {
                'fill': 'none',
                'pointer-events': 'none'
            }
        }, {
            tagName: 'polyline',
            selector: 'dashedLine',
            attributes: {
                'fill': 'none',
                'pointer-events': 'none'
            }
        }];
    }

    initialize(...args) {
        super.initialize(...args);
        this.on('change', ({ changed }, opt) => {
            if ('vertices' in changed) {
                this.updateBindings(opt);
            }
        });
        this.updateBindings();
    }

    updateBindings(opt) {
        const polyline = new g.Polyline(this.vertices());
        this.attr({
            dashedLine: {
  ...