2016-10-25 34 views
1

我實際上正在研究一種可視化數據流的工具。我有不同的類型 應該使用的元素,並希望爲這些元素(對象)的每個人都擁有自己的html模板。有沒有人有一個想法,如果這是可能的,如何實現這一點?JointJS:針對不同對象的多個模板

非常感謝您的幫助,我真的很感激!

尊敬的問候,

拉斐爾

這裏我的代碼(遺憾的混亂):

 (function() { 

    var graph = new joint.dia.Graph; 
    var paper = new joint.dia.Paper({ el: $('#paper'), width: 650, height: 400, gridSize: 1, model: graph }); 

// Create a system element. 
// ----------------------------------------------------------------------------- 
    joint.shapes.html = {}; 
    joint.shapes.html.Element = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, { 
     markup: '<g class="rotatable"><g class="scalable"><rect/></g><g class="inPorts"/><g class="outPorts"/></g>', 
     portMarkup: '<g class="port<%= id %>"><circle/></g>', 
     defaults: joint.util.deepSupplement({ 
      type: 'html.Element', 
      size: { width: 100, height: 80 }, 
      inPorts: [], 
      outPorts: [], 
      attrs: { 
       '.': { magnet: false }, 
       rect: { 
        stroke: 'none', 'fill-opacity': 0, width: 170, height: 250, 
       }, 
       circle: { 
        r: 6, //circle radius 
        magnet: true, 
        stroke: 'black' 
       }, 

       '.inPorts circle': { fill: 'green', magnet: 'passive', type: 'input'}, 
       '.outPorts circle': { fill: 'red', type: 'output'} 
      } 
     }, joint.shapes.basic.Generic.prototype.defaults), 
     getPortAttrs: function (portName, index, total, selector, type) { 

      var attrs = {}; 
      var portClass = 'port' + index; 
      var portSelector = selector + '>.' + portClass; 
      var portCircleSelector = portSelector + '>circle'; 
      attrs[portCircleSelector] = { port: { id: portName || _.uniqueId(type), type: type } }; 
      attrs[portSelector] = { ref: 'rect', 'ref-y': (index + 0.5) * (1/total) }; 
      if (selector === '.outPorts') { attrs[portSelector]['ref-dx'] = 0; } 
      return attrs; 
     } 
    })); 
// ------------------------------------------------------------------------------------------------------------------------------------- 


// Create a custom view for that element that displays an HTML div above it. 
// ------------------------------------------------------------------------------------------------------------------------------------- 


    joint.shapes.html.ElementView = joint.dia.ElementView.extend({ 
     objectname: "System", 
     template: [ 
      '<div class="html-element" id=>', 
      '<button class="delete">x</button>', 
      '<button class="add">+</button>', 
      '<div class="head">', 
      '<h3>', 
      'System', 
      '</h3>', 
      '<input type="text" class="systemComment" placeholder = "Add a comment to this System"/>', 
      '</div> </br>', 
      '</div>' 
     ].join(''), 

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

      this.$box = $(_.template(this.template)()); 
      // Prevent paper from handling pointerdown. 
      this.$box.find('input,select').on('mousedown click', function(evt) { 
       evt.stopPropagation(); 
      }); 
      // This is an example of reacting on the input change and storing the input data in the cell model. 
      this.$box.find('input').on('change', _.bind(function(evt) { 
       this.model.set('input', $(evt.target).val()); 
      }, this)); 
      this.$box.find('select').on('change', _.bind(function(evt) { 
       this.model.set('select', $(evt.target).val()); 
      }, this)); 
      this.$box.find('select').val(this.model.get('select')); 
      this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model)); 
      $('.add').on('click', function(){ 
       //we select the box clone it and insert it after the box 
       $(".html-element").clone().appendTo("#paper"); 
      }); 
      // Update the box position whenever the underlying model changes. 
      this.model.on('change', this.updateBox, this); 
      // Remove the box when the model gets removed from the graph. 
      this.model.on('remove', this.removeBox, this); 

      this.updateBox(); 
     }, 
     //::: End initialize function ::: 

     //::: Start render function ::: 
     render: function() { 
      joint.dia.ElementView.prototype.render.apply(this, arguments); 
      this.paper.$el.prepend(this.$box); 
      // this.paper.$el.mousemove(this.onMouseMove.bind(this)), this.paper.$el.mouseup(this.onMouseUp.bind(this)); 
      this.updateBox(); 
      return this; 
     }, 
     //::: End render function ::: 

     //::: Start renderPortst function ::: 
     renderPorts: function() { 
      var $inPorts = this.$('.inPorts').empty(); 
      var $outPorts = this.$('.outPorts').empty(); 

      var portTemplate = _.template(this.model.portMarkup); 

      _.each(_.filter(this.model.ports, function (p) { return p.type === 'in' }), function (port, index) { 

       $inPorts.append(V(portTemplate({ id: index, port: port })).node); 
      }); 
      _.each(_.filter(this.model.ports, function (p) { return p.type === 'out' }), function (port, index) { 

       $outPorts.append(V(portTemplate({ id: index, port: port })).node); 
      }); 
     }, 
     //::: End renderPortst function ::: 

     //::: Start update function 
     update: function() { 
      // First render ports so that `attrs` can be applied to those newly created DOM elements 
      // in `ElementView.prototype.update()`. 
      this.renderPorts(); 
      joint.dia.ElementView.prototype.update.apply(this, arguments); 
     }, 
     //::: End update function ::: 

     //::: Start updateBox function 
     updateBox: function() { 
      // Set the position and dimension of the box so that it covers the JointJS element. 
      var bbox = this.model.getBBox(); 
      // Example of updating the HTML with a data stored in the cell model. 
      // paper.on('blank:pointerdown', function(evt, x, y) { this.$box.find('textarea').toBack(); }); 
      this.model.on('cell:pointerclick', function(evt, x, y) { this.$box.find('textarea').toFront(); }); 
      this.$box.css({ width: bbox.width, height: bbox.height, left: bbox.x + 15, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)' }); 
     }, 
     //::: End updateBox function ::: 

     //::: Start removeBox function ::: 
     removeBox: function(evt) { 
      this.$box.remove(); 
     } 
     //::: End removeBox function ::: 

    }); 

// ------------------------------------------------------------------------------------------------------------------------------------- 


// Create JointJS elements and add them to the graph as usual. 
// ------------------------------------------------------------------------------------------------------------------------------------- 

    var system = new joint.shapes.html.Element({ 
     position: { x: 80, y: 80 }, 
     size: { width: 240, height: 180 }, 
     outPorts:['systemOut'], 
     inPorts: ['systemIn'], 
    }); 

    var dbo = new joint.shapes.html.Element({ 
     position: { x: 120, y: 210 }, 
     size: { width: 240, height: 180 }, 
     outPorts:['dboOut'], 
     inPorts: ['dboIn'], 
    }) 
// ------------------------------------------------------------------------------------------------------------------------------------- 

//Adding all to the graph 
    graph.addCells([system, dbo]); 

}()) 

回答

2

你可以把模板定義的模型,那麼你就可以實例化自定義元素模板,如下所示:

new joint.shapes.html.Element({ 
     template: [ 
      '<div class="my-html-element">', 
      '<div><input data-attribute="myinput" type="checkbox"/></div>', 
      '<div><input data-attribute="myinput" type="checkbox"/></div>', 
      '<div><input data-attribute="myinput" type="checkbox"/></div>', 
      '</div>' 
     ].join(''), 
}); 

下面是一個完整的示例:https://jsfiddle.net/vtalas/pruz7h9w/

請注意,自v1.0版以來,有一個新的API更易於與端口一起操作(它也適用於上面的演示)。

+0

非常感謝您的幫助! 這正是我需要的:)! –