How to Update the value of point in Highchart? - json

I have a Highchart that is receiving JSON data via AJAX and jQuery in setInterval function,when i use series.data[i].y = response[i].y , the value of y is change ,but dosent Display in chart and the hight of point has previous value but in tooltip show recent value ? and the x value dosent changhe at all, please help me how to update the the x and y value if it is changhed?
chart:{ renderTo: 'container',
zoomType: 'xy',
plotBackgroundImage: 'graphics/skies.jpg',
events: {
load: function () {
var series = this.series[0];setInterval(function () {ajax({type: "POST",url: "/Home/GetData",data: null),contentType: "application/json; charset=utf-8",success: function (response) { for (var i = 0; i < response.length; i++) { if (series.data[i].y =response[i].y || series.data[i].category != response[i].x) { series.data[i].y =response[i].y; series.data[i].category = response[i].x;} }}, dataType: "json",failure: ajaxCallFailed });}, 50000);}

You should not directly modify the this.series[0] object. Highcharts has api calls that you can use, which should be uses for correct results and not breaking anything unintentionally.
Here is a list of methods supported by the series object # http://www.highcharts.com/ref/#series-object
You may want to use addPoint or setData, as per your requirements.
I don't recommend doing it the say you are doing, but try calling the redraw method (this.redraw()) after you do your magic, http://www.highcharts.com/ref/#chart-object

Related

Calculating total-items in AngularJs Pagination (ui.bootstrap) doesn't work correctly

I use controllerAs and avoid using the $scope as a model.
I want to add pagination in my search result. I have a paging object in my controller as below, which will be shared with angular service and then with the server API.
vm.paging = {
pageNumber: 1,
pageSize: 10,
totalCount: 0
};
totalCount will be set by server and then be read from response.
My pagination in html:
<pagination total-items="ctrl.pageCount"
items-per-page="ctrl.paging.pageSize"
ng-model="ctrl.paging.pageNumber"
class="pagination-sm"
boundary-links="true"
ng-change="ctrl.find()">
</pagination>
I calculate pageCount in controller as below:
vm.pageCount = function () {
return Math.ceil(vm.paging.totalCount / vm.paging.pageSize);
};
But it doesn't work. when I set vm.pageCount = 1000; it works. It seems the problem is the function. How can I fix this problem? (the buttons are disabled and It should return 100 pages, not one! )
Update: Sample Plunker
you CAN use an Immediately Invoked Function Expression (IFEE) to get your vm.pageCount like so
ctrl.pageCount = (function() {
return Math.ceil(ctrl.paging.totalItems / ctrl.paging.pageSize);
})();
but you don't need to calculate pageCount and put it under total-items (the amount of pages in the pagination will be calculated automatically), you should provide it the length of you record array instead!
lets say if you get table data vm.data from http, you should place the length of this data inside total-items like so
total-items="vm.data.length"
HTML
<uib-pagination total-items="ctrl.paging.totalItems"
items-per-page="ctrl.paging.pageSize"
ng-model="ctrl.paging.pageNumber"
class="pagination-sm"
boundary-links="true"
ng-change="ctrl.find()">
</uib-pagination>
JS
ctrl.paging = {
pageNumber: 1,
pageSize: 10,
totalItems: response.length // this is your remote data
};
I've made this plunker for you
EDIT 1
since version 0.14.0, the directives are prefixed by uib-
Since version 0.14.0 we started to prefix all our components. If you are upgrading from ui-bootstrap 0.13.4 or earlier, check our migration guide.
so you should also use uib-pagination (instead of pagination) because your plunk uses the 1.3.2 version.
I did it! Of course, with the guidance of my colleague :) . As in my plunk (script.js), I hadn't Initialized the vm.paging object after the response, so the computing was based on default values in vm.paging. Since totalCount was 0, always the Division result was 1 and I had just one page. So I edited the vm.find body as below:
vm.find = function () {
vm.result.length = 0;
vm.findingPromise = myService.find(vm.filter, vm.paging);
vm.findingPromise
.then(function (response) {
vm.result = response.data.result;
// EDITED PART:
vm.paging = response.data.paging;
//
}, function (response) {
var r = response;
ngNotify.set('Some problems occurred!',
{
type: 'error',
position: 'top',
sticky: true
});
});
And also, I couldn't take advantages of uib-pagination, but when I replaced ui-bootstrap-tpls-1.3.2.min.js anywhere I was using ui-bootstrap-tpls.min.js before, it works correctly.
Also I removed the function of computing pageCount. With many thanks to svarog.

Undefined variable error in jQuery

I am getting a JSON data with jQuery in real-time, later I am printing this data to screen. When I get data from screen and I print this on screen again, I take error "undefined". Codes:
var yenile = setInterval(function() {
$.getJSON("ayarlar.asp",function(veri) {
$(".wfloodnum").html("Şu anki değer:" + veri.floodwarno);
$(".nfloodnum").html("Şu anki değer:" + veri.floodnum);
});
},100);
var anlikwar = $(".wfloodnum").text().split(":")[1];
var anlikflood = $(".nfloodnum").text().split(":")[1];
alert(anlikflood);
What should I do?
EDIT: I cant access this variables' values out of $.getJSON function. And I need accessibilty for these value out of this function. So, I must define variables out of $.getJSON function. That's why I tried to apply .split() to text on a screen.
The problem with your code is that, because of the asynchronous call you have there the order of execution might look like this (of course it can differ because of the interval and multiple calls to the getJSON):
// 1. the call to setInterval is initiated (the function in it will not be called until the sequential instructions after setInterval are finished)
var yenile = setInterval(function() {...}, 100);
// 2
var anlikwar = $(".wfloodnum").text().split(":")[1];
// 3
var anlikflood = $(".nfloodnum").text().split(":")[1];
// 4
alert(anlikflood);
// 5. NOW COMES THE function given to setInterval
$.getJSON("ayarlar.asp",function(veri) { ... });
// 6. now would come any other instructions in the function given to setInterval after the getJSON
// 7.
$(".wfloodnum").html("Şu anki değer:" + veri.floodwarno);
// 8
$(".nfloodnum").html("Şu anki değer:" + veri.floodnum);
In the above sequence you see that at steps 2 and 3 the variables there are undefined because the element you access does not have any text yet. Or, it has empty string, split is by : and you get the array [""] and therefore the index 1 in this array is undefined.
You must re-think the structure of your code. At least the variables anlikwar and anlikwar should be assigned after the JSON request completes.
At least you coud do something like:
var anlikwar;
var anlikflood;
var yenile = setInterval(function() {
$.getJSON("ayarlar.asp",function(veri) {
$(".wfloodnum").html("Şu anki değer:" + veri.floodwarno);
$(".nfloodnum").html("Şu anki değer:" + veri.floodnum);
anlikwar = $(".wfloodnum").text().split(":")[1];
// or simply: anlikwar = veri.floodwarno
anlikflood = $(".nfloodnum").text().split(":")[1];
// or simply: anlikflood = veri.floodnum
});
},100);
It looks like you want to monitor something on the server. This looks like a WebSockets use case. Depending on the server framework you are using, there are different web socket packages you can use.

JSON results into a variable and store in hidden input field

I wrote code below that is working perfectly for displaying the results of my sales tax calculation into a span tag. But, I am not understanding how to change the "total" value into a variable that I can work with.
<script type="text/javascript">
function doStateTax(){
var grandtotalX = $('#GRANDtotalprice').val();
var statetaxX = $('#ddl').val();
$.post('statetax.php',
{statetaxX:statetaxX, grandtotalX:grandtotalX},
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
// ...
});
return false;
};
</script>
Currently, $('.total-placeholder').html(data.total); is successfully placing the total number into here:
<span class="total-placeholder"></span>
but how would I make the (data.total) part become a variable? With help figuring this out, I can pass that variable into a hidden input field as a "value" and successfully give a proper total to Authorize.net
I tried this and id didn't work (see the testtotal part to see what I'm trying to accomplish)..
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
$testtotal = (data.total);
// ...
If you are using a hidden field inside a form, you could do:
//inside $.post -> success handler.
$('.total-placeholder').html(data.total);
$('input[name=yourHiddenFieldName]', yourForm).val(data.total);
This will now be submitted along with the usual submit. Or if you want to access the data elsewhere:
var dataValue = $('input[name=yourHiddenFieldName]', yourForm).val();
The "data" object you are calling can be used anywhere within the scope after you have a success call. Like this:
$.post('statetax.php',
{statetaxX:statetaxX, grandtotalX:grandtotalX},
function(data) {
data = $.parseJSON(data);
var total = data.total;
var tax = data.total * 0.19;
});
return false;
};
Whenever you get an object back always try to see with an alert() or console.log() what it is.
alert(data); // This would return <object> or <undefined> or <a_value> etc.
After that try to delve deeper (when not "undefined").
alert(data.total); // <a_value>?
If you want 'testotal' to be recognized outside the function scope, you need to define it outside the function, and then you can use it somewhere else:
var $testtotal;
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
$testtotal = (data.total);
EDIT:
The comments are becoming too long so i'll try and explain here:
variables defined in javascript cannot be accessed by PHP and vice versa, the only way PHP would know about your javascript variable is if you pass it that variable in an HTTP request (regular or ajax).
So if you want to pass the $testtotal variable to php you need to make an ajax request(or plain old HTTP request) and send the variable to the php script and then use $_GET/$_POST to retrieve it.
Hope that answers your question, if not then please edit your question so it'll be clearer.

Highcharts: Updating a Pie Chart with setData()

I am trying to work out how to update a Highcharts pie chart but for the life of me cannot seem to get it working right.
I have looked over the documentation and have been able to get a bar and line and spline graph to update fine but when using this function for pie charts it just does not work.
I am currently feeding in:
item.setData([["none", 100]], true);
Where item equals the series like so:
$.each(browser_chart.series, function(i, item){
if(item.name == 'Browser share'){
console.log(data.browsers);
item.setData([["none", 100]], true);
}
});
Which as shown in the demos is how the data for a pie chart is formatted. Problem is it cannot seem to read the series correctly. I try:
item.setData([\"none\", 100], true);
And it seems to do something but cannot read the x and y values right (which of course means it's wrong).
Can anyone here point me in the direction to get this working?
Thanks,
Edited:
When you set a new data you have to set as array of arrays for all pie parts in this case.
In my Example I have six categories, so I've to set data for all of them.
So, in this case you have to do something like:
var seriesData = [];
$.each(browser_chart.series, function(i, item) {
if(item.name == 'Browser share'){
seriesData.push(["serie"+i, someNumber]);
}
});
chart.series[0].setData(seriesData, true);
I have marked Ricardos answer however my question involved a tad more that I didn't explain properly.
I was updating the pie chart through AJAX from JSON generated by a PHP Backend. When I applied new data to the pie chart it would break.
Using Ricardos answer I was able to find out it is because I have a different number of points so I cannot just update the pie chart I must remake it like so:
browser_chart_config.series[0].data = data.browsers;
browser_chart = new Highcharts.Chart(browser_chart_config);
This will allow you to update a chart when you have a different number of points.
Hope it helps,
EDIT: I also found out that this is a known issue with HighCharts: https://github.com/highslide-software/highcharts.com/issues/542
//initialise
var new_data;
new_data = [{ name: 'load percentage', y: 10.0, color: '#b2c831' },{ name: 'rest', y: 60.0, color: '#3d3d3d' }];
function requestData()
{
$.ajax({
url: 'live-server-data.php',
success: function(point)
{
var series = chart.series[0];
var y_val = parseInt(point[1]);
var x_val = 100 - y_val;
console.log(point[0]+ "," +point[1] );//["0"]
new_data = [{ name: 'load percentage', y:y_val, color: '#b2c831' },{ name: 'rest', y:x_val, color: '#3d3d3d' }];
series.setData(new_data);
// call it again after one second
},
cache: false
});
}

Looping through JSON with node.js

I have a JSON file which I need to iterate over, as shown below...
{
"device_id": "8020",
"data": [{
"Timestamp": "04-29-11 05:22:39 pm",
"Start_Value": 0.02,
"Abstract": 18.60,
"Editor": 65.20
}, {
"Timestamp": "04-29-11 04:22:39 pm",
"End_Value": 22.22,
"Text": 8.65,
"Common": 1.10,
"Editable": "true",
"Insert": 6.0
}]
}
The keys in data will not always be the same (i've just used examples, there are 20 different keys), and as such, I cannot set up my script to statically reference them to get the values.
Otherwise I could state
var value1 = json.data.Timestamp;
var value2 = json.data.Start_Value;
var value3 = json.data.Abstract;
etc
In the past i've used a simple foreach loop on the data node...
foreach ($json->data as $key => $val) {
switch($key) {
case 'Timestamp':
//do this;
case: 'Start_Value':
//do this
}
}
But don't want to block the script. Any ideas?
You can iterate through JavaScript objects this way:
for(var attributename in myobject){
console.log(attributename+": "+myobject[attributename]);
}
myobject could be your json.data
I would recommend taking advantage of the fact that nodeJS will always be ES5. Remember this isn't the browser folks you can depend on the language's implementation on being stable. That said I would recommend against ever using a for-in loop in nodeJS, unless you really want to do deep recursion up the prototype chain. For simple, traditional looping I would recommend making good use of Object.keys method, in ES5. If you view the following JSPerf test, especially if you use Chrome (since it has the same engine as nodeJS), you will get a rough idea of how much more performant using this method is than using a for-in loop (roughly 10 times faster). Here's a sample of the code:
var keys = Object.keys( obj );
for( var i = 0,length = keys.length; i < length; i++ ) {
obj[ keys[ i ] ];
}
You may also want to use hasOwnProperty in the loop.
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
switch (prop) {
// obj[prop] has the value
}
}
}
node.js is single-threaded which means your script will block whether you want it or not. Remember that V8 (Google's Javascript engine that node.js uses) compiles Javascript into machine code which means that most basic operations are really fast and looping through an object with 100 keys would probably take a couple of nanoseconds?
However, if you do a lot more inside the loop and you don't want it to block right now, you could do something like this
switch (prop) {
case 'Timestamp':
setTimeout(function() { ... }, 5);
break;
case 'Start_Value':
setTimeout(function() { ... }, 10);
break;
}
If your loop is doing some very CPU intensive work, you will need to spawn a child process to do that work or use web workers.
If you want to avoid blocking, which is only necessary for very large loops, then wrap the contents of your loop in a function called like this: process.nextTick(function(){<contents of loop>}), which will defer execution until the next tick, giving an opportunity for pending calls from other asynchronous functions to be processed.
My most preferred way is,
var objectKeysArray = Object.keys(yourJsonObj)
objectKeysArray.forEach(function(objKey) {
var objValue = yourJsonObj[objKey]
})
If we are using nodeJS, we should definitely take advantage of different libraries it provides. Inbuilt functions like each(), map(), reduce() and many more from underscoreJS reduces our efforts. Here's a sample
var _=require("underscore");
var fs=require("fs");
var jsonObject=JSON.parse(fs.readFileSync('YourJson.json', 'utf8'));
_.map( jsonObject, function(content) {
_.map(content,function(data){
if(data.Timestamp)
console.log(data.Timestamp)
})
})
A little late but I believe some further clarification is given below.
You can iterate through a JSON array with a simple loop as well, like:
for(var i = 0; i < jsonArray.length; i++)
{
console.log(jsonArray[i].attributename);
}
If you have a JSON object and you want to loop through all of its inner objects, then you first need to get all the keys in an array and loop through the keys to retrieve objects using the key names, like:
var keys = Object.keys(jsonObject);
for(var i = 0; i < keys.length; i++)
{
var key = keys[i];
console.log(jsonObject.key.attributename);
}
Not sure if it helps, but it looks like there might be a library for async iteration in node hosted here:https://github.com/caolan/async
Async is a utility module which provides straight-forward, powerful functions for working with asynchronous JavaScript. Although originally designed for use with node.js, it can also be used directly in the browser.
Async provides around 20 functions that include the usual 'functional' suspects (map, reduce, filter, forEach…) as well as some common patterns for asynchronous control flow (parallel, series, waterfall…). All these functions assume you follow the node.js convention of providing a single callback as the last argument of your async function.
Take a look at Traverse. It will recursively walk an object tree for you and at every node you have a number of different objects you can access - key of current node, value of current node, parent of current node, full key path of current node, etc. https://github.com/substack/js-traverse. I've used it to good effect on objects that I wanted to scrub circular references to and when I need to do a deep clone while transforming various data bits. Here's some code pulled form their samples to give you a flavor of what it can do.
var id = 54;
var callbacks = {};
var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
var scrubbed = traverse(obj).map(function (x) {
if (typeof x === 'function') {
callbacks[id] = { id : id, f : x, path : this.path };
this.update('[Function]');
id++;
}
});
console.dir(scrubbed);
console.dir(callbacks);