TypeScript

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

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
  text-align: center;
}

TypeScript

joint.config.useCSSSelectors = false;

const graph = new joint.dia.Graph();

const paper = new joint.dia.Paper({
    el: document.getElementById('paper'),
    width: 800,
    height: 800,
    model: graph,
    async: true,
    interactive: { linkMove: false },
    sorting: joint.dia.Paper.sorting.APPROX,
    defaultConnectionPoint: {
        name: 'boundary',
    },
    defaultRouter: {
        name: 'normal'
    }
});
let OneLane = joint.dia.Element.define('custom.OneLane', {
    attrs: {
        body: {
            width: 129,
            height: 90,
            fill: "#E0E0E0",
            rx: '10',
            ry: '10',
        },
        fo:{
            width:129,
            height:90
        }
    },
},
{
    initialize: function() {
        joint.dia.Element.prototype.initialize.apply(this);
        this.on('change', this.onChange, this);
        this.buildMarkup();
    },
    onChange: function(_:any, opt:any) {
        if (opt.list !== this.id && this.hasChanged('markup')) {
            throw new Error('Markup can not be modified.');
        }
        if (this.hasChanged('lanes')) {
            this.buildMarkup(opt);
        }
    },
    buildMarkup: function(opt:any) {

        let lanes = this.get('lanes');
        if (!Array.isArray(lanes)) {
            lanes = [];
        }
        const itemsMarkup = lanes.map((lane:any) =>{
            const el = this.buildItemMarkup(lane)
            return el;
        });
        const markup = [{
            tagName: 'rect',
            selector: 'body'
         }, {           
           tagName: 'foreignObject',
           selector: 'fo',
           children: itemsMarkup
        }];

        const flags = { list: this.id, dry: true, ...opt };
        this.set('markup', markup, flags);
    },
    buildItemMarkup: function(lane:any) {
        const {tagName = 'label', label = 'Label', value = '' } = lane;
        const markupWrap = 
                {
                    tagName:'div',
                   ...