[Answered ]-How to open a Popup window which contains a graph written in javascript?

2👍

There can be two ways of performing the task that you want. Here are the methods.

Version 1 (The synchronous way)

Suppose you have a url say /x/ which opens main.html. So you can add whatever data, graph needs to the context on a GET call. Example:

def x(request):
    context = {}
    # Add data that is needed to draw the graph, in your context
    return render(request, "main.html",context)

Now you have the data that is needed to draw your graph, in your main.html‘s context. Now you can simply use a Bootstrap modal to draw your graph in a pop up.

<div class="col-lg-4">
    <p><button class="btn btn-primary" type="button" data-toggle="modal" data-target="#myModal"id="display_list">Display List</button></p>
</div>

<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
  <div class="modal-dialog">

    <!-- Modal content-->
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">&times;</button>
        <h4 class="modal-title">Modal Header</h4>
      </div>
      <div class="modal-body" id="modal-body">
        <p>Some text in the modal.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
      </div>
    </div>

  </div>
</div>

You don’t need the click event listener on #display_list since Bootstrap handles that.

<script>
    // Put your graph logic here and use '#modal-body' to render the graph
</script>

Version 2 (The Async way)
In this case we have already opened the page on /x/ and we will get data from /display_list/ via an AJAX GET call.

def display_list(request):
    ''' Function to return data in json format to ajax call '''
    context = {}
    #Get all data required to draw the graph and put it in context

    return JsonResponse(context)

Since when you click the button you want to send AJAX request and then open the modal, you need to remove data-toggle="modal" data-target="#myModal" from the button to prevent it from opening. Change the button to:

<p><button class="btn btn-primary" type="button" id="display_list">Display List</button></p>

Now you can hit the url /display_list/ to get your data. In your main.html add the Bootstrap modal element as in version 1. Now add the following Javascript to main.html to get the data.

<script>
    $(document).ready(function(){
        $("#display_list").click(function(e){
            e.preventDefault();
            var modalBody = $("#modal-body");
            // AJAX call to get the data
            $.ajax({
                url: '/display_list/',
                type: 'GET',
                success: function(data, status, xhr) {
                    console.log(data);
                    // Add your graph logic here and use modalBody to draw on it
                }
            });

            //Now display the modal
            $("#myModal").modal('show');
        });
    });
</script>

NOTE
Remember to add Bootstrap’s CSS and JS files.

<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

Example
So I will be going by version 1 here in the example. I am using the graph provided here
Step 1: Your view x should look like this:

def x(request):
    context = {}
    links = [
        {'source': "Microsoft", 'target': "Amazon", 'type': "licensing"},
        {'source': "Microsoft", 'target': "HTC", 'type': "licensing"},
        {'source': "Samsung", 'target': "Apple", 'type': "suit"},
        {'source': "Motorola", 'target': "Apple", 'type': "suit"},
        {'source': "Nokia", 'target': "Apple", 'type': "resolved"},
        {'source': "HTC", 'target': "Apple", 'type': "suit"},
        {'source': "Kodak", 'target': "Apple", 'type': "suit"},
        {'source': "Microsoft", 'target': "Barnes & Noble", 'type': "suit"},
        {'source': "Microsoft", 'target': "Foxconn", 'type': "suit"},
        {'source': "Oracle", 'target': "Google", 'type': "suit"},
        {'source': "Apple", 'target': "HTC", 'type': "suit"},
        {'source': "Microsoft", 'target': "Inventec", 'type': "suit"},
        {'source': "Samsung", 'target': "Kodak", 'type': "resolved"},
        {'source': "LG", 'target': "Kodak", 'type': "resolved"},
        {'source': "RIM", 'target': "Kodak", 'type': "suit"},
        {'source': "Sony", 'target': "LG", 'type': "suit"},
        {'source': "Kodak", 'target': "LG", 'type': "resolved"},
        {'source': "Apple", 'target': "Nokia", 'type': "resolved"},
        {'source': "Qualcomm", 'target': "Nokia", 'type': "resolved"},
        {'source': "Apple", 'target': "Motorola", 'type': "suit"},
        {'source': "Microsoft", 'target': "Motorola", 'type': "suit"},
        {'source': "Motorola", 'target': "Microsoft", 'type': "suit"},
        {'source': "Huawei", 'target': "ZTE", 'type': "suit"},
        {'source': "Ericsson", 'target': "ZTE", 'type': "suit"},
        {'source': "Kodak", 'target': "Samsung", 'type': "resolved"},
        {'source': "Apple", 'target': "Samsung", 'type': "suit"},
        {'source': "Kodak", 'target': "RIM", 'type': "suit"},
        {'source': "Nokia", 'target': "Qualcomm", 'type': "suit"}
    ]
    context['links'] = links
    return render(request, 'main.html', context)

Step 2: In your main.html add the following to your <head> tag.

<script   src="https://code.jquery.com/jquery-2.2.4.min.js"   integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="   crossorigin="anonymous"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>    
    .link {
        fill: none;
        stroke: #666;
        stroke-width: 1.5px;
    }

    #licensing {
        fill: green;
    }

    .link.licensing {
        stroke: green;
    }

    .link.resolved {
        stroke-dasharray: 0,2 1;
    }

    circle {
        fill: #ccc;
        stroke: #333;
        stroke-width: 1.5px;
    }

    text {
        font: 10px sans-serif;
        pointer-events: none;
        text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
    }
    .modal-dialog {
        width: 63% !important;
    }
</style>

Step 3: This will be your <body> tag in main.html, in this you will need to have a global var links = {{ links|safe }} variable. We cant shift the script to a separate file since django template tag wont work there.

<body>
    <div class="col-lg-4">
        <p><button class="btn btn-primary" type="button" data-toggle="modal" data-target="#myModal" id="display_list">Display List</button></p>
    </div>

    <!-- Modal -->
    <div id="myModal" class="modal fade" role="dialog">
      <div class="modal-dialog">

        <!-- Modal content-->
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal">&times;</button>
            <h4 class="modal-title">Modal Header</h4>
          </div>
          <div class="modal-body" id="modal-body">

          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          </div>
        </div>

      </div>
    </div>

    <script>

        var links = {{ links|safe}};
        var nodes = {};

        // Use elliptical arc path segments to doubly-encode directionality.
        function tick() {
          path.attr("d", linkArc);
          circle.attr("transform", transform);
          text.attr("transform", transform);
        }

        function linkArc(d) {
          var dx = d.target.x - d.source.x,
              dy = d.target.y - d.source.y,
              dr = Math.sqrt(dx * dx + dy * dy);
          return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
        }

        function transform(d) {
          return "translate(" + d.x + "," + d.y + ")";
        }

        // Compute the distinct nodes from the links.
        links.forEach(function(link) {
          link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
          link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
        });

        var width = 860,
            height = 500;

        var force = d3.layout.force()
            .nodes(d3.values(nodes))
            .links(links)
            .size([width, height])
            .linkDistance(60)
            .charge(-300)
            .on("tick", tick)
            .start();

        var svg = d3.select("#modal-body").append("svg")
            .attr("width", width)
            .attr("height", height);
            // Per-type markers, as they don't inherit styles.
            svg.append("defs").selectAll("marker")
            .data(["suit", "licensing", "resolved"])
          .enter().append("marker")
            .attr("id", function(d) { return d; })
            .attr("viewBox", "0 -5 10 10")
            .attr("refX", 15)
            .attr("refY", -1.5)
            .attr("markerWidth", 6)
            .attr("markerHeight", 6)
            .attr("orient", "auto")
          .append("path")
            .attr("d", "M0,-5L10,0L0,5");

        var path = svg.append("g").selectAll("path")
            .data(force.links())
          .enter().append("path")
            .attr("class", function(d) { return "link " + d.type; })
            .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

        var circle = svg.append("g").selectAll("circle")
            .data(force.nodes())
          .enter().append("circle")
            .attr("r", 6)
            .call(force.drag);

        var text = svg.append("g").selectAll("text")
            .data(force.nodes())
          .enter().append("text")
            .attr("x", 8)
            .attr("y", ".31em")
            .text(function(d) { return d.name; });


    </script>
</body>

Thats it you are ready to go. Look carefully you don’ require to add a click event to #display_list as Bootstrap handles all that.

Here’s a JSBin demo

👤Aakash

0👍

It’s completely possible using bootstrap modals, here’s documentation about it :
http://www.w3schools.com/bootstrap/bootstrap_modal.asp

And a sample code :

<div class="modal fade" id="id_you_want_for_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog modal-lg">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="myModalLabel"> Title you want </h4>
      </div>
           <div class="modal-body">
               <!-- Your Graph here  -->
          </div>
    </div>
  </div>
</div>  

Do not forget to include the bootstrap js and css files in your project :

http://getbootstrap.com/getting-started/

http://www.w3schools.com/bootstrap/bootstrap_get_started.asp

Hope it helps !

Leave a comment