Index: vue/src/assets/images/devops/DevSupport/github.png =================================================================== diff -u -r11f26ca6ddd6fd698fc3ccd8cda9117bacce7623 -re14af7fcea77025bbc4685a47c80c63750802c03 --- vue/src/assets/images/devops/DevSupport/github.png (.../github.png) (revision 11f26ca6ddd6fd698fc3ccd8cda9117bacce7623) +++ vue/src/assets/images/devops/DevSupport/github.png (.../github.png) (revision e14af7fcea77025bbc4685a47c80c63750802c03) @@ -895,7 +895,7 @@ stroke-width: 1.5px; } .node text { - font-size: 12px; + font-size: 13px; } .link { fill: none; Index: arms/js/pdServiceJira.js =================================================================== diff -u -r11f26ca6ddd6fd698fc3ccd8cda9117bacce7623 -re14af7fcea77025bbc4685a47c80c63750802c03 --- arms/js/pdServiceJira.js (.../pdServiceJira.js) (revision 11f26ca6ddd6fd698fc3ccd8cda9117bacce7623) +++ arms/js/pdServiceJira.js (.../pdServiceJira.js) (revision e14af7fcea77025bbc4685a47c80c63750802c03) @@ -12,9 +12,6 @@ setSideMenu("sidebar_menu_product", "sidebar_menu_product_jira_connect"); dataTableLoad(); - - // 차트 초기화 - rederD3Chart(); } // --- 데이터 테이블 설정 --- // @@ -296,106 +293,102 @@ } }); -//////////////////////////////////////////////////////////////////////////////////////// -// --- 연결 차트 표시 --- // -//////////////////////////////////////////////////////////////////////////////////////// -function rederD3Chart() { - /* ---------------------------------------- d3 config ------------------------------------ */ - /* d3 */ - var treeData = { - name: "1. 제품(서비스) 선택 → 2. Version 선택 → 3. 제품(서비스) ~ Jira 연결", - type: "a-RMS" - }; +/* ---------------------------------------- d3 config ------------------------------------ */ +/* d3 */ +var treeData = { + name: "1.제품(서비스) 선택 → 2.Version 선택 → 3.JIRA 프로젝트 선택", + type: "a-RMS" +}; +//treeJSON = d3.json(flare_data, function(error, treeData) { - // Calculate total nodes, max label length - var totalNodes = 0; - var maxLabelLength = 0; - // variables for drag/drop - var selectedNode = null; - var draggingNode = null; - // panning variables - var panSpeed = 200; - var panBoundary = 20; // Within 20px from edges will pan when dragging. - // Misc. variables - var i = 0; - var duration = 750; - var root; +// Calculate total nodes, max label length +var totalNodes = 0; +var maxLabelLength = 0; +// variables for drag/drop +var selectedNode = null; +var draggingNode = null; +// panning variables +var panSpeed = 200; +var panBoundary = 20; // Within 20px from edges will pan when dragging. +// Misc. variables +var i = 0; +var duration = 750; +var root; // size of the diagram var viewerWidth = $("#tree_container")[0].clientWidth; var viewerHeight = 295; - var tree = d3.layout.tree().size([viewerHeight, viewerWidth]); +var tree = d3.layout.tree().size([viewerHeight, viewerWidth]); - // define a d3 diagonal projection for use by the node paths later on. - var diagonal = d3.svg.diagonal().projection(function (d) { - return [d.y, d.x]; - }); +// define a d3 diagonal projection for use by the node paths later on. +var diagonal = d3.svg.diagonal().projection(function (d) { + return [d.y, d.x]; +}); - // A recursive helper function for performing some setup by walking through all nodes - function visit(parent, visitFn, childrenFn) { - if (!parent) return; +// A recursive helper function for performing some setup by walking through all nodes +function visit(parent, visitFn, childrenFn) { + if (!parent) return; - visitFn(parent); + visitFn(parent); - var children = childrenFn(parent); - if (children) { - var count = children.length; - for (var i = 0; i < count; i++) { - visit(children[i], visitFn, childrenFn); - } + var children = childrenFn(parent); + if (children) { + var count = children.length; + for (var i = 0; i < count; i++) { + visit(children[i], visitFn, childrenFn); } } +} - // Call visit function to establish maxLabelLength - visit( - treeData, - function (d) { - totalNodes++; - maxLabelLength = Math.max(d.name.length, maxLabelLength); - }, - function (d) { - return d.children && d.children.length > 0 ? d.children : null; - } - ); - - // sort the tree according to the node names - function sortTree() { - tree.sort(function (a, b) { - return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1; - }); +// Call visit function to establish maxLabelLength +visit( + treeData, + function (d) { + totalNodes++; + maxLabelLength = Math.max(d.name.length, maxLabelLength); + }, + function (d) { + return d.children && d.children.length > 0 ? d.children : null; } +); - // Sort the tree initially incase the JSON isn't in a sorted order. - sortTree(); +// sort the tree according to the node names +function sortTree() { + tree.sort(function (a, b) { + return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1; + }); +} +// Sort the tree initially incase the JSON isn't in a sorted order. +sortTree(); - // TODO: Pan function, can be better implemented. - function pan(domNode, direction) { - var speed = panSpeed; - if (panTimer) { - clearTimeout(panTimer); - translateCoords = d3.transform(svgGroup.attr("transform")); - if (direction == "left" || direction == "right") { - translateX = direction == "left" ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed; - translateY = translateCoords.translate[1]; - } else if (direction == "up" || direction == "down") { - translateX = translateCoords.translate[0]; - translateY = direction == "up" ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed; - } - scaleX = translateCoords.scale[0]; - scaleY = translateCoords.scale[1]; - scale = zoomListener.scale(); - svgGroup.transition().attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + scale + ")"); - d3.select(domNode) - .select("g.node") - .attr("transform", "translate(" + translateX + "," + translateY + ")"); - zoomListener.scale(zoomListener.scale()); - zoomListener.translate([translateX, translateY]); - panTimer = setTimeout(function () { - pan(domNode, speed, direction); - }, 50); +// TODO: Pan function, can be better implemented. +function pan(domNode, direction) { + var speed = panSpeed; + if (panTimer) { + clearTimeout(panTimer); + translateCoords = d3.transform(svgGroup.attr("transform")); + if (direction == "left" || direction == "right") { + translateX = direction == "left" ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed; + translateY = translateCoords.translate[1]; + } else if (direction == "up" || direction == "down") { + translateX = translateCoords.translate[0]; + translateY = direction == "up" ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed; } + scaleX = translateCoords.scale[0]; + scaleY = translateCoords.scale[1]; + scale = zoomListener.scale(); + svgGroup.transition().attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + scale + ")"); + d3.select(domNode) + .select("g.node") + .attr("transform", "translate(" + translateX + "," + translateY + ")"); + zoomListener.scale(zoomListener.scale()); + zoomListener.translate([translateX, translateY]); + panTimer = setTimeout(function () { + pan(domNode, speed, direction); + }, 50); } +} // Define the zoom function for the zoomable tree function zoom() { @@ -404,539 +397,472 @@ //svgGroup.attr("transform", "translate(" + "221,79" + ")scale(" + 1.5 + ")"); } - // define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents - var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom); +// define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents +var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom); - function initiateDrag(d, domNode) { - draggingNode = d; - d3.select(domNode).select(".ghostCircle").attr("pointer-events", "none"); - d3.selectAll(".ghostCircle").attr("class", "ghostCircle show"); - d3.select(domNode).attr("class", "node activeDrag"); +function initiateDrag(d, domNode) { + draggingNode = d; + d3.select(domNode).select(".ghostCircle").attr("pointer-events", "none"); + d3.selectAll(".ghostCircle").attr("class", "ghostCircle show"); + d3.select(domNode).attr("class", "node activeDrag"); - svgGroup.selectAll("g.node").sort(function (a, b) { - // select the parent and sort the path's - if (a.id != draggingNode.id) return 1; // a is not the hovered element, send "a" to the back - else return -1; // a is the hovered element, bring "a" to the front - }); - // if nodes has children, remove the links and nodes - if (nodes.length > 1) { - // remove link paths - links = tree.links(nodes); - nodePaths = svgGroup - .selectAll("path.link") - .data(links, function (d) { - return d.target.id; - }) - .remove(); - // remove child nodes - nodesExit = svgGroup - .selectAll("g.node") - .data(nodes, function (d) { - return d.id; - }) - .filter(function (d, i) { - if (d.id == draggingNode.id) { - return false; - } - return true; - }) - .remove(); - } - - // remove parent link - parentLink = tree.links(tree.nodes(draggingNode.parent)); - svgGroup + svgGroup.selectAll("g.node").sort(function (a, b) { + // select the parent and sort the path's + if (a.id != draggingNode.id) return 1; // a is not the hovered element, send "a" to the back + else return -1; // a is the hovered element, bring "a" to the front + }); + // if nodes has children, remove the links and nodes + if (nodes.length > 1) { + // remove link paths + links = tree.links(nodes); + nodePaths = svgGroup .selectAll("path.link") + .data(links, function (d) { + return d.target.id; + }) + .remove(); + // remove child nodes + nodesExit = svgGroup + .selectAll("g.node") + .data(nodes, function (d) { + return d.id; + }) .filter(function (d, i) { - if (d.target.id == draggingNode.id) { - return true; + if (d.id == draggingNode.id) { + return false; } - return false; + return true; }) .remove(); - - dragStarted = null; } - // define the baseSvg, attaching a class for styling and the zoomListener - var baseSvg = d3 - .select("#tree_container") - .append("svg") - .attr("width", viewerWidth) - .attr("height", viewerHeight) - .attr("class", "overlay") - .call(zoomListener); - - // Define the drag listeners for drag/drop behaviour of nodes. - dragListener = d3.behavior - .drag() - .on("dragstart", function (d) { - if (d == root) { - return; + // remove parent link + parentLink = tree.links(tree.nodes(draggingNode.parent)); + svgGroup + .selectAll("path.link") + .filter(function (d, i) { + if (d.target.id == draggingNode.id) { + return true; } - dragStarted = true; - nodes = tree.nodes(d); - d3.event.sourceEvent.stopPropagation(); - // it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none'); + return false; }) - .on("drag", function (d) { - if (d == root) { - return; - } - if (dragStarted) { - domNode = this; - initiateDrag(d, domNode); - } + .remove(); - // get coords of mouseEvent relative to svg container to allow for panning - relCoords = d3.mouse($("svg").get(0)); - if (relCoords[0] < panBoundary) { - panTimer = true; - pan(this, "left"); - } else if (relCoords[0] > $("svg").width() - panBoundary) { - panTimer = true; - pan(this, "right"); - } else if (relCoords[1] < panBoundary) { - panTimer = true; - pan(this, "up"); - } else if (relCoords[1] > $("svg").height() - panBoundary) { - panTimer = true; - pan(this, "down"); - } else { - try { - clearTimeout(panTimer); - } catch (e) {} - } + dragStarted = null; +} - d.x0 += d3.event.dy; - d.y0 += d3.event.dx; - var node = d3.select(this); - node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")"); - updateTempConnector(); - }) - .on("dragend", function (d) { - if (d == root) { - return; - } +// define the baseSvg, attaching a class for styling and the zoomListener +var baseSvg = d3 + .select("#tree_container") + .append("svg") + .attr("width", viewerWidth) + .attr("height", viewerHeight) + .attr("class", "overlay") + .call(zoomListener); + +// Define the drag listeners for drag/drop behaviour of nodes. +dragListener = d3.behavior + .drag() + .on("dragstart", function (d) { + if (d == root) { + return; + } + dragStarted = true; + nodes = tree.nodes(d); + d3.event.sourceEvent.stopPropagation(); + // it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none'); + }) + .on("drag", function (d) { + if (d == root) { + return; + } + if (dragStarted) { domNode = this; - if (selectedNode) { - // now remove the element from the parent, and insert it into the new elements children - var index = draggingNode.parent.children.indexOf(draggingNode); - if (index > -1) { - draggingNode.parent.children.splice(index, 1); - } - if (typeof selectedNode.children !== "undefined" || typeof selectedNode._children !== "undefined") { - if (typeof selectedNode.children !== "undefined") { - selectedNode.children.push(draggingNode); - } else { - selectedNode._children.push(draggingNode); - } - } else { - selectedNode.children = []; + initiateDrag(d, domNode); + } + + // get coords of mouseEvent relative to svg container to allow for panning + relCoords = d3.mouse($("svg").get(0)); + if (relCoords[0] < panBoundary) { + panTimer = true; + pan(this, "left"); + } else if (relCoords[0] > $("svg").width() - panBoundary) { + panTimer = true; + pan(this, "right"); + } else if (relCoords[1] < panBoundary) { + panTimer = true; + pan(this, "up"); + } else if (relCoords[1] > $("svg").height() - panBoundary) { + panTimer = true; + pan(this, "down"); + } else { + try { + clearTimeout(panTimer); + } catch (e) {} + } + + d.x0 += d3.event.dy; + d.y0 += d3.event.dx; + var node = d3.select(this); + node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")"); + updateTempConnector(); + }) + .on("dragend", function (d) { + if (d == root) { + return; + } + domNode = this; + if (selectedNode) { + // now remove the element from the parent, and insert it into the new elements children + var index = draggingNode.parent.children.indexOf(draggingNode); + if (index > -1) { + draggingNode.parent.children.splice(index, 1); + } + if (typeof selectedNode.children !== "undefined" || typeof selectedNode._children !== "undefined") { + if (typeof selectedNode.children !== "undefined") { selectedNode.children.push(draggingNode); + } else { + selectedNode._children.push(draggingNode); } - // Make sure that the node being added to is expanded so user can see added node is correctly moved - expand(selectedNode); - sortTree(); - endDrag(); } else { - endDrag(); + selectedNode.children = []; + selectedNode.children.push(draggingNode); } - }); - - function endDrag() { - selectedNode = null; - d3.selectAll(".ghostCircle").attr("class", "ghostCircle"); - d3.select(domNode).attr("class", "node"); - // now restore the mouseover event or we won't be able to drag a 2nd time - d3.select(domNode).select(".ghostCircle").attr("pointer-events", ""); - updateTempConnector(); - if (draggingNode !== null) { - update(root); - centerNode(draggingNode); - draggingNode = null; + // Make sure that the node being added to is expanded so user can see added node is correctly moved + expand(selectedNode); + sortTree(); + endDrag(); + } else { + endDrag(); } + }); + +function endDrag() { + selectedNode = null; + d3.selectAll(".ghostCircle").attr("class", "ghostCircle"); + d3.select(domNode).attr("class", "node"); + // now restore the mouseover event or we won't be able to drag a 2nd time + d3.select(domNode).select(".ghostCircle").attr("pointer-events", ""); + updateTempConnector(); + if (draggingNode !== null) { + update(root); + centerNode(draggingNode); + draggingNode = null; } +} - // Helper functions for collapsing and expanding nodes. - function collapse(d) { - if (d.children) { - d._children = d.children; - d._children.forEach(collapse); - d.children = null; - } +// Helper functions for collapsing and expanding nodes. +function collapse(d) { + if (d.children) { + d._children = d.children; + d._children.forEach(collapse); + d.children = null; } +} - function expand(d) { - if (d._children) { - d.children = d._children; - d.children.forEach(expand); - d._children = null; - } +function expand(d) { + if (d._children) { + d.children = d._children; + d.children.forEach(expand); + d._children = null; } +} - var overCircle = function (d) { - selectedNode = d; - updateTempConnector(); - }; - var outCircle = function (d) { - selectedNode = null; - updateTempConnector(); - }; +var overCircle = function (d) { + selectedNode = d; + updateTempConnector(); +}; +var outCircle = function (d) { + selectedNode = null; + updateTempConnector(); +}; - // Function to update the temporary connector indicating dragging affiliation - var updateTempConnector = function () { - var data = []; - if (draggingNode !== null && selectedNode !== null) { - // have to flip the source coordinates since we did this for the existing connectors on the original tree - data = [ - { - source: { - x: selectedNode.y0, - y: selectedNode.x0 - }, - target: { - x: draggingNode.y0, - y: draggingNode.x0 - } +// Function to update the temporary connector indicating dragging affiliation +var updateTempConnector = function () { + var data = []; + if (draggingNode !== null && selectedNode !== null) { + // have to flip the source coordinates since we did this for the existing connectors on the original tree + data = [ + { + source: { + x: selectedNode.y0, + y: selectedNode.x0 + }, + target: { + x: draggingNode.y0, + y: draggingNode.x0 } - ]; - } - var link = svgGroup.selectAll(".templink").data(data); + } + ]; + } + var link = svgGroup.selectAll(".templink").data(data); - link.enter().append("path").attr("class", "templink").attr("d", d3.svg.diagonal()).attr("pointer-events", "none"); + link.enter().append("path").attr("class", "templink").attr("d", d3.svg.diagonal()).attr("pointer-events", "none"); - link.attr("d", d3.svg.diagonal()); + link.attr("d", d3.svg.diagonal()); - link.exit().remove(); - }; + link.exit().remove(); +}; - // Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children. - function centerNode(source) { - var nodes = tree.nodes(root); - console.log(nodes); +// Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children. +function centerNode(source) { + var nodes = tree.nodes(root); + console.log(nodes); - scale = zoomListener.scale(); - scale = 1.0; - x = source.y0; - y = -source.x0; + scale = zoomListener.scale(); + scale = 1.0; + x = source.y0; + y = -source.x0; - console.log("x => " + x); + console.log("x => " + x); - translateCoords = d3.transform(svgGroup.attr("transform")); - var speed = panSpeed; - translateCoords = d3.transform(svgGroup.attr("transform")); - translateX = translateCoords.translate[0] + speed; - console.log("translateX = " + translateX); + translateCoords = d3.transform(svgGroup.attr("transform")); + var speed = panSpeed; + translateCoords = d3.transform(svgGroup.attr("transform")); + translateX = translateCoords.translate[0] + speed; + console.log("translateX = " + translateX); - x = x * scale + viewerWidth / 2 - translateX; + x = x * scale + viewerWidth / 2 - translateX; - console.log("x => " + x); - y = y * scale + viewerHeight / 2; + console.log("x => " + x); + y = y * scale + viewerHeight / 2; - d3.select("g") - .transition() - .duration(duration) - .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); - zoomListener.scale(scale); - zoomListener.translate([x, y]); - } + d3.select("g") + .transition() + .duration(duration) + .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); + zoomListener.scale(scale); + zoomListener.translate([x, y]); +} - // Toggle children function - function toggleChildren(d) { - if (d.children) { - d._children = d.children; - d.children = null; - } else if (d._children) { - d.children = d._children; - d._children = null; - } - return d; +// Toggle children function +function toggleChildren(d) { + if (d.children) { + d._children = d.children; + d.children = null; + } else if (d._children) { + d.children = d._children; + d._children = null; } + return d; +} - // Toggle children on click. - function click(d) { - console.log("clickEvent", d); - if (d3.event.defaultPrevented) return; // click suppressed - d = toggleChildren(d); - update(d); - centerNode(d); - } +// Toggle children on click. +function click(d) { + console.log("clickEvent", d); + if (d3.event.defaultPrevented) return; // click suppressed + d = toggleChildren(d); + update(d); + centerNode(d); +} - function update(source) { - // Compute the new height, function counts total children of root node and sets tree height accordingly. - // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed - // This makes the layout more consistent. - var levelWidth = [1]; - var childCount = function (level, n) { - if (n.children && n.children.length > 0) { - if (levelWidth.length <= level + 1) levelWidth.push(0); +function update(source) { + // Compute the new height, function counts total children of root node and sets tree height accordingly. + // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed + // This makes the layout more consistent. + var levelWidth = [1]; + var childCount = function (level, n) { + if (n.children && n.children.length > 0) { + if (levelWidth.length <= level + 1) levelWidth.push(0); - levelWidth[level + 1] += n.children.length; - n.children.forEach(function (d) { - childCount(level + 1, d); - }); - } - }; - childCount(0, root); - var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line - tree = tree.size([newHeight, viewerWidth]); - - // Compute the new tree layout. - var nodes = tree.nodes(root).reverse(), - links = tree.links(nodes); - - // Set widths between levels based on maxLabelLength. - nodes.forEach(function (d) { - d.y = d.depth * (maxLabelLength * 10); //maxLabelLength * 10px - // alternatively to keep a fixed scale one can set a fixed depth per level - // Normalize for fixed-depth by commenting out below line - // d.y = (d.depth * 500); //500px per level. - }); - - // Update the nodes… - node = svgGroup.selectAll("g.node").data(nodes, function (d) { - return d.id || (d.id = ++i); - }); - - // Enter any new nodes at the parent's previous position. - var nodeEnter = node - .enter() - .append("g") - .call(dragListener) - .attr("class", "node") - .attr("transform", function (d) { - return "translate(" + source.y0 + "," + source.x0 + ")"; - }) - .on("click", click); - - nodeEnter - .append("circle") - .attr("class", "nodeCircle") - .attr("r", 0) - .style("fill", function (d) { - return d._children ? "lightsteelblue" : "#fff"; + levelWidth[level + 1] += n.children.length; + n.children.forEach(function (d) { + childCount(level + 1, d); }); + } + }; + childCount(0, root); + var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line + tree = tree.size([newHeight, viewerWidth]); - nodeEnter - .append("text") - .attr("x", function (d) { - return d.children || d._children ? -10 : 10; - }) - .attr("dy", ".35em") - .attr("class", "nodeText") - .attr("text-anchor", function (d) { - return d.children || d._children ? "end" : "start"; - }) - .text(function (d) { - return d.name; - }) - .style("fill-opacity", 0); + // Compute the new tree layout. + var nodes = tree.nodes(root).reverse(), + links = tree.links(nodes); - nodeEnter - .append("text") - .attr("x", function (d) { - return -15; - }) - .attr("y", function (d) { - return 15; - }) - .text(function (d) { - return d.type; - }) - .on("click", function (d) { - window.location = d.url; - }) - .style("font-size", "11px"); + // Set widths between levels based on maxLabelLength. + nodes.forEach(function (d) { + d.y = d.depth * (maxLabelLength * 10); //maxLabelLength * 10px + // alternatively to keep a fixed scale one can set a fixed depth per level + // Normalize for fixed-depth by commenting out below line + // d.y = (d.depth * 500); //500px per level. + }); - // phantom node to give us mouseover in a radius around it - nodeEnter - .append("circle") - .attr("class", "ghostCircle") - .attr("r", 30) - .attr("opacity", 0.2) // change this to zero to hide the target area - .style("fill", "red") - .attr("pointer-events", "mouseover") - .on("mouseover", function (node) { - overCircle(node); - }) - .on("mouseout", function (node) { - outCircle(node); - }); + // Update the nodes… + node = svgGroup.selectAll("g.node").data(nodes, function (d) { + return d.id || (d.id = ++i); + }); - // Update the text to reflect whether node has children or not. - node - .select("text") - .attr("x", function (d) { - return d.children || d._children ? -10 : 10; - }) - .attr("text-anchor", function (d) { - return d.children || d._children ? "end" : "start"; - }) - .text(function (d) { - return d.name; - }); + // Enter any new nodes at the parent's previous position. + var nodeEnter = node + .enter() + .append("g") + .call(dragListener) + .attr("class", "node") + .attr("transform", function (d) { + return "translate(" + source.y0 + "," + source.x0 + ")"; + }) + .on("click", click); - // Change the circle fill depending on whether it has children and is collapsed - node - .select("circle.nodeCircle") - .attr("r", 4.5) - .style("fill", function (d) { - return d._children ? "lightsteelblue" : "#fff"; - }); + nodeEnter + .append("circle") + .attr("class", "nodeCircle") + .attr("r", 0) + .style("fill", function (d) { + return d._children ? "lightsteelblue" : "#fff"; + }); - // Transition nodes to their new position. - var nodeUpdate = node - .transition() - .duration(duration) - .attr("transform", function (d) { - return "translate(" + d.y + "," + d.x + ")"; - }); + nodeEnter + .append("text") + .attr("x", function (d) { + return d.children || d._children ? -10 : 10; + }) + .attr("dy", ".35em") + .attr("class", "nodeText") + .attr("text-anchor", function (d) { + return d.children || d._children ? "end" : "start"; + }) + .text(function (d) { + return d.name; + }) + .style("fill-opacity", 0); - // Fade the text in - nodeUpdate.select("text").style("fill-opacity", 1); + nodeEnter + .append("text") + .attr("x", function (d) { + return -15; + }) + .attr("y", function (d) { + return 15; + }) + .text(function (d) { + return d.type; + }) + .on("click", function (d) { + window.location = d.url; + }) + .style("font-size", "11px"); - // Transition exiting nodes to the parent's new position. - var nodeExit = node - .exit() - .transition() - .duration(duration) - .attr("transform", function (d) { - return "translate(" + source.y + "," + source.x + ")"; - }) - .remove(); + // phantom node to give us mouseover in a radius around it + nodeEnter + .append("circle") + .attr("class", "ghostCircle") + .attr("r", 30) + .attr("opacity", 0.2) // change this to zero to hide the target area + .style("fill", "red") + .attr("pointer-events", "mouseover") + .on("mouseover", function (node) { + overCircle(node); + }) + .on("mouseout", function (node) { + outCircle(node); + }); - nodeExit.select("circle").attr("r", 0); + // Update the text to reflect whether node has children or not. + node + .select("text") + .attr("x", function (d) { + return d.children || d._children ? -10 : 10; + }) + .attr("text-anchor", function (d) { + return d.children || d._children ? "end" : "start"; + }) + .text(function (d) { + return d.name; + }); - nodeExit.select("text").style("fill-opacity", 0); - - // Update the links… - var link = svgGroup.selectAll("path.link").data(links, function (d) { - return d.target.id; + // Change the circle fill depending on whether it has children and is collapsed + node + .select("circle.nodeCircle") + .attr("r", 4.5) + .style("fill", function (d) { + return d._children ? "lightsteelblue" : "#fff"; }); - // Enter any new links at the parent's previous position. - link - .enter() - .insert("path", "g") - .attr("class", "link") - .attr("d", function (d) { - var o = { - x: source.x0, - y: source.y0 - }; - return diagonal({ - source: o, - target: o - }); - }); - - // Transition links to their new position. - link.transition().duration(duration).attr("d", diagonal); - - // Transition exiting nodes to the parent's new position. - link - .exit() - .transition() - .duration(duration) - .attr("d", function (d) { - var o = { - x: source.x, - y: source.y - }; - return diagonal({ - source: o, - target: o - }); - }) - .remove(); - - // Stash the old positions for transition. - nodes.forEach(function (d) { - d.x0 = d.x; - d.y0 = d.y; + // Transition nodes to their new position. + var nodeUpdate = node + .transition() + .duration(duration) + .attr("transform", function (d) { + return "translate(" + d.y + "," + d.x + ")"; }); - } - // Append a group which holds all nodes and which the zoom Listener can act upon. - var svgGroup = baseSvg.append("g"); + // Fade the text in + nodeUpdate.select("text").style("fill-opacity", 1); - // Define the root - root = treeData; - root.x0 = viewerWidth / 2; - root.y0 = viewerHeight / 2; + // Transition exiting nodes to the parent's new position. + var nodeExit = node + .exit() + .transition() + .duration(duration) + .attr("transform", function (d) { + return "translate(" + source.y + "," + source.x + ")"; + }) + .remove(); - // Layout the tree initially and center on the root node. - update(root); - centerNode(root); + nodeExit.select("circle").attr("r", 0); - function updateD3ByDataTable() { - treeData.children = []; + nodeExit.select("text").style("fill-opacity", 0); - treeData.name = selectName; - treeData.type = "product(service)"; + // Update the links… + var link = svgGroup.selectAll("path.link").data(links, function (d) { + return d.target.id; + }); - update(treeData); - } - - function updateD3ByVersionList() { - console.log("versionList - " + versionList); - - treeData.children = []; - for (var k in versionList) { - var obj = versionList[k]; - var item = {}; - item["name"] = obj.c_title; - item["type"] = "version"; - item.children = []; - treeData.children.push(item); - } - update(treeData); - } - - function updateD3ByMultiSelect() { - treeData.children = []; - var item = {}; - item["name"] = selectVersionName; - item["type"] = "version"; - item.children = []; - treeData.children.push(item); - - var test = $("#multiselect :selected").val(); - console.log("test-----" + test); - if ($("#multiselect :selected").val() == undefined) { - console.log("test-----"); - item.children = []; - } - $("#multiselect :selected").each(function (i, sel) { - var temp = {}; - temp["name"] = $(sel).text(); - temp["type"] = "jira"; - item.children.push(temp); + // Enter any new links at the parent's previous position. + link + .enter() + .insert("path", "g") + .attr("class", "link") + .attr("d", function (d) { + var o = { + x: source.x0, + y: source.y0 + }; + return diagonal({ + source: o, + target: o + }); }); - update(treeData); - } + // Transition links to their new position. + link.transition().duration(duration).attr("d", diagonal); - function d3Update() { - if (typeof treeData.children == "undefined" || treeData.children == "" || treeData.children == null) { - console.log("it is not inner element"); - treeData.children = []; - } else { - treeData.children.splice(0, treeData.children.length); - } + // Transition exiting nodes to the parent's new position. + link + .exit() + .transition() + .duration(duration) + .attr("d", function (d) { + var o = { + x: source.x, + y: source.y + }; + return diagonal({ + source: o, + target: o + }); + }) + .remove(); - $("#sampleMultiTest :selected").each(function () { - item = {}; - item["name"] = this.text; - item["type"] = "Jira JQL"; - treeData.children.push(item); - }); - update(root); - } + // Stash the old positions for transition. + nodes.forEach(function (d) { + d.x0 = d.x; + d.y0 = d.y; + }); } +// Append a group which holds all nodes and which the zoom Listener can act upon. +var svgGroup = baseSvg.append("g"); +// Define the root +root = treeData; +root.x0 = viewerHeight / 2; +root.y0 = 0; + +// Layout the tree initially and center on the root node. +update(root); +centerNode(root); + /* --------------------------- multi select & slim scroll ---------------------------------- */ $(function () { // JIRA 프로젝트 데이터 로드 후 멀티 셀렉트 빌드 하고 슬림스크롤 적용