$(document).ready(function() { var initTab = function(tab, push) { if (!tab) { tab = location.hash.replace('#', '') || 'styles'; } console.log(tab, push); $(`a#${tab}-tab`).tab('show'); if (push) { history.pushState({}, '', '#' + tab); } }; $.when( $.getJSON('beers.json'), $.getJSON('breweries.json'), $.getJSON('styles.json') ).done(function(beerData, breweryData, styleData) { var compileDate = Date.parse($('time#compile-date').attr('datetime')); var beers = beerData[0]; $.each(beers, function(idx, beer) { var addedDate = new Date(); addedDate.setYear(beer.added.year); addedDate.setMonth(beer.added.month-1); addedDate.setDate(beer.added.day); var dateDiff = Math.ceil((compileDate - addedDate.getTime()) / (1000 * 60 * 60 * 24 * 30)); if (!beer.in_production) { dateDiff = Math.min(dateDiff, 12); } beer.ratings.adjusted = beer.ratings.count / dateDiff; beer['scatter-data'] = [ { x: beer.abv, y: beer.ratings.adjusted, ref: beer }, { x: beer.abv, y: beer.ratings.average, ref: beer }, { x: beer.ratings.adjusted, y: beer.ratings.average, ref: beer } ]; }); var minYear = Math.min.apply(null, beers.map(b => b.added.year)); var maxYear = Math.max.apply(null, beers.map(b => b.added.year)); var minMonth = Math.min.apply(null, beers.filter(b => (b.added.year == minYear)).map(b => b.added.month)); var maxMonth = Math.max.apply(null, beers.filter(b => (b.added.year == maxYear)).map(b => b.added.month)); var fullYears = maxYear - minYear - 1; var dateCount = fullYears * 12 + (12 - minMonth + 1) + maxMonth; var dateMapping = []; var year = minYear; var month = minMonth; for (var c = 0; c < dateCount; c++) { dateMapping[c] = year + '-' + ('0' + month).slice(-2); month++; if (month > 12) { year++; month = 1; } } var valSpan = [0, dateCount-1]; var currRange = 12-minMonth+1; var lastRange = 'odd'; var yearRanges = [{'start': 0, 'end': currRange-1, 'class': lastRange}]; while (currRange < dateCount) { lastRange = lastRange == 'odd' ? 'even' : 'odd'; yearRanges.push({ 'start': currRange, 'end': Math.min(currRange+11, dateCount-1), 'class': lastRange }); currRange += 12; } $('#date-filter input[name="date"]').slider({ min: 0, max: dateCount-1, value: valSpan, ticks: valSpan, ticks_labels: valSpan.map(v => dateMapping[v]), rangeHighlights: yearRanges, formatter: function(val) { if (isNaN(val)) { return val.map(v => dateMapping[v]).join(' - '); } else { return dateMapping[val]; } } }); var breweries = breweryData[0]; var breweryTemplate = $('#brewery-template').html(); var breweryFilter = $('#brewery-filter'); $.each(breweries, function(brewery, data) { var fieldId = 'brewery-' + brewery; var field = $(breweryTemplate); field.find('input').attr('value', brewery).attr('id', fieldId); field.find('label').attr('for', fieldId).attr('title', data['name']).find('img').attr('src', 'img/' + data['logo']); breweryFilter.append(field); field.find('label').tooltip(); }); $('#brewery-all').change(function() { if ($(this).is(':checked')) { $('#brewery-filter .form-check input').prop('checked', 'checked'); } else { $('#brewery-filter .form-check input').prop('checked', null); } }); var styles = styleData[0]; $.each(styles, function(idx, style) { style.styleTree = {}; $.each(style.styles.map(s => s.split(' - ')), function(idx, splitStyle) { if (splitStyle.length > 1) { if (!style.styleTree[splitStyle[0]]) { style.styleTree[splitStyle[0]] = []; } style.styleTree[splitStyle[0]].push(splitStyle[1]); } else { style.styleTree[splitStyle[0]] = null; } }); }); var styleNames = styles.map(s => s.name); var styleCounts = styles.map(s => 0); var substyleCounts = []; var styleSubstyles = styles.map(s => s.styles); var styleColours = styles.map(s => s.colour); var scatterChartData = []; for (var i = 0; i < 3; i++) { scatterChartData[i] = { datasets: styles.map(function(style) { return { borderColor: style.colour, backgroundColor: Color(style.colour).alpha(0.5).rgbString(), label: style.name, data: [] }; }) }; } var displayTooltip = function(chart, tooltip, data, contentFunction) { var container = $('#chart-tooltip'); if (!container.length) { container = $('
'); $('body').append(container); } if (tooltip.body) { var positionY = chart.canvas.offsetTop; var positionX = chart.canvas.offsetLeft; container.html(contentFunction(tooltip, data)).show(); container.css({ 'top': Math.min( positionY + tooltip.caretY, $('body').height() - container.outerHeight() ), 'left': Math.min( positionX + tooltip.caretX, $('body').width() - container.outerWidth() ) }).addClass(chart.canvas.id).show(); } else { container.html('').removeAttr('class').hide(); } }; var scatterTooltip = function(tooltip, data) { var content = $('
'); var datasets = data.datasets; $.each(tooltip.dataPoints, function(d, dataPoint) { var beer = datasets[dataPoint.datasetIndex].data[dataPoint.index].ref; content.append( $('
').append($('').text(beer.name)), $('
').append($('').text(breweries[beer.brewery].name)), $('
').append($('').text(beer.style.join(' - '))), $('
').append( $('
').text('ABV'), $('
').text(`${beer.abv}%`), $('
').text('L. ocen'), $('
').text(beer.ratings.count), $('
').text('Śr. ocen'), $('
').text(beer.ratings.average), $('
').text('Dodane'), $('
').text([ `0${beer.added.day}`.slice(-2), `0${beer.added.month}`.slice(-2), beer.added.year ].join('-')) ) ); }); return content; }; var stylesChart; $('a#styles-tab').on('shown.bs.tab', function() { if (!stylesChart) { var ctx = $('#styles-chart')[0].getContext('2d'); stylesChart = new Chart(ctx, { type: 'bar', data: { labels: styleNames, datasets: [{ data: styleCounts, backgroundColor: styleColours.map(c => Color(c).alpha(0.5).rgbString()), borderColor: styleColours, borderWidth: 1 }] }, options: { legend: { display: false }, scales: { yAxes: [{ ticks: { beginAtZero: true } }] }, tooltips: { enabled: false, custom: function(tooltip) { displayTooltip(this._chart, tooltip, this._data, function(tooltip, data) { var content = $('
    '); $.each(styles[tooltip.dataPoints[0].index].styleTree, function(style, substyles) { var getItem = function(style, substyle) { var count = substyleCounts[substyle ? (`${style} - ${substyle}`) : style]; if (count) { var term = $('
    '); var value = $('
    '); var item = $('
  • ').append($('
    ').append(term, value)); term.html(substyle || style); value.html(count); return item; } return null; }; if (substyles) { var sublist = $('
      '); var nonZero = false; $.each(substyles, function(id, substyle) { var item = getItem(style, substyle); if (item) { sublist.append(item); nonZero = true; } }); if (nonZero) { content.append($('
    • ').append(style, sublist)); } } else { content.append(getItem(style)); } }); return content; }); } } } }); } }); var ratingAxis = { type: 'logarithmic', ticks: { min: 0, callback: value => value.toLocaleString(), autoSkipPadding: 20 } }; var averageAxis = { ticks: { min: Math.floor(Math.min.apply(null, beers.map(b => b.ratings.average)) * 2) * 0.5, max: 5 } }; var abvAxis = { ticks: { min: 0 } }; var abvRatingsChart; $('a#abv-ratings-tab').on('shown.bs.tab', function() { if (!abvRatingsChart) { var ctx = $('#abv-ratings-chart')[0].getContext('2d'); abvRatingsChart = new Chart.Scatter(ctx, { data: scatterChartData[0], options: { scales: { xAxes: [abvAxis], yAxes: [ratingAxis] }, tooltips: { enabled: false, custom: function(tooltip) { displayTooltip(this._chart, tooltip, this._data, scatterTooltip); } } } }); } }); var abvAverageChart; $('a#abv-average-tab').on('shown.bs.tab', function() { if (!abvAverageChart) { var ctx = $('#abv-average-chart')[0].getContext('2d'); abvAverageChart = new Chart.Scatter(ctx, { data: scatterChartData[1], options: { scales: { xAxis: [abvAxis], yAxes: [averageAxis] }, tooltips: { enabled: false, custom: function(tooltip) { displayTooltip(this._chart, tooltip, this._data, scatterTooltip); } } } }); } }); var ratingsAverageChart; $('a#ratings-average-tab').on('shown.bs.tab', function() { if (!ratingsAverageChart) { var ctx = $('#ratings-average-chart')[0].getContext('2d'); ratingsAverageChart = new Chart.Scatter(ctx, { data: scatterChartData[2], options: { scales: { xAxes: [ratingAxis], yAxes: [averageAxis] }, tooltips: { enabled: false, custom: function(tooltip) { displayTooltip(this._chart, tooltip, this._data, scatterTooltip); } } } }); } }); var getFilteredBeers = function(beers) { var dates = $('#date-filter input[name="date"]').val().split(',').map(d => dateMapping[parseInt(d)]); var breweries = $('#brewery-filter input:checked').map(function(i, input) { return input.value; }).toArray(); return beers.filter(function(beer) { var added = beer.added.year + '-' + `0${beer.added.month}`.slice(-2); return (breweries.indexOf(beer.brewery) > -1) && (added >= dates[0] && added <= dates[1]); }); }; var updateCharts = function() { var filtered = getFilteredBeers(beers); var bySubstyle = {}; for (var s in substyleCounts) { substyleCounts[s] = 0; } for (var beer in filtered) { var style = filtered[beer].style.join(' - '); if (!substyleCounts[style]) { substyleCounts[style] = 0; } substyleCounts[style]++; if (!bySubstyle[style]) { bySubstyle[style] = []; } bySubstyle[style].push(filtered[beer]['scatter-data']); } for (var s in styleCounts) { styleCounts[s] = 0; for (var i = 0; i < 3; i++) { scatterChartData[i].datasets[s].data = []; } for (var ss in styleSubstyles[s]) { var substyle = styleSubstyles[s][ss]; if (substyleCounts[substyle]) { styleCounts[s] += substyleCounts[substyle]; for (var j = 0; j < 3; j++) { scatterChartData[j].datasets[s].data = scatterChartData[j].datasets[s].data.concat(bySubstyle[substyle].map(d => d[j])); } } } } if (stylesChart) { stylesChart.update(); } if (abvRatingsChart) { abvRatingsChart.update(); } if (abvAverageChart) { abvAverageChart.update(); } if (ratingsAverageChart) { ratingsAverageChart.update(); } }; var changeTimeout = null; $('#date-filter, #brewery-filter').find('input').change(function() { clearTimeout(changeTimeout); changeTimeout = setTimeout(updateCharts, 500); }); initTab(false, true); updateCharts(); }); $('#tab-menu a').on('click', function (e) { e.preventDefault(); e.stopImmediatePropagation(); initTab($(this).attr('aria-controls'), true); return false; }); $(window).on('popstate', function(ev) { initTab(false, false); }); });