Related
The legend labels are not in the DOM when using time series data.
I have around 1500 data points. Here is reduced it to 3 because it seems like the amount of data points is not the cause of the issue.
Is this a bug or did I misconfigure something?
I also tried using a separate div for the legend (like described here but it seems to have no effect.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AmCharts</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="http://cdn.date-fns.org/v2.0.0-alpha0/date_fns.min.js"></script>
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<style>
html, body {
font-size: 16px;
}
#chartdiv,
#legenddiv {
width: 100%;
height: 500px;
border: 1px dotted #c99;
margin: 1em 0;
}
#legenddiv {
height: 150px;
}
</style>
</head>
<body>
<div id="chartdiv"></div>
Legend:
<div id="legenddiv"></div>
<script src="./main.js"></script>
</body>
</html>
am4core.ready(function () {
am4core.useTheme(am4themes_animated); // theming
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.data = [{
"date": 1574861644000,
"value": 13505
},
{
"date": 1574861645000,
"value": 13505
},
{
"date": 1574861645000,
"value": 13492
}];
// Create axes
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.baseInterval = { timeUnit: "second", count: 1 };
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = "value";
series.dataFields.dateX = "date";
series.tooltipText = "{value}";
series.tooltip.pointerOrientation = "vertical";
chart.cursor = new am4charts.XYCursor();
chart.cursor.snapToSeries = series;
chart.cursor.xAxis = dateAxis;
// create a legend for the sensors
chart.legend = new am4charts.Legend();
let legendContainer = am4core.create("legenddiv", am4core.Container);
legendContainer.width = am4core.percent(100);
legendContainer.height = am4core.percent(100);
chart.legend.parent = legendContainer;
}); // end am4core.ready()
By default the legend will look at the series' name property to use as the legend label as documented here. Adding this to your series will fix the problem, e.g. series.name = "Series #1"
I have a django application with this model.py:
from __future__ import unicode_literals
from django.db import models
class Events(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=100,null=True,blank=True)
start = models.DateTimeField(null=True,blank=True)
end = models.DateTimeField(null=True,blank=True)
def __str__(self):
return self.name
this view.py:
from django.shortcuts import render
from django.http import JsonResponse
from mycalendars.models import Events
def calendar(request):
all_events = Events.objects.all()
context = {
"events":all_events,
}
return render(request,'calendar.html',context)
def add_event(request):
start = request.GET.get("start", None)
end = request.GET.get("end", None)
title = request.GET.get("title", None)
event = Events(title=str(title), start=start, end=end)
event.save()
data = {}
return JsonResponse(data)
def remove(request):
id = request.GET.get("id", None)
event = Events.objects.get(id=id)
event.delete()
data = {}
return JsonResponse(data)
this urls.py:
from django.conf.urls import url
from django.contrib import admin
from mycalendars import views
urlpatterns = [
url('^calendar', views.calendar, name='calendar'),
url('^add_event$', views.add_event, name='add_event'),
url('^remove', views.remove, name='remove'),
]
in templates I have the calendar.html with all the full calendar like this:
<html><head>
<link href='https://unpkg.com/#fullcalendar/core#4.4.0/main.min.css' rel='stylesheet' />
<link href='https://unpkg.com/#fullcalendar/daygrid#4.4.0/main.min.css' rel='stylesheet' />
<link href='https://unpkg.com/#fullcalendar/timegrid#4.4.0/main.min.css' rel='stylesheet' />
<script src='https://unpkg.com/#fullcalendar/core#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/interaction#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/daygrid#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/timegrid#4.4.0/main.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var Calendar = FullCalendar.Calendar;
var Draggable = FullCalendarInteraction.Draggable;
var containerEl = document.getElementById('external-events');
var calendarEl = document.getElementById('calendar');
new Draggable(containerEl, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
return {
title: eventEl.innerText,
duration: '24:00',
};
}
});
var calendar = new Calendar(calendarEl, {
events: [
{% for event in events %}
{
title: "{{ event.title}}",
start: '{{ event.start|date:"Y-m-d" }}',
end: '{{ event.end|date:"Y-m-d" }}',
id: '{{ event.id }}',
},
{% endfor %}
],
plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
editable: true,
selectable: true,
selectHelper: true,
eventLimit: true,
droppable: true,
eventRender: function(info) {
var descrip = info.event.title;
if (descrip.indexOf('Birthday') !== -1) {
info.el.firstChild.setAttribute("style", "background-color: red;");
} else if (descrip.indexOf('Medical') !== -1) {
info.el.firstChild.setAttribute("style", "background-color: blu;");
} else if (descrip.indexOf('Work') !== -1) {
info.el.firstChild.setAttribute("style", "background-color: green;");
}
eventReceive: function (info) {
var title = info.event.title;
var start = moment(info.event.start).format('YYYY-MM-DD hh:mm');
var end = moment(info.event.end).format('YYYY-MM-DD hh:mm');
$.ajax({
type: "GET",
url: '/add_event',
data: {'title': title, 'start': start, 'end': end},
dataType: "json",
success: function (data) {
calendar.refetchEvents();
alert("Added Successfully");
},
failure: function (data) {
alert('There is a problem!!!');
}
});
},
eventClick: function (info) {
if (confirm("Are you sure you want to remove it?")) {
var id = info.event.id;
$.ajax({
type: "GET",
url: '/remove',
data: {'id': id},
dataType: "json",
success: function (data) {
calendar.refetchEvents();
alert('Event Removed');
},
failure: function (data) {
alert('There is a problem!!!');
}
});
}
},
});
calendar.render();
});
</script>
<style>
#external-events {
position: fixed;
z-index: 2;
top: 20px;
left: 20px;
width: 150px;
padding: 0 10px;
border: 1px solid #ccc;
background: #eee;
}
.demo-topbar + #external-events {
top: 60px;
}
#external-events .fc-event {
margin: 1em 0;
cursor: move;
}
#calendar-container {
position: relative;
z-index: 1;
margin-left: 200px;
}
#calendar {
max-width: 900px;
margin: 20px auto;
}
</style>
</head><body>
<div id='external-events'>
<p>
<strong>Type of event:</strong>
</p>
<div class='fc-event' style="background-color:red">Birthday</div>
<div class='fc-event' style="background-color:blu">Medical</div>
<div class='fc-event' style="background-color:green">Work</div>
</div>
<div id='calendar-container'>
<div id='calendar'></div>
</div>
</html>
Now my question, when I drag and drop the label work, medical or birthday into the calendar this will ben render correctly but if I try to canel one with the event click on one of thoose I get an error. I notice the events will not be updated ( I have the events in my daabase, but non in current page) if I reload the page the new events will be loaded.
I read a lot of posts said my events is static but they are not static after $ajax get /add_event or /remove the data should be reloaded with the calendar.refetchEvents() . I tried to add an eventSource, I tried to have e new view in my djago view.py with list_event with JSON events, but none of those works.
Any hints is welcome.
Thanks in advance
thanks to all I found a solution:
I put in javascript:
events: {
url :'/all_events',
},
and in views.py and urls.py I add
def all_events(request):
data = Events.objects.filter().values('id', 'title', 'start', 'end')
json_str = simplejson.dumps(list(data), cls=DjangoJSONEncoder)
return HttpResponse(json_str , content_type='application/json')
and
...
url('^all_events', views.all_events, name='all_events'),
Now the fetchEvents is working.
I am gettting this below error when i try to draw a line graph. i dont understand where i am doing wrong
ReferenceError: CAE is not defined
[ "January 16",CAE,18],
Nationa...ers.jsp (line 11, col 36)
Error: Invalid row type for row 0
Here is my code
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# page import="java.sql.*" %>
<%# page import="java.io.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript">
var theData = [ // Start of JavaScript data object
<%
Class.forName("oracle.jdbc.OracleDriver").newInstance();
String connectionURL = "someurl";
Connection connection = null;
connection = DriverManager.getConnection(connectionURL);
PreparedStatement ps = connection.prepareStatement("SELECT TRIM(TO_CHAR(order_date, 'Month')) ||' '|| TO_CHAR(order_date, 'yy') month, order_channel, total FROM ( SELECT order_date, order_channel, COUNT(*) total FROM order_channel WHERE order_date >= TO_DATE('01-Jan-2016', 'dd-Mon-yyyy') GROUP BY order_date, order_channel) ORDER BY TO_DATE(order_date), order_channel");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
%>
[ "<%= rs.getString(1)%>",<%= rs.getString(2)%>,<%= rs.getString(3)%>],
<%
};
// End of JavaScript object holding the data
%>
];
</script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:['corechart', 'Bar']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([['Month', 'OrderChannel', 'Total']].concat(theData), false);
var options = {
title: 'National Monthly Orders',
hAxis: {
title: 'Month of Orderdate'
},
vAxis: {
title: 'Distinct count'
},
legend:{position:'none'}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="chart_div" style="width: 1000px; height: 350px;"></div>
</body>
</html>
looks like the second column should be type: 'string'
try this...
["<%= rs.getString(1)%>", "<%= rs.getString(2)%>", <%= rs.getString(3)%>]
vs.
["<%= rs.getString(1)%>", <%= rs.getString(2)%>, <%= rs.getString(3)%>]
I have tried to pass some array data to google charts but it says not enough columns to draw chart.here is my code.
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var someStr = '["JAN","1088626"],["FEB","1478093"],["MAR","1232870"],["APR","1151634"],["MAY","1083623"],["JUN","740591"],["JUL","769227"],["AUG","1162995"],["SEP","951794"],["OCT","884736"],["NOV","500902"],["DEC","1221438"]';
var data1=someStr.replace(/(["'])(\d+)\1/g,"$2")
console.log(data1);
var data = google.visualization.arrayToDataTable([['year'],[data1]]);
console.log(data);
var options = {
title: 'My Daily Activities',
is3D: true,
};
var chart = new google.visualization.PieChart(document.getElementById('piechart_3d'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="piechart_3d" style="width: 900px; height: 500px;"></div>
</body>
</html>
Please help me to do this.
Thank in advance.
Your data has two columns: Month and a Number. ("JAN","1088626")
But you're only providing a header for one column: year
Plus, you need to pass an actual array to arrayToDataTable. (not a string)
Try something like this...
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var someStr = '["JAN","1088626"],["FEB","1478093"],["MAR","1232870"],["APR","1151634"],["MAY","1083623"],["JUN","740591"],["JUL","769227"],["AUG","1162995"],["SEP","951794"],["OCT","884736"],["NOV","500902"],["DEC","1221438"]';
var data1 = JSON.parse('[' + someStr.replace(/(["'])(\d+)\1/g,"$2") + ']');
// data array - add two column headings to data1
data1.splice(0, 0, ['month', 'number']);
// data table
var data = google.visualization.arrayToDataTable(data1);
// chart options
var options = {
title: 'My Daily Activities',
is3D: true
};
// chart
var chart = new google.visualization.PieChart(document.getElementById('piechart_3d'));
chart.draw(data, options);
}
<script src="https://www.google.com/jsapi"></script>
<div id="piechart_3d" style="width: 900px; height: 500px;"></div>
You are getting this error since invalid input data is passed into google.visualization.arrayToDataTable function. The provided regex /(["'])(\d+)\1/g fails while parsing the input string, i would suggest to parse input string with JSON.parse function.
google.visualization.PieChart object expects data to be provided in
the following format:
var data = google.visualization.arrayToDataTable([
['Name', 'Value'],
['<name1>', <value1>],
['<name2>', <value2>],
['<name3>', <value3>],
...
['<namen>', <valuen>]
]);
Below is provided the modified example:
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
var stringData = '["JAN","1088626"],["FEB","1478093"],["MAR","1232870"],["APR","1151634"],["MAY","1083623"],["JUN","740591"],["JUL","769227"],["AUG","1162995"],["SEP","951794"],["OCT","884736"],["NOV","500902"],["DEC","1221438"]';
var data = JSON.parse("[" + stringData + "]");
data = data.map(function (item) {
item[1] = parseInt(item[1]);
return item;
});
data.splice(0, 0, ['year', 'hours']);
var dataTable = google.visualization.arrayToDataTable(data);
var options = {
title: 'My Daily Activities',
is3D: true,
};
var chart = new google.visualization.PieChart(document.getElementById('piechart_3d'));
chart.draw(dataTable, options);
}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div id="piechart_3d" style="width: 900px; height: 500px;"></div>
I've been using Google Fusion Tables periodically for a few years, though I'm still a novice.
I've recently been charged with querying one of my tables on a geo-spatial relationship. I found a great example that functions exactly as I need it to, and updated the code with my tableId, ensured that the location column was exactly the same (spelling, capitalization, etc), but when I try to update the map layer, it gives me a permanent "Data may still be loading. Drag or refresh to find out!" on the tiles. My table is public, the data downloadable... I'm not sure what I'm missing.
I'm stumped. I've included the code below and simply used // to disable the tableid from the example.
Any assistance/suggestions would be greatly appreciated!
~Nicole
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Austin TX Delivery Locations</title>
<style>
body { font-family: Arial, sans-serif; padding: 0px; margin: 0px; }
#map_canvas { height: 80%; width:100%; }
#query{font-family:courier;}
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var tableid = '11QnfV_1v3N5GQs70e13SRxGR6_zYOSFJlCpMuD3C';
//var tableid = 790805;
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(30.35, -97.70),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(map, 'click', function(event) {
latlng = event.latLng;
updateQuery();
});
query = {
select: 'address',
from: tableid
}
layer = new google.maps.FusionTablesLayer(tableid);
layer.setMap(map);
}
function updateQuery(){
var limit = document.getElementById('limit').value;
var lat = parseInt(latlng.lat() * 1000) / 1000;
var lng = parseInt(latlng.lng() * 1000) / 1000;
query = "SELECT address FROM " + tableid;
query += " ORDER BY ST_Distance(address, LatLng(" + lat + ',' + lng + "))";
query += " LIMIT " + limit;
layer.setQuery(query);
document.getElementById('query').innerHTML = layer.getQuery();
}
</script>
</head>
<body onLoad="initialize()">
<div id="map_canvas"></div>
<input type="text" id="limit" value="50" onChange="javascript:updateQuery()"/>
<div id="query"></div>
</body>
</html>
When you see the ""Data may still be loading." message it usually means your query is invalid.
Your example has an old "numeric" table id. The syntax for the new "encrypted" table ids is different (and as currently documented)
Constructor Description
FusionTablesLayer(options:FusionTablesLayerOptions) A layer that displays data from a Fusion Table.
Change:
query = {
select: 'address',
from: tableid
}
layer = new google.maps.FusionTablesLayer(tableid);
layer.setMap(map);
To:
query = {
select: 'address',
from: tableid,
};
layer = new google.maps.FusionTablesLayer({query: query });
layer.setMap(map);
And your query in updateQuery to:
query = {
select: 'address',
from: tableid,
limit: limit,
orderBy: ST_Distance(address, LATLNG(" + lat + ',' + lng + "))"
}
layer.setQuery(query);
working fiddle
code snippet:
var tableid = '11QnfV_1v3N5GQs70e13SRxGR6_zYOSFJlCpMuD3C';
//var tableid = 790805;
var latlng;
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(30.35, -97.70),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(map, 'click', function(event) {
latlng = event.latLng;
updateQuery(latlng);
});
query = {
select: 'address',
from: tableid
};
layer = new google.maps.FusionTablesLayer({
query: query
});
layer.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
function updateQuery(latlng) {
var limit = document.getElementById('limit').value;
query = {
select: 'address',
from: tableid,
limit: limit,
orderBy: 'ST_Distance(address, LATLNG(' + latlng.lat() + ',' + latlng.lng() + '))'
}
layer.setQuery(query);
var queryObj = layer.getQuery()
var queryStr = "from:" + queryObj.from + "<br>";
queryStr += "select:" + queryObj.select + "<br>";
queryStr += "limit:" + queryObj.limit + "<br>";
queryStr += "orderBy:" + queryObj.orderBy + "<br>";
document.getElementById('query').innerHTML = queryStr;
}
html,
body {
font-family: Arial, sans-serif;
padding: 0px;
margin: 0px;
height: 100%;
width: 100%;
}
#map_canvas {
height: 80%;
width: 100%;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas"></div>
<input type="text" id="limit" value="50" onChange="javascript:updateQuery()" />
<div id="query"></div>