Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
de.uniks.networkparser.graph.graph.js Maven / Gradle / Ivy
/*
NetworkParser
Copyright (c) 2011 - 2014, Stefan Lindel
All rights reserved.
Licensed under the EUPL, Version 1.1 or (as soon they
will be approved by the European Commission) subsequent
versions of the EUPL (the "Licence");
You may not use this work except in compliance with the Licence.
You may obtain a copy of the Licence at:
http://ec.europa.eu/idabc/eupl5
Unless required by applicable law or agreed to in
writing, software distributed under the Licence is
distributed on an "AS IS" basis,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied.
See the Licence for the specific language governing
permissions and limitations under the Licence.
*/
// VERSION: 2015.11.09 20:21
//var uniId = 0;
//function generateId() { return uniId++; };
//Object.prototype.uniId = function () {
// var newId = generateId();
// this.uniId = function () { return newId; };
// return newId;
//};vars: true
/*jslint forin:true, newcap:true, node: true, continue: true */
/*jshint forin:true, laxbreak: true, newcap: false, node: true, nomen: true, -W089, -W079 */
/*global document: false, window: false, navigator: false, unescape: false, Edge: false, DagreLayout: false, Drawer: false */
/*global jsPDF: false, svgConverter: false, Image: false, Blob: false, dagre: false, SymbolLibary: false */
/*global FileReader:false, java:false, ChoiceBox:false */
"use strict";
var ObjectCreate = Object.create || function (o) {var F = function () {}; F.prototype = o; return new F(); };
/* Pos */
var Pos = function (x, y, id) {this.x = Math.round(x || 0); this.y = Math.round(y || 0); if (id) {this.$id = id; } };
/* GraphUtil */
var GraphUtil = function (ns) {if (ns) {this.ns = ns; } };
GraphUtil.prototype.copy = function (ref, src, full, replace) {
if (src) {
var i;
for (i in src) {
if (!src.hasOwnProperty(i) || typeof (src[i]) === "function") {
continue;
}
if (i.charAt(0) === "$") {
if (full) {ref[i] = src[i]; }
continue;
}
if (typeof (src[i]) === "object") {
if (replace) {
ref[i] = src[i];
continue;
}
if (!ref[i]) {
if (src[i] instanceof Array) {
ref[i] = [];
} else {
ref[i] = {};
}
}
this.copy(ref[i], src[i], full);
} else {
if (src[i] === "") {
continue;
}
ref[i] = src[i];
}
}
if (src.width) {ref.$startWidth = src.width; }
if (src.height) {ref.$startHeight = src.height; }
}
return ref;
};
GraphUtil.prototype.minJson = function (target, src, ref) {
var i, temp, value;
for (i in src) {
if (!src.hasOwnProperty(i) || typeof (src[i]) === "function") {
continue;
}
if (src[i] === null || src[i] === "" || src[i] === 0 || src[i] === false || i.charAt(0) === "$") {
continue;
}
value = src[i];
if (value instanceof GraphUtil.Options || ref !== null) {
if (typeof (value) === "object") {
temp = (value instanceof Array) ? [] : {};
if (ref) {
value = this.minJson(temp, value, ref[i]);
} else {
value = this.minJson(temp, value, new GraphUtil.Options());
}
}
if (ref && value === ref[i]) {
continue;
}
}
if (typeof (value) === "object") {
if (value instanceof Array && value.length < 1) {
continue;
}
if (value instanceof Array) {
target[i] = this.minJson([], value);
} else {
temp = this.minJson({}, value);
if (JSON.stringify(temp, null, "") === "{}") {
continue;
}
target[i] = temp;
}
} else {
target[i] = value;
}
}
return target;
};
GraphUtil.prototype.bind = function (el, eventName, eventHandler) {
if (el.addEventListener) {
el.addEventListener(eventName, eventHandler, false);
} else if (el.attachEvent) {
el.attachEvent('on' + eventName, eventHandler);
}
};
GraphUtil.prototype.create = function (node) {
var style, item, xmlns, key, tag, k;
if (document.createElementNS && (node.xmlns || this.ns)) {
if (node.xmlns) {
xmlns = node.xmlns;
} else {
xmlns = this.ns;
}
if (node.tag === "img" && xmlns === "http://www.w3.org/2000/svg") {
item = document.createElementNS(xmlns, "image");
item.setAttribute('xmlns:xlink', "http://www.w3.org/1999/xlink");
item.setAttributeNS("http://www.w3.org/1999/xlink", 'href', node.src);
} else {
item = document.createElementNS(xmlns, node.tag);
}
} else {
item = document.createElement(node.tag);
}
tag = node.tag.toLowerCase();
for (key in node) {
if (!node.hasOwnProperty(key)) {
continue;
}
k = key.toLowerCase();
if (node[key] === null) {
continue;
}
if (k === 'tag' || k.charAt(0) === '$' || k === 'model') {
continue;
}
if (k.charAt(0) === '#') {
item[k.substring(1)] = node[key];
continue;
}
if (k === 'rotate') {
item.setAttribute("transform", "rotate(" + node[key] + "," + node.model.x + "," + node.model.y + ")");
continue;
}
if (k === 'value') {
if (!node[key]) {
continue;
}
if (tag !== "input") {
if (tag === "text") {// SVG
item.appendChild(document.createTextNode(node[key]));
} else {
item.innerHTML = node[key];
}
} else {
item[key] = node[key];
}
continue;
}
if (k.indexOf("on") === 0) {
this.bind(item, k.substring(2), node[key]);
continue;
}
if (k.indexOf("-") >= 0) {
item.style[key] = node[key];
} else {
if (k === "style" && typeof (node[key]) === "object") {
for (style in node[key]) {
if (!node[key].hasOwnProperty(style)) {
continue;
}
if (node[key][style]) {
if ("transform" === style) {
item.style.transform = node[key][style];
item.style.msTransform = item.style.MozTransform = item.style.WebkitTransform = item.style.OTransform = node[key][style];
} else {
item.style[style] = node[key][style];
}
}
}
} else {
item.setAttribute(key, node[key]);
}
}
}
if (node.$font) {
if (this.model && this.model.options && this.model.options.font) {
for (key in this.model.options.font) {
if (!this.model.options.font.hasOwnProperty(key)) {
continue;
}
if (this.model.options.font[key]) {
if (item.style) {
item.style[key] = this.model.options.font[key];
} else {
item.setAttribute(key, this.model.options.font[key]);
}
}
}
}
}
if (node.$parent) {
node.$parent.appendChild(item);
}
if (node.model) {
item.model = node.model;
}
return item;
};
GraphUtil.prototype.getModelNode = function (element) {
if (!element.model) {
if (element.parentElement) {
return this.getModelNode(element.parentElement);
}
return null;
}
return element;
};
GraphUtil.prototype.getValue = function (value) {return parseInt(("0" + value).replace("px", ""), 10); };
GraphUtil.prototype.isIE = function () {return document.all && !window.opera; };
GraphUtil.prototype.isFireFox = function () {return navigator.userAgent.toLowerCase().indexOf('firefox') > -1; };
GraphUtil.prototype.isOpera = function () {return navigator.userAgent.indexOf("Opera") > -1; };
GraphUtil.prototype.getEventX = function (event) {return (this.isIE) ? window.event.clientX : event.pageX; };
GraphUtil.prototype.getEventY = function (event) {return (this.isIE) ? window.event.clientY : event.pageY; };
GraphUtil.prototype.set = function (id, value) {if (value) {this[id] = value; } };
GraphUtil.prototype.selectText = function (text) {
var selection, range;
if (this.isIE()) {
range = document.body.createTextRange();
range.moveToElementText(text);
range.select();
} else if (this.isFireFox() || this.isOpera()) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(text);
selection.removeAllRanges();
selection.addRange(range);
}
};
GraphUtil.prototype.sizeHTML = function (html, node) {
if (!html) {return; }
if (this.$parent) {
return this.$parent.sizeHTML(html, node);
}
this.board.appendChild(html);
var rect = html.getBoundingClientRect();
this.board.removeChild(html);
if (node) {
if (!node.$startWidth) {
node.width = Math.round(rect.width);
}
if (!node.$startHeight) {
node.height = Math.round(rect.height);
}
}
return rect;
};
GraphUtil.prototype.hasClass = function (ele, cls) {return ele.className.indexOf(cls) > 0; };
GraphUtil.prototype.addClass = function (ele, cls) {if (!this.hasClass(ele, cls)) {
ele.className = ele.className + " " + cls;
} };
GraphUtil.prototype.removeClass = function (ele, cls) {
if (this.hasClass(ele, cls)) {
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
ele.className = ele.className.replace(reg, ' ');
}
};
/* Info */
GraphUtil.Info = function (info, parent, edge) {
this.type = "Info";
if (typeof (info) === "string") {
this.id = info;
} else {
if (info.property) {this.property = info.property; }
if (info.cardinality) {this.cardinality = info.cardinality; }
this.id = info.id;
}
this.x = this.y = this.width = this.height = 0;
this.$center = new Pos();
this.custom = false;
this.$parent = parent;
this.$edge = edge;
this.$isdraggable = true;
};
GraphUtil.Info.prototype.getX = function () {return this.x; };
GraphUtil.Info.prototype.getY = function () {return this.y; };
GraphUtil.Line = function (source, target, line, style) {this.source = source; this.target = target; this.line = line; this.style = style; };
GraphUtil.Line.Format = {SOLID: "SOLID", DOTTED: "DOTTED"};
/* Options */
GraphUtil.Options = function () {
this.raster = false;
this.addBorder = true;
this.display = "svg";
this.font = {"font-size": "10px", "font-family": "Verdana"};
this.layout = {name: "Dagre", rankDir: "TB", nodesep: 10}; // Dagre TB, LR
this.CardinalityInfo = true;
this.propertyinfo = true;
this.rotatetext = true;
this.linetyp = "center";
this.buttons = ["HTML", "SVG"]; // ["HTML", "SVG", "PNG", "PDF"]
};
/* Node */
var GraphNode = function (id) {
this.type = "node";
this.id = id;
this.$edges = [];
this.attributes = [];
this.methods = [];
this.$parent = null;
this.x = this.y = this.width = this.height = 0;
this.$isdraggable = true;
};
GraphNode.prototype = ObjectCreate(GraphUtil.prototype);
GraphNode.prototype.getX = function () {if (this.$parent) {return this.$parent.getX() + this.x; } return this.x; };
GraphNode.prototype.getY = function () {if (this.$parent) {return this.$parent.getY() + this.y; } return this.y; };
GraphNode.prototype.getEdges = function () {return this.$edges; };
GraphNode.prototype.clear = function () {this.$RIGHT = this.$LEFT = this.$UP = this.$DOWN = 0; };
GraphNode.prototype.removeFromBoard = function (board) {if (this.$gui) {board.removeChild(this.$gui); this.$gui = null; } };
GraphNode.prototype.isClosed = function () {
if (this.status === "close") {
return true;
}
if (this.$parent) {return this.$parent.isClosed(); }
return false;
};
GraphNode.prototype.getShowed = function () {
if (this.status === "close") {
if (!this.$parent.isClosed()) {
return this;
}
}
if (this.isClosed()) {
return this.$parent.getShowed();
}
return this;
};
var GraphModel = function (json, options) {
this.type = "classdiagram";
this.$isdraggable = true;
json = json || {};
this.left = json.left || 0;
this.top = json.top || 0;
this.x = this.y = this.width = this.height = 0;
if (json.minid) {
this.minid = json.minid;
}
this.$nodeCount = 0;
this.nodes = {};
this.edges = [];
json = json || {};
this.type = json.type || "classdiagram";
this.set("id", json.id);
this.options = this.copy(this.copy(new GraphUtil.Options(), json.options), options, true, true);
this["package"] = "";
this.set("info", json.info);
this.set("style", json.style);
var i;
if (json.nodes) {
for (i = 0; i < json.nodes.length; i += 1) {
this.addNode(json.nodes[i]);
}
}
if (json.edges) {
for (i = 0; i < json.edges.length; i += 1) {
this.addEdgeModel(json.edges[i]);
}
}
};
GraphModel.prototype = ObjectCreate(GraphNode.prototype);
GraphModel.prototype.clear = function () {
var i;
GraphNode.prototype.clear.call(this);
for (i in this.nodes) {
if (!this.nodes.hasOwnProperty(i)) {
continue;
}
this.nodes[i].clear();
}
};
GraphModel.prototype.addEdgeModel = function (e) {
var edge, type = e.type || "edge";
type = type.charAt(0).toUpperCase() + type.substring(1).toLowerCase();
if (typeof window[type] === "function") {
edge = new window[type]();
} else {
edge = new Edge();
}
edge.source = new GraphUtil.Info(e.source, this, edge);
edge.target = new GraphUtil.Info(e.target, this, edge);
edge.$sNode = this.getNode(edge.source.id, true);
edge.$sNode.$edges.push(edge);
if (e.info) {
if (typeof (e.info) === "string") {
edge.info = {id: e.info};
} else {
edge.info = {id: e.info.id, property: e.info.property, cardinality: e.info.cardinality};
}
}
edge.$parent = this;
edge.set("style", e.style);
edge.set("counter", e.counter);
edge.$tNode = this.getNode(edge.target.id, true);
edge.$tNode.$edges.push(edge);
this.edges.push(edge);
return edge;
};
GraphModel.prototype.addEdge = function (source, target) {
var edge = new Edge();
edge.source = this.addNode(source);
edge.target = this.addNode(target);
return this.addEdgeModel(edge);
};
GraphModel.prototype.addNode = function (node) {
/* testing if node is already existing in the graph */
if (typeof (node) === "string") {
node = {id: node, type: "node"};
}
node.type = node.type || "node";
node.type = node.type.toLowerCase();
if (!(node.id)) {
node.id = node.type + "$" + (this.$nodeCount + 1);
}
if (this.nodes[node.id] !== undefined) {
return this.nodes[node.id];
}
if (node.type.indexOf("diagram", node.type.length - 7) !== -1) {
node = new GraphModel(node, new GraphUtil.Options());
} else {
node = this.copy(new GraphNode(), node);
}
this.nodes[node.id] = node;
node.$parent = this;
this.$nodeCount += 1;
return this.nodes[node.id];
};
GraphModel.prototype.removeEdge = function (idSource, idTarget) {
var z, e;
for (z = 0; z < this.edges.length; z += 1) {
e = this.edges[z];
if (e.$sNode.id === idSource && e.$tNode.id === idTarget) {
this.edges.splice(z, 1);
z -= 1;
} else if (e.$tNode.id === idSource && e.$sNode.id === idTarget) {
this.edges.splice(z, 1);
z -= 1;
}
}
};
GraphModel.prototype.removeNode = function (id) {
delete (this.nodes[id]);
var i;
for (i = 0; i < this.edges.length; i += 1) {
if (this.edges[i].$sNode.id === id || this.edges[i].$tNode.id === id) {
this.edges.splice(i, 1);
i -= 1;
}
}
};
GraphModel.prototype.getNode = function (id, isSub, deep) {
var n, i, r;
deep = deep || 0;
if (this.nodes[id]) {
return this.nodes[id];
}
if (!isSub) {
return this.addNode(id);
}
for (i in this.nodes) {
if (!this.nodes.hasOwnProperty(i)) {
continue;
}
n = this.nodes[i];
if (n instanceof GraphModel) {
r = n.getNode(id, isSub, deep + 1);
if (r) {
return r;
}
}
}
if (deep === 0) {
return this.addNode(id);
}
return null;
};
GraphModel.prototype.toJson = function () {return this.copy({}, this); };
GraphModel.prototype.createElement = function (element, typ) {this.$parent.createElement(element, typ); };
GraphModel.prototype.removeFromBoard = function (board) {
if (this.$gui) {
board.removeChild(this.$gui);
this.$gui = null;
}
};
GraphModel.prototype.resize = function (mode) {};
GraphModel.prototype.getEdges = function () {return this.edges; };
GraphModel.prototype.calcLines = function (drawer) {
var i, n, sourcePos, e, ownAssoc = [];
for (i in this.nodes) {
if (!this.nodes.hasOwnProperty(i) || typeof (this.nodes[i]) === "function") {
continue;
}
this.nodes[i].clear();
}
for (i = 0; i < this.edges.length; i += 1) {
e = this.edges[i];
if (!e.calculate(this.$gui, drawer)) {
ownAssoc.push(e);
}
}
for (i = 0; i < ownAssoc.length; i += 1) {
ownAssoc[i].calcOwnEdge();
sourcePos = ownAssoc[i].getCenterPosition(ownAssoc[i].$sNode, ownAssoc[i].$start);
ownAssoc[i].calcInfoPos(sourcePos, ownAssoc[i].$sNode, ownAssoc[i].source);
sourcePos = ownAssoc[i].getCenterPosition(ownAssoc[i].$tNode, ownAssoc[i].$end);
ownAssoc[i].calcInfoPos(sourcePos, ownAssoc[i].$tNode, ownAssoc[i].target);
}
};
GraphModel.prototype.validateModel = function () {
var e, z, n, id, node, list;
if (this.type === "classdiagram") {
list = this.edges;
for (e = 0; e < list.length; e += 1) {
node = list[e].$sNode;
z = node.id.indexOf(":");
if (z > 0) {
id = node.id.substring(z + 1);
n = this.getNode(id, true, 1);
delete (this.nodes[node.id]);
this.edges[e].source.id = id;
if (n) {
this.edges[e].$sNode = n;
} else {
node.id = id;
this.nodes[node.id] = node;
}
}
node = list[e].$tNode;
z = node.id.indexOf(":");
if (z > 0) {
id = node.id.substring(z + 1);
n = this.getNode(id, true, 1);
delete (this.nodes[node.id]);
this.edges[e].target.id = id;
if (n) {
this.edges[e].$tNode = n;
} else {
node.id = id;
this.nodes[node.id] = node;
}
}
if (!list[e].source.cardinality) {
list[e].source.cardinality = "one";
}
if (!list[e].target.cardinality) {
list[e].target.cardinality = "one";
}
// Refactoring Edges for same property and type set cardinality
for (z = e + 1; z < list.length; z += 1) {
id = typeof (java);
if (!(id === typeof list[z])) {
continue;
}
if (this.validateEdge(list[e], list[z])) {
list[e].target.cardinality = "many";
list.splice(z, 1);
z -= 1;
} else if (this.validateEdge(list[z], list[e])) {
list[e].source.cardinality = "many";
list.splice(z, 1);
z -= 1;
}
}
}
}
};
GraphModel.prototype.validateEdge = function (sEdge, tEdge) {
return (sEdge.source.id === tEdge.source.id && sEdge.target.id === tEdge.target.id) && (sEdge.source.property === tEdge.source.property && sEdge.target.property === tEdge.target.property);
};
// ######################################################### Graph #########################################################
var Graph = function (json, options) {
this.x = this.y = this.width = this.height = 0;
json = json || {};
json.top = json.top || 50;
json.left = json.left || 10;
this.model = new GraphModel(json, options);
this.initLayouts();
this.loader = new GraphUtil.Loader(this);
this.initOption();
};
Graph.prototype = ObjectCreate(GraphNode.prototype);
Graph.prototype.initOption = function (typ, value) {
this.init = true;
if (this.model.options.display.toLowerCase() === "html") {
this.drawer = new Drawer.HTMLDrawer();
} else {
this.initDrawer("svg");
}
var i, layout = this.layouts[0];
for (i = 0; i < this.layouts.length; i += 1) {
if (this.layouts[i].name === this.model.options.layout.name.toLowerCase()) {
layout = this.layouts[i];
break;
}
}
this.layouter = layout.value;
if (this.model.options.canvasid) {
this.root = document.getElementById(this.model.options.canvasid);
}
if (this.root) {
if (this.model.options.clearCanvas) {
for (i = this.root.children.length - 1; i >= 0; i -= 1) {
this.root.removeChild(this.root.children[i]);
}
}
} else {
this.root = document.createElement("div");
if (this.model.options.canvasid) {
this.root.id = this.model.options.canvasid;
}
document.body.appendChild(this.root);
}
};
Graph.prototype.addOption = function (typ, value) {
this.model.options[typ] = value;
this.init = false;
};
Graph.prototype.initLayouts = function () { this.layouts = [{name: "dagre", value: new DagreLayout()}]; };
Graph.prototype.initInfo = function (edge, info) {
if (!this.model.options.CardinalityInfo && !this.model.options.propertyinfo) {
return null;
}
var infoTxt = edge.getInfo(info);
if (infoTxt.length > 0) {
this.sizeHTML(this.drawer.getInfo(info, infoTxt, 0), info);
}
return infoTxt;
};
Graph.prototype.clearBoard = function (onlyElements) {
var i, n;
if (this.board) {
this.clearLines(this.model);
for (i in this.model.nodes) {
if (!this.model.nodes.hasOwnProperty(i)) {
continue;
}
n = this.model.nodes[i];
if (this.board.children.length > 0) {
n.removeFromBoard(this.board);
}
n.$RIGHT = n.$LEFT = n.$UP = n.$DOWN = 0;
}
if (!onlyElements) {
this.root.removeChild(this.board);
}
}
if (!onlyElements && this.drawer) {
this.drawer.clearBoard();
}
};
Graph.prototype.addNode = function (node) {return this.model.addNode(node); };
Graph.prototype.addEdge = function (source, target) {return this.model.addEdge(source, target); };
Graph.prototype.removeNode = function (id) {return this.model.removeNode(id); };
Graph.prototype.calcLines = function (model) {
model = model || this.model;
model.calcLines(this.drawer);
};
Graph.prototype.drawLines = function (model) {
this.clearLines(model);
var i, e, startShow, endShow, items = [], id;
for (i = 0; i < model.edges.length; i += 1) {
e = model.edges[i];
startShow = !e.$sNode.isClosed();
endShow = !e.$tNode.isClosed();
if (startShow && endShow) {
e.draw(this.board, this.drawer);
} else if ((startShow && !endShow) || (!startShow && endShow)) {
id = e.$sNode.getShowed().id + "-" + e.$tNode.getShowed().id;
if (items.indexOf(id) < 0) {
items.push(id);
e.draw(this.board, this.drawer);
}
}
}
};
Graph.prototype.clearLines = function (model) {
var i;
for (i = 0; i < model.edges.length; i += 1) {
model.edges[i].removeFromBoard(this.board);
}
};
Graph.prototype.MinMax = function (node, min, max) {
max.x = Math.max(max.x, node.x + Number(node.width) + 10);
max.y = Math.max(max.y, node.y + Number(node.height) + 10);
min.x = Math.max(min.x, node.x);
min.y = Math.max(min.y, node.y);
};
Graph.prototype.resize = function (model) {
var nodes, n, max, i, min = new Pos();
max = new Pos(model.minSize.x, model.minSize.y);
nodes = model.nodes;
for (i in nodes) {
if (!nodes.hasOwnProperty(i) || typeof (nodes[i]) === "function") {
continue;
}
n = nodes[i];
this.moveToRaster(n);
this.MinMax(n, min, max);
}
this.calcLines(model);
for (i = 0; i < model.edges.length; i += 1) {
n = model.edges[i];
this.MinMax(n.source, min, max);
this.MinMax(n.target, min, max);
}
model.height = max.y;
model.width = max.x;
this.drawer.setSize(model.$gui, max.x, max.y);
if (model.options.raster) {
this.drawRaster();
}
this.drawLines(model);
return max;
};
Graph.prototype.drawRaster = function () {
var width, height, line, i;
while (this.board.rasterElements.length > 0) {
this.board.removeChild(this.board.rasterElements.pop());
}
width = this.board.style.width.replace("px", "");
height = this.board.style.height.replace("px", "");
for (i = 10; i < width; i += 10) {
line = this.drawer.getLine(i, 0, i, height, null, "#ccc");
line.setAttribute("className", "lineRaster");
this.board.rasterElements.push(line);
this.board.appendChild(line);
}
for (i = 10; i < height; i += 10) {
line = this.drawer.getLine(0, i, width, i, null, "#ccc");
line.setAttribute("className", "lineRaster");
this.board.rasterElements.push(line);
this.board.appendChild(line);
}
};
Graph.prototype.draw = function (model, width, height) {
var i, n, nodes = model.nodes;
if (model.options.addBorder) {
for (i in nodes) {
if (!nodes.hasOwnProperty(i) || typeof (nodes[i]) === "function") {
continue;
}
n = nodes[i];
if (model.left > 0 || model.top > 0) {
n.x += model.left;
n.y += model.top;
}
}
model.options.addBorder = false;
}
model.minSize = new Pos(width || 0, height || 0);
if (this.loader.abort && this.loader.images.length > 0) {
return;
}
this.resize(model);
for (i in nodes) {
if (!nodes.hasOwnProperty(i) || typeof (nodes[i]) === "function") {
continue;
}
n = nodes[i];
n.$gui = this.drawer.getNode(n, true);
model.$gui.appendChild(n.$gui);
}
};
Graph.prototype.moveToRaster = function (node) {
if (this.model.options.raster) {
node.x = parseInt(node.x / 10, 10) * 10;
node.y = parseInt(node.y / 10, 10) * 10;
if (node.$gui) {
this.drawer.setPos(node.$gui, node.x, node.y);
}
}
};
Graph.prototype.initGraph = function (model) {
var i, n, isDiag, html, e;
model.validateModel();
for (i in model.nodes) {
if (typeof (model.nodes[i]) === "function") {
continue;
}
n = model.nodes[i];
isDiag = n.type.indexOf("diagram", n.type.length - 7) !== -1;
if (isDiag) {
this.initGraph(n);
}
html = this.drawer.getNode(n);
if (html) {
this.sizeHTML(html, n);
if (isDiag) {
n.$center = new Pos(n.x + (n.width / 2), n.y + (n.height / 2));
}
}
}
for (i = 0; i < model.edges.length; i += 1) {
e = model.edges[i];
this.initInfo(e, e.source);
this.initInfo(e, e.target);
}
};
Graph.prototype.layout = function (minwidth, minHeight, model) {
if (!this.init) {
this.initOption();
}
if (model) {
this.initGraph(model);
} else {
model = this.model;
this.initDrawer();
this.initGraph(model);
}
if (this.loader.images.length < 1) {
this.layouter.layout(this, model, Math.max(minwidth || 0, 100), Math.max(minHeight || 0, 100));
} else {
this.loader.width = minwidth;
this.loader.height = minHeight;
}
};
Graph.prototype.createElement = function (element, typ, node) {
var that = this;
element.node = node;
this.bind(element, "mousedown", function (e) {that.startDrag(e); });
};
Graph.prototype.appendImage = function (img) {
this.loader.add(img);
};
// ######################################################### DRAG AND DROP #########################################################
Graph.prototype.initDragAndDrop = function () {
this.objDrag = null;
this.mouse = new Pos();
this.offset = new Pos();
this.startObj = new Pos();
var that = this;
this.bind(this.board, "mousemove", function (e) {that.doDrag(e); });
this.bind(this.board, "mouseup", function (e) {that.stopDrag(e); });
this.bind(this.board, "mouseout", function (e) {that.stopDrag(e); });
};
Graph.prototype.setSelectable = function (node, value) {
if (node.nodeType === 1) {
if (value) {
node.setAttribute("unselectable", value);
} else {
node.removeAttribute("unselectable");
}
}
var child = node.firstChild;
while (child) {
this.setSelectable(child, value);
child = child.nextSibling;
}
};
Graph.prototype.getDragNode = function (node) {
if (node.model) {
if (!node.model.$isdraggable) {
return null;
}
return node;
}
if (node.parentElement.model) {
if (!node.parentElement.model.$isdraggable) {
return null;
}
return node.parentElement;
}
return null;
};
Graph.prototype.startDrag = function (event) {
var graph, i, n = this.getDragNode(event.currentTarget);
if (!n) {
return;
}
if (this.objDrag) {
return;
}
this.objDrag = n;
graph = this.objDrag.parentElement;
if (graph) {
for (i = 0; i < graph.children.length; i += 1) {
this.setSelectable(graph.children[i], "on");
}
}
this.offset.x = this.isIE ? window.event.clientX : event.pageX;
this.offset.y = this.isIE ? window.event.clientY : event.pageY;
this.startObj.x = this.objDrag.model.x;
this.startObj.y = this.objDrag.model.y;
};
Graph.prototype.doDrag = function (event) {
var x, y;
this.mouse.x = this.isIE ? window.event.clientX : event.pageX;
this.mouse.y = this.isIE ? window.event.clientY : event.pageY;
if (this.objDrag !== null) {
x = (this.mouse.x - this.offset.x) + this.startObj.x;
y = (this.mouse.y - this.offset.y) + this.startObj.y;
if (this.model.options.display === "svg") {
x = x - this.startObj.x;
y = y - this.startObj.y;
this.objDrag.setAttribute('transform', "translate(" + x + " " + y + ")");
} else {
this.drawer.setPos(this.objDrag, x, y);
if (this.objDrag.model) {
this.objDrag.model.x = x;
this.objDrag.model.y = y;
this.objDrag.model.$parent.resize(this.model);
}
}
}
};
Graph.prototype.stopDrag = function (event) {
var x, y, z, item, entry, parent, pos;
if (!this.objDrag) {
return;
}
if (!(event.type === "mouseup" || event.type === "mouseout") && !event.currentTarget.isdraggable) {
return;
}
if (event.type === "mouseout") {
x = this.isIE ? window.event.clientX : event.pageX;
y = this.isIE ? window.event.clientY : event.pageY;
if (x < this.board.offsetWidth && y < this.board.offsetHeight) {
return;
}
}
item = this.objDrag;
this.objDrag = null;
entry = item.parentElement;
if (entry) {
for (z = 0; z < entry.children.length; z += 1) {
this.setSelectable(entry.children[z], null);
}
}
parent = item.parentElement;
if (item.model) {
if (this.model.options.display === "svg") {
if (item.getAttributeNS(null, "transform")) {
z = item.getAttributeNS(null, "transform");
if (z.substring(0, 6) !== "rotate") {
pos = z.slice(10, -1).split(' ');
item.model.x = item.model.x + Number(pos[0]);
item.model.y = item.model.y + Number(pos[1]);
}
}
item.model.$center = new Pos(item.model.x + (item.model.width / 2), item.model.y + (item.model.height / 2));
parent.removeChild(item);
if (item.model.board) {
item.model.board = null;
}
} else {
this.board.removeChild(item);
}
if (item.model.type === "Info") {
item.model.custom = true;
item.model.$edge.removeElement(item);
entry = item.model.$edge.getInfo(item.model);
item.model.$edge.drawText(this.board, this.drawer, entry, item.model);
} else {
item.model.$gui = this.drawer.getNode(item.model, true);
if (item.model.$gui) {
parent.appendChild(item.model.$gui);
}
entry = item.model.getEdges();
for (z = 0; z < entry.length; z += 1) {
entry[z].source.custom = false;
entry[z].target.custom = false;
}
}
parent = item.model.$parent;
entry = parent;
while (entry) {
this.resize(entry);
entry = entry.$parent;
}
if (parent.$parent) {
this.redrawNode(parent, true);
this.resize(this.model);
} else {
this.resize(parent);
}
}
};
Graph.prototype.redrawNode = function (node, draw) {
var infoTxt, parent = node.$gui.parentElement;
parent.removeChild(node.$gui);
if (node.board) {
node.board = null;
}
if (node.type === "Info") {
infoTxt = node.edge.getInfo(node.node);
node.edge.drawText(this.board, this.drawer, infoTxt, node.node);
} else {
node.$gui = this.drawer.getNode(node, draw);
if (node.$gui) {
parent.appendChild(node.$gui);
}
}
node.$center = new Pos(node.x + (node.width / 2), node.y + (node.height / 2));
this.resize(node.$parent);
};
Graph.prototype.initDrawer = function (typ) {
if (typ) {
typ = typ.toLowerCase();
if (this.model.options.display === typ) {
return;
}
this.model.options.display = typ;
} else {
typ = this.model.options.display;
}
this.clearBoard();
if (typ === "html") {
this.drawer = new Drawer.HTMLDrawer();
} else if (typ === "svg") {
this.drawer = new Drawer.SVGDrawer();
}
this.board = this.drawer.getBoard(this);
this.model.$gui = this.board;
this.initDragAndDrop();
this.root.appendChild(this.board);
};
Graph.prototype.serializeXmlNode = function (xmlNode) {
if (window.XMLSerializer !== undefined) {
return (new window.XMLSerializer()).serializeToString(xmlNode);
}
if (xmlNode.xml !== undefined) {
return xmlNode.xml;
}
return xmlNode.outerHTML;
};
Graph.prototype.utf8$to$b64 = function (str) {
return window.btoa(unescape(encodeURIComponent(str)));
};
Graph.prototype.ExportPDF = function () {
var converter, pdf = new jsPDF('l','px',[this.model.width, this.model.height]);
converter = new svgConverter(this.board, pdf, {removeInvalid: false});
pdf.save('Download.pdf');
};
Graph.prototype.ExportEPS = function () {
var converter, doc = new svgConverter.jsEPS({inverting: true});
converter = new svgConverter(this.board, doc, {removeInvalid: false});
doc.save();
};
Graph.prototype.ExportPNG = function () {
var canvas, context, a, image = new Image();
image.src = 'data:image/svg+xml;base64,' + this.utf8$to$b64(this.serializeXmlNode(this.board));
image.onload = function () {
canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
a = document.createElement('a');
a.download = "download.png";
a.href = canvas.toDataURL('image/png');
a.click();
};
};
Graph.prototype.SaveAs = function (typ) {
typ = typ.toLowerCase();
if (typ === "svg") {
this.Save("image/svg+xml", this.serializeXmlNode(this.board), "download.svg");
} else if (typ === "html") {
this.ExportHTML();
} else if (typ === "png") {
this.ExportPNG();
} else if (typ === "pdf") {
this.ExportPDF();
} else if (typ === "eps") {
this.ExportEPS();
}
};
Graph.prototype.SavePosition = function () {
var data = [], node, id;
for (id in this.model.nodes) {
node = this.model.nodes[id];
data.push({id: node.id, x: node.x, y: node.y});
}
if (window.localStorage && this.model.id) {
window.localStorage.setItem(this.model.id, JSON.stringify(data));
}
};
Graph.prototype.LoadPosition = function () {
if (this.model.id && window.localStorage) {
var node, id, data = window.localStorage.getItem(this.model.id);
if (data) {
data = JSON.parse(data);
for (id in data) {
node = data[id];
if (this.model.nodes[node.id]) {
this.model.nodes[node.id].x = node.x;
this.model.nodes[node.id].y = node.y;
}
}
this.clearBoard(true);
this.draw(this.model);
}
}
};
Graph.prototype.Save = function (typ, data, name) {
var a = document.createElement("a");
a.href = window.URL.createObjectURL(new Blob([data], {type: typ}));
a.download = name;
a.click();
};
Graph.prototype.ExportHTML = function () {
var data, json = this.model.toJson();
data = "" + document.head.innerHTML.trim() + "