0

I'm trying to get data from a mysql database via php, encoding it as JSON, then parsing it into an array that displays data in a bar chart.

If I explicitly declare values, such as:

var data = new Array ();
data.push ([[5,66],[6,65],[7,68],[8,67],[9,64],[10,68],[11,73],[12,66],[13,70],[14,72],[15,74],[16,75],[17,67],[18,67],[19,39],[20,25]]);

This works.
enter image description here enter image description here

If I create a loop, such as:

var data = new Array ();
var namespacedata = [];
for (var j=5; j<20; j++) {
    namespacedata.push([j,66]);
}
data.push(namespacedata);

This also works. enter image description here

If i use the console in chrome along with some logging, I can see the array being passed is 15 elements long: enter image description here

However, when I try to parse my json array, which looks like this coming from php:

[{"NAMESPACE":"5","used":"66"},{"NAMESPACE":"6","used":"64"},{"NAMESPACE":"7","used":"68"},{"NAMESPACE":"8","used":"67"},{"NAMESPACE":"9","used":"64"},{"NAMESPACE":"10","used":"67"},{"NAMESPACE":"11","used":"72"},{"NAMESPACE":"12","used":"67"},{"NAMESPACE":"13","used":"70"},{"NAMESPACE":"14","used":"71"},{"NAMESPACE":"15","used":"74"},{"NAMESPACE":"16","used":"74"},{"NAMESPACE":"17","used":"67"},{"NAMESPACE":"18","used":"70"},{"NAMESPACE":"19","used":"41"},{"NAMESPACE":"20","used":"25"}]

using this code:

var data = new Array ();
var namespacedata = [];
$.getJSON("resources/get_namespace_usage.php", function(result) {
    $.each(result, function(i, item) {
        namespacedata.push([Number(item.NAMESPACE),Number(item.used)]);
    });

    console.log(namespacedata);
    data.push(namespacedata);
    console.log(data);
});

I get a 16 element array, and the graph doesn't work enter image description here

enter image description here

As far as I can tell, everything looks like it should, if I inspect the 2D arrays inside the console, the data looks correct, yet I can't understand why I'm getting an extra element, and why the graph doesn't work. I've tried splicing the array, that doesn't work.

What is so fundamentally different between these three implementations (two that work, one that doesn't?) I suppose I could do a for loop given a fixed number (j=5; j<20;j++), but this doesn't scale well, and will be messier than getting the $.each to work.

Thanks in advance!

Edit: full bar.js file:

$(function () {
    var data = new Array ();
    var ds = new Array();
    var namespacedata = [];

    $.getJSON("resources/get_namespace_usage.php", function(result) {
        $.each(result, function(i, item) {
            namespacedata.push([Number(item.NAMESPACE),Number(item.used)]);
        });
        data.push(namespacedata);
        console.log(data);
    });

    for (var i=0, j=data.length; i<j; i++) {

        ds.push({
            data:data[i],
            grid:{
                hoverable:false
            },
            bars: {
                show: true,
                barWidth: 0.8,
                order: 1,
                align: "center",
                lineWidth: 0.5,
                fillColor: { colors: [ { opacity: 0.75 }, { opacity: 1 } ] }
            }
        });
    }

    var somePlot = $.plot($("#bar-chart"), ds, {
        colors: ["#F90"],
        yaxis: {
            min: 0,
            max: 100,
        },
        xaxis: {
            ticks: [[5,"NS5"],[6,"NS6"],[7,"NS7"],[8,"NS8"],[9,"NS9"],[10,"NS10"],[11,"NS11"],[12,"NS12"],[13,"NS13"],[14,"NS14"],[15,"NS15"],[16,"NS16"],[17,"NS17"],[18,"NS18"],[19,"D2C"],[20,"BPN"]]
        }
    });

    var ctx = somePlot.getCanvas().getContext("2d"); // get the context
    var data = somePlot.getData()[0].data;  // get your series data
    var xaxis = somePlot.getXAxes()[0]; // xAxis
    var yaxis = somePlot.getYAxes()[0]; // yAxis
    var offset = somePlot.getPlotOffset(); // plots offset
    ctx.font = "14px 'Segoe UI'"; // set a pretty label font
    ctx.fillStyle = "black";
    for (var i = 0; i < data.length; i++){
        var text = data[i][1] + '';
        var metrics = ctx.measureText(text);
        var xPos = (xaxis.p2c(data[i][0])+offset.left) - metrics.width/2; // place  it in the middle of the bar
        var yPos = yaxis.p2c(data[i][1]) + offset.top + 13; // place at top of bar, slightly up
        ctx.fillText(text, xPos, yPos);
    }
});
Barmar
  • 741,623
  • 53
  • 500
  • 612
Evan R.
  • 1,210
  • 1
  • 27
  • 42
  • 2
    The array you posted as "coming from PHP" has 16 entries in it. – Pointy Mar 03 '16 at 00:47
  • Note that your loop condition was `j < 20`, not `j <= 20`. – Pointy Mar 03 '16 at 00:49
  • 1
    When are you calling the function that plots the data? You need to do that in the `$.getJSON` callback, otherwise you'll plot the data before the response comes. – Barmar Mar 03 '16 at 00:59
  • @[pointy the plot comes after the each loop is run.. I'll amend the question with the entire .js file – Evan R. Mar 03 '16 at 21:58
  • @barmar can you post your answer as comment? I ended up moving the end of the success brackets to the end of the file, causing the plotting to be performed on success, graphs work now. Thanks! – Evan R. Mar 03 '16 at 22:12
  • Answers can't be added to questions that have been closed as a duplicate. – Barmar Mar 03 '16 at 22:14

1 Answers1

0

It's not a problem with $.each. Check the response coming from PHP.

Add console.log(result) just before the $.each line.

Also, note that Array#push adds its argument to the array. So the line data.push(namespacedata); will add a single item to data containing the 16 elements. If you wanted to append the 16 items to data, then you should look in to Array#concat

matpie
  • 17,033
  • 9
  • 61
  • 82
  • The graphing library he's using apparently expects the data to be a sub-array, so `data.push(namespacedata)` is correct. It works in the earlier examples. – Barmar Mar 03 '16 at 00:56
  • Ah, ignore my last paragraph then. Thanks! – matpie Mar 03 '16 at 00:57