Google Chart not display data - google-visualization

I have a problem with Google Chart, Twig ans Symfony. I make an ajax call to a function which send data to the js function drawing chart. I displayed data outside of the chart and it's working well. I also tried to display a chart with data hard-coded in it and it also displays well. It's only when I put datas from my Controller in chart's datatable that it's not working.
I don't show my Controller because it's sending datas correctly.
Here's my code :
Drawing function :
function drawGraphRepNoteOfColle() {
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Notes', 'Nombre'],
{% for r in repartitionsColle %}
[{{ r.note }}, {{ r.nombre }}],
{% endfor %}
]);
var options = {
chart: {
title: 'Company Performance',
subtitle: 'Sales, Expenses, and Profit: 2014-2017'
}
};
var chart = new google.charts.Bar(document.getElementById('graphRepNoteColle'));
chart.draw(data, options);
}
}
Ajax Call :
function rechargerColleStats() {
var groupes = document.getElementsByClassName("filled-in");
var groupesSelected = getSelectedGroupesOf(groupes);
var colleId = document.getElementById('collapside_colle_form_colles').value;
var numAdherent = document.getElementById('numAdherent').value;
var DATA = {groupesSelected: groupesSelected, idColle: colleId, numAdherent: numAdherent};
var request = $.ajax({
type: "POST",
url: "{{ path('paces_statistique_calculstatistique_getstatscolle') }}",
datatype: "html",
data: DATA,
success: function (response) {
document.getElementById("bodyColapColle").innerHTML = response;
drawGraphRepNoteOfColle();
document.getElementById("tableauQ").reload(true);
}
});
}
index.html.twig :
<nav class="top-nav panel-title">Statistiques</nav>
<div class="card-panel hoverable">
// Groupes selected field (checkboxes)
<div id="bodyColapGroupes">
{% include 'PACESStatistiqueBundle:Default:groupesCheckBoxes.html.twig' %}
</div>
// Form to get colleId
<fieldset style='display: inline; border: 2px solid deepskyblue;'>
<legend> Choix de la colle</legend>
{{ form_start(formColle) }}
{{ form_end(formColle) }}
</fieldset>
</div>
<div class="card-panel hoverable">
Colles
<div id="bodyColapColle">
{% include 'PACESStatistiqueBundle:Default:collapsideColle.html.twig' %}
</div>
</div>
collapsibleColle.html.twig :
<div id="colles">
<fieldset style='display: inline; border: 2px solid deepskyblue;'>
<legend> Minor </legend>
{% if minor is defined %}
{{ minor }} / {% if typeColle == 'QC' %}{{ nbQc }}{% else %}20{% endif %}
{% endif %}
</fieldset>
<div class="center">
<fieldset id="fieldchartA" style='height:100%; width: 100% ;border: 2px solid deepskyblue;'>
<legend> Chart1</legend>
<div id="graphRepNoteColle"></div>
</fieldset>
</div>
</div>
getStatsColleAction in Controller :
$repartitionsColles=$em->getRepository( RepartitionColle::class )->findBy(['idStatColle'=>$statsColle]);
//on en recupere les données minor, major, medianne
$notes=array();
$nbRepartition = 0;
foreach($repartitionsColles as $repartitionsColle){
$repartition[$nbRepartition]['note'] = $repartitionsColle->getNote();
$repartition[$nbRepartition]['nombre'] = $repartitionsColle->getNombre();
$nbRepartition++;
}
array_multisort(array_column($repartition, 'note'), SORT_ASC, SORT_NUMERIC, $repartition);
Array sent is $repartition. getNote() is a float and getNombre is an integer.
Drawing function and Ajax call are in index.html.twig.
GetStatsColle (function called with AJAX) returns collapsideColle.html.twig with required datas.
Ajax is working : I send other infos with the same call and it is rendered.

i would recommend not relying on google.charts.setOnLoadCallback to draw the chart everytime,
especially if you plan to draw multiple charts, it should only be called once per page
instead, swap the order of things and start with google.chart.load first,
then you can draw the chart directly from the ajax call
you can include the callback in the load statement as well...
try something like...
google.charts.load('current', {
callback: rechargerColleStats,
packages:['bar']
});
function drawGraphRepNoteOfColle() {
var data = google.visualization.arrayToDataTable([
['Notes', 'Nombre'],
{% for r in repartitionsColle %}
[{{ r.note }}, {{ r.nombre }}],
{% endfor %}
]);
var options = {
chart: {
title: 'Company Performance',
subtitle: 'Sales, Expenses, and Profit: 2014-2017'
}
};
var chart = new google.charts.Bar(document.getElementById('graphRepNoteColle'));
chart.draw(data, options);
}
function rechargerColleStats() {
var groupes = document.getElementsByClassName("filled-in");
var groupesSelected = getSelectedGroupesOf(groupes);
var colleId = document.getElementById('collapside_colle_form_colles').value;
var numAdherent = document.getElementById('numAdherent').value;
var DATA = {groupesSelected: groupesSelected, idColle: colleId, numAdherent: numAdherent};
var request = $.ajax({
type: "POST",
url: "{{ path('paces_statistique_calculstatistique_getstatscolle') }}",
datatype: "html",
data: DATA,
success: function (response) {
document.getElementById("bodyColapColle").innerHTML = response;
drawGraphRepNoteOfColle();
document.getElementById("tableauQ").reload(true);
}
});
}

Related

How can change the color of like button and increase by one when hit the like button in Django using ajax

I found difficult to change the color of the like button when the button hit and increase by +1 (in likes) in Django using ajax
my html template
<form method="POST" action="{% url 'video:like' video.pk %}" id="my-like-form">
{% csrf_token %}
<input type="hidden" class="likin" name="next" value="{{ request.path }}">
<button class="remove-default-btn" type="submit" id="openPopup" class="like-btn{{ request.path }}" style="border: none; ">
<i class="fa fa-thumbs-up" aria-hidden="true"><span>{{ video.likes.all.count }}</span></i>
Like
</button>
JavaScript
$("#my-like-form").submit(function(e){
e.preventDefault(); // Prevent form submission
let form = $(this);
let url = form.attr("action");
let res
const likes = $(`.like-btn{{ request.path }}`).text();// this code stopping the function of like button from work
const trimCount = parseInt(likes)
$.ajax({
type: "POST",
url: url,
data: form.serialize(),
dataType: "json",
success: function(response) {
selector = document.getElementsByName(response.next);
if(response.liked==true){
$(selector).css("color","blue");
res = trimCount - 1
} else if(response.liked==false){
$(selector).css("color","black");
res = trimCount + 1
}
}
})
})
Instead of using jinja code inside jquery code you can simple use $(this).find("button[class*=like-btn] span") this will give you span tag which have your total likes count then using .text() add new count to span tag.
Demo Code :
//suppose this return from server
var response = {
"liked": true
}
$("#my-like-form").submit(function(e) {
e.preventDefault();
let form = $(this);
let url = form.attr("action");
let res
//get like button and then find span to get total value
const likes = $(this).find("button[class*=like-btn] span").text();
const trimCount = parseInt(likes)
console.log(trimCount)
var selector = $(this).find("button[class*=like-btn]") //to select that button
/* $.ajax({
type: "POST",
url: url,
data: form.serialize(),
dataType: "json",
success: function(response) {
*/
if (response.liked == true) {
$(selector).css("color", "blue");
res = trimCount + 1
} else if (response.liked == false) {
$(selector).css("color", "black");
res = trimCount - 1
}
$(selector).find("span").text(res) //add that value inside span
/*}
})*/
})
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" integrity="sha512-HK5fgLBL+xu6dm/Ii3z4xhlSUyZgTT9tuc/hSrtw6uzJOvgRr2a9jyxxT1ely+B+xFAmJKVSTbpM/CuL7qxO8w==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="POST" action="{% url 'video:like' video.pk %}" id="my-like-form">
{% csrf_token %}
<input type="hidden" class="likin" name="next" value="{{ request.path }}">
<!--you have two clas attribute merge that in one here `1` is just for demo replace that with like-btn{{ request.path }} -->
<button class="remove-default-btn like-btn1" type="submit" id="openPopup" style="border: none; ">
<i class="fa fa-thumbs-up" aria-hidden="true"><span>23</span></i>
Like
</button>
</form>

Getting an error when integrated django-private-chat in the django project? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am working on an application where I want to implement the django-private-chat in for one to one messaging feature after I did everything which is said in the documentation I ran the server and got to the link http://127.0.0.1:8000/dialogs/ I am getting this error please help me out I have included the error traceback also
dialogs.html:
% extends "base.html" %
{% load static %}
{% load i18n %}
{% block css %}
{{ block.super }}
<link href="{% static "django_private_chat/css/django_private_chat.css" %}" rel="stylesheet" type="text/css" media="all">
{% endblock css %}
{% block content %}
<input id="owner_username" type="hidden" value="{{ request.user.username }}">
<div class="container">
<div class="col-md-3">
<div class="user-list-div">
<ul>
{% for dialog in object_list %}
<li>
{% if dialog.owner == request.user %}
{% with dialog.opponent.username as username %}
<a href="{% url 'dialogs_detail' username %}" id="user-{{ username }}"
class="btn btn-danger">{% trans "Chat with" %} {{ username }}</a>
{% endwith %}
{% else %}
{% with dialog.owner.username as username %}
<a href="{% url 'dialogs_detail' username %}" id="user-{{ username }}"
class="btn btn-danger">{% trans "Chat with" %} {{ username }}</a>
{% endwith %}
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</div>
<div class="col-md-9">
<div class="row">
<div class="col-md-3 col-md-offset-9">
<span class="pull-right" hidden id="typing-text">
<strong>{{ opponent_username }} {% trans "is typing..." %}</strong>
</span>
</div>
<p>
{{ opponent_username }}
</p>
<p class="text-success" id="online-status" style="display: none">{% trans "Online" %}</p>
<p class="text-danger" id="offline-status" style="display: none">{% trans "Offline" %}</p>
<div class="messages-container">
<div id="messages" class="messages">
{% for msg in active_dialog.messages.all %}
<div class="row {% if msg.read %}msg-read{% else %}msg-unread{% endif %}"
data-id="{{ msg.id }}">
<p class="{% if msg.sender == request.user %}pull-left{% else %}pull-right{% endif %}">
<span class="username">{{ msg.sender.username }}:</span>
{{ msg.text }}
<span class="timestamp">– <span
data-livestamp="{{ msg.get_formatted_create_datetime }}">{{ msg.get_formatted_create_datetime }}</span></span>
</p>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="row">
<div class="add-message">
<div class="form-group">
<textarea id="chat-message" class="form-control message"
placeholder="{% trans 'Write a message' %}"></textarea>
</div>
<div class="form-group clearfix">
<input id="btn-send-message" type="submit" class="btn btn-primary pull-right send-message"
style="margin-left: 10px;" value="{% trans 'Send' %}"/>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/scrollmonitor/1.2.0/scrollMonitor.js"
integrity="sha256-BseZlDlA+yL4qu+Voi82iFa5aaifralQEXIjOjaXgeo=" crossorigin="anonymous"></script>
<script>
var base_ws_server_path = "{{ ws_server_path }}";
$(document).ready(function () {
var websocket = null;
var monitor = null;
function initReadMessageHandler(containerMonitor, elem) {
var id = $(elem).data('id');
var elementWatcher = containerMonitor.create(elem);
elementWatcher.enterViewport(function () {
var opponent_username = getOpponnentUsername();
var packet = JSON.stringify({
type: 'read_message',
session_key: '{{ request.session.session_key }}',
username: opponent_username,
message_id: id
});
$(elem).removeClass('msg-unread').addClass('msg-read');
websocket.send(packet);
});
}
function initScrollMonitor() {
var containerElement = $("#messages");
var containerMonitor = scrollMonitor.createContainer(containerElement);
$('.msg-unread').each(function (i, elem) {
if ($(elem).hasClass('opponent')){
initReadMessageHandler(containerMonitor, elem);
}
});
return containerMonitor
}
function getOpponnentUsername() {
return "{{ opponent_username }}";
}
// TODO: Use for adding new dialog
function addNewUser(packet) {
$('#user-list').html('');
packet.value.forEach(function (userInfo) {
if (userInfo.username == getUsername()) return;
var tmpl = Handlebars.compile($('#user-list-item-template').html());
$('#user-list').append(tmpl(userInfo))
});
}
function addNewMessage(packet) {
var msg_class = "";
if (packet['sender_name'] == $("#owner_username").val()) {
msg_class = "pull-left";
} else {
msg_class = "pull-right";
}
var msgElem =
$('<div class="row msg-unread" data-id="' + packet.message_id + '">' +
'<p class="' + msg_class + '">' +
'<span class="username">' + packet['sender_name'] + ': </span>' +
packet['message'] +
' <span class="timestamp">– <span data-livestamp="' + packet['created'] + '"> ' + packet['created'] + '</span></span> ' +
'</p> ' +
'</div>');
$('#messages').append(msgElem);
scrollToLastMessage()
}
function scrollToLastMessage() {
var $msgs = $('#messages');
$msgs.animate({"scrollTop": $msgs.prop('scrollHeight')})
}
function generateMessage(context) {
var tmpl = Handlebars.compile($('#chat-message-template').html());
return tmpl({msg: context})
}
function setUserOnlineOffline(username, online) {
var elem = $("#user-" + username);
if (online) {
elem.attr("class", "btn btn-success");
} else {
elem.attr("class", "btn btn-danger");
}
}
function gone_online() {
$("#offline-status").hide();
$("#online-status").show();
}
function gone_offline() {
$("#online-status").hide();
$("#offline-status").show();
}
function flash_user_button(username) {
var btn = $("#user-" + username);
btn.fadeTo(700, 0.1, function () {
$(this).fadeTo(800, 1.0);
});
}
function setupChatWebSocket() {
var opponent_username = getOpponnentUsername();
websocket = new WebSocket(base_ws_server_path + '{{ request.session.session_key }}/' + opponent_username);
websocket.onopen = function (event) {
var opponent_username = getOpponnentUsername();
var onOnlineCheckPacket = JSON.stringify({
type: "check-online",
session_key: '{{ request.session.session_key }}',
username: opponent_username
{# Sending username because the user needs to know if his opponent is online #}
});
var onConnectPacket = JSON.stringify({
type: "online",
session_key: '{{ request.session.session_key }}'
});
console.log('connected, sending:', onConnectPacket);
websocket.send(onConnectPacket);
console.log('checking online opponents with:', onOnlineCheckPacket);
websocket.send(onOnlineCheckPacket);
monitor = initScrollMonitor();
};
window.onbeforeunload = function () {
var onClosePacket = JSON.stringify({
type: "offline",
session_key: '{{ request.session.session_key }}',
username: opponent_username,
{# Sending username because to let opponnent know that the user went offline #}
});
console.log('unloading, sending:', onClosePacket);
websocket.send(onClosePacket);
websocket.close();
};
websocket.onmessage = function (event) {
var packet;
try {
packet = JSON.parse(event.data);
console.log(packet)
} catch (e) {
console.log(e);
}
switch (packet.type) {
case "new-dialog":
// TODO: add new dialog to dialog_list
break;
case "user-not-found":
// TODO: dispay some kind of an error that the user is not found
break;
case "gone-online":
if (packet.usernames.indexOf(opponent_username) != -1) {
gone_online();
} else {
gone_offline();
}
for (var i = 0; i < packet.usernames.length; ++i) {
setUserOnlineOffline(packet.usernames[i], true);
}
break;
case "gone-offline":
if (packet.username == opponent_username) {
gone_offline();
}
setUserOnlineOffline(packet.username, false);
break;
case "new-message":
if (packet['sender_name'] == opponent_username || packet['sender_name'] == $("#owner_username").val()) {
addNewMessage(packet);
if (packet['sender_name'] == opponent_username) {
initReadMessageHandler(monitor, $("div[data-id='" + packet['message_id'] + "']"));
}
} else {
flash_user_button(packet['sender_name']);
}
break;
case "opponent-typing":
var typing_elem = $('#typing-text');
if (!typing_elem.is(":visible")) {
typing_elem.fadeIn(500);
} else {
typing_elem.stop(true);
typing_elem.fadeIn(0);
}
typing_elem.fadeOut(3000);
break;
case "opponent-read-message":
if (packet['username'] == opponent_username) {
$("div[data-id='" + packet['message_id'] + "']").removeClass('msg-unread').addClass('msg-read');
}
break;
default:
console.log('error: ', event)
}
}
}
function sendMessage(message) {
var opponent_username = getOpponnentUsername();
var newMessagePacket = JSON.stringify({
type: 'new-message',
session_key: '{{ request.session.session_key }}',
username: opponent_username,
message: message
});
websocket.send(newMessagePacket)
}
$('#chat-message').keypress(function (e) {
if (e.which == 13 && this.value) {
sendMessage(this.value);
this.value = "";
return false
} else {
var opponent_username = getOpponnentUsername();
var packet = JSON.stringify({
type: 'is-typing',
session_key: '{{ request.session.session_key }}',
username: opponent_username,
typing: true
});
websocket.send(packet);
}
});
$('#btn-send-message').click(function (e) {
var $chatInput = $('#chat-message');
var msg = $chatInput.val();
if (!msg) return;
sendMessage($chatInput.val());
$chatInput.val('')
});
setupChatWebSocket();
scrollToLastMessage();
});
</script>
{% endblock %}
base.html:
{% load static %}
<!-- Their site uses old school block layout -->
{% block extra_js %}
<!-- Your package using 2SoD block layout -->
{% block javascript %}
<script src="{% static 'js/ninja.js' %}" type="text/javascript"></script>
{% endblock javascript %}
{% endblock extra_js %}
It seems you are calling {{ block.super }} on a base template.
You should include a base template using {% extends "base_template_name.html" %} before calling {{ block.super }}.
This would include content from the super template ("base_template_name.html") in your "dialog.html" template, instead of overriding it. You may also try just removing or commenting out the {{ block.super }} call if you don't need any content from the super template.
Please post your code here if you still can't get it to work. Hope it works for you!
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% block css %}
<link href="{% static "django_private_chat/css/django_private_chat.css" %}" rel="stylesheet" type="text/css" media="all">
{% endblock css %}

Dynamically Multiple marker google map doesn't show with Django

I have a model class name Restaurant with Latitude and Longitude and inserted many data already in this class and by these fields, I wanna show multiple markers of google map.
# restaurant.html
<div id="map"></div>
{% for i in restaurents %}
<script>
var locations = [
[{{ i.restaurant }}, {{ i.latitude }}, {{ i.longitude }}, {{ i.id }}]
];
{#var locations = [#}
{# ['Bondi Beach', -33.890542, 151.274856, 4],#}
{# ['Coogee Beach', -33.923036, 151.259052, 5],#}
{# ['Cronulla Beach', -34.028249, 151.157507, 3],#}
{# ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],#}
{# ['Maroubra Beach', -33.950198, 151.259302, 1]#}
{#];#}
// When the user clicks the marker, an info window opens.
function initMap() {
var myLatLng = {lat: -33.90, lng: 151.16};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: myLatLng
});
var count=0;
for (count = 0; count < locations.length; count++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[count][1], locations[count][2]),
map: map
});
marker.info = new google.maps.InfoWindow({
content: locations [count][0]
});
google.maps.event.addListener(marker, 'click', function() {
// this = marker
var marker_map = this.getMap();
this.info.open(marker_map, this);
// Note: If you call open() without passing a marker, the InfoWindow will use the position specified upon construction through the InfoWindowOptions object literal.
});
}
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBqEz7ozYxKa53JAeN4GFN2HfilyiFCbvw&callback=initMap">
</script>
{% endfor %}
Initially, I have defined some data and it's working good that has commented out in this code. But when I retrieved data via looping from my database then map doesn't work.
I don't understand from where and how I can access this data.
access
var locations = [
[{{ i.restaurant }}, {{ i.latitude }}, {{ i.longitude }}, {{ i.id }}]
];
many time I searched and also got some answer but doesn't work properly.
Thanks for Advance.
{% for i in restaurents %}
<div id="map" style="padding-bottom: 140px; padding-top: 140px"></div>
<script>
function initMap() {
var locations = [];
locations.push({name: {{ i.restaurant }}, latlng: new google.maps.LatLng( {{ i.latitude }}, {{ i.longitude }}) });
locations.push({name: 'Bondi Beach', latlng: new google.maps.LatLng( -33.890542, 151.274856) });
locations.push({name: 'Coogee Beach', latlng: new google.maps.LatLng( -33.923036, 151.259052) });
var uluru = { lat: {{ i.latitude }}, lng: {{ i.longitude }} };
var map = new google.maps.Map(
document.getElementById('map'), {zoom: 8, center: uluru});
for(var j=0; j<locations.length; j++){
var marker = new google.maps.Marker({
position: new google.maps.LatLng({position: locations[j].latlng, map: map, title: locations[j].name}),
});
bounds.extend(locations[j].latlng);
}
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBqEz7ozYxKa53JAeN4GFN2HfilyiFCbvw&callback=initMap">
</script>
{% endfor %}
Several kinds of steps already I've followed. For example the above code. When I'm gonna access that data then don't work but if I initially define those data it's working fine.

django leaflet_map how to add geojson layer on demand

I have a geodjango project using django-leaflet. A base map is displayed in the body of the html file using {% leaflet_map "mapid" %} . No other initialization is needed for the base map to display. Also, there is a choice box of polygon features that user can select. Upon selection the selected feature should display on top of the base map. As shown, the selected feature is the success response of a post ajax call. I get the correct data, however, I don't know how to display it on the map.
<html>
<head>
{% load leaflet_tags %}
{% leaflet_css %}
{% leaflet_js %}
<style>
#mapid {
width: 870px;
height: 530px;
}
</style>
</head>
<body>
<div> {% leaflet_map "mapid" %} </div>
<form id="aoi-form" method="post" action="" >
{% csrf_token %}
<select id="aoi-choice" name="modelarea_sel_name" >
{% for aoi in modelarea.aois.field.choices %}
<option>{{aoi|title}}</option>
{% endfor %}
</select>
</form>
<script type="text/javascript">
$(document).ready(function() {
// sets the csrf token for all the ajax calls
setCSRFToken();
function displayModelArea(data) {
window.addEventListener("map:init", function(event) {
var map = event.detail.map;
L.geoJson(data, {
onEachFeature: function onEachFeature(feature, layer) {
layer.bindPopup(feature.properties.name);
}
}).addTo(map);
});
}
$('#aoi-choice').on('change', function(e) {
var selecteditem = $(this).find("option:selected").val();
$.ajax({
url: $("#aoi-form").attr("action"),
type: $("#aoi-form").attr("method"),
data: { "aoi-choice": selecteditem },
success: function(response) {
alert(response);
<How to add this geojson to the map in success?>
<something like:>
displayModelArea(response) // this is not working
},
error : function(xhr,errmsg,err) {}
}); // end of ajax
}); // end of on change
}); // end of document
</script>
</body>
</html>
views.py
def rsmgui_home(request):
template_name = 'rsmgui_nav.html'
if request.POST.get("aoi-choice"):
polydata = serialize('geojson', ModelArea.objects.filter(name=request.POST.get("aoi-choice")))
return JsonResponse(polydata, safe=False)
For those interested in the solution, I must say, my original code contained two mistakes:
1) Had to return HttpResponse instead of JsonResponse from the views.py.
2) Had to initialize and get handle of the map (i.e. mymap) outside of the $(document).ready. Although, I am sure I should be able to do the same with jquery, But I did not know how!
FYI - the data format returned from views was somethings like this:
{"type": "FeatureCollection", "features": [{"type": "Feature",
"properties": {
"objectid": 3235,
"name": "WCU-L38E-2",
"shape_area": 5178189.95436,
"shape_len": 20962.4168727,
"model": "rsmgui.modelarea"
},
"id": 3,
"geometry": {
"type": "MultiPolygon",
"coordinates":
[[[[-80.4431746089703, 26.1496150525031], [-80.4438712320284, 26.1494779568429], [-80.4438714835869, 26.1494791485814],
[-80.4438767327393, 26.1495038898062], [-80.443876985872, 26.1495050844166], [-80.4439596517546, 26.1498945523],
[-80.4439599048889, 26.1498957469102], [-80.4445181371852, 26.1525257445301], [-80.444518396688, 26.1525269377307],
[-80.4454063419315, 26.1566079785707], [-80.4454066030393, 26.1566091717754], [-80.4454367956768, 26.1567473825391],
[-80.4454269367566, 26.1568310621773], [-80.4454019935245, 26.1569010164227], [-80.4451487080981, 26.1572161211586],
[-80.4451198504533, 26.1572690055153], [-80.4451124234237, 26.1572826141087], [-80.4450987418606, 26.1573731140696],
[-80.4451097451673, 26.1574483323541], [-80.4451099518947, 26.1574492731537], [-80.4454045318579, 26.1587738519124],
[-80.4454291560893, 26.1588281989547], [-80.4454726925214, 26.158873231686], [-80.4454745412333, 26.1588751446035],
[-80.4457224526486, 26.1590556968988], [-80.4459825369665, 26.1592924192246], [-80.4460113732483, 26.1593318182711],
[-80.446029694147, 26.1594029793378], [-80.4460299489157, 26.1594041725167], [-80.4461426842445, 26.1599298599992],
[-80.4461429406032, 26.159931053184], [-80.4461632993508, 26.1600259843658], [-80.4461635557098, 26.1600271775505],
[-80.4461662854139, 26.1600399110449], [-80.446166541773, 26.1600411042296], [-80.4461669349025, 26.1600429241313],
[-80.4461698308018, 26.1600564420782], [-80.4461703745794, 26.1600589761589], [-80.4461706309386, 26.1600601693436],
[-80.4461724673901, 26.1600687195423], [-80.446172720567, 26.1600699141476], [-80.4461890554485, 26.1601460828104],
[-80.4461892651751, 26.1601470637419], [-80.4461894764895, 26.1601480446796], [-80.4464055948207, 26.1611557705659],
[-80.4464058511845, 26.1611569637501], [-80.4465182479751, 26.1616803740569], [-80.446518504341, 26.1616815672408],
[-80.4467438353217, 26.1627308699823], [-80.4467440932799, 26.1627320631719], [-80.4471482872166, 26.1646036789173],
[-80.4471485483585, 26.1646048721181], [-80.4483626433148, 26.1701518069936], [-80.4483628854181, 26.1701530015516],
[-80.4483814524309, 26.1702450510074], [-80.4483896526105, 26.1703196621089], [-80.44837083869, 26.1703813120244],
[-80.4483349119681, 26.1704454670367], [-80.448238820436, 26.1705762562447], [-80.4480865737154, 26.1708302726741],
[-80.4480562687647, 26.1709111657153], [-80.4480474043405, 26.1709779965095], [-80.4480570552683, 26.1710631695728],
[-80.4480726187489, 26.1711178954947], [-80.4480728735615, 26.1711190886688], [-80.448600444514, 26.1735684214603],
[-80.4486318283615, 26.1736785332924], [-80.4486793668728, 26.1737445068659], [-80.4492087688318, 26.1741548565954],
[-80.4492476879068, 26.1742313275962], [-80.4492734967374, 26.1743198523785], [-80.4492737277215, 26.1743210511907],
[-80.4493637707618, 26.174788553371], [-80.4494647807674, 26.1752251203668], [-80.4494649710993, 26.1752261843278],
[-80.4495030325796, 26.1754400354424], [-80.4495075156305, 26.1755698630249], [-80.4494919585678, 26.1757079020217],
[-80.4494654601658, 26.1758137385183], [-80.4494247803613, 26.1759047014177], [-80.4493654321733, 26.1760018949102],
[-80.449291361239, 26.1760990334811], [-80.449224827617, 26.1761585592545], [-80.4490944858737, 26.176220056103],
[-80.448817683956, 26.176319577968], [-80.4486133770828, 26.176391343208], [-80.448294685515, 26.1764133756087],
[-80.4482742214126, 26.1764147902816], [-80.4482629422319, 26.1764173105563], [-80.4482608358316, 26.1764177810802],
[-80.4481701381423, 26.1764380517997], [-80.4480857500865, 26.1764548904322], [-80.4480278075929, 26.1764455275992],
[-80.4479938505702, 26.1764255169321], [-80.4447866204566, 26.1616803278906], [-80.4427502472453, 26.1523162458952],
[-80.4425042672057, 26.1511130652601], [-80.4424324383669, 26.1508789484218], [-80.4422838184404, 26.1506638659222],
[-80.442263580685, 26.150586872045], [-80.4422584377825, 26.1505622200219], [-80.4422537121117, 26.1505393091941],
[-80.4422484417484, 26.1505144173773], [-80.4422447794031, 26.1504939380542], [-80.4422409109672, 26.1504737273243],
[-80.4422344502975, 26.1504440606653], [-80.4422140566669, 26.1500502089701], [-80.4421980585152, 26.1498452491223],
[-80.4421989899204, 26.149844702483], [-80.4422962649397, 26.149811382303], [-80.4423241174424, 26.1498018149787],
[-80.442339856439, 26.1497964493973], [-80.4423577440382, 26.1497903226474], [-80.4423887913014, 26.1497796872474],
[-80.4424405282263, 26.1497619686973], [-80.4424639436836, 26.1497539446344], [-80.4424890564009, 26.1497459185392],
[-80.4426580984819, 26.1496918891336], [-80.4431746089703, 26.1496150525031]]]]}}],
"crs": {
"type": "link",
"properties": {
"href": "http://spatialreference.org/ref/epsg/4326/",
"type": "proj4"
}
}
};
Corrected code:
<html>
<head>
{% load leaflet_tags %}
{% leaflet_css %}
{% leaflet_js %}
<style>
#mapid {
width: 870px;
height: 530px;
}
</style>
</head>
<body>
<div>
{% leaflet_map "mapid" %}
</div>
<form id="aoi-form" method="post" action="" >
{% csrf_token %}
<select id="aoi-choice" name="modelarea_sel_name" >
{% for aoi in modelarea.aois.field.choices %}
<option>{{aoi|title}}</option>
{% endfor %}
</select>
</form>
<script type="text/javascript">
var mymap;
window.addEventListener("map:init", function (event) {
mymap = event.detail.map;
}, false);
$(document).ready(function() {
function displayModelArea(map, data) {
L.marker([26.92, -81.5]).addTo(mymap);
L.geoJSON(data).addTo(mymap);
}
$('#aoi-choice').on('change', function(e) {
var selecteditem = $(this).find("option:selected").val();
$.ajax({
url: $("#aoi-form").attr("action"),
type: $("#aoi-form").attr("method"),
data: { "aoi-choice": selecteditem },
success: function(response) {
displayModelArea(mymap, response)
},
error : function(xhr,errmsg,err) {}
}); // end of ajax
}); // end of on change
}); // end of document
</script>
</body>
</html>
views.py
def rsmgui_home(request):
template_name = 'rsmgui_nav.html'
if request.POST.get("aoi-choice"):
polydata = serialize('geojson', ModelArea.objects.filter(name=request.POST.get("aoi-choice")))
return HttpResponse(polydata, content_type='json')

Create pie chart with HighCharts in Django error - Blank page

I'm trying to create a pie chart with highcharts with Django (with Mac Maverick), but I just get a blank page. Is there some error in my code below?
My data consists of a dictionary with 2 keys (body and id__count), the loop inside it works perfectly in body tag. But it's not working in script tag.
<script>
function numberWithCommas(x) {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
$(function () {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'categoryPieChart'
},title: {
text: 'Category'
},tooltip: {
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ numberWithCommas(this.y.toFixed(2));
}
},exporting: {
enabled: false
},plotOptions: {
pie: {
dataLabels: {
enabled: true,
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ Math.round(this.percentage) +' %';
}
}
}
},series: [{
type: 'pie',
data: [
{% for cat in responses_pie %}
[
'{{ cat.body }}',
{% if cat.id__count > 0 %}
{{ cat.id__count }}
{% else %}
0
{% endif %}
],
{% endfor %}
]
}]
});
});
});
});
</script>
This is the view source on Chrome in the script tag:
function numberWithCommas(x) {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
$(function () {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'categoryPieChart'
},title: {
text: 'Category'
},tooltip: {
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ numberWithCommas(this.y.toFixed(2));
}
},exporting: {
enabled: false
},plotOptions: {
pie: {
dataLabels: {
enabled: true,
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ Math.round(this.percentage) +' %';
}
}
}
},series: [{
type: 'pie',
data: [
[
'apple',
2
],
]
}]
});
});
});
});
And my view (views.py)
def piechart(request):
responses_pie = AnswerRadio.objects.values("body").annotate(Count("id"))
return render(request, 'chart_code_v2.html', {'responses_pie': responses_pie})
You have an extra }); at the end (one from Highcharts.Chart({, one from $(document).ready(function() {, one from $(function () { and one too much). This should be visible as a syntax error in your javascript console.
Also, calling $(document).ready(fn) is superfluous, because $(fn), which you use on the function around it, is a shorthand for $(document).ready(fn).
If you plan to support old Internet Explorer versions, you will also need to remove the last comma from your data, for example like this:
{% for cat in responses_pie %}
[
'{{ cat.body }}',
{% if cat.id__count > 0 %}
{{ cat.id__count }}
{% else %}
0
{% endif %}
]{% if not forloop.last %},{% endif %}
{% endfor %}
Generally, it is better to serialize data in the view via json.dumps and pass the string to the template, as it is less error prone. For example:
import json
def piechart(request):
responses_pie = AnswerRadio.objects.values("body").annotate(Count("id"))
res = []
for cat in responses_pie:
res.append([
cat.body,
cat.id__count,
# ... more stuff
])
return render(request, 'chart_code_v2.html', {'responses_pie_json': json.dumps(res)})
then just use data: {{ responses_pie_json|safe }} in your template. Be aware that some Python objects (datetime, Decimal, ...) need some extra work for JSON serialization.