I have an editable flowchart constructed from data. When I convert one of the sub-elements into a magnet so that users can form new links, all existing links emitted from that element are gone, the target pointer arrow resets to the leftmost part of the window and I am getting the following error messages until I release the mouse button:
Uncaught TypeError: Cannot read property 'el' of undefined
joint.js:16929 Error: Invalid value for <path> attribute d="M NaN NaN C NaN NaN NaN NaN NaN NaN"
joint.js:16929 Error: Invalid value for <path> attribute d="M NaN NaN C NaN NaN NaN NaN NaN NaN"
joint.js:16929 Error: Invalid value for <path> attribute transform="translate(NaN,0) scale(1,1)"
joint.js:16929 Error: Invalid value for <path> attribute transform="translate(NaN,0) scale(1,1) rotate(NaN)"
joint.js:16929 Error: Invalid value for <path> attribute transform="translate(NaN,0) scale(1,1)"
joint.js:16929 Error: Invalid value for <path> attribute transform="translate(NaN,0) scale(1,1) rotate(NaN)"
joint.js:16929 Error: Invalid value for <g> attribute transform="translate(NaN,0) scale(0.5,0.5)"
joint.js:16929 Error: Invalid value for <g> attribute transform="translate(NaN,0) scale(0.5,0.5) rotate(NaN)"
joint.js:16929 Error: Invalid value for <g> attribute transform="translate(NaN,0) scale(0.5,0.5)"
joint.js:16929 Error: Invalid value for <g> attribute transform="translate(NaN,0) scale(0.5,0.5) rotate(NaN)"
joint.js:22209 Uncaught TypeError: Cannot read property 'x' of undefined
The code I am using is the following:
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el: $('#paper'),
width: window.innerWidth,
height: window.innerHeight,
gridSize: 1,
model: graph,
validateConnection: function(cellViewS, magnetS, cellViewT, magnetT, end, linkView) {
// Prevent loop linking
return (magnetS !== magnetT);
}
});
function invertColor(hex) { //This is just for text
var color = hex;
color = color.substring(1);
color = parseInt(color, 16);
color = 0xFFFFFF ^ color;
color = color.toString(16);
color = ("000000" + color).slice(-6);
color = "#" + color;
return color;
}
var shapenodes = []; //Here I store all the nodes with data
var connections = {}; //Here I store the SourceID: [targetIDs] relationships
var links = []; //Here I store links generated from above
for (var i=0;i<nodes.length;i++){ //Loop through data from the DB
var wraptext = joint.util.breakText(nodes[i].text, {width: nodes[i].width - 20}); //Process text so it doesn't overflow
var newNode = new joint.shapes.basic.Rect({
position: {x: nodes[i].x, y: nodes[i].y},
size: {width: nodes[i].width, height: nodes[i].height},
attrs: {
rect: {
fill: nodes[i].color,
rx: 8,
ry: 8,
stroke: '',
magnet: true //Convert the underlying the rectangle to magnet
},
text: { //This is used to drag the shape
text: wraptext,
fill: invertColor(nodes[i].color),
'font-family': 'Arial',
'font-size': 18,
'font-weight': 'bold',
'font-variant': 'small-caps'
}
},
id: nodes[i].ID //Assign the same ID as in database (unique)
});
var sourceID = newNode.id;
connections[sourceID] = []; //Store the targets
Array.prototype.push.apply(connections[sourceID], nodes[i].targets);
shapenodes.push(newNode);
}
for (var SID in connections){ //for all Source IDs in connections
if(connections[SID].length>0) { //if there are targets
_.each(connections[SID], function (target) {
var link = new joint.dia.Link({ //make link for each target
source: {id: SID},
target: {id: ''+target+''},
'smooth': true,
attrs: {
'.connection': {'stroke-width': 3},
'.marker-source':{},
'.marker-target':{d: 'M 10 0 L 0 5 L 10 10 z', stroke: 'black', fill: 'black'},
'z-index': -1 //I am not sure if this has any effect anyway...
}
});
links.push(link);
});
}
}
graph.addCells(shapenodes); //Add to graph
graph.addCell(links);
The sample data I am using is as follows:
var nodes = [ //Sample data
{
ID: 1,
Chart: 1,
x: 50,
y: 50,
width: 100,
height: 80,
color: "#003253",
text: "Try to code",
label: "Start",
targets: [2]
},
{
ID: 2,
Chart: 1,
x: 500,
y: 170,
width: 100,
height: 80,
color: "#365C5A",
text: "Fail",
label: "End",
targets: [3]
},
{
ID: 3,
Chart: 1,
x: 270,
y: 350,
width: 150,
height: 80,
color: "#81271E",
text: "Cry a lot",
label: "Mid",
targets: [1]
}
];
I looked at a lot of examples and it seems like mine should work. Do you have any idea why this is happening? JSfiddle