0

In D3 I am working on customizing and adding to this timeline: http://bl.ocks.org/rengel-de/5603464 by rengel Rengel. All has been going well until when recently I have been having a problem showing all of the events on my timeline from my JSON dataset. Instead of showing from 1970-1953, it shows only 1966-1953.

D3 Only Showing Partial Results from JSON

My dates in my JSON file are in YYYY-MM-DD format, and I am laying out the timeline using tracks. This function appends elements into these tracks and it sorts through the results from later to earlier dates (see code below). But for some reason, if I sort these JSON results backwards, my dates only start at 1966, and if I sort forward() they only start half way through (1958) from the opposite side. I have been thinking this is happening because the dates aren't being calculated properly.

Here is the compareDescending function that checks each pair of dates:

function compareDescending(item1, item2) {
  // Every item must have two fields: 'start' and 'end'.
  // Read the dataset in and then compare the dates of the first value with the next value

        var firstdatestartdesc = new Date(item1.DateStart);
        var seconddatestartdesc = new Date(item2.DateStart);

        // later first
        var result = new Date(item1.DateStart) - new Date(item2.DateStart) ;

        if (result < 0) { return 1; }
        if (result > 0) { return -1; }

        return 0;

        var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
        var firstdatefinishdesc = new Date(item1.DateFinish);
        var seconddatefinishdesc =new Date(item2.DateFinish);


        result = new Date(item2.DateFinish) - new Date(item1.DateFinish);

        if (result < 0) { return 1; }
        if (result > 0) { return -1; }

        return 0;
}

I am then using the calculateTracks function to sort through:

function calculateTracks(item, sortOrder, timeOrder) {
        var i, track;

        sortOrder = sortOrder || "descending"; // "ascending", "descending"
        timeOrder = timeOrder || "backward";   // "forward", "backward"

        function sortBackward() {
            // older items end deeper
            data.projects.forEach(function (item) { /
                for (i = 0, track = 0; i < tracks.length; i++, track++) { 
                    if (item.DateFinish < tracks[i]) { break; }

                }
                item.track = track
                tracks[track] = item.DateStart;
            });
        }

        //won't need to use this when we have sort backward instead
        function sortForward() {
            // younger items end deeper
           data.projects.forEach(function (item) {
                for (i = 0, track = 0; i < tracks.length; i++, track++) {
                    if (item.DateStart > tracks[i]) { break; }
                }
                item.track = track;
                tracks[track] = item.DateFinish;
            });
        }

        if (sortOrder === "ascending")
            data.projects.sort(compareAscending);
        else
            data.projects.sort(compareDescending);
        if (timeOrder === "forward"){
            ;
            sortForward();
        }else{
            sortBackward();
        }
    }

While debugging this, I can see that changing the value of the "result" variable produces different layouts, so that's why I think that it isn't computing dates properly. So I have then tried a number of other ways to compare dates, but no luck yet. (Actually in one case, the rectangles displayed from 1970 back to 1953, but instead of 'stacking' in lanes, each rectangle was added below the preceding rectangle, but the rectangles ended up below the x-axis without stacking properly. The following adjustments were tried with the result variable:

var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
var result =  Math.round(firstdatestartdesc.getTime() - seconddatestartdesc.getTime());
var result =  Math.round(Math.round(firstdatestartdesc - seconddatestartdesc)/(oneDay));
var result =  Math.round((firstdatestartdesc - seconddatestartdesc)/(oneDay));
var result =  Math.round((firstdatestartdesc - seconddatestartdesc)/(oneDay));

How might I get all of the rectangles to display, instead of the results starting only half way through the dataset?

Thanks in advance.

rootseire
  • 15
  • 6
  • stick your code in a working jsfiddle with some data, then we can all have a poke about – mgraham Apr 26 '16 at 19:43
  • i've created a fiddle here: https://jsfiddle.net/rootseire/t1vrbLc4/7/ but haven't yet setup the json object. But there is a link to the php service and also the first 10 results are stored in a variable above the d3.json call. I'll continue to try get it working but hope that helps in the meantime. Thank you – rootseire Apr 26 '16 at 21:02
  • @rootseire—you've been given poor advice. Post code here as a runnable snipped. Links don't last forever, and many will not follow the link. Note that parsing strings with the Date constructor as in `new Date(item1.DateStart)` is not recommended, manually parse the strings (a library may help but a 2 line function is sufficient). A string in "YYYY-MM-DD" will be parsed as UTC in current browsers, or local in some slightly older browsers, or invalid date before that. – RobG Apr 26 '16 at 22:55
  • thanks for your advice Rob. For parsing strings, I have checked this post: http://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results - and it seems to be the same problem. On there, the function parseDate seems parse ok but not sure about the second line. function parseDate(input) { var parts = input.split('-'); return new Date(parts[0], parts[1]-1, parts[2]); } – rootseire Apr 26 '16 at 23:20

1 Answers1

0

Nothing to do with dates, as thanks to the power of that fully armed and operational jsfiddle, your problem was this:

vis.selectAll ("g:not(.xaxis)")

should be

vis.selectAll ("g.rectclass")

g:not(.xaxis) only excludes the xaxis, but not the child g elements that hold the axis labels. So your first X data points are getting joined to these g elements that hold these labels. Since they already exist, they don't get picked up by the .enter() clause and your first X results are discarded (which is also why your missing results changed depending on which end you started sorting from.)

mgraham
  • 6,147
  • 1
  • 21
  • 20