(function () {
/**
* workaround to register events only once
* and get just the inner-event
*/
var eventMap = {};
window.addEventListener('message', function (event) {
var innerEvent = event.data;
var handler = eventMap[innerEvent.type];
if (handler instanceof Function) {
handler(innerEvent.data);
}
});
/**
* Use this function to register to post message events
*/
window.registerPostMessageEvent = function (type, handler) {
eventMap[type] = handler;
};
})();
function alertNoFlowTypeSelected() {
$('#selected-type-mt')
.addClass('pulse-info')
.on('change', function (event) {
$(event.target).removeClass('pulse-info');
})
alertError('Please select the flow type to continue');
}
var CompositionEditor = function () {
var componentId = document
.getElementById('iframe')
.getAttribute('componentid');
var userId = document
.getElementById('iframe')
.getAttribute('user_id');
var readOnlyComponent = document
.getElementById('iframe')
.getAttribute('readOnlyComponent');
var curcomp = {
cid: null,
//1806 US374595 save flow type in cdump
flowType: null,
version: 0,
nodes: [],
relations: [],
inputs: [],
outputs: []
};
window.d3Data = curcomp;
curcomp.cid = componentId;
this.curcomp = curcomp;
var flowTypes = window.flowTypes;
var typeSelect = document.getElementById("selected-type-mt");
if (flowTypes.length > 0) {
flowTypes
.forEach(function (flowType) {
var myOption = document.createElement("option");
myOption.text = flowType;
myOption.value = flowType;
typeSelect.add(myOption);
});
}
typeSelect
.addEventListener("change", function () {
curcomp.flowType = typeSelect.value;
});
document
.getElementById("savebtn")
.setAttribute("data-tests-id", "SaveButton");
document
.getElementById("savebtn")
.setAttribute("disabled", "true");
document
.getElementById("savebtn")
.setAttribute("style", "opacity:0.5");
if (readOnlyComponent == 'true') {
var componentUser = document
.getElementById('iframe')
.getAttribute('componentUser');
alertError("The resource is already checked out by user: " + componentUser);
} else {
document
.getElementById("savebtn")
.removeAttribute("disabled");
document
.getElementById("savebtn")
.setAttribute("style", "opacity:1");
}
document
.getElementById("savebtn")
.addEventListener("click", function () {
var mt = $('#selected-type-mt').val();
if (!mt) {
alertNoFlowTypeSelected();
return;
}
compController.saveComposition(curcomp);
});
var vfni = document
.getElementById('iframe')
.getAttribute('vnfiname');
// document.getElementById("submitbtn").setAttribute("data-tests-id",
// "SubmitButton"); if (!(vfni !== null && vfni !== "") || readOnlyComponent ==
// 'true') { //
// document.getElementById("submitbtn").setAttribute("disabled", "true"); //
// document.getElementById("submitbtn").setAttribute("style", "opacity:0.5"); }
// else { document.getElementById("submitbtn").addEventListener("click",
// function () { var mt = $('#selected-type-mt').val(); if (mt
// == null) { alertNoFlowTypeSelected(); return; }
// console.log('entered submitbtn eventlistener'); var component_Id =
// document.getElementById('iframe').getAttribute('componentid'); var
// serviceuuid = document.getElementById('iframe').getAttribute('serviceuuid');
// var vnfiname =
// document.getElementById('iframe').getAttribute('vnfiname');
// compController.createBlueprint(component_Id, serviceuuid, vnfiname, mt); });
// //console.log(x); }
function log(x, y) {
var args = ["composition:"].concat(Array.prototype.slice.call(arguments, 0));
console
.log
.apply(console, args);
}
function simulateclick(x, y, target) {
target = target || document.body;
var e = document.createEvent("MouseEvent");
e.initMouseEvent("click", true, true, window, 1, 0, 0, x, y, false, false, false, false, 0, null);
target.dispatchEvent(e);
}
function addcss(id, text) {
var head = document.getElementsByTagName("head")[0];
var style = document.createElement("style");
style.id = id;
style.type = "text/css";
style.innerHTML = text;
// if style with this id exists, remove it
try {
var styles = head.getElementsByTagName("style");
if (styles)
_.each(styles, function (x) {
if (x.id == id)
head.removeChild(x);
}
);
}
catch (e) {
log(e);
}
head.appendChild(style);
return style;
}
function parentmsg(s) {
return parent.postMessage(s, '*');
}
var msgid = 0;
function basemsg(action) {
return {
"action": action,
"channelID": "ice-to-cart",
"id": msgid++,
"timestamp": new Date()
};
}
function uuid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
function parsequery(s) {
s = s.substring(s.indexOf('?') + 1).split('&');
var params = {},
pair;
// march and parse
for (var i = s.length - 1; i >= 0; i--) {
pair = s[i].split('=');
params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return params;
}
var cid = "NULL";
function getCompositionError(error) {
console.error("unable to get composition: %o", error);
}
function init(cid) {
log("init");
cid = cid || uuid();
log("cid", cid);
curcomp.cid = cid;
console.log("get composition is called ");
$
.get(window.configOptions.backend_url + "getComposition/" + cid)
.then(function (resData) {
if (resData && resData.successResponse) {
try {
var composition = JSON.parse(resData.successResponse);
composition.cid = cid;
onCompositionEvent("initend");
restoregraph(composition);
} catch (error) {
getCompositionError(error);
}
} else {
document.dispatchEvent(new CustomEvent('noComposition'));
}
})
.fail(getCompositionError);
deletebutton();
}
function deletebutton() {
d3
.select("#compositiondiv")
.append("div")
.style("position", "absolute")
.style("bottom", "30px")
.style("right", "5px")
.style("background", "rgba(255,0,0,0.3)")
.html("toggle node deletion")
.on("click", function (d) {
if (d3.selectAll(".deletenode").style("visibility") == "hidden")
d3.selectAll(".deletenode").style("visibility", "visible");
else
d3
.selectAll(".deletenode")
.style("visibility", "hidden");
}
);
}
function getcdump(cid) {
var pe = svg.style("pointer-events");
log("suspend pointer-events");
svg.style("pointer-events", "none");
// fallback in case xhrget doesn't reset svg pointer events
setTimeout(function () {
if (svg.style("pointer-events") != pe) {
log("restore pointer-events fallback");
svg.style("pointer-events", pe);
}
}, 2000);
return new Promise(function (resolve, reject) {
xhrget("/cdump?cid=" + cid, function (resp) {
log("restore pointer-events");
if (svg.style("pointer-events") != "none") // assert?
log("wtf pointer-events");
svg.style("pointer-events", pe);
try {
resolve(JSON.parse(resp));
} catch (e) {
reject({"exception": e, "response": resp});
}
});
});
}
function compositionreadonly(val) {
if (val == undefined)
val = true;
if (val)
svg.style("pointer-events", "none");
else
svg.style("pointer-events", "all");
return svg.style("pointer-events");
}
function restoregraph(c) {
if (!c.nodes)
return;
curcomp.cid = c.cid;
rc = c;
c
.nodes
.forEach(function (n) {
addnode(n, 0, 0, n.ndata);
});
c
.relations
.forEach(function (r) {
var m = r.meta;
addlink(m.n1, m.n2, m.p1, m.p2, true);
});
sortinterfaces(); // HACK
//1806 US374595 flowType saved to cdump
if (c.flowType && _.contains(flowTypes, c.flowType)) {
typeSelect.value = c.flowType;
curcomp.flowType = typeSelect.value;
} else {
console.log(c.flowType + " not in flowTypes DDL")
}
}
function postcompimg() {
log("postcompimg");
/*xhrpostraw("/compimg?cid="+cid, serialsvg(),
function(resp) { log("compimg", resp); },
"image/svg");*/
}
function commitcomposition(callback) {
console.log("commitcomposition");
/*xhrpost("/composition.commit?cid="+cid, {},
function(resp) {
callback(resp);
});*/
}
function jsonparse(x) {
try {
return JSON.parse(x);
} catch (e) {
log("jsonparse", x, e);
throw e;
}
}
function template(id, fn) {
/*xhrget("/template?" + id, function(resp) {
var tp = JSON.parse(resp);
if (! tp.nodes) {
log("template:oops", tp);
fn(null);
}
var nn = tp.nodes.length;
if (nn == 0)
fn(tp);
else {
tp.nodes.map(function(n) {
if (n.id == 0) { // dummy node special case
if (--nn == 0)
fn(tp);
} else {
xhrget("/type?" + n.type.name, function(resp) {
var ti = JSON.parse(resp);
n.typeinfo = ti;
if (--nn == 0)
fn(tp);
});
}
});
}
});*/
}
function template0(id, fn) {
/*xhrget("/template?" + id, function(resp) {
var tp = JSON.parse(resp);
fn(tp);
});*/
}
function addtemplate(id) {
template(id, addcomp);
}
function addproduct(prod, x, y) {
log("addproduct", prod);
if (prod.offer) {
clearComposition();
}
catalogitem(prod.uuid, function (p) {
log("addproduct p", p);
// HACK -- this can't be right
log("HACK node.id", prod.uuid);
p
.model
.nodes
.forEach(function (n) {
n.id = prod.uuid;
});
if (p.models && p.models.length > 0) {
// addcomp
p
.models
.map(function (w) {
dropdata(w, x || bw / 2, y || bh / 2);
});
}
onCompositionEvent("added.product.to.composition", prod);
});
}
function setnodeproperties(nid, properties) {
/*xhrpost("/composition.setnodeproperties?cid="+cid, {"nid":nid, "properties":_.clone(properties)},
function(resp) {
});*/
}
function setnodepolicies(nid, policies) {
/*xhrpost("/composition.setnodepolicies?cid="+cid, {"nid":nid, "policies":_.clone(policies)},
function(resp) {
});*/
}
function deepclone(x) {
return JSON.parse(JSON.stringify(x));
}
var gensym = (function () {
var n = 0;
return function (x) {
var t = new Date().getTime();
return (x || "g") + "." + t + "." + n++;
};
})();
var xhrprefix = configOptions.backend_url;
function xhrgetBE(url, callback) {
var req = new XMLHttpRequest;
if (!(url.startsWith("https://") || url.startsWith("http://")))
url = xhrprefix + url;
req.open("GET", url, true); // asynchronous request
req.onreadystatechange = function (x) {
if (req.readyState === 4)
callback(req.responseText);
};
req.send(null);
}
function xhrget(url, callback) {
var req = new XMLHttpRequest;
if (!(url.startsWith("https://") || url.startsWith("http://")))
url = xhrprefix + url;
req.open("GET", url, true); // asynchronous request
req.onreadystatechange = function (x) {
if (req.readyState === 4)
callback(req.responseText);
};
req.send(null);
}
function xhrgetsync(url, callback) {
var req = new XMLHttpRequest;
if (!(url.startsWith("https://") || url.startsWith("http://")))
url = xhrprefix + url;
req.open("GET", url, false);
req.onreadystatechange = function (x) {
if (req.readyState === 4)
callback(req.responseText);
};
req.send(null);
}
callback = function (responseText) {
// write your own handler here.
console.log('result from http://localhost:8446/saveComposition/ac297d4d-0199-458f-99ff-2a6ff6' +
'ed849a \n' + responseText);
};
/**
* Callback function of AJAX request if the request fails.
*/
failCallback = function () {
// write your own failure handler here.
console.log('AJAXRequest failure!');
};
var apiService = new ApiService(xhrprefix, userId);
var compController = new CompController(apiService);
function xhrpost(url, obj, callback, type, async) {
var req = new XMLHttpRequest;
if (!(url.startsWith("https://") || url.startsWith("http://")))
url = xhrprefix + url;
req.open("POST", url, true); // asynchronous request
req.setRequestHeader("Content-Type", type || "application/json;charset=UTF-8");
req.setRequestHeader('USER_ID', userId);
req.onreadystatechange = function (x) {
if (req.readyState === 4)
callback(req.responseText);
};
try {
req.send(JSON.stringify(obj));
} catch (e) {
if (e.name == "TypeError")
req.send(JSON.stringify(obj));
else
throw(e);
}
}
function xhrpostraw(url, obj, callback, type) {
var req = new XMLHttpRequest;
if (!(url.startsWith("https://") || url.startsWith("http://")))
url = xhrprefix + url;
req.open("POST", url, true);
req.setRequestHeader("Content-Type", type || "text/plain");
req.setRequestHeader('USER_ID', userId);
req.onreadystatechange = function (x) {
if (req.readyState === 4)
callback(req.responseText);
};
req.send(obj);
}
var bw = document
.getElementById("compositioncontainer")
.clientWidth;
var bh = document
.getElementById("compositioncontainer")
.clientHeight;
// initially setting linkdistance to smaller value will help layout sort out
// edge crossings
var force = d3
.layout
.force()
.gravity(.9)
.charge(-3000)
.linkDistance(500)
.linkStrength(1)
.size([bw, bh]);
setTimeout(function () {
init(componentId);
});
function unfix() {
force
.nodes()
.forEach(function (n) {
n.fixed = false;
});
}
function fix() {
force
.nodes()
.forEach(function (n) {
n.fixed = true;
});
}
function resize() {
bw = document
.getElementById("compositioncontainer")
.clientWidth;
bh = document
.getElementById("compositioncontainer")
.clientHeight;
svg
.attr("width", bw)
.attr("height", bh);
force.size([
bw - 30,
bh - 30
]);
force.start();
}
var rev = 0;
var svg = d3
.select("#compositioncontainer")
.append("svg:svg")
.style("overflow", "visible")
.attr("width", bw)
.attr("height", bh);
var undergraph = svg.append("svg:g");
var graph = svg.append("svg:g");
var edgegroup = graph.append("svg:g");
function bbox(sel) { // arg is d3 svg selection
return sel[0][0].getBBox();
}
function clamp(d) {
var pad = 120; // HACK
var x1 = pad,
y1 = pad,
x2 = bw - pad,
y2 = bh - pad;
if (d.x < x1)
d.x = x1;
if (d.y < y1)
d.y = y1;
if (d.x > x2)
d.x = x2;
if (d.y > y2)
d.y = y2;
return d;
}
function circleclamp(d) {
var p2 = 2 * Math.PI;
if (d.a < 0)
d.a += p2;
if (d.a > p2)
d.a -= p2;
return d;
}
function tick() {
if (force.alpha() < .05) // chill
force.alpha(0);
graph
.selectAll(".node")
.attr("transform", function (d) {
clamp(d);
// (d.x > 350) { d.x = 350; } break;
// case 2: if (d.x < bw - 350) { d.x = bw - 350;
// } break; } } HACK for vLAN nodes in uCPE
var modelName = d
.model
.name
.toUpperCase()
.replace(/-/g, " ");
if (modelName.match(/\bVPN\sFACING\b/) || modelName.match(/\bINTERNET\sFACING\b/)) {
if (d.y > 130)
d.y = 130;
}
else if (modelName.match(/\bLAN\sFACING\b/)) {
if (d.y < bh - 130)
d.y = bh - 130;
}
else if (modelName.match(/\bNM\sVLAN\b/)) {
if (d.x < bw - 150)
d.x = bw - 150;
}
else if (modelName.match(/\bOAM\sVLAN\b/)) {
if (d.x > 150)
d.x = 150;
}
// END TODO
return "translate(" + d.x + "," + d.y + ")";
});
d3
.selectAll(".relation")
.attr("d", epath);
d3
.selectAll(".nodeport")
.attr("transform", function (d) {
circleclamp(d);
if (d.link) {
if (d.link.srcport == d)
n1 = d.link.source,
n2 = d.link.target;
else
n1 = d.link.target,
n2 = d.link.source;
var p1 = {
x: n1.x,
y: n1.y
},
p2 = {
x: n2.x,
y: n2.y
};
var dx = n2.x - n1.x,
dy = n2.y - n1.y;
d.a = Math.atan2(dx, dy);
circleclamp(d);
var p = nodeboundarypoint(p1, p2, d.parent.name);
d.x = p.x - d.parent.x;
d.y = p.y - d.parent.y;
} else {
if (d.parent.ports.length > 1) {
d
.parent
.ports
.forEach(function (x) {
if (d != x && Math.abs(x.a - d.a) < 0.8) {
d.a += x.a > d.a
? -.02
: .02;
}
});
}
var p1 = {
x: d.parent.x,
y: d.parent.y
},
p2 = {
x: d.parent.x + 100 * Math.sin(d.a),
y: d.parent.y + 100 * Math.cos(d.a)
};
var p = nodeboundarypoint(p1, p2, d.parent.name);
d.x = p.x - d.parent.x;
d.y = p.y - d.parent.y;
}
return "translate(" + d.x + "," + d.y + ")";
});
}
force.on("tick", tick);
// p1 inside, p2 outside
function nodeboundarypoint(p1, p2, nodename) {
if ((Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y)) < 0.2) {
return p1;
}
if (typeof document.elementsFromPoint === 'function') {
var mp = {
x: (p1.x + p2.x) / 2,
y: (p1.y + p2.y) / 2
};
var r = svg
.node()
.getBoundingClientRect();
var n = document
.elementsFromPoint(mp.x + r.left, mp.y + r.top)
.find(function (x) {
var d = d3
.select(x)
.datum();
return d3
.select(x)
.classed("nodebody") && d && d.name == nodename;
});
if (n)
p1 = mp;
else
p2 = mp;
return nodeboundarypoint(p1, p2, nodename);
}
// ... here when no function document.elementsFromPoint (FF <46) ... -- put on
// circle
var r = 30;
var dx = p2.x - p1.x,
dy = p2.y - p1.y;
if (!dx) {
if (r < Math.abs(dy)) {
p1.y += r * Math.sign(dy);
} else {
p1.y += dy;
}
return p1;
}
alpha = Math.atan2(dx, dy);
p1.x += r * Math.sin(alpha);
p1.y += r * Math.cos(alpha);
return p1;
}
var hitrect = svg
.node()
.createSVGRect();
hitrect.height = 1;
hitrect.width = 1;
// ffs, chrome's svg.getIntersectionList uses bbox for intersection
function nodeboundarypoint0(p1, p2, node) {
if ((Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y)) < 0.5)
return p1;
else {
var n,
mp = {
x: (p1.x + p2.x) / 2,
y: (p1.y + p2.y) / 2
};
hitrect.x = mp.x;
hitrect.y = mp.y;
var hits = svg
.node()
.getIntersectionList(hitrect, null);
if (hits) {
function itol(x) {
var v,
r = [],
i = 0;
while (v = x.item(i++))
r.push(v);
return r;
}
hits = itol(hits);
n = hits.find(function (x) {
var d = d3
.select(x)
.datum();
return d3
.select(x)
.classed("nodebody") && d && d.name == node;
});
}
if (n)
p1 = mp;
else
p2 = mp;
return nodeboundarypoint0(p1, p2, node);
}
}
function abs(n) {
return n < 0
? -n
: n;
}
function rand(n) {
n = n || 1.0;
return (Math.random() * n) - n / 2;
}
function elt(selection) {
return selection[0][0];
}
function nameof(x) {
return x
? x.name
: "...";
}
function dnode(name) {
return force
.nodes()
.find(function (n) {
return n.model.name === name;
});
}
function dlink(name) {
return force
.links()
.filter(function (l) {
return l.source.model.name === name || l.target.model.name === name;
});
}
function matchnodetype(n, tname) {
return ((n.type.name === tname) || (n.typeinfo && n.typeinfo.hierarchy && n.typeinfo.hierarchy.find(function (t) {
return t.name === tname;
})));
}
// "transactions" for composition operations
var logtxn = false;
var incompositiontxn = false;
function txn(name, fn) {
if (incompositiontxn) // already in transaction
return fn();
else {
try {
if (logtxn)
log("TXN.begin", name);
incompositiontxn = true;
return fn();
} finally {
incompositiontxn = false;
if (logtxn)
log("TXN.end", name);
onCompositionEvent("composition.done");
}
}
}
function addnode(model, x, y, ndata) {
return txn("addnode", function () {
return _addnode(model, x, y, ndata);
});
}
function _addnode(model, x, y, ndata) {
var hasdata = !!ndata;
curmodel = model;
if (!ndata) {
ndata = {
name: gensym("n"),
label: model.name,
x: x,
y: y,
px: x - 1,
py: y - 1,
ports: [],
radius: 30
};
if (matchnodetype(model, "tosca.nodes.network.Port"))
ndata.radius = 10;
if (model.name === "CPE")
ndata.radius = 80;
}
//log("node", model.name, ndata.x, ndata.y, ndata.fixed);
ndata.x = ndata.x || bw / 2 + rand(100);
ndata.y = ndata.y || bh / 2 + rand(100);
ndata.px = ndata.x - 1;
ndata.py = ndata.y - 1;
ndata.ports = ndata.ports || [];
ndata.label = model.name;
model = _.clone(model);
model.nid = ndata.name;
var node = _.extend({}, model, {ndata: ndata});
curcomp
.nodes
.push(deepclone(node));
if (!hasdata) {
/*xhrpost("/composition.addnode?cid="+cid, node,
function(resp) {
});
xhrpost("/composition.savecomp?cid="+cid, curcomp,
function(resp) {
});*/
onCompositionEvent("composition.add.node", model);
}
ndata.model = model;
force
.nodes()
.push(ndata);
var nodes = force.nodes();
var gnode = graph
.selectAll(".node")
.data(nodes, function (d) {
return d.name;
});
var n = gnode
.enter()
.append("g")
.attr("id", model.nid.replace(/\W/g, "_"))
// this must come first, because ?? .attr("class", "node draggable")
.classed("node", true)
.classed("draggable", true)
.attr("draggable", "true")
.classed(model.type.name.replace(/\W/g, "_"), true)
.attr("transform", function (d) {
if (!d.x || isNaN(d.x))
d.x = bw / 2 + rand(100);
if (!d.y || isNaN(d.y))
d.y = bh / 2 + rand(100);
return "translate(" + d.x + "," + d.y + ")";
})
.on("click", function (d) {
if (d3.event.metaKey || d3.event.ctrlKey)
removenode(d);
}
);
rendernode(n);
n.call(force.drag().on("dragstart", function (d) {
d3
.select(this)
.classed("fixed", d.fixed = true);
}));
function rti(n, name) {
return n
.typeinfo
.requirements
.find(function (tr) {
return tr.name === r.name;
})
}
if (!model.typeinfo)
model.typeinfo = {}; // dummy node special case
if (model.requirements) {
model.requirements = dedup(model.requirements);
model
.requirements
.forEach(function (x) {
if (x.name == "host") // CCD hack
return;
ndata
.ports
.push({
name: x.name,
parent: ndata,
ptype: "req",
id: uuid(),
portinfo: _.clone(x)
});
});
model
.requirements
.forEach(function (r) {
r.ti = model
.typeinfo
.requirements
.find(function (tr) {
return tr.name == r.name;
});
});
}
// this may become uneccessary(?) (serban: type info now merged with
// requirements/capabilities)
if (model.typeinfo.requirements) {
model.typeinfo.requirements = dedup(model.typeinfo.requirements);
model
.typeinfo
.requirements
.forEach(function (x) {
var port = ndata
.ports
.find(function (y) {
return y.name == x.name && y.ptype == "req";
});
if (port)
port.portinfo = _.extend(_.clone(x), port.portinfo); // this should never happen
else {
if (x.name == "host") // CCD hack
return;
log("UNEXPECTED TYPEINFO", x.name);
}
});
}
if (model.capabilities) {
model.capabilities = dedup(model.capabilities);
model
.capabilities
.forEach(function (x) {
ndata
.ports
.push({
name: x.name,
parent: ndata,
ptype: "cap",
id: uuid(),
portinfo: _.clone(x)
});
});
model
.capabilities
.forEach(function (c) {
c.ti = model
.typeinfo
.capabilities
.find(function (tc) {
return tc.name == c.name;
});
});
}
if (model.typeinfo.capabilities) {
model.typeinfo.capabilities = dedup(model.typeinfo.capabilities);
model
.typeinfo
.capabilities
.forEach(function (x) {
var port = ndata
.ports
.find(function (y) {
return y.name == x.name && y.ptype == "cap";
});
if (port)
port.portinfo = _.extend(_.clone(x), port.portinfo); // this should never happen
else {
log("UNEXPECTED TYPEINFO", x.name);
}
});
}
addports(n);
force.start();
return ndata;
}
// pin lans and wans in lexicographic order
function sortinterfaces() {
// var rx = [/^WAN/, /^LAN/]; for (var i in rx) { var x = 200;
// d3.selectAll(".node") .filter(function (d) { return
// d.label.match(rx[i]); }) .sort(function (a, b) { return
// a.label > b.label; }) .each(function (d) { d.x = d.px = x;
// x += 100; d.fixed = true; }); }
}
var _nd = [];
function updatenodes() {
var nd = force
.nodes()
.map(function (d) {
var f = {
nid: d.name,
x: d.x,
y: d.y,
px: d.px,
py: d.py,
radius: d.radius,
fixed: true
};
f.ndata = _.clone(f);
f.ndata.name = d.name;
return f;
});
// only consider x,y values in computing sameness
function same(a, b) {
return a.every(function (c) {
return b.some(function (d) {
return c.x == d.x && c.y == d.y;
});
});
}
if (!same(nd, _nd)) {
log("updatenodes...changed");
onCompositionEvent("after.loaded.composition");
} else {
log("updatenodes...stable");
}
_nd = nd;
}
force.on("end", updatenodes);
function pp(x) {
return JSON.stringify(x, null, 2);
}
function str(x) {
return JSON.stringify(x);
}
function dedup(a) {
var r = [];
a.forEach(function (x) {
if (!r.find(function (y) {
return x.name == y.name;
}))
r.push(x)
});
return r;
}
function addport(n, name, ptype, portinfo) {
n
.each(function (d) {
d
.ports
.push({
name: name || gensym(),
parent: d,
ptype: ptype,
portinfo: portinfo,
id: uuid()
});
});
addports(n);
}
var iconbase = "/images/ice/";
iconbase = "/img/";
var icons = {};
function ngon(node, n, offset) {
offset = offset || 0;
//var offset = n == 4 ? Math.PI/4 : 0;
var r = node
.datum()
.radius * (1 + 1 / n),
p = [];
for (var i = 0; i < n; i++) {
// offset is so squares are squared :/
var a = (i * Math.PI * 2) / n + offset;
p.push(r * Math.sin(a));
p.push(r * Math.cos(a));
}
return node
.append("svg:polygon")
.classed("nodebody", true)
.attr("points", p.join(","));
}
var compositionDraggingType;
function allowDropByType(event, type) {
if (compositionDraggingType === type) {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
return true;
}
return false;
}
/* DEAD CODE?
// handle dropping location data on a node
function dropLocation(event,that) {
compositionDraggingType = null;
var locText = event.dataTransfer.getData('location');
if (locText === '') {return;}
if (event.stopPropagation) {event.stopPropagation();}
var nodeData = d3.select(that).datum();
log("dropLocation",locText,nodeData);
var loc = shoppingCart.locations.findByKey(Location.genKey(JSON.parse(locText)));
log("dropLocation loc",loc);
closeNodePropertiesEditor();
setLocationOnSite(nodeData.model,loc);
d3.select(that).select("#confignode").html(function(d) {return getShortPropertyValues(d.model);});
}
*/
// var getShortPropertyValues = getShortPropertyValues || function(x) { return
// "{property values}" };
var getShortPropertyValues = getShortPropertyValues || function (x) {
return ""
};
var cpe;
function renderucpe() {
cpe = undergraph
.append("svg:rect")
.classed("ucpecontainer", true)
.attr("width", bw - 200)
.attr("height", bh - 100)
.attr("x", 100)
.attr("y", 50)
.attr("rx", 20)
.attr("ry", 20)
.attr("stroke", "black")
.attr("stroke-width", 5)
.attr("fill", "rgba(0,0,0,0.1)")
.style("opacity", 0.2);
}
function rendernode(n) {
var type = n
.datum()
.model
.type
.name;
var model = n
.datum()
.model;
// HACK
if (matchnodetype(n.datum().model, "tosca.nodes.network.Port")) {
ngon(n, 4);
return;
}
n
.append("svg:rect")
.classed("nodebody", true)
/*
.attr("width", 70)
.attr("height", 44)
.attr("x", -35)
.attr("y", -22)
*/
.attr("width", 90)
.attr("height", 64)
.attr("x", -45)
.attr("y", -32)
.attr("rx", 5)
.attr("ry", 5);
n.classed(type.replace(/\W/g, "_"), true);
n.classed(n.datum().model.name.replace(/\W/g, "_"), true);
var w = 150,
h = 50; // node width, height
// n.append("g") .attr("transform", "translate(" + (-(w / 2 - 15)) + "," +
// (-(h / 2 - 5)) + ")") .append("foreignObject") .attr({ width:
// 100, height: 50, fill: '#7413E8', 'class':
// 'svg-tooltip' }) .append('xhtml:div') .append('div')
// .html(function (d) { return squishnodename(d.label) }) .append("div")
// .attr({ width: 50, height: 50, fill: 'red', color:
// 'green' }) .style("pointer-events", "all") .style("cursor",
// "pointer") .html("config") .on("click", function (d) { if
// (d3.event.metaKey || d3.event.ctrlKey) { return; } if
// (typeof editNodeProperties === 'function') { editNodeProperties(this); }
// else { configeditor(d3.select(this), d.model); } });
n
.append("g")
.attr("transform", "translate(" + (-(w / 2 - 15)) + "," + (-(h / 2 - 5)) + ")")
.append("foreignObject")
.attr("width", (w - 10) + "px")
.attr("height", (h + 60) + "px")
.append("xhtml:div")
.classed("compositionbody", true)
//.classed(type.replace(/\./g,"_"), true)
.classed("nodetext", true)
.style("width", (w - 30) + "px")
.style("height", (h - 20) + "px")
.style("pointer-events", function () {
return (type == "asc.nodes.Site"
? null
: "none");
})
.attr("ondragover", function () {
return (type == "asc.nodes.Site"
? "allowDropByType(event,'location');"
: null);
})
.attr("ondrop", function () {
return (type == "asc.nodes.Site"
? "dropLocation(event,this);"
: null);
})
.html(function (d) {
var icon = icons[d.model.type.name];
if (!icon) {
if (d.model.typeinfo && d.model.typeinfo.hierarchy) {
var h = d.model.typeinfo.hierarchy;
for (i in h) {
var type = h[i].name;
if (icon = icons[type])
break;
}
}
}
if (icon)
icon = iconbase + icon;
else
icon = window.location.origin + iconbase + "3net.png";
icon = "dcae/comp-fe/img/death.png";
if (propertynameval(d.model.properties, "designer_name")) {
// return "" + "
" +
// "