diff --git a/public/app.css b/public/app.css index 1125924..2cebff0 100644 --- a/public/app.css +++ b/public/app.css @@ -12,3 +12,6 @@ th, td { padding:10px; text-align: center; } +li { + display:inline; +} diff --git a/public/app.js b/public/app.js index a7b75e4..635355a 100644 --- a/public/app.js +++ b/public/app.js @@ -7,6 +7,8 @@ const parseTime = d3.timeParse("%B %e, %Y"); let instances; let xScale, yScale; let highlighted = [] +const courses = []; +const metros = []; const randomColor = ()=>{ const red = Math.floor(Math.random()*128) + 64; @@ -61,27 +63,36 @@ const renderPoints = () => { .append('circle'); d3.selectAll('circle') - .attr('cy', (datum, index) => yScale(datum.ninety_day_outcomes/datum.graduates*100) ); - - d3.selectAll('circle') - .attr('cx', (datum, index) => xScale(parseTime(datum.graduation_date)) ); - - d3.selectAll('circle') + .attr('cy', (datum, index) => yScale(datum.ninety_day_outcomes/datum.graduates*100) ) + .attr('cx', (datum, index) => xScale(parseTime(datum.graduation_date)) ) .attr('fill', datum => datum.color? datum.color : 'black') .attr('r', datum => datum.color? 10 : 5) - - d3.selectAll('circle').on('click', (event, datum) => { - const found = highlighted.find(i => i.instance_id === datum.instance_id) - if(found === undefined){ - datum.color = randomColor() - highlighted.push(datum) - } else { - delete datum.color - highlighted = highlighted.filter(i => i.instance_id != datum.instance_id) - } - renderPoints() - renderTable() - }); + .style('display', (datum)=>{ + const instanceMetro = datum.course.split('-')[0] + const instanceCourse = datum.course.split('-')[1] + + const metro = metros.find(m => m.metro === instanceMetro) + const course = courses.find(c => c.course === instanceCourse) + + if(metro.checked && course.checked){ + return 'block' + } else { + return 'none' + } + }) + .on('click', (event, datum) => { + const found = highlighted.find(i => i.instance_id === datum.instance_id) + + if(found === undefined){ + datum.color = randomColor() + highlighted.push(datum) + } else { + delete datum.color + highlighted = highlighted.filter(i => i.instance_id != datum.instance_id) + } + renderPoints() + renderTable() + }); } @@ -135,8 +146,47 @@ const createFormSubmissionHandler = () => { }); } +const populateMetrosCoursesCheckboxes = ()=>{ + for(let instance of instances){ + const segments = instance.course.split('-') + + if(metros.find(m => m.metro === segments[0]) === undefined){ + metros.push({ checked:true, metro: segments[0] }) + } + + if(courses.find(c => c.course === segments[1]) === undefined){ + courses.push({ checked:true, course: segments[1] }) + } + + } + d3.select('#courses') + .selectAll('li') + .data(courses) + .enter() + .append('li').text(d => d.course) + .append('input').attr('type', 'checkbox') + .property('checked', d => d.checked) + .on('click', (event, datum)=>{ + datum.checked = !datum.checked + renderPoints() + }) + + d3.select('#metros') + .selectAll('li') + .data(metros) + .enter() + .append('li').text(d => d.metro) + .append('input').attr('type', 'checkbox') + .property('checked', d => d.checked) + .on('click', (event, datum)=>{ + datum.checked = !datum.checked + renderPoints() + }) +} + window.onload = async ()=>{ instances = await d3.json('/instances'); + populateMetrosCoursesCheckboxes(); setupGraph(); createAxes(); renderPoints(); diff --git a/public/index.html b/public/index.html index 4f486b1..87b943d 100644 --- a/public/index.html +++ b/public/index.html @@ -18,6 +18,10 @@