Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
containerlab / etc / containerlab / templates / graph / exp / graph.html
Size: Mime:
<!DOCTYPE html>
<!--
 Copyright 2020 Nokia
 Licensed under the BSD 3-Clause License.
 SPDX-License-Identifier: BSD-3-Clause
-->

<html>

<head>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
    integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <title>ContainerLab Topology '{{ .Name }}'</title>
  <style>
    html,
    body {
      width: 100%;
      height: 100%;
    }

    #graph {
      width: 80%;
      height: 100%;
    }

    #content {
      width: 80%;
      height: 50%;
    }
  </style>
</head>

<body>
  <div id="content" class="container-fluid" style="margin:0 auto;">
    <h1 class="display-4">ContainerLab Topology '{{ .Name }}'</h1>
    <div>
      <button id='saveButton' type="button" class="btn btn-primary">Export as PNG</button>
    </div>

    <div id="graph"></div>

    <script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script>
    <script
      src="https://cdn.rawgit.com/eligrey/canvas-toBlob.js/f1a01896135ab378aa5c0118eadd81da55e698d8/canvas-toBlob.js"></script>
    <script
      src="https://cdn.rawgit.com/eligrey/FileSaver.js/e9d941381475b5df8b7d7691013401e171014e89/FileSaver.min.js"></script>
    <script>

      var width, height
      var chartWidth, chartHeight
      var margin
      var svg = d3.select("#graph").append("svg")
      var chartLayer = svg.append("g").classed("chartLayer", true)

      var r = 20;
      var color = d3.scaleOrdinal(d3.schemeCategory20);
      var data = `{{ .Data }}`
      data = JSON.parse(data)
      console.log(data)

      main()

      function main() {
        setSize(data)
        draw()
        tabulate(data.nodes, ["name", "image", "kind", "group", "state", "ipv4_address", "ipv6_address"]);
        // Set-up the export button
        d3.select('#saveButton').on('click', function () {
          var svgString = getSVGString(svg.node());
          svgString2Image(svgString, 2 * width, 2 * height, 'png', save); // passes Blob and filesize String to the callback

          function save(dataBlob, filesize) {
            saveAs(dataBlob, '{{ .Name }}.png'); // FileSaver.js function
          }
        });
      }

      function setSize() {
        width = document.querySelector("#graph").clientWidth
        height = document.querySelector("#graph").clientHeight

        margin = { top: 0, left: 0, bottom: 0, right: 0 }


        chartWidth = width - (margin.left + margin.right)
        chartHeight = height - (margin.top + margin.bottom)

        svg.attr("width", width).attr("height", height)
        console.log(width, height)

        chartLayer
          .attr("width", chartWidth)
          .attr("height", chartHeight)
          .attr("transform", "translate(" + [margin.left, margin.top] + ")")
      }

      function draw() {
        var simulation = d3.forceSimulation()
          .force("link", d3.forceLink().id(function (d) { return d.name }))
          .force("collide", d3.forceCollide(2 * r))
          .force("charge", d3.forceManyBody().strength(-500))
          .force("x", d3.forceX(chartWidth / 2))
          .force("y", d3.forceY(chartHeight / 2))

        var link = svg.append("g")
          .attr("class", "links")
          .selectAll("line")
          .data(data.links)
          .enter()
          .append("line")
          .attr("stroke", "black")

        var node = svg.append("g")
          .attr("class", "nodes")
          .selectAll("circle")
          .data(data.nodes)
          .enter().append("circle")
          .attr("r", r)
          .style("fill", function (d) { return color(d.group); })
          .call(d3.drag()
            .on("start", dragstarted)
            .on("drag", dragged)
            .on("end", dragended));

        var labels = svg.selectAll("text")
          .data(data.nodes)
          .enter()
          .append("text")
          .text(function (d) { return d.name; })
          .style("font", "20px Georgia")
          .call(d3.drag()
            .on("start", dragstarted)
            .on("drag", dragged)
            .on("end", dragended));


        var ticked = function () {
          link
            .attr("x1", function (d) { return d.source.x; })
            .attr("y1", function (d) { return d.source.y; })
            .attr("x2", function (d) { return d.target.x; })
            .attr("y2", function (d) { return d.target.y; });

          node
            .attr("cx", function (d) { return d.x; })
            .attr("cy", function (d) { return d.y; });

          labels
            .attr("x", function (d) { return d.x - r; })
            .attr("y", function (d) { return d.y + 2 * r; });


        }
        function dragstarted(d) {
          if (!d3.event.active) simulation.alphaTarget(0.3).restart();
          d.fx = d.x;
          d.fy = d.y;
        }

        function dragged(d) {
          d.fx = d3.event.x;
          d.fy = d3.event.y;

        }

        function dragended(d) {
          if (!d3.event.active) simulation.alphaTarget(0);
          d.fx = Math.ceil((d.fx) / 10) * 10;
          d.fy = Math.ceil((d.fy) / 10) * 10;
        }
        simulation
          .nodes(data.nodes)
          .on("tick", ticked);

        simulation.force("link")
          .links(data.links);
      }

      // The table generation function
      function tabulate(data, columns) {
        var table = d3.select("#content").append("table")
          .attr("class", "table table-sm table-dark")
          .attr("width", chartWidth * 0.7)
          .style("border-collapse", "collapse")// <= Add this line in
          .style("border", "2px black solid"), // <= Add this line in

          thead = table.append("thead"),
          tbody = table.append("tbody");

        // append the header row
        thead.append("tr")
          .selectAll("th")
          .data(columns)
          .enter()
          .append("th")
          .text(function (column) {
            return column.replace("_", " ");
          });

        // create a row for each object in the data
        var rows = tbody.selectAll("tr")
          .data(data)
          .enter()
          .append("tr");

        // create a cell in each row for each column
        var cells = rows.selectAll("td")
          .data(function (row) {
            return columns.map(function (column) {
              return { column: column, value: row[column] };
            });
          })
          .enter()
          .append("td")
          .attr("style", "font-family: Courier") // sets the font style
          .html(function (d) { return d.value; });

        return table;
      }

      // Below are the functions that handle actual exporting:
      // getSVGString ( svgNode ) and svgString2Image( svgString, width, height, format, callback )
      function getSVGString(svgNode) {
        svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink');
        var cssStyleText = getCSSStyles(svgNode);
        appendCSS(cssStyleText, svgNode);

        var serializer = new XMLSerializer();
        var svgString = serializer.serializeToString(svgNode);
        svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
        svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix

        return svgString;

        function getCSSStyles(parentElement) {
          var selectorTextArr = [];

          // Add Parent element Id and Classes to the list
          selectorTextArr.push('#' + parentElement.id);
          for (var c = 0; c < parentElement.classList.length; c++)
            if (!contains('.' + parentElement.classList[c], selectorTextArr))
              selectorTextArr.push('.' + parentElement.classList[c]);

          // Add Children element Ids and Classes to the list
          var nodes = parentElement.getElementsByTagName("*");
          for (var i = 0; i < nodes.length; i++) {
            var id = nodes[i].id;
            if (!contains('#' + id, selectorTextArr))
              selectorTextArr.push('#' + id);

            var classes = nodes[i].classList;
            for (var c = 0; c < classes.length; c++)
              if (!contains('.' + classes[c], selectorTextArr))
                selectorTextArr.push('.' + classes[c]);
          }

          // Extract CSS Rules
          var extractedCSSText = "";
          for (var i = 0; i < document.styleSheets.length; i++) {
            var s = document.styleSheets[i];

            try {
              if (!s.cssRules) continue;
            } catch (e) {
              if (e.name !== 'SecurityError') throw e; // for Firefox
              continue;
            }

            var cssRules = s.cssRules;
            for (var r = 0; r < cssRules.length; r++) {
              if (contains(cssRules[r].selectorText, selectorTextArr))
                extractedCSSText += cssRules[r].cssText;
            }
          }


          return extractedCSSText;

          function contains(str, arr) {
            return arr.indexOf(str) === -1 ? false : true;
          }

        }

        function appendCSS(cssText, element) {
          var styleElement = document.createElement("style");
          styleElement.setAttribute("type", "text/css");
          styleElement.innerHTML = cssText;
          var refNode = element.hasChildNodes() ? element.children[0] : null;
          element.insertBefore(styleElement, refNode);
        }
      }

      function svgString2Image(svgString, width, height, format, callback) {
        var format = format ? format : 'png';

        var imgsrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgString))); // Convert SVG string to data URL

        var canvas = document.createElement("canvas");
        var context = canvas.getContext("2d");

        canvas.width = width;
        canvas.height = height;

        var image = new Image();
        image.onload = function () {
          context.clearRect(0, 0, width, height);
          context.drawImage(image, 0, 0, width, height);

          canvas.toBlob(function (blob) {
            var filesize = Math.round(blob.length / 1024) + ' KB';
            if (callback) callback(blob, filesize);
          });


        };

        image.src = imgsrc;
      }

    </script>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
      integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
      crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
      integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
      crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
      integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
      crossorigin="anonymous"></script>
  </div>
</body>

</html>