javascripthtmlsvgjointjsforeignobject

JointJS: Unable to display a foreignObject in a custom shape with JSON


I am trying to define a custom shape in JointJS that includes a tag. If I define the markup as a string, it works just fine:

joint.shapes.examples.CustomRectangle = joint.shapes.standard.Rectangle.define('examples.CustomRectangle', {
  markup: '<rect class="card"/><foreignObject x="10" y="10" height="60" width="100"><input xmlns="http://www.w3.org/1999/xhtml" type="text"></input></foreignObject>',

  attrs: {
    rect: {
      refWidth: '100%',
      refHeight: '100%',
      strokeWidth: 5,
      stroke: '#000000',
      fill: 'white'
    },
  }
});

See this codepen and note that the input box is visible inside the square: http://jsfiddle.net/dovrosenberg/kbmwfg1a/89/

If I define what appears to be the same XML inside the SVG but using JSON:

joint.shapes.examples.CustomRectangle = joint.shapes.standard.Rectangle.define('examples.CustomRectangle', {
  markup: [{
      tagName: 'rect',
      selector: 'rect'
    },
    {
      tagName: 'foreignObject',
      selector: 'fo',
      attributes: {
        x: '10',
        y: '10',
        width: '60',
        height: '100',
      },
      children: [{
        tagName: 'input',
        selector: 'inpt',
        attributes: {
          xmlns: 'http://www.w3.org/1999/xhtml',
          type: 'text',
        },
      }]
    }
  ],
  attrs: {
    rect: {
      refWidth: '100%',
      refHeight: '100%',
      strokeWidth: 5,
      stroke: '#000000',
      fill: 'white'
    },
  }
});

See this codepen and note that the input box is not visible: http://jsfiddle.net/dovrosenberg/asnvwe1r/4/

When I look at it in the browser, the resulting SVG looks virtually the same. The only differences I can see are the JSON version inserts joint-selector attributes, but I wouldn't think that would matter.

Stranger yet, if you edit the HTML in the debugger and make a minor change to the foreignObject tag (say changing one of the joint-selector attributes) then the input becomes visible.

Shouldn't this work?


Solution

  • Thanks to the great comment from Robert Longson, I was able to figure it out. The right markup is as below (or see http://jsfiddle.net/dovrosenberg/asnvwe1r/8/). The difference is the new namespaceURI key.

    joint.shapes.examples.CustomRectangle = joint.shapes.standard.Rectangle.define('examples.CustomRectangle', {
      markup: [{
          tagName: 'rect',
          selector: 'rect'
        },
        {
          tagName: 'foreignObject',
          selector: 'fo',
          attributes: {
            x: '10',
            y: '10',
            width: '60',
            height: '100',
          },
          children: [{
            tagName: 'input',
            selector: 'inpt',
            namespaceURI: 'http://www.w3.org/1999/xhtml',
            attributes: {
              type: 'text',
            },
          }]
        }
      ],
      attrs: {
        rect: {
          refWidth: '100%',
          refHeight: '100%',
          strokeWidth: 5,
          stroke: '#000000',
          fill: 'white'
        },
      }
    });