JSFiddle - React, Tailwind, and code Playground

by Yuki Moriyama

HTML

<script src="http://jointjs.com/js/vendor/jquery/jquery.min.js"></script>
<script src="http://jointjs.com/js/vendor/lodash/lodash.min.js"></script>
<script src="http://jointjs.com/js/vendor/backbone/backbone-min.js"></script>
<script src="http://jointjs.com/downloads/joint.min.js"></script>
<link rel="stylesheet" href="http://jointjs.com/downloads/joint.min.css">
<body>
  <div id="paper"></div>
</body>

CSS

#paper {
   position: relative;
   border: 1px solid gray;
   display: inline-block;
   background: transparent;
   overflow: hidden;
}
#paper svg {
   background: transparent;
}
#paper svg .link {
   z-index: 2;
}
.html-element {
   position: absolute;                                                                                                                                         
   background: #3498DB;
   /* Make sure events are propagated to the JointJS element so, e.g. dragging works.*/
   pointer-events: none;
   -webkit-user-select: none;
   border-radius: 4px;
   border: 2px solid #2980B9;
   box-shadow: inset 0 0 5px black, 2px 2px 1px gray;
   padding: 5px;
   box-sizing: border-box;
   z-index: 2;
}
.html-element select,
.html-element input,
.html-element button {
   /* Enable interacting with inputs only. */
   pointer-events: auto;
}
.html-element button.delete {
   color: white;
   border: none;
   background-color: #C0392B;
   border-radius: 20px;
   width: 15px;
   height: 15px;
   line-height: 15px;
   text-align: middle;
   position: absolute;
   top: -15px;
   left: -15px;
   padding: 0;
   margin: 0;
   font-weight: bold;
   cursor: pointer;
}
.html-element button.delete:hover {
   width: 20px;
   height: 20px;
   line-height: 20px;
}
.html-element select {
   position: absolute;
   right: 2px;
   bottom: 28px;
}
.html-element input {
   position: absolute;
   bottom: 0;
   left: 0;
   right: 0;
   border: none;
   color: #333;
   padding: 5px;
   height: 16px;
}
.html-element label {
   color: #333;
   text-shadow: 1px 0 0 lightgray;
   font-weight: bold;
}
.html-element span {
   position: absolute;
   top: 2px;
   right: 9px;
   color: white;
   font-size: 10px;
}

JavaScript

$(function() {
  graph = new joint.dia.Graph;
  paper = new joint.dia.Paper({ 
   el: $('#paper'), 
  width: 800, 
   height: 800, 
   gridSize: 100, 
   model: graph
  });

  // 初期から出ているbox
  var el1 = new joint.shapes.html.Element({
    position: { x: 80, y: 80 },
    size: { width: 170, height: 80 },
    divName: 'Atrae',
    isCompany: true
  });

  graph.addCells([el1]);

  paper.on('cell:pointerup', function(cellView, evt, x, y) {
    var elementBelow = graph.get('cells').find(function(cell) {
      if (cell instanceof joint.dia.Link) return false;
      if (cell.id === cellView.model.id) return false;
      if (cell.getBBox().containsPoint(g.point(x, y))) return true;
      return false;
    });                                                                                                                                                        

    if (elementBelow && !_.contains(graph.getNeighbors(elementBelow), cellView.model)) {
      graph.addCell(new joint.shapes.org.Arrow({
        source: { id: cellView.model.id },
        target: { id: elementBelow.id }
      }));
      cellView.model.translate(-200, 0);
    }
  });
});

joint.shapes.html = {};
joint.shapes.html.Element = joint.shapes.basic.Rect.extend({
  defaults: joint.util.deepSupplement({
    type: 'html.Element',
    attrs: {
      rect: { stroke: 'none', 'fill-opacity': 0 }
    }
  }, joint.shapes.basic.Rect.prototype.defaults)
});

joint.shapes.html.ElementView = joint.dia.ElementView.extend({
  template: [
    '<div class="html-element">',
    '<button class="delete">x</button>',
    '<input type="text" value=""/>',
    '<button class="js-divName"></button>',
    '<button class="add">+</button>',
    '</div>'
  ].join(''),

  initialize: function() {
    _.bindAll(this, 'updateBox');
    joint.dia.ElementView.prototype.initialize.apply(this, arguments);

    this.$box = $(_.template(this.template)());
    this.$box.find('input').on('mousedown click', function(evt) { evt.stopPropagation();...