JavaScript Variable and passing data issues - javascript

I have an issue in that the $.getJSON segment of code works fine and produces a variable called 'zippy'. I need to access 'zippy' under 'series: data' further down in the code.
I have tried a number of things unfortunately I can't make it work. The easiest would be way to 'return data' $.getJSON(jsonUrl,function(zippy) out of the function(zippy) call but I'm lost as to how to make that data available.
$(function() {
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
console.log("+++++++++++++++++++++++++++++++++++++");
var jsonUrl = "http://www.someurl.com/thing.php?callback=?";
$.getJSON(jsonUrl, function(zippy) {
for(i = 0; i < zippy.cpmdata.length; i++) {
console.log("TIMESTAMP: " + zippy.cpmdata[i].timestamp + " AFTER: ");
zippy.cpmdata[i].timestamp = Date.parse(zippy.cpmdata[i].timestamp).getTime() / 1000;
//var unixtime Date.parse(temptime).getTime()/1000
console.log(" TESST " + zippy.cpmdata[i].timestamp + " \r\n");
}
});
console.log("+++++++++++++++++++++++++++++++++++++");
var chart;
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'spline',
marginRight: 10,
events: {
load: function() {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.random();
series.addPoint([x, y], true, true);
}, 1000);
}
}
},
series: [{
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
console.log("++NEED ACCESS HERE FOR ZIPPY++");
console.log(" =============== \r\n");
console.log(" FINAL " + zippy.cpmdata[5].timestamp + " \r\n");
return data;
})()
}]
}

Your problem is that getJSON is asynchronous. What's happening in your code is this:
document.ready is triggered
getJSON is called and registers a callback "function(zippy)"
note that getJSON returns immediately without executing the callback
You try to draw a chart using HighCharts
... several hundred milliseconds later
The browser makes the JSON request
... several hundred milliseconds later
The JSON request returns with data and triggers the
callback to "function(zippy)"
"function(zippy)" is executed
So you see. The problem is not how "function(zippy)" is executed but when it is executed. As such, you cannot execute code that wants to use the return value of the JSON request outside of the callback function. (Actually you can but we'll ignore polling with setTimeout or using synchronous ajax for now)
The solution is to move all the code that you want to run later on inside the callback function:
$.getJSON(jsonUrl, function(zippy) {
for(i = 0; i < zippy.cpmdata.length; i++) {
console.log("TIMESTAMP: " + zippy.cpmdata[i].timestamp + " AFTER: ");
zippy.cpmdata[i].timestamp = Date.parse(zippy.cpmdata[i].timestamp).getTime() / 1000;
//var unixtime Date.parse(temptime).getTime()/1000
console.log(" TESST " + zippy.cpmdata[i].timestamp + " \r\n");
}
var chart;
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'spline',
marginRight: 10,
events: {
load: function() {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.random();
series.addPoint([x, y], true, true);
}, 1000);
}
}
},
series: [{
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
console.log(" FINAL " + zippy.cpmdata[5].timestamp + " \r\n");
return data;
})()
}]
});

You need to put all of the new Highcharts.Chart({...}) stuff inside the getJSON callback, because you need to wait until the json request completes before creating the chart. See my code comment that says CUT AND PASTE chart = new Highcharts.Chart({...}) STUFF HERE!!!.
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
console.log("+++++++++++++++++++++++++++++++++++++");
var jsonUrl = "http://www.someurl.com/thing.php?callback=?";
$.getJSON(jsonUrl, function(zippy) {
for(i = 0; i < zippy.cpmdata.length; i++) {
console.log("TIMESTAMP: " + zippy.cpmdata[i].timestamp + " AFTER: ");
zippy.cpmdata[i].timestamp = Date.parse(zippy.cpmdata[i].timestamp).getTime() / 1000;
//var unixtime Date.parse(temptime).getTime()/1000
console.log(" TESST " + zippy.cpmdata[i].timestamp + " \r\n");
// CUT AND PASTE chart = new Highcharts.Chart({...}) STUFF HERE!!!
}
});
console.log("+++++++++++++++++++++++++++++++++++++");
});

Related

Highcharts does not render values received from Flask-socketio

var myChart = Highcharts.chart('containerX', {
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
var socket = io.connect('http://' + document.domain + ':' + location.port + '/test');
var series = this.series[0]
var numbers_received = []
socket.on('newnumber', function(msg) {
var x = (new Date()).getTime() // current time
var y = msg.number
series.addPoint([x, y], true, true);
});
......
The x-axis of Highchart is moving on my HTML page based on the (new Date()).getTime(), and the y-axis is scaling based on the value received from flask-socketio, but nothing is displayed on the chart.
ps: The value received is changing every seconds.
Also I can see the value msg.number showing on the terminal.
Can anyone help? I am new to highcharts and flask-socketio. Thanks.
You need to pass y values to the addPoint method as numbers not as strings.
var y = parseFloat(msg.number);
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/4908/

How to filter Tasks to show only the active ones?

Hello i try to query the tasks from sharepoint 2013 with javascript.
This is what i got so far:
var context = new SP.ClientContext.get_current();
var userSessionManager = new SP.WorkManagement.OM.UserOrderedSessionManager(context);
var userSession = userSessionManager.createSession();
var userSettingsManager = new SP.WorkManagement.OM.UserSettingsManager(context);
var locations = userSettingsManager.getAllLocations();
var locationFilter = userSettingsManager.locationFilter
var query = new SP.WorkManagement.OM.TaskQuery(context);
var myTasks = userSession.readTasks(query);
var task;
var tasks = [];
var overDue = [];
var dueSoon = [];
var anTimeDue = [];
var dateForEvaluation = new Date();
getMyTasks();
function getMyTasks() {
context.load(locations);
context.load(myTasks);
context.executeQueryAsync(onGetMyTasksSuccess, onGetMyTasksFail);
}
function onGetMyTasksSuccess() {
console.log("Successfully retrieved tasks...");
var taskEnumerator = myTasks.getEnumerator();
while (taskEnumerator.moveNext()) {
task = taskEnumerator.current;
//console.log("Task: " + task.get_id() + " - Taskname: " + task.get_name() + " - Beschreibung: " + task.get_description() + " - dueDatum: " + task.get_dueDate() + " - Startdatum: " + task.get_startDate() + " - Persönlich: " + task.get_isPersonal() + " - Fertiggestellt: " + task.get_isCompleted());
tasks.push({
taskName: task.get_name(),
description: task.get_description(),
dueDate: task.get_dueDate(),
startDate: task.get_startDate(),
personally: task.get_isPersonal(),
complete: task.get_isCompleted(),
location: task.get_locationId()
});
}
console.log(tasks);
console.log(locations)
}
// This function is executed if the above call fails
function onGetMyTasksFail(sender, args) {
console.log('Failed to get tasks. Error:' + args.get_message());
}
This code works but gives me always all Tasks back. I only need the not completed Tasks. Well i tried too look a the referenc pages but there are no code examples or anything.
So my question is how to filte the tasks to get only the not completed Tasks?
Any Advise or held would be great and thanks for your time.
As i discoverd the only working option for me is to us an if Statement where i query the is_completet method result.
Here is the now Working Code:
function onGetMyTasksSuccess() {
console.log("Successfully retrieved tasks...");
var taskEnumerator = myTasks.getEnumerator();
while (taskEnumerator.moveNext()) {
task = taskEnumerator.current;
if (task.get_isCompleted() === false) {
tasks.push({
taskName: task.get_name(),
description: task.get_description(),
dueDate: task.get_dueDate(),
startDate: task.get_startDate(),
personally: task.get_isPersonal(),
complete: task.get_isCompleted(),
location: task.get_locationId()
});
}
}
console.log(tasks);
countForForm(tasks);
}
The importend thing here is if (task.get_isCompleted() === false) its by no means perfect but i works good enough. Sadly the JavaScript API is not good documented for sharepoint sp.workmanagment.js.

Chart.js - Cannot read property 'getContext' of null

I have the following Javascript in my main.js file:
//array object of API stuff
function createChartWinLoss(wins, losses) {
var pieData = [
{
value: losses,
color: "#F7464A",
highlight: "#FF5A5E",
label: "Losses"
},
{
value: wins,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Wins"
}
];
var pieOptions = {
segmentShowStroke : false,
animateScale : true
}
var winLossChart = document.getElementById('winLossChart').getContext('2d');
new Chart(winLossChart).Pie(pieData, pieOptions);
}
//creates the chart with test data
createChartWinLoss();
function summonerLookUp() {
var SUMMONER_ID = "";
var API_KEY = "keyhere";
var sumID = $("#theKey").val();
var div = document.getElementById('stuff');
var combine = "";
var array = [sumID];
var wins;
var losses;
div.innerHTML = div.innerHTML + "<br />array count: " + array.length + "<br />";
for (var i = 0; i < array.length; i++) {
combine = "";
SUMMONER_ID = array[i];
getStuff(SUMMONER_ID, combine, API_KEY, div, i);
}
}
function getStuff(SUMMONER_ID, combine, API_KEY, div, count) {
var Topuser = SUMMONER_ID;
$.ajax({
url: 'https://euw.api.pvp.net/api/lol/euw/v2.5/league/by-summoner/' + SUMMONER_ID + '/entry?api_key=' + API_KEY,
type: 'GET',
dataType: 'json',
async: false,
data: {},
success: function (json) {
var user = Topuser;
if (typeof json[user][0].queue != "undefined") {
if (json[user][0].queue == "RANKED_SOLO_5x5") {
combine = json[user][0].tier + " " + json[user][0].entries[0].division + " - " + json[user][0].entries[0].wins + " Wins " + json[user][0].entries[0].losses + " losses";
div.innerHTML = div.innerHTML + "<br />" + count + ": " + user + " " + combine;
var wins = json[user][0].entries[0].wins;
var losses = json[user][0].entries[0].losses;
//populates chart with wins losses from api
createChartWinLoss(wins,losses);
}
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
var user = Topuser;
console.log(errorThrown);
if (errorThrown === "Not Found") {
div.innerHTML = div.innerHTML + "<br />" + count + ": " + user + " " + "UNRANKED";
}
}
});
}
And the HTML is as follows:
<div class="container">
<h2>Wins/Losses</h2>
<canvas id="winLossChart" width="400" height="200"></canvas>
</div>
As the title suggests, I am getting Uncaught TypeError: Cannot read property 'getContext' of null and I'm not entirely sure what the issue is. If I had to guess I'd say it was trying to reference something that wasn't there but I'm not 100% sure on if I am correct and how to fix it. Any advice would be great.
The line that is throwing the error is
var winLossChart = document.getElementById('winLossChart').getContext('2d');
It is saying that document.getElementById('winLossChart') does not exist.
This would be because your script is being interpreted before the elements have finished being created in the DOM.
You could either kick off the script in a window.onload function:
window.onload = function() {
createChartWinLoss();
}
Or you could put the script tag itself as the last element in the body element of your html file.
<body>
<div class="container">
<h2>Wins/Losses</h2>
<canvas id="winLossChart" width="400" height="200"></canvas>
</div>
<script src="myscript.js"></script>
</body>
Either solution would mean that the main entry point of your code (createChartWinLoss) would only happen after the other elements on the page, including the canvas, were created.
As a general process towards solving these kinds of problems, when you saw the exception in your Javascript console, you should have been able to open the stack trace, which would have led you to the fact that the error originated on the line var winLossChart = ..., which would have made you more likely to have been able to discover the source of the problem.
I was having this same problem. The element was being returned as dispHTMLUnkownElement.
The solution was to add <!DOCTYPE html>to the top of my response and then IE picked up the element type properly.
Perhaps this can help someone else...
You have to use destroy() method.
To made that you have to change a few things in your code:
var winLossChart = "";// Here you make your chart var global
function createChartWinLoss(wins, losses) {
var pieData = [{
value: losses,
color: "#F7464A",
highlight: "#FF5A5E",
label: "Losses"
}, {
value: wins,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Wins"
}];
var pieOptions = {
segmentShowStroke: false,
animateScale: true
}
//Here´s the change inside the function where you run destroy().
if(typeof winLossChart.destroy != "undefined") winLossChart.destroy();
winLossChart = document.getElementById('winLossChart').getContext('2d');
new Chart(winLossChart).Pie(pieData, pieOptions);
}
//creates the chart with test data...
https://github.com/chartjs/Chart.js/issues/3231

Javascript/jQuery plug-in Highcharts does not recognize my data array. Is it my syntax?

I have successfully called an ajax request to my rails db and grabbed the return data, putting each returned object's "level" and "date" values into an array within an array, or a coordinate pair in an array with my search() function (below). Next, that function calls drawChart(object_data) which should set the array within an array data to the series. Only problem is it's not working and I do not know why. The object_data array that I am putting in the chart falls in line with examples on the Highcharts website, but it does not seem to be working for some reason.
Search function:
function search() {
var full_date_from = $( "#from" ).datepicker("getDate");
var full_date_to = $( "#to" ).datepicker("getDate");
var date_from = full_date_from.getMonth()+1 + "-" + full_date_from.getDate() + "-" + full_date_from.getFullYear();
var date_to = full_date_to.getMonth()+1 + "-" + full_date_to.getDate() + "-" + full_date_to.getFullYear();
$.ajax({
url:"<%= url_for :controller => 'objects', :action => 'search' %>",
data:'date_from=' + encodeURIComponent(date_from) + '&date_to=' + encodeURIComponent(date_to) + '&river_id=' + <%= #id %>,
dataType: "json",
cache:false,
success:function (data) {
var levels = [];
var dates = [];
var object_data = [];
for (var i = 0; i < data.length; i++) {
var dt1 = parseInt(data[i].date.substring(8,10));
var mon1 = parseInt(data[i].date.substring(5,7));
var yr1 = parseInt(data[i].date.substring(0,4));
var date1 = Date.UTC(yr1, mon1-1, dt1);
levels[i] = data[i].level;
dates[i] = date1;
var temp = [dates[i], levels[i]];
object_data.push(temp);
}
drawChart(object_data);
}
});
}
drawChart function:
function drawChart(object_data)
{
var chart = $('#container').highcharts();
chart.series[0].setData(object_data);
}
chart initialization:
$(function () {
$('#container').highcharts({
xAxis: {
type: 'datetime'
},
series: [{
data: []
}]
});
});
The way you have it written, drawChart() is re-initializing Highcharts on #container every time you call it, effectively resetting any options you would have set.
You should only have to call $('#container').highcharts({...}); once.
Toss your empty initialization and change drawChart() to
function drawChart(object_data) {
$('#container').highcharts({
xAxis: { type: 'datetime' },
series: [{ data: object_data }]
});
}

google visualization multiple charts with own data queries

On my Google Visualization web page I want both a bar chart and an area chart but I can get only one or the other to display.
Each chart requires its own data and employs its own google.visualization.Query object against my own Python-based server. My initialize function calls the function to display the first chart, and at the bottom of the query response handler for the first chart, I'm calling the function to display the second chart. (I am doing this to make sure my second data query does not start until after the first chart is done drawing.) Each chart displays correctly when I code to draw only one chart at a time. But when I try to draw both charts, only the first chart ever draws even though I am verifying that both data queries are running and returning valid json responses, at the correct times.
Thanks for any help, BH
Edit 10/27/2013:
This post solved my problem:
Google Charts - "Missing Query for request id: 0"
To anyone implementing a Python data source, parse the reqId parameter like this:
import cgi
form = cgi.FieldStorage()
tqx = form.getvalue("tqx") # tqx comes back like "reqId:1"
req_id = int(tqx[tqx.find("reqId"): ].split(":")[1])
And pass it to the ToJSonResponse call:
response = data_table.ToJSonResponse(req_id=req_id,
columns_order=("vehicle_id", "num_events"))
print "Content-type: text/plain"
print
print response
Here is my updated code, which also uses the "ready" event.
<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(initialize);
var timelineDate1 = "";
var messageCountsDate1 = "";
var timeline_drawn = false;
var message_count_drawn = false;
function initialize()
{
drawTimeline();
}
function drawTimeline()
{
var rows = QueryString.rows || "4";
var date1 = QueryString.date1 || "2013-9-1"; // Date start
timelineDate1 = date1;
var page = parseInt(QueryString.page) || 1;
if (page < 1)
{
page = 1;
}
// Timeline
var url_timeline = "http://localhost/emit_event_timeline.py"
+ "?date1=" + date1 + "&rows=" + rows + "&page=" + page;
var query_timeline = new google.visualization.Query(url_timeline);
query_timeline.setTimeout(14400);
query_timeline.send(handleTimelineQueryResponse);
}
function handleTimelineQueryResponse(response)
{
var stack = parseInt(QueryString.stack) || 1
var timeline_options =
{
title: 'Event Count Timeline, ' + timelineDate1 + ' to Present',
vAxis: {title: 'Date', titleTextStyle: {color: 'red'}},
hAxis: {title: 'Event Count', titleTextStyle: {color: 'blue'}},
isStacked: stack
};
if (response.isError())
{
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var timeline_data_table = response.getDataTable();
var timeline_chart = new google.visualization.AreaChart(document.getElementById('timeline_div'));
google.visualization.events.addListener(timeline_chart, 'ready', timeline_chart_ready);
google.visualization.events.addListener(timeline_chart, 'error', errorHandler);
timeline_chart.draw(timeline_data_table, timeline_options);
}
function timeline_chart_ready()
{
timeline_drawn = true;
if (!message_count_drawn)
{
drawMessagecounts();
}
}
function mc_chart_ready()
{
message_count_drawn = true;
if (!timeline_drawn)
{
drawTimeline();
}
}
function drawMessagecounts()
{
var rows = QueryString.rows || "20";
var date1 = QueryString.date1 || "2013-9-1"; // Date start
messageCountsDate1 = date1
var page = parseInt(QueryString.page) || 1;
if (page < 1)
{
page = 1;
}
// Message counts
var url_message_counts = "http://localhost/emit_all_message_counts.py"
+ "?date1=" + date1 + "&page=" + page + "&rows=" + rows;
var query_message_counts = new google.visualization.Query(url_message_counts)
query_message_counts.setTimeout(14400);
query_message_counts.send(handleMessageCountQueryResponse);
}
function handleMessageCountQueryResponse(response)
{
var stack = parseInt(QueryString.stack) || 1
var mc_options =
{
title: 'Message Counts, ' + messageCountsDate1 + ' to Present',
vAxis: {title: 'Message Source', titleTextStyle: {color: 'red'}},
hAxis: {title: 'Message Count', titleTextStyle: {color: 'blue'}},
isStacked: stack
};
if (response.isError())
{
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var mc_data_table = response.getDataTable();
var mc_chart = new google.visualization.BarChart(document.getElementById('message_count_div'));
google.visualization.events.addListener(mc_chart, 'ready', mc_chart_ready);
google.visualization.events.addListener(mc_chart, 'error', errorHandler);
mc_chart.draw(mc_data_table, mc_options);
}
// Thanks to:
// https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values
var QueryString = function ()
{
// This function is anonymous, is executed immediately and
// the return value is assigned to QueryString!
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
// If first entry with this name
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = pair[1];
// If second entry with this name
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]], pair[1] ];
query_string[pair[0]] = arr;
// If third or later entry with this name
} else {
query_string[pair[0]].push(pair[1]);
}
}
return query_string;
} ();
function errorHandler(e)
{
// Called when an error occurs during chart processing
alert('Error handler: ' + e.message);
}
</script>
</head>
<body>
<div id="timeline_div" style="width:800px;height:500px;border:1px solid gray;float:left">
</div>
<div id="message_count_div" style="width:800px;height:500px;border:1px solid gray;float:left">
</div>
<div id="control_div" style="width:80px;height:60px;float:left">
</div>
</body>
</html>
The solution was for my Python data source to pass the reqId parameter from the request back on the json reqponse. This post solved my problem:
Google Charts - "Missing Query for request id: 0"

Categories

Resources