Home > Software design >  Javascript makes new Element in Array appear in different index after arr.push (not in arr.length in
Javascript makes new Element in Array appear in different index after arr.push (not in arr.length in

Time:12-02

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();  
  • Related