/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ define(['require', ''], function(require) { 'use strict'; var LinegaeUtils = {}; LinegaeUtils.DragNode = function(options) { var that = this, g = options.g, svg = options.svg, guid = options.guid, edgePathEl = options.edgeEl; return { init: function() { var that = this; //give IDs to each of the nodes so that they can be accessed svg.selectAll("g.node rect") .attr("id", function(d) { return "node" + d; }); svg.selectAll("g.edgePath path") .attr("id", function(e) { return e.v + "-" + e.w; }); svg.selectAll("g.edgeLabel g") .attr("id", function(e) { return 'label_' + e.v + "-" + e.w; }); g.nodes().forEach(function(v) { var node = g.node(v); node.customId = "node" + v; }) g.edges().forEach(function(e) { var edge = g.edge(e.v, e.w); edge.customId = e.v + "-" + e.w }); var nodeDrag = d3.behavior.drag() .on("dragstart", this.dragstart) .on("drag", function(d) { that.dragmove(this, d) }); var edgeDrag = d3.behavior.drag() .on("dragstart", this.dragstart) .on('drag', function(d) { that.translateEdge(g.edge(d.v, d.w), d3.event.dx, d3.event.dy); $('#' + g.edge(d.v, d.w).customId).attr('d', that.calcPoints(d)); }); nodeDrag.call(svg.selectAll("g.node")); edgeDrag.call(svg.selectAll("g.edgePath")); }, dragstart: function(d) { d3.event.sourceEvent.stopPropagation(); }, dragmove: function(elem, d) { var that = this, node = d3.select(elem), selectedNode = g.node(d), prevX = selectedNode.x, prevY = selectedNode.y; selectedNode.x += d3.event.dx; selectedNode.y += d3.event.dy; node.attr('transform', 'translate(' + selectedNode.x + ',' + selectedNode.y + ')'); var dx = selectedNode.x - prevX, dy = selectedNode.y - prevY; g.edges().forEach(function(e) { if (e.v == d || e.w == d) { var edge = g.edge(e.v, e.w); that.translateEdge(g.edge(e.v, e.w), dx, dy); $('#' + edge.customId).attr('d', that.calcPoints(e)); var label = $('#label_' + edge.customId); var xforms = label.attr('transform'); if (xforms != "") { var parts = /translate\(\s*([^\s,)]+)[ ,]?([^\s,)]+)?/.exec(xforms), X = parseInt(parts[1]) + dx, Y = parseInt(parts[2]) + dy; if (isNaN(Y)) { Y = dy; } label.attr('transform', 'translate(' + X + ',' + Y + ')'); } } }); LinegaeUtils.refreshGraphForIE({ "edgeEl": edgePathEl }) }, translateEdge: function(e, dx, dy) { e.points.forEach(function(p) { p.x = p.x + dx; p.y = p.y + dy; }); }, calcPoints: function(e) { var edge = g.edge(e.v, e.w), tail = g.node(e.v), head = g.node(e.w), points = edge.points.slice(1, edge.points.length - 1), afterslice = edge.points.slice(1, edge.points.length - 1); points.unshift(this.intersectRect(tail, points[0])); points.push(this.intersectRect(head, points[points.length - 1])); return d3.svg.line() .x(function(d) { return d.x; }) .y(function(d) { return d.y; }) .interpolate("basis") (points); }, intersectRect: function(node, point) { var that = this, x = node.x, y = node.y, dx = point.x - x, dy = point.y - y, w = node.id == guid ? 24 : 21, h = node.id == guid ? 24 : 21, sx = 0, sy = 0; if (Math.abs(dy) * w > Math.abs(dx) * h) { // Intersection is top or bottom of rect. if (dy < 0) { h = -h; } sx = dy === 0 ? 0 : h * dx / dy; sy = h; } else { // Intersection is left or right of rect. if (dx < 0) { w = -w; } sx = w; sy = dx === 0 ? 0 : w * dy / dx; } return { x: x + sx, y: y + sy }; }, } } LinegaeUtils.refreshGraphForSafari = function(options) { var edgePathEl = options.edgeEl, IEGraphRenderDone = 0; edgePathEl.each(function(argument) { var eleRef = this, childNode = $(this).find('pattern'); setTimeout(function(argument) { $(eleRef).find('defs').append(childNode); }, 500); }); } LinegaeUtils.refreshGraphForIE = function(options) { var edgePathEl = options.edgeEl, IEGraphRenderDone = 0; edgePathEl.each(function(argument) { var childNode = $(this).find('marker'); $(this).find('marker').remove(); var eleRef = this; ++IEGraphRenderDone; setTimeout(function(argument) { $(eleRef).find('defs').append(childNode); --IEGraphRenderDone; if (IEGraphRenderDone === 0) { this.$('.fontLoader').hide(); this.$('svg').fadeTo(1000, 1) } }, 1000); }); } LinegaeUtils.centerNode = function(options) { var nodeID = options.guid, svg = options.svg, g = options.g, afterCenterZoomed = options.afterCenterZoomed, zoom = d3.behavior.zoom(), svgGroup = svg.find("g"), edgePathEl = options.edgeEl, zoomBind = function() { svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); }, selectedNode = $(svg).find("g.nodes").find('>g#' + nodeID); return { init: function() { if (selectedNode.length > 0) { selectedNode = selectedNode; var matrix = selectedNode.attr('transform').replace(/[^0-9\-.,]/g, '').split(','); if (platform.name === "IE" || platform.name === "Microsoft Edge") { var matrix = selectedNode.attr('transform').replace(/[a-z\()]/g, '').split(' '); } var x = matrix[0], y = matrix[1]; } else { selectedNode = $(svg).find("g.nodes").find('g').eq(1); var x = g.graph().width / 2, y = g.graph().height / 2; } var viewerWidth = $(svg).width(), viewerHeight = $(svg).height(), gBBox = d3.select('g').node().getBBox(), zoomListener = zoom.scaleExtent([0.01, 50]).on("zoom", zoomBind), scale = 1.2, xa = -((x * scale) - (viewerWidth / 2)), ya = -((y * scale) - (viewerHeight / 2)); zoom.translate([xa, ya]); d3.select('g').transition() .duration(350) .attr("transform", "translate(" + xa + "," + ya + ")scale(" + scale + ")"); zoomListener.scale(scale); zoomListener.translate([xa, ya]); zoom.scale(scale); afterCenterZoomed({ newScale: scale, newTranslate: [xa, ya] }); LinegaeUtils.refreshGraphForIE({ "edgeEl": edgePathEl }) } } } LinegaeUtils.onHoverFade = function(options) { var opacity = options.opacity, d = options.selectedNode, nodesToHighlight = options.highlight, svg = options.svg, isConnected = function(a, b, o) { if (a === o || (b && b.length && b.indexOf(o) != -1)) { return true; } }, node = svg.selectAll('.node'), path = svg.selectAll('.edgePath'); return { init: function() { node.classed("hover-active", function(selectedNode, i, nodes) { if (isConnected(d, nodesToHighlight, selectedNode)) { return true; } else { return false; } }); path.classed('hover-active-node', function(c) { var _thisOpacity = c.v === d || c.w === d ? 1 : 0; if (_thisOpacity) { return true; } else { return false; } }); } } } LinegaeUtils.base64Encode = function(options) { var str = options.data, CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", out = "", i = 0, len = str.length, c1, c2, c3; while (i < len) { c1 = str.charCodeAt(i++) & 0xff; if (i == len) { out += CHARS.charAt(c1 >> 2); out += CHARS.charAt((c1 & 0x3) << 4); out += "=="; break; } c2 = str.charCodeAt(i++); if (i == len) { out += CHARS.charAt(c1 >> 2); out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); out += CHARS.charAt((c2 & 0xF) << 2); out += "="; break; } c3 = str.charCodeAt(i++); out += CHARS.charAt(c1 >> 2); out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)); out += CHARS.charAt(c3 & 0x3F); } return out; } return LinegaeUtils; });