Javascript/JQuery- Match string in dropdown to string in JSON and display the JSON sibling's array

I'm attempting to display part of an array from JSON when the user clicks on an ID in the dropdown. The data is loading data twice and then subsequent clicks just layer array upon array even though I have set my array to clear when update() is fired. I'm also getting a "update is not defined at HTMLAnchorElement.onclick" although that function itself is firing when the page loads.

How can I resolve the error and only display the one set of matching data? Here is a fiddle: https://jsfiddle.net/dtepdc/4e6mfoct/

Here is the code:

let dataset = [
    {
        "scene": "IR0006426320",
        "scene_start_time": "2018-02-05T15:03:30",
        "chips": [
        {
            "chip": "2018.02.05.150",
            "start_date": "2018-02-05T00:05:07",
            "end_date": "2018-02-05T01:26:23",
            "co_num":["None"],
            "cause": false
        },
        {
            "chip": "2018.02.05.192",
            "start_date": "2018-02-05T15:48:08",
            "end_date": "2018-02-05T17:22:34",
            "co_num": [
                "C03619354",
                "C03618763",
                "C03619064",
                "C03619325"
            ],
            "cause": false
        },
        {
            "chip": "2018.02.05.26",
            "start_date": "2018-02-05T16:38:56",
            "end_date": "2018-02-05T21:08:00",
            "co_num": [
                "C03610724"
            ],
            "cause": false
        },
        {
            "chip": "2018.02.05.303",
            "start_date": "2018-02-05T13:34:58",
            "end_date": "2018-02-05T13:34:58",
            "co_num": [
                "C03610724"
            ],
            "cause": true
        },
        {
            "chip": "2018.02.05.44",
            "start_date": "2018-02-05T21:20:39",
            "end_date": "2018-02-05T23:41:59",
            "co_num": [
                "C03610724"
            ],
            "cause": false
        },
        {
            "chip": "2018.02.05.53",
            "start_date": "2018-02-05T13:59:46",
            "end_date": "2018-02-05T16:01:35",
            "co_num": [
                "C03610724"
            ],
            "cause": true
        },
        {
            "chip": "2018.02.05.54",
            "start_date": "2018-02-05T01:04:53",
            "end_date": "2018-02-05T01:09:58",
            "co_num":["None"],
            "cause": false
        },
        {
            "chip": "2018.02.06.63",
            "start_date": "2018-02-05T23:44:23",
            "end_date": "2018-02-05T23:59:18",
            "co_num": [
                "C03610724"
            ],
            "cause": false
        }
    ]
},
{
    "scene": "IR0006633836",
    "scene_start_time": "2018-05-2418T14:20:00",
    "chips": [
        {
            "chip": "2018.05.25.50",
            "start_date": "2018-05-24T02:10:04",
            "end_date": "2018-05-24T06:39:41",
            "co_num": [
                "C03726697", "None"
            ],
            "cause": false
        },
        {
            "chip": "2018.05.25.59",
            "start_date": "2018-05-24T03:02:01",
            "end_date": "2018-05-24T04:26:06",
            "co_num": [
                "C03728974",
                "C03729029",
                "C03704816",
                "C03728657",
                "C03719067"
            ],
            "cause": false
        },
        {
            "chip": "2018.05.26.137",
            "start_date": "2018-05-24T18:02:47",
            "end_date": "2018-05-24T18:43:10",
            "co_num":["None"],
            "cause": false
        },
        {
            "chip": "2018.05.26.194",
            "start_date": "2018-05-24T15:08:40",
            "end_date": "2018-05-24T15:10:40",
            "co_num":["None"],
            "cause": false
        },
        {
            "chip": "2018.05.26.197",
            "start_date": "2018-05-24T18:20:53",
            "end_date": "2018-05-24T18:20:53",
            "co_num": [
                "C03726648"
            ],
            "cause": false
        },
        {
            "chip": "2018.05.26.269",
            "start_date": "2018-05-24T21:07:35",
            "end_date": "2018-05-24T21:08:48",
            "co_num": [
                "C03726648"
            ],
            "cause": false
        },
        {
            "chip": "2018.05.26.30",
            "start_date": "2018-05-24T14:20:17",
            "end_date": "2018-05-24T21:14:25",
            "co_num":[
                "C03704816",
                "C03719067",
                "C03728657"
            ],
            "cause": false
        },
        {
            "chip": "2018.05.26.31",
            "start_date": "2018-05-24T15:19:35",
            "end_date": "2018-05-24T17:33:52",
            "co_num": [
                "C03704816",
                "C03719067",
                "C03728657", "None"
            ],
            "cause": false
        },
        {
            "chip": "2018.05.26.377",
            "start_date": "2018-05-24T14:59:08",
            "end_date": "2018-05-24T15:25:06",
            "co_num": [
                "C03730107",
                "C03714722",
                "C03728407",
                "C03728209"
            ],
            "cause": false
        },
        {
            "chip": "2018.05.26.39",
            "start_date": "2018-05-24T18:13:52",
            "end_date": "2018-05-24T18:13:53",
            "co_num": [
                "C03728284"
            ],
            "cause": false
        }
    ]
}
]

Open in new window

        $.each(dataset, function (i) {
            $('#dropdownMenuButtonAnchor').append('<a class="dropdown-item" onclick="update()" href="#">' + dataset[i].scene  + '</a>');
    });

            $.each(dataset, function (j) {
            let firstIncident = dataset[0].scene;
            $("#incidentNumber").html(firstIncident);

        });


setTimeout(function() {
    update();
}, 100);

  /* change() ********************* */
  function update() {
    d3.selectAll('svg').remove();
    let changed = [];
    let start = moment().subtract(24, 'months').valueOf();
    let timeRange =     d3.select('input[name="options"]:checked').property("value");

if (timeRange < 12) {
    start = moment().subtract(timeRange, 'minutes').valueOf();
} else if (timeRange >= 12 && timeRange < 36) {
    start = moment().subtract(timeRange, 'hours').valueOf();
} else if (timeRange === 24) {
    start = moment().subtract(16, 'months').valueOf();
}

let end = moment().valueOf();

const coNumW = window.innerWidth,
        coNumH = window.innerHeight,
        margin = {top: coNumH * 0.15, right: coNumW * 0.05, bottom: coNumH * 0.12, left: coNumW * 0.12},
        w = coNumW - margin.left - margin.right,
        h = coNumH - margin.top - margin.bottom;

let x = d3.scaleTime().range([w, 0]),
    y = d3.scaleBand().range([h, 0]),
    xAxis = d3.axisBottom(x)
    yAxis = d3.axisLeft(y),
    filtered = [],
    dateFormat = d3.timeFormat("%Y-%m-%d %I:%M %p"),
    weekdayFormat = d3.timeFormat("%w");

    let newSvg = d3.select("body")
    .append("svg")
    .attr("width", coNumW)
    .attr("height", coNumH)
    .append("g").classed("no-select", true)
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// ********************************************* LOOPS *********************************************
   $('div#dropdownMenuButtonAnchor a').click(function(){

    let incident = $(this).text();
    $("#incidentNumber").html(incident);

            //dataset.forEach(function(d, i) {
                for (let i = 0;i < dataset.length;i++){
                    if (incident === dataset[i].scene) {
                        dataset[i].chips.forEach(function(c, j) {
                            changed.push(c);

                            $('.incidentInfo').append('<a class="dropdown-item" onclick="update()" href="#">' + c.co_num  + '</a>');

                          });


// ********************************************* LOOPS *********************************************

x.domain([new Date(start), new Date(end)]).range([0, w]);
y.domain(changed.map(d => d.chip)).padding(0.1);

newSvg.append("g")
        .attr("class", "x_Axis")
        .attr("transform", "translate(0, " + h + ")")
        .call(xAxis)

newSvg.append("g")
        .attr("class", "y_Axis")
        .call(yAxis);

let tasksChange = newSvg.append("g")
        .attr("class", "dataCont")
        .selectAll("g")
        .data(changed)
        .enter()
        .append("g")
        .on("mouseenter", showData);

    let parseDate = d3.timeParse('%Y-%m-%dT%H:%m:%s');
    tasksChange.append("rect")
            .attr("x", function(d) {
                return x(moment(d.start_date).valueOf()) + 2;
            })
            .attr("y", function(d) {
            return y(d.chip);
            })
            .attr("width", function(d) {
                return x(moment(d.end_date)) - x(moment(d.start_date)) +2;
            })
            .attr("height", function(d) {
                return y.bandwidth();
            });


            d3.selectAll("#inlineRadio2, #inlineRadio3, #inlineRadio4")
                .on("change", function(){
                    update();
            });

            d3.selectAll("#inlineRadio1")
                .on("change", function(){
                setInterval(update, 10);
                var svg = d3.select("svg");

                let start = moment().subtract(timeRange, 'minutes').valueOf();
                let end = moment().valueOf();

                x.domain([start, end]);
                xAxis.scale(x);

                    //move the xaxis left
                svg.select(".x_axis")
                  .transition()
                  .duration(100)
                  .ease(d3.easeLinear)
                  .call(xAxis);
              });


    function showData(d) {
        console.log("Start Date: " + moment(d.start_date).format());
        console.log("End Date: " + moment(d.end_date).format());
        console.log('CO: ', d.chip)
        console.log('************************* ')

    }
}
}
});
  }

Open in new window

DawnAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

DawnAuthor Commented:
Will do...
Julian HansenCommented:
Hint:You have posted a significant amount of code. In future try to narrow it down to what code is integral to the problem or at least give pointers as to where to start looking.
A short synopsis of your code will also help.

Let's look at your code you have this

setTimeout(function() {
	update();
}, 100);

Open in new window

In other words, every 100 milliseconds you are calling the update function.
In the update function you have this
$('div#dropdownMenuButtonAnchor a').click(function(){
		let incident = $(this).text();

Open in new window

So every 100 milliseconds you are binding ANOTHER click handler to your markup. That means every time it fires ALL handlers are going to fire.
Whether or not this is the cause of your problem is not clear but it is something you need to fix.

Move your click handler outside of the update function - move the function closing } to above the $(`div#dropdown...) line

You may need to change your .click to a .on handler - it is important to understand the difference between these two and why you would use one over the other.
If you are creating content dynamically that you need to bind a click event to then it will fail because the element needs to exist when you bind it. The .on() handler will allow you to bind the handler to a static parent and specify a child class / element to relate the event to.

You can also move your showData function outside of the event handler.

I updated your fiddle as best I could (see below)
Hint2: Tidy code is much easier to work with than untidy code. Take some time to format your code neatly and lay it out in an ordered way. I found it very difficult to figure out what your code was doing as the formatting and layout were very chaotic.
let dataset = [
    {
        "scene": "IR0006426320",
        "scene_start_time": "2018-02-05T15:03:30",
        "chips": [
            {
                "chip": "2018.02.05.150",
                "start_date": "2018-02-05T00:05:07",
                "end_date": "2018-02-05T01:26:23",
                "co_num":["None"],
                "cause": false
            },
            {
                "chip": "2018.02.05.192",
                "start_date": "2018-02-05T15:48:08",
                "end_date": "2018-02-05T17:22:34",
                "co_num": [
                    "C03619354",
                    "C03618763",
                    "C03619064",
                    "C03619325"
                ],
                "cause": false
            },
            {
                "chip": "2018.02.05.26",
                "start_date": "2018-02-05T16:38:56",
                "end_date": "2018-02-05T21:08:00",
                "co_num": [
                    "C03610724"
                ],
                "cause": false
            },
            {
                "chip": "2018.02.05.303",
                "start_date": "2018-02-05T13:34:58",
                "end_date": "2018-02-05T13:34:58",
                "co_num": [
                    "C03610724"
                ],
                "cause": true
            },
            {
                "chip": "2018.02.05.44",
                "start_date": "2018-02-05T21:20:39",
                "end_date": "2018-02-05T23:41:59",
                "co_num": [
                    "C03610724"
                ],
                "cause": false
            },
            {
                "chip": "2018.02.05.53",
                "start_date": "2018-02-05T13:59:46",
                "end_date": "2018-02-05T16:01:35",
                "co_num": [
                    "C03610724"
                ],
                "cause": true
            },
            {
                "chip": "2018.02.05.54",
                "start_date": "2018-02-05T01:04:53",
                "end_date": "2018-02-05T01:09:58",
                "co_num":["None"],
                "cause": false
            },
            {
                "chip": "2018.02.06.63",
                "start_date": "2018-02-05T23:44:23",
                "end_date": "2018-02-05T23:59:18",
                "co_num": [
                    "C03610724"
                ],
                "cause": false
            }
        ]
    },
    {
        "scene": "IR0006633836",
        "scene_start_time": "2018-05-2418T14:20:00",
        "chips": [
            {
                "chip": "2018.05.25.50",
                "start_date": "2018-05-24T02:10:04",
                "end_date": "2018-05-24T06:39:41",
                "co_num": [
                    "C03726697", "None"
                ],
                "cause": false
            },
            {
                "chip": "2018.05.25.59",
                "start_date": "2018-05-24T03:02:01",
                "end_date": "2018-05-24T04:26:06",
                "co_num": [
                    "C03728974",
                    "C03729029",
                    "C03704816",
                    "C03728657",
                    "C03719067"
                ],
                "cause": false
            },
            {
                "chip": "2018.05.26.137",
                "start_date": "2018-05-24T18:02:47",
                "end_date": "2018-05-24T18:43:10",
                "co_num":["None"],
                "cause": false
            },
            {
                "chip": "2018.05.26.194",
                "start_date": "2018-05-24T15:08:40",
                "end_date": "2018-05-24T15:10:40",
                "co_num":["None"],
                "cause": false
            },
            {
                "chip": "2018.05.26.197",
                "start_date": "2018-05-24T18:20:53",
                "end_date": "2018-05-24T18:20:53",
                "co_num": [
                    "C03726648"
                ],
                "cause": false
            },
            {
                "chip": "2018.05.26.269",
                "start_date": "2018-05-24T21:07:35",
                "end_date": "2018-05-24T21:08:48",
                "co_num": [
                    "C03726648"
                ],
                "cause": false
            },
            {
                "chip": "2018.05.26.30",
                "start_date": "2018-05-24T14:20:17",
                "end_date": "2018-05-24T21:14:25",
                "co_num":[
                    "C03704816",
                    "C03719067",
                    "C03728657"
                ],
                "cause": false
            },
            {
                "chip": "2018.05.26.31",
                "start_date": "2018-05-24T15:19:35",
                "end_date": "2018-05-24T17:33:52",
                "co_num": [
                    "C03704816",
                    "C03719067",
                    "C03728657", "None"
                ],
                "cause": false
            },
            {
                "chip": "2018.05.26.377",
                "start_date": "2018-05-24T14:59:08",
                "end_date": "2018-05-24T15:25:06",
                "co_num": [
                    "C03730107",
                    "C03714722",
                    "C03728407",
                    "C03728209"
                ],
                "cause": false
            },
            {
                "chip": "2018.05.26.39",
                "start_date": "2018-05-24T18:13:52",
                "end_date": "2018-05-24T18:13:53",
                "co_num": [
                    "C03728284"
                ],
                "cause": false
            }
        ]
    }
]
    
        $.each(dataset, function (i) {
            $('#dropdownMenuButtonAnchor').append('<a class="dropdown-item" onclick="update()" href="#">' + dataset[i].scene  + '</a>');
        });
        
            $.each(dataset, function (j) {
            let firstIncident = dataset[0].scene;
            $("#incidentNumber").html(firstIncident);
            
        });


setTimeout(function() {
    update();
}, 100);

  /* change() ********************* */
  function update() {
    d3.selectAll('svg').remove();
    let changed = [];
    let start = moment().subtract(24, 'months').valueOf();
    let timeRange = d3.select('input[name="options"]:checked').property("value");
    
    if (timeRange < 12) {
        start = moment().subtract(timeRange, 'minutes').valueOf();
    } else if (timeRange >= 12 && timeRange < 36) {
        start = moment().subtract(timeRange, 'hours').valueOf();
    } else if (timeRange === 24) {
        start = moment().subtract(16, 'months').valueOf();
    }

    let end = moment().valueOf();

    const coNumW = window.innerWidth,
            coNumH = window.innerHeight,
            margin = {top: coNumH * 0.15, right: coNumW * 0.05, bottom: coNumH * 0.12, left: coNumW * 0.12},
            w = coNumW - margin.left - margin.right,
            h = coNumH - margin.top - margin.bottom;

    let x = d3.scaleTime().range([w, 0]),
        y = d3.scaleBand().range([h, 0]),
        xAxis = d3.axisBottom(x)
        yAxis = d3.axisLeft(y),
        filtered = [],
        dateFormat = d3.timeFormat("%Y-%m-%d %I:%M %p"),
        weekdayFormat = d3.timeFormat("%w");

        let newSvg = d3.select("body")
        .append("svg")
        .attr("width", coNumW)
        .attr("height", coNumH)
        .append("g").classed("no-select", true)
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // ********************************************* LOOPS *********************************************
}

$('div#dropdownMenuButtonAnchor a').click(function(){
  let incident = $(this).text();
  $("#incidentNumber").html(incident);

  //dataset.forEach(function(d, i) {
  for (let i = 0;i < dataset.length;i++){
    if (incident === dataset[i].scene) {
      dataset[i].chips.forEach(function(c, j) {
        changed.push(c);
        $('.incidentInfo')
        	.append('<a class="dropdown-item" onclick="update()" href="#">' + c.co_num  + '</a>');
      });
                    

      // ********************************************* LOOPS *********************************************
        
      x.domain([new Date(start), new Date(end)]).range([0, w]);
      y.domain(changed.map(d => d.chip)).padding(0.1);
    
      newSvg.append("g")
        .attr("class", "x_Axis")
        .attr("transform", "translate(0, " + h + ")")
        .call(xAxis)

    	newSvg.append("g")
        .attr("class", "y_Axis")
        .call(yAxis);
            
    	let tasksChange = newSvg.append("g")
        .attr("class", "dataCont")
        .selectAll("g")
        .data(changed)
        .enter()
        .append("g")
        .on("mouseenter", showData);

			let parseDate = d3.timeParse('%Y-%m-%dT%H:%m:%s');
      tasksChange.append("rect")
        .attr("x", function(d) {
          return x(moment(d.start_date).valueOf()) + 2;
        })
        .attr("y", function(d) {
	        return y(d.chip);
  	    })
        .attr("width", function(d) {
    	    return x(moment(d.end_date)) - x(moment(d.start_date)) +2;
      	})
        .attr("height", function(d) {
        	return y.bandwidth();
      	});

				d3.selectAll("#inlineRadio2, #inlineRadio3, #inlineRadio4")
					.on("change", function(){
						update();
				});

				d3.selectAll("#inlineRadio1")
					.on("change", function(){
						setInterval(update, 10);
						var svg = d3.select("svg");

						let start = moment().subtract(timeRange, 'minutes').valueOf();
						let end = moment().valueOf();

            x.domain([start, end]);
            xAxis.scale(x);
                
            //move the xaxis left
            svg.select(".x_axis")
              .transition()
              .duration(100)
              .ease(d3.easeLinear)
              .call(xAxis);
					});
	    }
    }
});
function showData(d) {
	console.log("Start Date: " + moment(d.start_date).format());
	console.log("End Date: " + moment(d.end_date).format());
  console.log('CO: ', d.chip)
  console.log('************************* ')
}

Open in new window

DawnAuthor Commented:
Ok, I'll keep this simple :) In the code below (and fiddle here: https://jsfiddle.net/dtepdc/qcvrh5ez/), I'm simply trying to display the array items from "co_num" in the browser when the "incident" number matches "dataset.scene". The items are currently displayed, but entire blocks of items are displayed as opposed to one-by-one. I can see that this is because I still need to drill down into "co_num" and display those items as opposed to the entire array but that is where I'm getting stuck:

let dataset = [
    {
        "scene": "IR0006426320",
        "scene_start_time": "2018-02-05T15:03:30",
        "chips": [
            {
                "chip": "2018.02.05.150",
                "start_date": "2018-02-05T00:05:07",
                "end_date": "2018-02-05T01:26:23",
                "co_num":["None"],
                "cause": false
            },
            {
                "chip": "2018.02.05.192",
                "start_date": "2018-02-05T15:48:08",
                "end_date": "2018-02-05T17:22:34",
                "co_num": [
                    "C03619354",
                    "C03618763",
                    "C03619064",
                    "C03619325"
                ],
                "cause": false
          }   
     ]
   }
]
     

          let incident = "IR0006426320"
	       for (const x in dataset) {
		
                    if (incident === dataset[x].scene) {
                	for (const a in dataset[x].chips) {
                    $('.incidentInfo').append('<a class="dropdown-item" onclick="update()" href="#">' + dataset[x].chips[a].co_num  + '</a><br />');
                  }
                    
                }
            }
       

Open in new window

Starting with Angular 5

Learn the essential features and functions of the popular JavaScript framework for building mobile, desktop and web applications.

Julian HansenCommented:
Is this what you were wanting
// Dummy our incident     
let incident = "IR0006426320";

// Find the item we are interested in
var item = dataset.find(x => x.scene === incident);

// Setup referecne to target element
var target = $('.incidentInfo');

// If we found him
if (item) {
  // iterate over the chips for this item
  item.chips.forEach(x => {
    // iterate over the co_num for each chip
    x.co_num.forEach(y => {
      // create and append a new <a> item with a click handler linked to the update function
        target.append(
          $('<a>', {class: 'dropdown-item', href: '#'})
            .html(y)
            .on('click', update)
        );
    })
  })
}

// Event handler for our click event
function update(e)
{
  // Prevent default behaviour
  e.preventDefault();
  
  // Dump some output
  console.log(e);
}

Open in new window


Updated fiddle here https://jsfiddle.net/ux3zf2n7/

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
DawnAuthor Commented:
Thank you so much! I can see how you did that in regards to the nested "co_num" array (as well as the more current javascript).
Julian HansenCommented:
You are welcome - be aware that arrow functions have not gained full cross browser support status( i.e. that browser).
I used them for brevity but depending on the target environment you may need to downgrade them to the normal anonymous functions.
DawnAuthor Commented:
Will do, thanks again!
DawnAuthor Commented:
Julian, I'm trying to remove duplicate items from within the rendered array.

For this block:

x.co_num.forEach(y => {

                            target.append($('<a>', {class: 'dropdown-item', href: '#'}).html(y).on('click', update));

Open in new window


I thought that I could use something like the code below but it's not working:

x.co_num.forEach(y => {
                                const deduped = [...new Set(y)];
                                
                            target.append($('<a>', {class: 'dropdown-item', href: '#'}).html(deduped).on('click', update));
                    });

Open in new window


Does "Set" need to happen before looping through "y"?
Julian HansenCommented:
If you are going to do it like that you need to build up your Set independently of the output otherwise you are going to output a progressive state of the Set on each iteration.
A better way is to use the Set to determine output.
let conum = new Set();
item.chips.forEach(x => {
  x.co_num.forEach(y => {
    if (!conum.has(y)) {
      target.append($('<a>', {class: 'dropdown-item', href: '#'}).html(y).on('click', update));
      conum.add(y);
    }
  });
});

Open in new window

However, Set has not reached full cross browser compatibility (i.e that browser again)

A more cross browser version would be
let conum = [];
item.chips.forEach(x => {
  x.co_num.forEach(y => {
    if (conum.indexOf(y) === -1) {
      target.append($('<a>', {class: 'dropdown-item', href: '#'}).html(y).on('click', update));
      conum.push(y);
    }
  });
});

Open in new window

DawnAuthor Commented:
Thank you! I realized I couldn't use Set with the code I had written since it was already a string. This makes total sense, thanks!
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.