I have an Array which is named tasks. There I have many tasks stored in. Example:
[
{
"id": "2",
"taskName": "dswrs",
"startDate": "1969-12-31T23:00:00.000Z",
"endDate": "1969-12-31T23:00:55.000Z",
"duration": "1969-12-31T23:00:55.000Z",
"categorie": "Processing"
},
{
"id": "1",
"taskName": "A",
"startDate": "1969-12-31T23:00:30.000Z",
"endDate": "1969-12-31T23:00:55.000Z",
"duration": "1969-12-31T23:00:25.000Z",
"categorie": "Processing"
}
]
Here you can already see my problem already. I added the Element with the id:2 after the one with id:1 ( with tasks.push(...)
)
So I expect it to be in this order:
[
{
"id": "1",
"taskName": "A",
"startDate": "1969-12-31T23:00:30.000Z",
"endDate": "1969-12-31T23:00:55.000Z",
"duration": "1969-12-31T23:00:25.000Z",
"categorie": "Processing"
},
{
"id": "2",
"taskName": "dswrs",
"startDate": "1969-12-31T23:00:00.000Z",
"endDate": "1969-12-31T23:00:55.000Z",
"duration": "1969-12-31T23:00:55.000Z",
"categorie": "Processing"
}
]
This problem only appears, when the new added element, has a lower startDate
than elements already existing.
The problem has to be in my D3.js code, which I use to show data in a gantt graph. I expect it to be in the gantt.redraw
function, because I call this directly after adding new data to my tasks array, but I just cant find the problem.
/* global d3 */
d3.gantt = function () {
var initTimeDomain = function (tasks) {
console.log(tasks);
if (timeDomainMode === FIT_TIME_DOMAIN_MODE) {
if (tasks === undefined || tasks.length < 1) {
timeDomainStart = new Date(0);
timeDomainEnd = new Date(10 ** 5);
return;
}
var tasksOrder = tasks;
tasksOrder.sort(function (a, b) {
return a.endDate - b.endDate;
});
timeDomainEnd = tasksOrder[tasksOrder.length - 1].endDate;
tasksOrder.sort(function (a, b) {
return a.startDate - b.startDate;
});
timeDomainStart = tasksOrder[0].startDate;
}
};
function gantt (tasks) {
initTimeDomain();
initAxis();
var svg = d3.select('svg')
.attr('class', 'chart')
.attr('width', width margin.left margin.right)
.attr('height', height margin.top margin.bottom)
.append('g')
.attr('class', 'gantt-chart')
.attr('width', width margin.left margin.right)
.attr('height', height margin.top margin.bottom)
.attr('transform', 'translate(' margin.left ', ' margin.top ')');
svg.selectAll('.chart')
.data(tasks, keyFunction).enter()
.append('rect')
.attr('rx', 5)
.attr('ry', 5)
.attr('class', function (d) {
if (taskCategorie[d.categorie] == null) { return 'bar-killed'; }
return taskCategorie[d.categorie];
})
.attr('y', 0)
.attr('transform', rectTransform)
// ----.attr('height', function (d) { return y.rangeBand(); })
.attr('height', function (d) { return y.bandwidth(); })
.attr('width', function (d) {
return (x(d.endDate) - x(d.startDate));
});
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0, ' (height - margin.top - margin.bottom) ')')
.transition()
.call(xAxis);
svg.append('g').attr('class', 'y axis').transition().call(yAxis);
return gantt;
};
gantt.redraw = function (tasks) {
console.log("TASKS IN REDRAW: ")
console.log(tasks);
initTimeDomain(tasks);
initAxis();
var svg = d3.select('svg');
var ganttChartGroup = svg.select('.gantt-chart');
var rect = ganttChartGroup.selectAll('rect').data(tasks, keyFunction);
var div = d3.select('body').append('div')
.attr('class', 'tooltip-donut')
.style('opacity', 0);
rect.enter()
.insert('rect', ':first-child')
.on('mouseover', function (d, i) {
d3.select(this).transition()
.duration('50')
.attr('opacity', '.85');
// Makes the new div appear on hover:
div.transition()
.duration(50)
.style('opacity', 1);
div.html(['Taskname: ' i.taskName, 'Start: ' i.startDate.toLocaleTimeString(), 'Ende: ' i.endDate.toLocaleTimeString()].join('<br/>'))
.style('left', (d.pageX 10) 'px')
.style('top', (d.pageY - 15) 'px');
})
.on('mouseout', function (d, i) {
d3.select(this).transition()
.duration('50')
.attr('opacity', '1');
div.transition()
.duration('50')
.style('opacity', 0);
})
.attr('rx', 5)
.attr('ry', 5)
.attr('class', function (d) {
if (taskCategorie[d.categorie] == null) { return 'bar-killed'; }
return taskCategorie[d.categorie];
})
.transition()
.attr('y', 0)
.attr('transform', rectTransform)
.attr('height', function (d) { return y.bandwidth(); })
.attr('width', function (d) {
return (x(d.endDate) - x(d.startDate));
});
rect.transition()
.attr('transform', rectTransform)
.attr('height', function (d) { return y.bandwidth(); })
.attr('width', function (d) {
return (x(d.endDate) - x(d.startDate));
});
rect.exit().remove();
svg.select('.x').transition().call(xAxis);
svg.select('.y').transition().call(yAxis);
console.log("TASKS NACH REDRAW: ")
console.log(tasks);
return gantt;
};
gantt.margin = function (value) {
if (!arguments.length)
return margin;
margin = value;
return gantt;
};
gantt.timeDomain = function (value) {
if (!arguments.length)
return [timeDomainStart, timeDomainEnd];
timeDomainStart = value[0], timeDomainEnd = value[1];
return gantt;
};
return gantt;
};
CodePudding user response:
The problem is in the initTimeDomain
method.
There you are creating a new reference to the tasks array with var tasksOrder = tasks;
and then you are sorting tasksOrder
by date.
Problem is here that Javascript objects and arrays are references, meaning tasksOrder
and tasks
are pointing to the same array.
To put is simple, modifying one will also change the other.
If you don't want this, you need to create a real copy, like this:
var tasksOrder = tasks.slice();