<label for"filter">Filter colors</label>
<select id="filter">
  <option value="all">all</option>
  <option value="pink">pink</option>
  <option value="gray">gray</option>
  <option value="black">black</option>
</select>
<label id="message"></label>
<div id="canvas" data-filter="all"></div>
<label for"addColor">Color of added node:</label>
<select id="addColor">
  <option value="pink">pink</option>
  <option value="gray">gray</option>
  <option value="black">black</option>
</select>
<button id="addCell">Add Node</button>
$elementsColors: pink #f1207d, gray #ABABAB, black #000000;

body {
  font-family: sans-serif;
  font-size: 20px;
}

select {
  font-size: inherit;
  padding: 5px;
  margin: 2px 2px 10px 2px;
}

#message {
  opacity: 0;
  transition: opacity 5s linear;
  
  &.visible {
    opacity: 1;
    transition: opacity 0.1s linear;
  }
}

#canvas {
  border: 1px solid;
  width: 100%;
  height: 35vh;
  min-height: 300px;
  
  .element-node {
    opacity: 0.2;
    
    @each $elementColor in $elementsColors {
      &[data-color="#{nth($elementColor, 1)}"] {
        fill: #{nth($elementColor, 2)};
      }
    }
    
    text {
      fill: #FFFFFF;
    }
  
    &:hover .port {
      opacity: 1;
    }
  }
  
  @each $elementColor in $elementsColors {
    &[data-filter="#{nth($elementColor, 1)}"] {
        .element-node[data-color="#{nth($elementColor, 1)}"] {
          opacity: 1;
        }
      }
    }  
  
  
  &[data-filter="all"] {
    .element-node {
      opacity: 1;
    }
  }
}

.port {
  width: 10px;
  height: 10px;
  transform: translate(70px, 40px);
  fill: #000;
  opacity: 0.5;
}

button {
  color: #FFFFFF;
  background-color: #f1207d;
  border-radius: 3px;
  border: 0;
  padding: 10px 20px;
  margin: 5px 0;
  cursor: pointer;
}
View Compiled
joint.shapes.devs.Model = joint.shapes.devs.Model.extend({
markup: '<g class="element-node">'+
             '<rect class="body" stroke-width="0" rx="5px" ry="5px"></rect>'+
            '<text class="label" y="0.8em" xml:space="preserve" font-size="14" text-anchor="middle" font-family="Arial, helvetica, sans-serif">'+
              '<tspan id="v-18" dy="0em" x="0" class="v-line"></tspan>'+
            '</text>'+
          '<g class="inPorts"/>' +
          '<g class="outPorts"/>' +
        '</g>',
portMarkup: '<g class="port port<%= id %>"><circle class="port-body"/></g>'
});
  
var canvas = $('#canvas');
var filter = $('#filter');
var addColor = $('#addColor');
var cells = [];
var message = $('#message');
var graph = new joint.dia.Graph();

var paper = new joint.dia.Paper({
  el: canvas,
  width: canvas.outerWidth(),
  height: canvas.outerHeight(),
  model: graph,
  gridSize: 20,
  defaultRouter: { name: 'metro' },
  clickThreshold: 1
});

cells[0] = new joint.shapes.devs.Model({
  type: 'devs.Model',
  position: {x: 20, y: 20},
  attrs: {
    '.body': {
      width: '140',
      height: '60'
    },
    '.label': {
      text: 'blok 1',
    },
    '.element-node' : {
      'data-color': 'pink'
    }
  },
  inPorts: ['center']
});
cells[0].translate(140, 100);
cells[1] = cells[0].clone();
cells[1].translate(300, 60);
cells[1].attr('.label/text', 'blok 2');
graph.addCells(cells);

var link = new joint.dia.Link({
  source: {
    id: cells[0].id,
    port: 'center'
  },
  target: {
    id: cells[1].id,
    port: 'center'
  }
});
graph.addCells([link]);

function addCell(){
  var color = addColor.val();
  var number = cells.length;
  cells[number] = cells[0].clone();
  cells[number].translate(-140, -100);
  cells[number].attr('.element-node/data-color', color);
  cells[number].attr('.label/text', 'blok '+cells.length);
  graph.addCells(cells);
}

$('#addCell').on('click', addCell);

$(filter).on('change', function(e){
  canvas.attr('data-filter', e.target.value);
});

var svgZoom = svgPanZoom('#canvas svg', {
  center: false,
  zoomEnabled: true,
  panEnabled: true,
  controlIconsEnabled: true,
  fit: false,
  minZoom: 0.5,
  maxZoom:2,
  zoomScaleSensitivity: 0.5
});

(function(){
  paper.on('cell:pointerdown', function(){
    svgZoom.disablePan();
  });
  paper.on('cell:pointerup', function(){
    svgZoom.enablePan();
  });
  
  paper.on('cell:pointerclick', function(e){
    message.addClass('visible');
    message.html(e.el.textContent+' clicked');
  setTimeout(function(){  message.removeClass('visible');
                       }, 1000);
  });
})();
Run Pen

External CSS

  1. //cdnjs.cloudflare.com/ajax/libs/jointjs/0.9.9/joint.core.css

External JavaScript

  1. https://ariutta.github.io/svg-pan-zoom/dist/svg-pan-zoom.min.js
  2. //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js
  4. https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js
  5. https://cdnjs.cloudflare.com/ajax/libs/jointjs/0.9.7/joint.js