fraverta
fraverta

Reputation: 85

In JointJS, How to create a user defined element with ports

I want to create a rectangle with 4 ports, one in each side in JointJS as user-defined element.

I need to create a user-defined element because I need show a tooltip when mouse is up. So I need a tag on markup. But I have problem with ports. This is my implementation:

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

joint.shapes.devs.CircleModel = joint.shapes.devs.Model.extend({

  markup: '<g class="rotatable"><g class="scalable"><rect class="body"/></g><text class="label"/><g class="inPorts"/><g class="outPorts"/><title /></g>',
/*  
portMarkup: '<g class="port port<%= id %>"><circle class="port-body"/><text class="port-label"/></g>',
*/
  defaults: joint.util.deepSupplement({

    type: 'devs.CircleModel',
    attrs: {
             title: {text: 'Static Tooltip'},
      '.body': {
        r: 50,
        cx: 50,
        stroke: 'blue',
        fill: 'lightblue'
      },
      '.label': {
        text: 'Model',
        'ref-y': 0.5,
        'y-alignment': 'middle'
      },
      '.port-body': {
        width: 10,
        height: 10,
        x: -5,
        stroke: 'gray',
        fill: 'lightgray',
        magnet: 'active'
      }
    }

  }, joint.shapes.devs.Model.prototype.defaults)
});

joint.shapes.devs.CircleModelView = joint.shapes.devs.ModelView;

var rect = new joint.shapes.devs.CircleModel({
  position: {
    x: 150,
    y: 50
  },
  size: {
    width: 100,
    height: 100
  },
   ports: {
        groups: {
            'top': {
                // port position definition
                position: 'top',
                label: {
                    // label layout definition:
                    position: {
                        name: 'manual', args: {
                            y: 5,
                            attrs: { '.': { 'text-anchor': 'middle' } }
                        }
                    }
                }
            },
            'down': {
                position: 'bottom',
                label: {
                    position: {
                        name: 'bottom', args: { y: -5 }
                    }
                }
            },
            'right': {
                position: 'right',
                label: {
                    position: {
                        name: 'bottom', args: { y: -5 }
                    }
                }
            },
            'left': {
                position: 'left',
                label: {
                    position: {
                        name: 'bottom', args: { y: -5 }
                    }
                }
            }
        }
    }
});


rect.addPort({ group: 'top', attrs: { 'text': { text: 'T' } } });
rect.addPort({ group: 'down', attrs: { 'text': { text: 'D' } } });
rect.addPort({ group: 'right', attrs: { 'text': { text: 'R' } } });
rect.addPort({ group: 'left', attrs: { 'text': { text: 'L' } } });


graph.addCell(rect);

All code is here: https://jsfiddle.net/fraverta/ustp4tcj/2/

I don't understand why that doesn't show ports as circles. Could someone help me?

Upvotes: 1

Views: 1993

Answers (2)

user8598044
user8598044

Reputation:

This is exactly what you need.

It is the implementation of one of the Joint-JS Rappid developers.

Take a look here at the jsfiddle live example.

jsfiddle live example

HTML:

<!-- JointJS Fiddle -->

Javascript:

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

joint.shapes.devs.MyImageModel = joint.shapes.devs.Model.extend({

  markup: '<g class="rotatable"><g class="scalable"><rect class="body"/></g><image/><text class="label"/><g class="inPorts"/><g class="outPorts"/></g>',

  defaults: joint.util.deepSupplement({

    type: 'devs.MyImageModel',
    size: {
      width: 80,
      height: 80
    },
    attrs: {
      rect: {
        stroke: '#d1d1d1',
        fill: {
          type: 'linearGradient',
          stops: [{
            offset: '0%',
            color: 'white'
          }, {
            offset: '50%',
            color: '#d1d1d1'
          }],
          attrs: {
            x1: '0%',
            y1: '0%',
            x2: '0%',
            y2: '100%'
          }
        }
      },
      circle: {
        stroke: 'gray'
      },
      '.label': {
        text: 'My Shape',
        'ref-y': -20
      },
      '.inPorts circle': {
        fill: '#c8c8c8'
      },
      '.outPorts circle': {
        fill: '#262626'
      },
      image: {
        'xlink:href': 'https://jointjs.com/images/logo.png',
        width: 80,
        height: 50,
        'ref-x': .5,
        'ref-y': .5,
        ref: 'rect',
        'x-alignment': 'middle',
        'y-alignment': 'middle'
      }
    }

  }, joint.shapes.devs.Model.prototype.defaults)
});

joint.shapes.devs.MyImageModelView = joint.shapes.devs.ModelView;

// Usage:

var imageModel = new joint.shapes.devs.MyImageModel({
  position: {
    x: 200,
    y: 250
  },
  size: {
    width: 150,
    height: 100
  },
  inPorts: ['in1', 'in2'],
  outPorts: ['out']
});

graph.addCell(imageModel);

CSS:

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

Upvotes: 0

Shahar Shokrani
Shahar Shokrani

Reputation: 8762

as @masterfan commented, the problem is with the creation of the var rect = joint.shapes.devs.Model.

to be more specific the way you implemented the ports section was not fully implemented.

To implement the ports correctly you can:

  1. just comment it and it will inherit from the JointJs model mentioned above.

  2. implement by this exact example: (yours was missing some attributes - so the UI port was missing the html attributes: fill="#fff" stroke="#000" r="10")

this is an example:

            groups: {
                'myCustomPort': {
                    position: {
                        name: 'left'
                    },
                    attrs: {
                        '.port-label': {
                            fill: '#000'
                        },
                        '.port-body': {
                            fill: '#fff',
                            stroke: '#000',
                            r: 10,
                            magnet: true
                        }
                    },
                    label: {
                        position: {
                            name: 'left',
                            args: {
                                y: 10
                            }
                        }
                    }
                }

rect.addPort({ group: 'myCustomPort', attrs: { 'text': { text: 'MyCustomText' } } });

Upvotes: 1

Related Questions