1

I have a jqPlot chart that I want to add links on and I believe I figured out a way to do it using an array such as [[[1,2,"http://google.com"]],[[2,3,"http://yahoo.com]]] however, when I try to load this via XML, jQuery, and Ajax it doesn't quite work.

I believe that the problem lies within the .each clauses found in this code:

function getBars(xml)
{
var categoryid = 1;
var bars = [];
$(xml).find("category").each(
    function()
    {
        bars.push(loadBars(categoryid,$(this)));
        categoryid++;
    });
return bars;
}
function loadBars(categoryid,xml)
{
var bar = [];
var bars = [];
$(xml).find("bar").each(function()
{
    bar.push(parseInt(categoryid));
    bar.push(parseInt($(this).attr("size")));
    bar.push($(this).attr("link"));
    bars.push(bar);
});
    $("#debug").append("\nBAR:")
    debug2dArray(bars);
    return bars;
    }

The XML looks like:

<?xml version="1.0"?>
    <chart>
    <category>
    <bar size="20" link="http://google.com"/>
    </category>
    <category>
    <bar size="70" link="http://yahoo.com" />
    </category>
    </chart>

Here is a jsFiddle

Update

After updating the variables to be non-global, the chart now displays right, but two of the same values are still being added to the array. Code has been updated to reflect changes.

Community
  • 1
  • 1
Travis Pessetto
  • 3,260
  • 4
  • 27
  • 55

5 Answers5

3

I haven't digested your whole code yet, but one really fatal pitfall you're doing is using variables in your functions that haven't been declared with var (I'm particularly looking at how you've used your bar variable on both functions).

When you use a variable without declaring it with var like you're doing here, you're bringing the variable to a global visibility. That means that that variable is the same variable used (most) everywhere in your code. The same bar in the first function is the same bar in the second.

When your two functions start, the first thing it does is clear the bar variable (i.e. bar = [];). Since they're sharing bar references, calling one function effectively nullifies what the other did.

Is this your intention? If not (or even so), you should declare your variable with var:

var categoryId = 1, 
    bar = [];
Richard Neil Ilagan
  • 14,627
  • 5
  • 48
  • 66
2

None of your variables are declared using var, particularly the bars array. This causes them to be implicitly global, and you overwrite the variable every time you call loadBars.

jbabey
  • 45,965
  • 12
  • 71
  • 94
2

In addition to the lack of var, you are returning variables at the end of the each iterators, instead of the end of the function. Here's a working fiddle: http://jsfiddle.net/fwRSH/1/

function loadBars(categoryid, xml) {
    var bar = [];
    var bars = [];
    $(xml).find("bar").each(function() {
        bar.push(parseInt(categoryid, 10));
        bar.push(parseInt($(this).attr("size"), 10));
        bar.push($(this).attr("link"));
        bars.push(bar);
        //$("#debug").append("\nBAR:"); //not defined in fiddle, commented out
        //debug2dArray(bars); //not defined in fiddle, commented out
    });
    return bars; //moved from end of "each" iterator to here.
}

function getBars(xml) {
    var categoryid = 1;
    var bars = [];
    $(xml).find("category").each(function() {
        bars.push(loadBars(categoryid, $(this)));
        categoryid++;
    });
    return bars;
}

$(document).ready(function() {
    var bars = [];
    $("div#barchart").css("background-color", "#F00");
    $("div#barchart").css("height", "200px");
    $("div#barhcart").css("width", "400px");
    //moved for debugging
    bars = getBars($('div#xmlDI'));
    /* returns:
     * [
     *     [
     *         [1, 20, "http://google.com"]
     *     ],
     *     [
     *         [2, 70, "http://yahoo.com"]
     *     ]
     * ]
     */
    $.jqplot("barchart", bars, {
        seriesDefaults: {
            renderer: $.jqplot.BarRenderer,
            rendererOptions: {
                fillToZero: true
            }
        },
        axes: {
            // Use a category axis on the x axis and use our custom ticks.
            xaxis: {
                renderer: $.jqplot.CategoryAxisRenderer,
                ticks: ['one', 'two'],
                autoscale: true
            },
            yaxis: {
                autoscale: true
            }
        }
    });
});​
pete
  • 24,141
  • 4
  • 37
  • 51
1

I am not sure how you want your graph to look like. Because the data you provide to the graph, in general terms, is 'correctly' displayed. If you would write it in the following way:

[
    [[1, 30, "http://google.com"], [2,0,""]],
    [[1,0,""],[2, 40, "http://yahoo.com"]]
]

...it would give exactly the same results, the library just assumes that the data which is not provided for a particular series is 0 and this is how it is treated as visible here.

Since you do not like it this way my guess is that you made a formatting error in your data variable, as we can see here the 'gap' is gone.

Therefore, I think that the below is the format you are after:

[[
    [1, 30, "http://google.com"],
    [2, 40, "http://yahoo.com"]
]]

Additionally, as it goes to clicking on a bar of a bar chart you could find useful the answer to the problem. There you could see how to capture the click and how to open a URL. You would just need to slightly adopt it to your need as I used a global array of URLs.

Community
  • 1
  • 1
Boro
  • 7,913
  • 4
  • 43
  • 85
0

Code to parse the XML:

var bars = [], cat = 0;
$.ajax({
  type: 'GET',
  url: 'plotlinks.xml',
  dataType: "xml",
  cache: true,
  success: function(data, textStatus, jqXHR) {

    $(data).find("category").each( function() {
      var barSet = [cat];
      $(this).find("bar").each(function() {
        var $elt = $(this);
        barSet.push([$elt.attr('size'),$elt.attr('link')]);
      });
      cat++;
      bars.push(barSet);
    });

    // bars is an array; each element is an array. 
    // The first element in the inner array is the 
    // category "index" (0,1,2,...). All other 
    // elements represent a link for that category. 
    // Those elements are arrays of [size,url].
    alert($.stringifyJSON(bars)); 
  }
});

Resulting json:

[[0,
   ["20","http://google.com"]
 ],
 [1,
   ["70","http://yahoo.com"]
 ]
]
Cheeso
  • 189,189
  • 101
  • 473
  • 713