/* global d3 queue */ const table = d3.select('.table-container').append('table'); table.append('thead'); table.append('tbody'); queue() .defer(d3.json, 'qcew.json') .defer(d3.json, 'stateface.json') .await(ready); function ready(error, qcew, stateface) { if (error) throw error; const columns = [ { head: 'State', cl: 'state', html(row) { const sfLetter = stateface[row.state_abbrev]; const icon = `${sfLetter}`; const text = `${row.state}`; return icon + text; }, }, { head: 'Employment (millions)', cl: 'emp', html(row) { const scale = d3.scaleThreshold() .domain([1, 2, 4, 6]) .range([1, 2, 3, 4, 5]); const icon = ''; const value = d3.format(',.1f')(row.emp / 1000000); const nIcons = scale(value); const text = `${value}`; return text + d3.range(nIcons) .map(() => icon).join(''); }, }, { head: 'Change in Employment', cl: 'emp_pc', html(row) { const scale = d3.scaleThreshold() .domain([0, 0.045]) .range(['down', 'right', 'up']); const icon = ``; const value = d3.format(',.0%')(row.emp_pc); const text = `${value}`; return text + icon; }, }, { head: 'Wage (weekly)', cl: 'wage', html(row) { const scale = d3.scaleThreshold() .domain([850, 1000]) .range([1, 2, 3]); const icon = ''; const nIcons = scale(row.wage); const value = d3.format('$,')(row.wage); const text = `${value}`; return text + d3.range(nIcons) .map(() => icon).join(''); }, }, { head: 'Change in Wage', cl: 'wage_pc', html(row) { const scale = d3.scaleThreshold() .domain([0, 0.07]) .range(['down', 'right', 'up']); const icon = ``; const value = d3.format(',.0%')(row.wage_pc); const text = `${value}`; return text + icon; }, }, ]; table.call(renderTable); function renderTable(table) { const tableUpdate = table.select('thead') .selectAll('th') .data(columns); const tableEnter = tableUpdate .enter().append('th') .attr('class', d => d.cl) .text(d => d.head) .on('click', (d) => { let ascending; if (d.ascending) { ascending = false; } else { ascending = true; } d.ascending = ascending; qcew.sort((a, b) => { if (ascending) { return d3.ascending(a[d.cl], b[d.cl]); } return d3.descending(a[d.cl], b[d.cl]); }); table.call(renderTable); }); const trUpdate = table.select('tbody').selectAll('tr') .data(qcew); const trEnter = trUpdate.enter().append('tr'); const trMerge = trUpdate.merge(trEnter) .on('mouseenter', mouseenter) .on('mouseleave', mouseleave); const tdUpdate = trMerge.selectAll('td') .data((row, i) => columns.map((c) => { const cell = {}; d3.keys(c).forEach((k) => { cell[k] = typeof c[k] === 'function' ? c[k](row, i) : c[k]; }); return cell; })); const tdEnter = tdUpdate.enter().append('td'); tdEnter .attr('class', d => d.cl) .style('background-color', '#fff') .style('border-bottom', '.5px solid white'); tdEnter.merge(tdUpdate).html(d => d.html); } } function mouseenter() { d3.select(this).selectAll('td') .style('background-color', '#f0f0f0') .style('border-bottom', '.5px solid slategrey'); } function mouseleave() { d3.select(this).selectAll('td') .style('background-color', '#fff') .style('border-bottom', '.5px solid white'); }