Reputation: 23
I am using Django to implement a website and I would like to add a button such that when someone clicks it, it would open a Popup window which contains a graph written in javascript. And since I am writing the website in Django, I need to call a function in views.py to get the updated data and then draw the graph based on that. I originally want to update the graph on one page but now I would like to open a popup window. Could someone help me on how to modify the code so that the button would Popup a smaller window which contains the graph I implemented? Thanks! Here is my code in main.html:
# I first have a button that could be clicked
<div class="col-lg-4">
<p><button class="btn btn-primary" type="button" name="display_list" id="display_list">Display List</button></p>
</div>
# here is the script I used to open up a Popup window such that the returned result would be displayed on that separate window
<script>
$(document).ready(function(){
$("#display_list").click(function(){
$.get("display_list/", function(ret){
$('#result').bPopup(); #I think probably I did this wrong?
});
});
});
</script>
And here is the code I used to draw the graph in a separate html file(show_result.html):
<div id="result">
<script> javascript that draws a graph on html webpage. I pass the updated variable from the corresponding function in views.py to here by calling render(). </script>
</div>
Here is my function in the views.py:
def display_list(request):
#some function implementation to get the result and put it in context
return render(request, "show_result.html",context)
And this is the code in my url file:
url(r'^display_list/$', views.display_list, name='display_list'),
Is it possible to Popup a div in html? And what should I do in my case?
Thanks a lot.
Upvotes: 1
Views: 2647
Reputation: 1515
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">×</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">×</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
Upvotes: 2
Reputation: 2070
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">×</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 !
Upvotes: 0