I'm trying to create some charts using highcharts, and doing so with dynamic div's.
It's successful on the first chart, but the rest are blank. Viewing the html source I would assume everything is ok.
Here are my dynamically created div's:
<!-- Break Down of all Signature names in each class -->
<% n = 0 %>
<% #sig_class_name_info.each do |scn_chart| %>
<div>
<%= scn_chart[:sig_class_name] %>
</div>
<table class="table">
<tr>
<td style='width:100%'>
<div class="panel panel-warning well">
<div class="panel-heading">
<h3 class="panel-title"></h3>
</div>
<div id="alert_name_bar_chart<%=+n%>" class="panel-body text-center">
</div>
</div>
</td>
</tr>
</table>
<%n = n+1%>
<% end %>
This is the html source created:
<!-- Break Down of all Signature names in each class -->
<div>
web-application-attack
</div>
<table class="table">
<tr>
<td style='width:100%'>
<div class="panel panel-warning well">
<div class="panel-heading">
<h3 class="panel-title"></h3>
</div>
<div id="alert_name_bar_chart0" class="panel-body text-center">
</div>
</div>
</td>
</tr>
</table>
<div>
attempted-admin
</div>
<table class="table">
<tr>
<td style='width:100%'>
<div class="panel panel-warning well">
<div class="panel-heading">
<h3 class="panel-title"></h3>
</div>
<div id="alert_name_bar_chart1" class="panel-body text-center">
</div>
</div>
</td>
</tr>
</table>
<div>
misc-attack
</div>
<table class="table">
<tr>
<td style='width:100%'>
<div class="panel panel-warning well">
<div class="panel-heading">
<h3 class="panel-title"></h3>
</div>
<div id="alert_name_bar_chart2" class="panel-body text-center">
</div>
</div>
</td>
</tr>
</table>
<div>
policy-violation
</div>
<table class="table">
<tr>
<td style='width:100%'>
<div class="panel panel-warning well">
<div class="panel-heading">
<h3 class="panel-title"></h3>
</div>
<div id="alert_name_bar_chart3" class="panel-body text-center">
</div>
</div>
</td>
</tr>
</table>
Here is the highcharts script:
<script type="text/javascript">
var charts = [];
$(function () {
var getChartConfig = function(renderId, title, data, x_axis) {
var config = {};
config.chart = {
renderTo: renderId,
defaultSeriesType: 'column',
margin: [50, 50, 100, 80]
};
new Highcharts.Chart ({
chart: {
type: 'bar',
renderTo: renderId
},
title: {
text: title,
style: {
color: '#52508d'
}
},
xAxis: {
categories: x_axis
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
location.href = this.series.options.url;
}
}
}
}
},
series: [{
data: data,
showInLegend: false,
name: 'Alerts',
url: '/ips_alert_classes?query=',
color: '#2a2874'
}]
});
}
<% n = 0%>
<% #sig_class_name_info.each do |i| %>
charts.push(new Highcharts.Chart(
getChartConfig("alert_name_bar_chart<%=+n%>",<%= raw i[:sig_class_name].to_json.html_safe %>,<%= raw i[:event_name_count].to_json.html_safe %>,<%= raw i[:event_name].to_json.html_safe %>)
))
<% n = n+1%>
<% end %>
});
</script>
Here is the html source from this highcharts script:
<script type="text/javascript">
var charts = [];
$(function () {
var getChartConfig = function(renderId, title, data, x_axis) {
var config = {};
config.chart = {
renderTo: renderId,
defaultSeriesType: 'column',
margin: [50, 50, 100, 80]
};
new Highcharts.Chart ({
chart: {
type: 'bar',
renderTo: renderId
},
title: {
text: title,
style: {
color: '#52508d'
}
},
xAxis: {
categories: x_axis
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
location.href = this.series.options.url;
}
}
}
}
},
series: [{
data: data,
showInLegend: false,
name: 'Alerts',
url: '/ips_alert_classes?query=',
color: '#2a2874'
}]
});
}
charts.push(new Highcharts.Chart(
getChartConfig("alert_name_bar_chart0", "web-application-attack", [919,1,1,1], ["drop - WP-Admin attempt","Snort Alert [1:16431:5]","Snort Alert [1:19438:9]","drop - SQL use of concat function with select - likely SQL injection"])
))
charts.push(new Highcharts.Chart(
getChartConfig("alert_name_bar_chart1", "attempted-admin", [1,10,4], ["Snort Alert [1:31976:4]","drop - SERVER-OTHER Wordpress linenity theme LFI attempt","drop - OS-OTHER Bash CGI environment variable injection attempt"])
))
charts.push(new Highcharts.Chart(
getChartConfig("alert_name_bar_chart2", "misc-attack", [1], ["drop - SQL union select - possible sql injection attempt - GET parameter"])
))
charts.push(new Highcharts.Chart(
getChartConfig("alert_name_bar_chart3", "policy-violation", [2], ["drop - POLICY-OTHER Adobe ColdFusion admin interface access attempt"])
))
});
</script>
As you can see the charts.push(new Highcharts.Chart() script seems to be working as expected.
What would cause the first chart to display just fine, but the rest be blank?
UPDATE:
This is the working HighCharts setup.
<script type="text/javascript">
var charts = [];
$(function () {
var getChartConfig = function (renderId, title, data, x_axis) {
var config = {
chart: {
renderTo: renderId,
defaultSeriesType: 'bar'
},
title: {
text: title,
style: {
color: '#52508d'
}
},
xAxis: {
categories: x_axis
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
//location.href = this.series.options.url;
}
}
}
}
},
series: [{
data: data,
showInLegend: false,
name: 'Alerts',
url: '/signatures?query=',
color: '#2a2874'
}]
};
return config;
}
<% n = 0%>
<% #sig_class_name_info.each do |i| %>
charts.push(new Highcharts.Chart(
getChartConfig("alert_name_bar_chart<%=n%>"
,<%= raw i[:sig_class_name].to_json.html_safe %>
,<%= raw i[:event_name_count].to_json.html_safe %>
,<%= raw i[:event_name].to_json.html_safe %>)
))
<% n = n+1%>
<% end %>
});
</script>
One important thing: you create every chart twice, first time when calling getChartConfig and second time before pushing to the charts array. So what I suggest to change:
Push chart only:
charts.push(getChartConfig(...))
and in getChartConfig method, return created chart:
return new Highcharts.Chart ({ ... });
Related
I'm trying to integrate datatable with chartjs, it works fine if i dont change the row numbers, or not do any filtration, from UI, when i change the row numbers for example, by default its 10, when i change it to 25, the charts also change, but when i move the mouse cursor to the chartjs canvas sometimes it shows the previous data(the 10 row data). how to fix it, or update the chartjs canvas data to the new
Here is my code:
$(document).ready(function(){
var list_daily_prices = document.getElementById('list_daily_prices')
if(list_daily_prices){
$('#list_daily_prices').DataTable({
"serverSide":true,
"processing":true,
"ordering": false,
"ajax":function(data,callback,settings){
$.get('/prices/daily/data',{
start:data.start,
limit:data.length,
filter:data.search.value,
},function(res){
callback({
recordsTotal:res.length,
recordsFiltered:res.length,
data:res.objects
});
},
);
},
"columns":[
{"data": "counter"},
{"data": function(data,type,dataToSet){
const date = new Date(data.day).toLocaleDateString('fr-CA')
return date
}},
{"data": "total_quantity"},
{"data": "total_price"},
{"data": "income"},
],
"drawCallback":function(settings){
var daily_date = []
var qnt = []
var total_price = []
var income = []
for(counter=0;counter<settings.aoData.length;counter++){
daily_date.push(new Date(settings.aoData[counter]._aData['day']).toLocaleDateString('fr-CA'))
qnt.push(settings.aoData[counter]._aData['total_quantity'])
total_price.push(parseFloat(settings.aoData[counter]._aData['total_price']).toFixed(2))
income.push(parseFloat(settings.aoData[counter]._aData['income']).toFixed(2))
}
var dailyPriceCanvas = $('#list_daily_prices_charts').get(0).getContext('2d')
var dailyPriceData = {
labels: daily_date,
datasets: [
{
label:'quantity',
data: qnt,
backgroundColor : '#9D0CA6',
},
{
label:'total price',
data: total_price,
backgroundColor : '#1392BE',
},
{
label:'income',
data: income,
backgroundColor : '#00a65a',
},
]
}
var dailyPriceOptions = {
responsive : true,
maintainAspectRatio : false,
datasetFill : false,
legend: { display: true },
title:{
display:true,
text:'total daily prices'
},
}
var dailyPriceChart = new Chart(dailyPriceCanvas, {
type: 'bar',
data: dailyPriceData,
options: dailyPriceOptions
})
},
"language":{
search:'',
searchPlaceholder: 'search ',
"paginate":{
'previous':'previous page',
'next':'next page',
},
"lengthMenu": "_MENU_",
"info": "showing _START_ to _END_ total _TOTAL_",
infoFiltered: "",
zeroRecords: "nothing found",
infoEmpty:""
},
dom: 'lBfrtip',
buttons: [
{
extend: 'excelHtml5',
exportOptions: {
columns: ':visible'
},
text:'excel',
},
],
})
}
})
<div class="card">
<section class="content">
<div class="container-fluid">
<div class="row">
<!-- /.col (LEFT) -->
<div class="col-md-12">
<!-- LINE CHART -->
<div class="card card-info">
<div class="card-header">
<h3 class="card-title">chart</h3>
</div>
<div class="card-body">
<div class="chart">
<canvas id="list_daily_prices_charts" style="height:400px; min-height:450px;"></canvas>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- /.card-header -->
<div class="card-body table-responsive">
<table class="table table-bordered table-striped text-center" id="list_daily_prices" style='width:100%'>
<thead>
<tr>
<th class="">id</th>
<th class="col-2">date</th>
<th class="col-1">quantity</th>
<th class="col-1">price</th>
<th class="col-1">income</th>
</tr>
</thead>
<tbody>
</tbody>
</tfoot>
</table>
</div>
</div>
thank you for your help
I have this 2 data tables below as you can see one of them is overlapping the data table and the other one is need to edit the width. I try to add width but don't have any effect on my first data table. Any suggestion about this two problems?.
HTML
<div class="row">
<div class="col-lg-6">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="row">
<div class="col-lg-6">
<i class="fa fa-list fa-fw"></i>Borrower Name
</div>
</div>
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="dataTable_wrapper">
<div class="col-lg-6">
<table class="table table-striped table-bordered table-hover table-responsive nowrap"
role="grid" style="width: 100%;" id="dtBorrowerName">
</table>
</div>
</div>
</div>
</div>
</div>
#*</div>
<div class="row">*#
<div class="col-lg-6">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="row">
<div class="col-lg-6">
<i class="fa fa-list fa-fw"></i>Book
</div>
</div>
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="dataTable_wrapper">
<div class="col-lg-6">
<table class="table table-striped table-bordered table-hover table-responsive nowrap"
role="grid" style="width: 10%;" id="dtBook">
</table>
</div>
</div>
</div>
</div>
</div>
</div>
JS CODE
var dtBorrowerName = $('#dtBorrowerName').DataTable({
responsive: true,
processing: true,
info: true,
search: true,
stateSave: true,
order: [[1, "desc"]],
lengthMenu: [[5, 10, 20, -1], [5, 10, 20, "All"]],
ajax: { "url": "/LS/GetBorrower" },
columns:
[
{ data: "BorrowerID", title: "", visible: false, searchable: false },
{ data: "IDNo", title: "ID Number" },
{ data: "Name", title: "Complete Name", sClass: "alignRight", width: " 100px" },
{ data: "BookTransactionHdrID", title: "BookTransactionHdrID", visible: false, searchable: false }
]
});
function GetStudentBook(getId) {
if (getId != 0 || getId != undefined || getId != "") {
dtStudBook = $('#dtBook').DataTable({
responsive: true,
processing: true,
info: true,
retrieve: true,
destroy: true,
search: true,
stateSave: true,
lengthMenu: [[5, 10, 20, -1], [5, 10, 20, "All"]],
ajax: {
"url": "/LS/GetStudentBook",
"data": function (d) {
d.BookTransactionDtlID = getId;
}
},
columns:
[
{ data: "BookId", title: "", visible: false, searchable: false },
//{ data: "Barcode", title: "Barcode", searchable: false },
{ data: "Author", title: "Author" }
// { data: "Title", title: "Title", sClass: "alignRight" },
// { data: "DatePublish", title: "Date Publish", sClass: "alignRight" },
// { data: "PlacePublish", title: "Place Publish" },
// { data: "NameOfPublisher", title: "Name Of Publisher"},
// { data: "ISBN", title: "ISBN"},
// { data: "BookTransactionDtlID", title: "", visible: false }
]
});
}
else {
//do nothing..
}
}
I hit this problem. It is caused by the length of the table headers and the padding around them. (I am assuming that it looks OK if the panel is wide?).
The solution is to write complicated JS to split words like "Publisher" or (as I did in the end) use Bootstrap visibility to show normal words on larger screens and use abbreviations on smaller screens (I found I had to write extra media queries to clean this up).
You may need a tooltip or whatever to explain your abbreviations. You are rather trying to fit a quart into a pint pot (that is a lot of headings for a small panel if you want them orderable etc) I think it will take quite a bit of hand crafting with very specific media queries.
Hope that helps.
I am new to Django. I am making polls application and want to use highcharts to display graphs. I have a template which displays all the polls. I want to show the corresponding results of poll beside it in form of chart. Part of the template:
{% for question in poll_questions %}
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-sm-12">
{{question.question_text}}
{% for choice in question.poll_choices_set.all %}
<div>
<label><input type="radio" name="{{question.pk}}" value="{{ choice.pk }}">  {{choice.choice_text}}</label>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div id="{{ question.pk }}" class="chart" style="height: 400px; width: 400px"></div><br>
<script>
var question_id = '{{ question.pk }}'
</script>
<script src="{% static 'er_interface/polls.js' %}"></script>
</div>
{% endfor %}
Javascript file- polls.js:
$.getJSON('/er/poll/'+question_id ,function(data) {
$('#'+question_id).highcharts({
chart: {
type: 'pie'
},
title: {
text: question_id
},
tooltip: {
pointFormat: ':<b>{point.y}</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
},
series: {
dataLabels: {
enabled: true,
formatter: function() {
return Math.round(this.percentage*100)/100 + ' %';
},
distance: 0,
}
}
},
series: data
});
});
The problem is that graph is shown just for the last poll question. Thanks
This is because in each of the for loops, question_id is overwritten. You might want to do something like this instead:
$('.chart').each(function() {
var that = this;
var question_id = $(this).attr('id');
$.getJSON('/er/poll/'+question_id ,function(data) {
$(that).highcharts({
...
That way, after rendering the page, you loop through each of the divs and render the appropriate chart.
Even better: use data-id="{{ book.id }}" and retrieve it with $(this).data('id') do avoid using the id attribute for something it's not really meant for.
I'm sure that someone already encountered this problem and posted here, but I just couldn't find it. So sorry for the dupe.
I am making a dashboard where there has to be a chart for every data set from the database.
I tried doing it with sending the data to a directive and draw the chart from within the directive's controller with the data passed to the directive.
This is the partial view
<div class="row">
<div class="col col-md-9">
<input type="text" class="form-control" ng-model="nameFilter" placeholder="Search for...">
</div>
</div>
<div class="row" ng-if="loading">
<div class="col col-md-6 col-md-offset-3">
<img src="../img/loader.gif"/>
</div>
</div>
<div class="row" ng-repeat="app in apps | filter: nameFilter">
<app-card name="app.name" android="app.android" ios="app.ios" date="app.date"></app-card>
</div>
The partial sends data to the directive
var app = angular.module('app');
app.directive('appCard', function() {
return {
restrict: 'E',
scope: {
name: '=name',
android: '=android',
ios: '=ios',
date: '=date'
},
templateUrl: 'http://testsite.nl/dashboard/partials/directives/app-card.html'
};
});
The directives template
<div class="panel panel-info app-card" ng-controller="appCardController">
<div class="panel-heading">
<div class="row">
<h4 class="col col-md-5">{{name}}</h4>
</div>
</div>
<div class="panel-body">
<div class="col col-md-12">
<h3>Android downloads: {{android}}</h3>
<h3>iOS downloads: {{ios}}</h3>
<div id="container" style="min-width: 310px; height:250px; margin: 0 auto;"></div>
</div>
</div>
</div>
And the controller looks like this
app.controller('appCardController', ['$scope', function($scope){
console.log("Downloads: " + $scope.android);
Highcharts.chart('container', {
chart: {
type: 'area'
},
title: {
text: 'Aantal downloads'
},
xAxis: {
allowDecimals: false,
categories: $scope.date
},
yAxis: {
title: { text:'Donwloads' },
floor: 0,
ceiling: getMaxDownloadCount()
},
tooltip: {
pointFormat: '{series.name} <b>{point.y:,.0f}</b>'
},
series: [{
name: 'Android',
data: convertAndroidArrayToInts($scope.android)
},
{
name: 'iOS',
data: convertIosArrayToInts($scope.ios)
}]
});
function convertAndroidArrayToInts(array){
var androidArray = new Array();
for(var i =0; i < array.length; i++){
androidArray.push(parseInt(array[i]));
}
return androidArray
}
function convertIosArrayToInts(array){
var iosArray = new Array();
for(var i =0; i < array.length; i++){
iosArray.push(parseInt(array[i]));
}
console.log(iosArray);
return iosArray
}
}]);
It shows the directive templates with the correct name and array values, the only problem is that there is only one chart drawn, which is the chart beloning to the last item in the list, but it is located in the first template.
How would I be able to make it so every template contains a chart beloning to its data?
I answered a very similar question related to using angular-chart, see my plunker here: https://plnkr.co/edit/8fJ4u0U2fL4lYTioCbG0?p=preview
The question/answer here: angular ng-repeat with directive
The actual issue you face is that the ID is container, and you cannot have duplicate "id" attributes in the DOM, so it will only find the first one.
Assuming the "name" is unique, change the controller so it uses the directives scope.name on Highchart.chart and change the directive template so the <div id="container"> becomes <div id="{{name}}"
After this you should have unique ID's and it will work
Hope that makes sense.
I have a highchart pie chart and a table to the right of the pie chart which displays the data in table form.
I would like to link the table with the pie chart so that when I hover over a row in the table it will be as if I am hovering over the pie chart segment.
I believe to do this I would need to add a class to the pie chart segment/path that I can then call using JS when hovering over the table row.
What would be the best way to either achieve this?
(I know it's possible to have a basic legend attached to the pie chart but because I need the table to be in a bootstrap column to the right along with some other data the legend isn't enough :) ).
Here is the current chart setup:
<!-- in Page JS -->
<script>
$(function () {
$('#results_donut').highcharts({
chart: {
type: 'pie'
},
title: {
text: false
},
credits: {
enabled: false
},
plotOptions: {
pie: {
dataLabels: {
enabled: false
},
shadow: false,
},
series: {
states: {
hover: {
enabled: false
}
},
point: {
events: {
mouseOver: function () {
this.options.oldColor = this.color;
this.graphic.attr("fill", "#F8464A");
},
mouseOut: function () {
this.graphic.attr("fill", this.options.oldColor);
}
}
},
}
},
tooltip: {
enabled: false,
formatter: function() {
return this.point.name + ': ' + this.y +' %';
},
style: {
fontFamily: 'Open Sans',
fontWeight: '300',
letterSpacing: '0.03em',
fontSize: '14px'
},
},
series: [{
name: 'Failure Reasons',
innerSize: '50%',
data: [["Brakes",74.6],["Seatbelts", 19.4]],
}],
});
});
</script>
And here is the view code:
<div class="row">
<div class="col-xs-12 col-sm-6">
<div id="results_donut"></div>
</div>
<div class="col-xs-12 col-sm-6 result-figures">
<div class="row failure-reasons">
<div class="col-xs-12">
<h4>Failure Reasons</h4>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<table class="table table-condensed table-hover">
<tbody>
<tr>
<td class="col-xs-6 text-uppercase failure-name">Brakes</td>
<td class="col-xs-2">74.6%</td>
<td class="col-xs-4 text-center">
<a class="transition" href="#">View Details</a>
</td>
</tr>
<tr>
<td class="col-xs-6 text-uppercase failure-name">Seatbelts</td>
<td class="col-xs-2">19.4%</td>
<td class="col-xs-4 text-center">
<a class="transition" href="#">View Details</a>
</td>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>