alfajango / jquery-dynatable

A more-fun, semantic, alternative to datatables
http://www.dynatable.com
Other
2.77k stars 361 forks source link

Dynatable using the wrong JSON after loading JSON manually in browser #44

Open brandondrew opened 10 years ago

brandondrew commented 10 years ago

In the process of trying to get JSON loaded from a URL to be used for my data in Dynatable I discovered a strange bug. This issue is about the bug, not about the problem I'm trying to solve, but if you are moved to answer the question on StackOverflow, I certainly wouldn't complain about it. :)

The circumstances in which I find the bug are a bit different from what is described in the SO question. I've got an HTML page with two tables. One pulls data from JSON that is embedded inside the page, in a <script> element (just like the example in the documentation that uses a <pre> element, but this hides it without adding any CSS to do so). The other pulls data (or tries to pull data) from a URL. In order to make sure that the problem was not merely the same origin policy blocking me, I am serving the page and assets with Serve running locally on my laptop.

It's not working (for reasons I haven't discovered yet—and as I said, that is not what this bug report is about) but if I load the JSON file manually by entering http://localhost:4000/music.json in the browser's address field, and then hit the back button to go back to http://localhost:4000/index.html, suddenly I'll see both tables filled out. At first I thought I'd gotten my Dynatable to do what I wanted, until I noticed that it had data in it that was not in music.json. I've got 13 records in the embedded JSON, but only 8 in music.json. For some reason both tables were taking their data from the embedded JSON. That's the bug.

image

Here's the version of index.html and music.json with which I noticed this bug:

<!DOCTYPE html>
<html>
<head>
  <title>Ad-Related Reports</title>
  <script src="./vendor/jquery-1.7.2.min.js"></script>
<!-- 
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" ></script>
  <script>window.jQuery || document.write('<script src="./vendor/jquery-1.7.2.min.js"><\/script>')</script>
 -->
  <script src="./jquery.dynatable.js"></script>
  <link rel="stylesheet" type="text/css" href="./bootstrap/css/bootstrap.css">
  <!-- <link rel="stylesheet" href="./jquery.dynatable.css" /> -->
  <link rel="stylesheet" type="text/css" href="./jquery.dynatable.css">
  <style type="text/css">
    body {
      padding: 10px;
    }
  </style>
</head>
<body>
<h3>Remote JSON</h3>
<table class="table table-striped" id="remote">
  <thead>
    <th>Band</th>
    <th>Album</th>
  </thead>
  <tbody>
  </tbody>
</table>

<hr>

<h3>Local JSON</h3>
<table class="table table-striped" id="local">
  <thead>
    <th>Band</th>
    <th>Album</th>
  </thead>
  <tbody>
  </tbody>
</table>

<script id="music">
[
  {
    "band": "The Police",
    "album": "Ghost In The Machine"
  },{
    "band": "Supertramp",
    "album": "Breakfast In America"
  },{
    "band": "Peter Tosh",
    "album": "Mama Africa"
  },{
    "band": "The Police",
    "album": "Regatta d'Blanc"
  },{
    "band": "The Police",
    "album": "Zenyatta Mondatta"
  },{
    "band": "Supertramp",
    "album": "Crime of the Century"
  },{
    "band": "Talking Heads",
    "album": "Remain in Light"
  },{
    "band": "Talking Heads",
    "album": "More Songs About Buildings & Food"
  },{
    "band": "Talking Heads",
    "album": "77"
  },{
    "band": "Talking Heads",
    "album": "Stop Making Sense"
  },{
    "band": "Talking Heads",
    "album": "Fear of Music"
  },{
    "band": "Talking Heads",
    "album": "Sand In The Vaseline"
  },{
    "band": "Talking Heads",
    "album": "Little Creatures"
  }
]
</script>

<script type="text/javascript">
  // getting JSON from the document works, but of what use is that?
  $(document).ready( function() {
    $('#local').dynatable({
      dataset: {
        records: JSON.parse($('#music').text())
      }
    });

    // var json_url = '//www.dynatable.com/dynatable-ajax.json';
    var json_url = '/music.json';
    $.getJSON(json_url, function(data) {
      //alert(data); //uncomment this for debug
      // for(proper_tea in data){
      //   alert(JSON.stringify(data[proper_tea]));
      // }
      //alert (":" + JSON.stringify(data));
      //$('#showdata').html("<p>item1="+data.item1+" item2="+data.item2+" item3="+data.item3+"</p>");
    });

    var json_string;
    $.get(json_url, function(json) {
      json_string = JSON.stringify(json); 
    })
      .done( function() {
        alert(json_string);
        alert("made it");
      });

    // getting JSON from a remote source fails:
    $('#remote').dynatable({
      dataset: {
        ajax: true,
        ajaxOnLoad: true,
        ajaxUrl: 'http://localhost:4000/music.json',
        records: []
      }
    });
  });
</script>

        <!-- ajaxUrl: '//www.dynatable.com/dynatable-ajax.json', -->

</body>
</html>

and

[
  {
    "band": "The Police",
    "song": "Ghost In The Machine"
  },{
    "band": "Supertramp",
    "song": "Breakfast In America"
  },{
    "band": "Peter Tosh",
    "song": "Mama Africa"
  },{
    "band": "The Police",
    "song": "Regatta d'Blanc"
  },{
    "band": "The Police",
    "song": "Zenyatta Mondatta"
  },{
    "band": "Supertramp",
    "song": "Crime of the Century"
  },{
    "band": "Talking Heads",
    "song": "Remain in Light"
  },{
    "band": "Talking Heads",
    "song": "Speaking in Tongues"
  }
]
brandondrew commented 10 years ago

Interestingly, I just discovered my question is the first (and so far only) StackOverflow question tagged with 'dynatable'.

JangoSteve commented 10 years ago

I can tell you up front, that your remote JSON doesn't contain the correct format of data, but that's related to your StackOverflow problem, so I'll explain that there.

For this issue, I honestly have no idea what's happening. You said you saw this when you hit the back-button, does that mean it doesn't happen if you reload the page? Seems strange, as this kind of issue would normally be caused by some variable accidentally being used in the global scope, leaking data from one dynatable instance to another. However, the dynatable docs have like 10 or so dynatable instances all on one page with no such issue.

Can you open the JS console in Chrome when you get this to happen and run these commands from the console to see what the output is?

$('#local').data('dynatable').settings.dataset.records;
$('#remote').data('dynatable').settings.dataset.records;

$('#local').data('dynatable').settings.dataset.originalRecords;
$('#remote').data('dynatable').settings.dataset.originalRecords;

I'm wondering if maybe it has something to do with the pushState. After doing the above, also try setting {features: {pushState: false}} in the config for the remote instance and see if it happens then.

JangoSteve commented 10 years ago

Interestingly, I just discovered my question is the first (and so far only) StackOverflow question tagged with 'dynatable'.

Yeah, there are other posts on SO about dynatable, but no one else actually tagged their questions with "dynatable".

brandondrew commented 10 years ago

You said you saw this when you hit the back-button, does that mean it doesn't happen if you reload the page?

Yeah, as soon as I hit reload it goes back to an empty remote table and full local table.

brandondrew commented 10 years ago

Sorry, I'm not ignoring the request for info, I just had to put this aside for a bit... I plan to get back to it soon.

brandondrew commented 10 years ago

Here're the results of the commands in the console: 1-31-2014 5-23-04 pm

brandondrew commented 10 years ago

Your hunch about pushState seems to be correct. After setting

{features: {pushState: false}}

I no longer saw the same behavior.