简体   繁体   中英

passing in a JSON object in HTML DOM

I am experimenting with a charting package called Highcharts (some of you may be familiar with it but regardless the problem is not related to Highcharts per se). What I wanted to do was have my PHP generated HTML embed a JSON object into the DOM which would then be picked up by a static jQuery listening function. Here's what it looks like:

 // Static JS file that get's loaded with every page load and 
 // and listens for a class with ".highchart_config".
 // When it finds a config class it then looks in the attribute "data-chart"
 // for the JSON configuration object
 jQuery.noConflict();
 jQuery(function($) {
   $(document).ready(function() {
    $(".highchart_config").each(function(index) {
        var config_obj = $(this).attr('data-chart');
        chart = new Highcharts.Chart( config_obj );
    });
   });
 }); 

And then the HTML is as follows:

 <div class="highchart_config" data-chart='         {chart: {"renderTo":"chart2","defaultSeriesType":"column"},title: {"text":"Monkies are Happy Animals"},xAxis:{"categories":["Apples","Oranges","Pears","Grapes","Bananas"],"min":null,"title":""},yAxis: {"min":0,"title":{"text":"Total fruit consumption"}},legend: {"align":"center","x":0,"verticalAlign":"bottom","y":0,"floating":false,"backgroundColor":null,"borderColor":"#CCC","borderWidth":1,"shadow":false,"reversed":true},tooltip: { formatter: function() { return this.series.name + ":" + this.y + " "}},plotOptions: {"column":{"stacking":"normal","dataLabels":{"enabled":false}}},series: [{"name":"Running","data":[5,3,4,7,2]},{"name":"Cycling","data":[2,2,3,2,1]},{"name":"Lifting","data":[3,4,4,2,5]}]}'></div>

Using a debugger I can see this working by placing a breakpoint on the line where Highcharts object instantiation takes place. When the breakpoint is hit I print the value of "chart_obj" which comes out as:

  {chart: {"renderTo":"chart2","defaultSeriesType":"column"},title: {"text":"Monkies are Happy Animals"},xAxis:{"categories":["Apples","Oranges","Pears","Grapes","Bananas"],"min":null,"title":""},yAxis: {"min":0,"title":{"text":"Total fruit consumption"}},legend: {"align":"center","x":0,"verticalAlign":"bottom","y":0,"floating":false,"backgroundColor":null,"borderColor":"#CCC","borderWidth":1,"shadow":false,"reversed":true},tooltip: { formatter: function() { return this.series.name + ":" + this.y + " "}},plotOptions: {"column":{"stacking":"normal","dataLabels":{"enabled":false}}},series: [{"name":"Running","data":[5,3,4,7,2]},{"name":"Cycling","data":[2,2,3,2,1]},{"name":"Lifting","data":[3,4,4,2,5]}]} 

That looks "right" to me but it doesn't work. Instead the instantiation of the object fails as the config_obj is somehow malformed. To make sure I wasn't making some stupid syntax error I cut and paste the value in config_obj and put it into a static JS file that looks like this:

 $(function () {
    var chart;
    $(document).ready(function() {
        chart = new Highcharts.Chart({
            chart: {"renderTo":"chart2","defaultSeriesType":"column"},title: {"text":"Monkies are Happy Animals"},xAxis: {"categories":["Apples","Oranges","Pears","Grapes","Bananas"],"min":null,"title":""},yAxis: {"min":0,"title":{"text":"Total fruit consumption"}},legend: {"align":"center","x":0,"verticalAlign":"bottom","y":0,"floating":false,"backgroundColor":null,"borderColor":"#CCC","borderWidth":1,"shadow":false,"reversed":true},tooltip: { formatter: function() { return this.series.name + ":" + this.y + " "}},plotOptions: {"column":{"stacking":"normal","dataLabels":{"enabled":false}}},series: [{"name":"Running","data":[5,3,4,7,2]},{"name":"Cycling","data":[2,2,3,2,1]},{"name":"Lifting","data":[3,4,4,2,5]}]
        });
    });
});

This "hardcoded" method works and yet the instantiation call should have precisely the same configuration object passed in. I'm at a loss now how to proceed. I have been reading other posts on stackoverflow around this topic but can't find anything to help me with my specific problem. Any and all help is greatly appreciated.

UPDATE: I have no tried ... to no avail using both data() and attr() methods and in both cases with and without a call to JSON.parse(config_obj). It DOES appear that the problem is related to config_obj being treated as a string so in the debugger I decided to assign a variable "test" to the cut-and-pasted string results of config_obj without the exterior quotation marks. It works fine so it's clearly a well structured JSON string but getting it converted to a string is still eluding me. Below I have an image of my debugging session which shows three things:

  1. First I get an error when using the JSON.parse() function on my config_obj string (that's true regardless if I used data() or attr() to retrieve config_obj from the DOM)
  2. If I instead just cut-and-paste the text into a test variable called "test" it is recognised as a valid JS object
  3. If I use the JSON.stringify() method on the test object it converts back to a string version that is CLOSE to the same as my config_obj variable ... the difference being that the first level attributes in the object have quotation marks around them. This might be a hint at what's going wrong but I still haven't cracked this nut ... any help would be greatly appreciated.

分配给变量然后stringify

When you get the attributes value - using .attr() - what you're being returned is a string. You'll need to parse that string to turn it into the actual object, so change the following line to:

chart = new Highcharts.Chart( JSON.parse(config_obj) );

It's the JSON.parse() function that's the important part.

Also, as a note, if you're using data-* attributes, it's better to use the .data() function, so you'd change the other line to:

var config_obj = $(this).data('chart');

As you may have seen in my "update" to the question I had found a variation in the string versions of the JSON object between my original object and the one I created by cut-and-pasting this same string into an object and then running JSON.stringify() on it.

This variation -- including double quote markers around object names -- seems to be important for it to work correctly. If you pass it in this way using jQuery's .data() method than it automatically converts it to a JSON object and there's no need to directly call JSON.parse().

I still find it odd that there is a stricter standard to convert a string to an object with JSON's parse() method than there is within JS itself and I'd be interested if anyone has any theories on this. In either event, wanted to thank @Anthony, @DCoder and everyone else who helped.

Here is the working DOM entry:

<div class="highchart_config" data-chart='{"chart":{"renderTo":"chart2","defaultSeriesType":"column"},"title":{"text":"Monkies are Happy Animals"},"xAxis":{"categories":["Apples","Oranges","Pears","Grapes","Bananas"],"min":null,"title":""},"yAxis":{"min":0,"title":{"text":"Total fruit consumption"}},"legend":{"align":"center","x":0,"verticalAlign":"bottom","y":0,"floating":false,"backgroundColor":null,"borderColor":"#CCC","borderWidth":1,"shadow":false,"reversed":true},"tooltip":{},"plotOptions":{"column":{"stacking":"normal","dataLabels":{"enabled":false}}},"series":[{"name":"Running","data":[5,3,4,7,2]},{"name":"Cycling","data":[2,2,3,2,1]},{"name":"Lifting","data":[3,4,4,2,5]}]}'></div> 

And the JS that takes this DOM entry as input is:

jQuery.noConflict();
jQuery(function($) {
  $(document).ready(function() {
    $(".highchart_config").each(function(index) {
        var config_obj = $(this).data('chart');
        chart = new Highcharts.Chart( config_obj );
    });
  });
}); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM