Last active
June 27, 2021 19:57
-
-
Save ryanwi/52d5dfa1aecf0bd11029d3ae079328dd to your computer and use it in GitHub Desktop.
page builder without jQuery or jQuery UI for autocomplete
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Look, no jQuery | |
'use strict'; | |
let terms; | |
let categories; | |
let series; | |
function populateTermsDatalist() { | |
const list = document.getElementById('datalistTerms'); | |
terms.forEach(item => { | |
let option = document.createElement('option'); | |
option.value = item; | |
list.appendChild(option); | |
}); | |
} | |
const highChartConverter = (function () { | |
return { | |
convertCategories: function () { | |
// initialize xaxis categories (months) | |
const months = []; | |
data.map(function ( datapoint, i ) { | |
months.push(datapoint["month"]); | |
}); | |
return months; | |
}, | |
convertSeries: function () { | |
// initialize series data | |
const series = []; | |
terms.map(function ( term, i ) { | |
const term_data = { "name": term, "data": [], "total_mentions": 0 } | |
// build data | |
data.map(function ( datapoint, i ) { | |
term_data["data"].push( datapoint["terms"][term]["percentage"] ); | |
term_data["total_mentions"] += datapoint["terms"][term]["count"]; | |
}); | |
// calculate YOY change | |
let first = term_data["data"][term_data["data"].length-13]; | |
let last = term_data["data"][term_data["data"].length-1] | |
// assign a floor to have more meaningful change calculation | |
if (first == 0) { | |
first = 1; | |
} | |
if (last == 0) { | |
last = 1; | |
} | |
term_data["change"] = (last - first) / first; | |
term_data["latest_mentions"] = last; | |
series.push(term_data); | |
}); | |
return series; | |
}, | |
convertCountYoySeries: function () { | |
const countSeries = []; | |
const months = {'Jan':0,'Feb':1,'Mar':2,'Apr':3,'May':4,'Jun':5,'Jul':6,'Aug':7,'Sep':8,'Oct':9,'Nov':10,'Dec':11}; | |
const years = {'18':0, '19':1, '20':2, '21':3}; | |
for (const [key, value] of Object.entries(years)) { | |
countSeries.push({ name: "'" + key, data: [0,0,0,0,0,0,0,0,0,0,0,0]}); | |
} | |
data.map(function(value, index) { | |
const month = value.month.substr(0, 3); | |
const year = value.month.substr(3, 2); | |
if (typeof countSeries[years[year]] !== 'undefined') { | |
countSeries[years[year]].data[months[month]] = parseInt(value.num_comments); | |
} | |
}); | |
return countSeries; | |
} | |
} | |
}) (); | |
const chartBuilder = (function () { | |
function render( seriesData ) { | |
Highcharts.chart({ | |
chart: { | |
renderTo: 'chart', | |
type: 'line' | |
}, | |
title: { | |
text: '' | |
}, | |
xAxis: { | |
categories: categories, | |
endOnTick: true, | |
labels: { | |
rotation: [-45], | |
step: 2 | |
} | |
}, | |
yAxis: { | |
title: { | |
text: 'Percentage of posts' | |
}, | |
min: 0 | |
}, | |
tooltip: { | |
}, | |
series: seriesData | |
}); | |
} | |
return { | |
renderTopTerms: function( numTerms ) { | |
render( series.slice( 0, numTerms ) ); | |
}, | |
renderComparison: function() { | |
let compareTerms = []; | |
for (let item of document.getElementsByClassName("term-compare")) { | |
compareTerms.push(item.value.toLowerCase()); | |
} | |
const compareSeries = series.filter(function(val, i) { | |
return compareTerms.includes(val.name.toLowerCase()); | |
}); | |
render( compareSeries ); | |
} | |
} | |
}) (); | |
window.addEventListener('DOMContentLoaded', (event) => { | |
data.reverse(); | |
terms = Object.keys( data[0]["terms"] ); | |
// transform raw data in to format consumable by highcharts | |
categories = highChartConverter.convertCategories(); | |
series = highChartConverter.convertSeries(); | |
// sort by cumulative popularity | |
series.sort(function(a,b){ return b.latest_mentions - a.latest_mentions }); | |
// wire up top terms filter | |
const selectElement = document.querySelector('#topfilter'); | |
selectElement.addEventListener('change', (event) => { | |
chartBuilder.renderTopTerms( parseInt(event.target.value) ); | |
}); | |
// process url parameters if present | |
const url = new URL(window.location); | |
let comparisons = url.searchParams.getAll("compare"); | |
if (comparisons.length > 0) { | |
if (comparisons.length < 4) { | |
comparisons = comparisons.concat(Array(4-comparisons.length).fill("")); | |
} | |
const comparisonsParent = document.getElementById("term_comparisons"); | |
while (comparisonsParent.firstChild) { | |
comparisonsParent.firstChild.remove() | |
} | |
var fragment = new DocumentFragment(); | |
comparisons.forEach(function(queryTerm) { | |
var div = document.createElement("div"); | |
div.className = 'col'; | |
var input = document.createElement("input"); | |
input.value = queryTerm; | |
input.type = 'text'; | |
input.className = 'term-compare form-control'; | |
input.name = 'compare'; | |
div.appendChild(input); | |
fragment.appendChild(div); | |
}); | |
comparisonsParent.appendChild(fragment); | |
chartBuilder.renderComparison(); | |
} else { | |
chartBuilder.renderTopTerms(5); | |
} | |
Highcharts.chart({ | |
chart: { | |
renderTo: 'comments_chart', | |
type: 'column' | |
}, | |
title: { | |
text: 'Total Posts on Ask HN: Who is hiring?' | |
}, | |
xAxis: { | |
categories: [ | |
'Jan', | |
'Feb', | |
'Mar', | |
'Apr', | |
'May', | |
'Jun', | |
'Jul', | |
'Aug', | |
'Sep', | |
'Oct', | |
'Nov', | |
'Dec' | |
], | |
}, | |
yAxis: { | |
min: 0, | |
title: { | |
enabled: false, | |
}, | |
labels: { | |
} | |
}, | |
legend: { | |
enabled: true | |
}, | |
series: highChartConverter.convertCountYoySeries() | |
}); | |
// wire up autocomplete/datalist | |
populateTermsDatalist(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment