[fixes] tooltip format, legend, labels, heatmap margin

This commit is contained in:
Prateeksha Singh 2018-03-06 03:05:40 +05:30
parent ded80791dd
commit 546ce96a12
21 changed files with 683 additions and 545 deletions

View File

@ -133,6 +133,9 @@ class SvgTip {
fill() { fill() {
let title; let title;
if(this.index) {
this.container.setAttribute('data-point-index', this.index);
}
if(this.titleValueFirst) { if(this.titleValueFirst) {
title = `<strong>${this.titleValue}</strong>${this.titleName}`; title = `<strong>${this.titleValue}</strong>${this.titleName}`;
} else { } else {
@ -179,13 +182,14 @@ class SvgTip {
} }
} }
setValues(x, y, titleName = '', titleValue = '', listValues = [], titleValueFirst = 0) { setValues(x, y, title = {}, listValues = [], index = -1) {
this.titleName = titleName; this.titleName = title.name;
this.titleValue = titleValue; this.titleValue = title.value;
this.listValues = listValues; this.listValues = listValues;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.titleValueFirst = titleValueFirst; this.titleValueFirst = title.valueFirst || 0;
this.index = index;
this.refresh(); this.refresh();
} }
@ -202,7 +206,7 @@ class SvgTip {
} }
} }
const VERT_SPACE_OUTSIDE_BASE_CHART = 40; const VERT_SPACE_OUTSIDE_BASE_CHART = 50;
const TRANSLATE_Y_BASE_CHART = 20; const TRANSLATE_Y_BASE_CHART = 20;
const LEFT_MARGIN_BASE_CHART = 60; const LEFT_MARGIN_BASE_CHART = 60;
const RIGHT_MARGIN_BASE_CHART = 40; const RIGHT_MARGIN_BASE_CHART = 40;
@ -220,7 +224,7 @@ const MIN_BAR_PERCENT_HEIGHT = 0.01;
const LINE_CHART_DOT_SIZE = 4; const LINE_CHART_DOT_SIZE = 4;
const DOT_OVERLAY_SIZE_INCR = 4; const DOT_OVERLAY_SIZE_INCR = 4;
const DEFAULT_CHAR_WIDTH = 8; const DEFAULT_CHAR_WIDTH = 7;
// Universal constants // Universal constants
const ANGLE_RATIO = Math.PI / 180; const ANGLE_RATIO = Math.PI / 180;
@ -574,7 +578,7 @@ function makeVertLine(x, label, y1, y2, options={}) {
dy: FONT_SIZE + 'px', dy: FONT_SIZE + 'px',
'font-size': FONT_SIZE + 'px', 'font-size': FONT_SIZE + 'px',
'text-anchor': 'middle', 'text-anchor': 'middle',
innerHTML: label innerHTML: label + ""
}); });
let line = createSVG('g', { let line = createSVG('g', {
@ -729,7 +733,7 @@ function yRegion(y1, y2, width, label) {
let labelSvg = createSVG('text', { let labelSvg = createSVG('text', {
className: 'chart-label', className: 'chart-label',
x: width - getStringWidth(label, 4.5) - LABEL_MARGIN, x: width - getStringWidth(label+"", 4.5) - LABEL_MARGIN,
y: 0, y: 0,
dy: (FONT_SIZE / -2) + 'px', dy: (FONT_SIZE / -2) + 'px',
'font-size': FONT_SIZE + 'px', 'font-size': FONT_SIZE + 'px',
@ -761,6 +765,8 @@ function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={})
height: height || meta.minHeight // TODO: correct y for positive min height height: height || meta.minHeight // TODO: correct y for positive min height
}); });
label += "";
if(!label && !label.length) { if(!label && !label.length) {
return rect; return rect;
} else { } else {
@ -777,6 +783,7 @@ function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={})
}); });
let group = createSVG('g', { let group = createSVG('g', {
'data-point-index': index,
transform: `translate(${x}, ${y})` transform: `translate(${x}, ${y})`
}); });
group.appendChild(rect); group.appendChild(rect);
@ -795,6 +802,8 @@ function datasetDot(x, y, radius, color, label='', index=0, meta={}) {
r: radius r: radius
}); });
label += "";
if(!label && !label.length) { if(!label && !label.length) {
return dot; return dot;
} else { } else {
@ -812,6 +821,7 @@ function datasetDot(x, y, radius, color, label='', index=0, meta={}) {
}); });
let group = createSVG('g', { let group = createSVG('g', {
'data-point-index': index,
transform: `translate(${x}, ${y})` transform: `translate(${x}, ${y})`
}); });
group.appendChild(dot); group.appendChild(dot);
@ -873,9 +883,10 @@ let makeOverlay = {
} }
let overlay = unit.cloneNode(); let overlay = unit.cloneNode();
let radius = unit.getAttribute('r'); let radius = unit.getAttribute('r');
overlay.setAttribute('r', radius + DOT_OVERLAY_SIZE_INCR); let fill = unit.getAttribute('fill');
overlay.style.fill = '#000000'; overlay.setAttribute('r', parseInt(radius) + DOT_OVERLAY_SIZE_INCR);
overlay.style.opacity = '0.4'; overlay.setAttribute('fill', fill);
overlay.style.opacity = '0.6';
if(transformValue) { if(transformValue) {
overlay.setAttribute('transform', transformValue); overlay.setAttribute('transform', transformValue);
@ -1266,7 +1277,10 @@ class BaseChart {
setTimeout(() => {this.update();}, this.initTimeout); setTimeout(() => {this.update();}, this.initTimeout);
} }
this.renderLegend(); if(!onlyWidthChange) {
this.renderLegend();
}
this.setupNavigation(init); this.setupNavigation(init);
} }
@ -1456,10 +1470,11 @@ class AggregationChart extends BaseChart {
renderLegend() { renderLegend() {
let s = this.state; let s = this.state;
this.statsWrapper.textContent = '';
this.legendTotals = s.sliceTotals.slice(0, this.config.maxLegendPoints); this.legendTotals = s.sliceTotals.slice(0, this.config.maxLegendPoints);
let x_values = this.formatted_labels && this.formatted_labels.length > 0 let xValues = s.labels;
? this.formatted_labels : s.labels;
this.legendTotals.map((d, i) => { this.legendTotals.map((d, i) => {
if(d) { if(d) {
let stats = $.create('div', { let stats = $.create('div', {
@ -1468,7 +1483,7 @@ class AggregationChart extends BaseChart {
}); });
stats.innerHTML = `<span class="indicator"> stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i> <i style="background: ${this.colors[i]}"></i>
<span class="text-muted">${x_values[i]}:</span> <span class="text-muted">${xValues[i]}:</span>
${d} ${d}
</span>`; </span>`;
} }
@ -1542,7 +1557,7 @@ class PercentageChart extends AggregationChart {
? this.formattedLabels[i] : this.state.labels[i]) + ': '; ? this.formattedLabels[i] : this.state.labels[i]) + ': ';
let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1); let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%"); this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip(); this.tip.showTip();
} }
}); });
@ -2008,7 +2023,7 @@ class PieChart extends AggregationChart {
return { return {
sliceStrings: s.sliceStrings, sliceStrings: s.sliceStrings,
colors: this.colors colors: this.colors
} };
}.bind(this) }.bind(this)
] ]
]; ];
@ -2038,7 +2053,7 @@ class PieChart extends AggregationChart {
let title = (this.formatted_labels && this.formatted_labels.length > 0 let title = (this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels[i] : this.state.labels[i]) + ': '; ? this.formatted_labels[i] : this.state.labels[i]) + ': ';
let percent = (this.state.sliceTotals[i] * 100 / this.state.grandTotal).toFixed(1); let percent = (this.state.sliceTotals[i] * 100 / this.state.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%"); this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip(); this.tip.showTip();
} else { } else {
transform(path,'translate3d(0,0,0)'); transform(path,'translate3d(0,0,0)');
@ -2106,8 +2121,6 @@ function addDays(date, numberOfDays) {
date.setDate(date.getDate() + numberOfDays); date.setDate(date.getDate() + numberOfDays);
} }
// export function getMonthName() {}
function normalize(x) { function normalize(x) {
// Calculates mantissa and exponent of a number // Calculates mantissa and exponent of a number
// Returns normalized number and exponent // Returns normalized number and exponent
@ -2328,15 +2341,15 @@ class Heatmap extends BaseChart {
this.domain = options.domain || ''; this.domain = options.domain || '';
this.subdomain = options.subdomain || ''; this.subdomain = options.subdomain || '';
this.data = options.data || {}; this.data = options.data || {};
this.discrete_domains = options.discrete_domains || 1; this.discreteDomains = options.discreteDomains === 0 ? 0 : 1;
this.count_label = options.count_label || ''; this.countLabel = options.countLabel || '';
let today = new Date(); let today = new Date();
this.start = options.start || addDays(today, 365); this.start = options.start || addDays(today, 365);
let legend_colors = (options.legend_colors || []).slice(0, 5); let legendColors = (options.legendColors || []).slice(0, 5);
this.legend_colors = this.validate_colors(legend_colors) this.legendColors = this.validate_colors(legendColors)
? legend_colors ? legendColors
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127']; : ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
// Fixed 5-color theme, // Fixed 5-color theme,
@ -2347,6 +2360,12 @@ class Heatmap extends BaseChart {
this.setup(); this.setup();
} }
setMargins() {
super.setMargins();
this.leftMargin = 10;
this.translateY = 10;
}
validate_colors(colors) { validate_colors(colors) {
if(colors.length < 5) return 0; if(colors.length < 5) return 0;
@ -2369,21 +2388,21 @@ class Heatmap extends BaseChart {
this.start = new Date(); this.start = new Date();
this.start.setFullYear( this.start.getFullYear() - 1 ); this.start.setFullYear( this.start.getFullYear() - 1 );
} }
this.first_week_start = new Date(this.start.toDateString()); this.firstWeekStart = new Date(this.start.toDateString());
this.last_week_start = new Date(this.today.toDateString()); this.lastWeekStart = new Date(this.today.toDateString());
if(this.first_week_start.getDay() !== 7) { if(this.firstWeekStart.getDay() !== 7) {
addDays(this.first_week_start, (-1) * this.first_week_start.getDay()); addDays(this.firstWeekStart, (-1) * this.firstWeekStart.getDay());
} }
if(this.last_week_start.getDay() !== 7) { if(this.lastWeekStart.getDay() !== 7) {
addDays(this.last_week_start, (-1) * this.last_week_start.getDay()); addDays(this.lastWeekStart, (-1) * this.lastWeekStart.getDay());
} }
this.no_of_cols = getWeeksBetween(this.first_week_start + '', this.last_week_start + '') + 1; this.no_of_cols = getWeeksBetween(this.firstWeekStart + '', this.lastWeekStart + '') + 1;
} }
calcWidth() { calcWidth() {
this.baseWidth = (this.no_of_cols + 3) * 12 ; this.baseWidth = (this.no_of_cols + 3) * 12 ;
if(this.discrete_domains) { if(this.discreteDomains) {
this.baseWidth += (12 * 12); this.baseWidth += (12 * 12);
} }
} }
@ -2397,21 +2416,20 @@ class Heatmap extends BaseChart {
'data-groups', 'data-groups',
`translate(0, 20)` `translate(0, 20)`
); );
// Array.prototype.slice.call(
// this.container.querySelectorAll('.graph-stats-container, .sub-title, .title') this.container.querySelector('.title').style.display = 'None';
// ).map(d => { this.container.querySelector('.sub-title').style.display = 'None';
// d.style.display = 'None'; this.container.querySelector('.graph-stats-container').style.display = 'None';
// }); this.chartWrapper.style.marginTop = '0px';
// this.chartWrapper.style.marginTop = '0px'; this.chartWrapper.style.paddingTop = '0px';
// this.chartWrapper.style.paddingTop = '0px';
} }
calc() { calc() {
let data_values = Object.keys(this.data).map(key => this.data[key]); let dataValues = Object.keys(this.data).map(key => this.data[key]);
this.distribution = calcDistribution(data_values, this.distribution_size); this.distribution = calcDistribution(dataValues, this.distribution_size);
this.month_names = ["January", "February", "March", "April", "May", "June", this.monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December" "July", "August", "September", "October", "November", "December"
]; ];
} }
@ -2425,118 +2443,118 @@ class Heatmap extends BaseChart {
this.domainLabelGroup.textContent = ''; this.domainLabelGroup.textContent = '';
this.dataGroups.textContent = ''; this.dataGroups.textContent = '';
let current_week_sunday = new Date(this.first_week_start); let currentWeekSunday = new Date(this.firstWeekStart);
this.week_col = 0; this.weekCol = 0;
this.current_month = current_week_sunday.getMonth(); this.currentMonth = currentWeekSunday.getMonth();
this.months = [this.current_month + '']; this.months = [this.currentMonth + ''];
this.month_weeks = {}, this.month_start_points = []; this.monthWeeks = {}, this.monthStartPoints = [];
this.month_weeks[this.current_month] = 0; this.monthWeeks[this.currentMonth] = 0;
this.month_start_points.push(13); this.monthStartPoints.push(13);
for(var i = 0; i < no_of_weeks; i++) { for(var i = 0; i < no_of_weeks; i++) {
let data_group, month_change = 0; let dataGroup, monthChange = 0;
let day = new Date(current_week_sunday); let day = new Date(currentWeekSunday);
[data_group, month_change] = this.get_week_squares_group(day, this.week_col); [dataGroup, monthChange] = this.get_week_squares_group(day, this.weekCol);
this.dataGroups.appendChild(data_group); this.dataGroups.appendChild(dataGroup);
this.week_col += 1 + parseInt(this.discrete_domains && month_change); this.weekCol += 1 + parseInt(this.discreteDomains && monthChange);
this.month_weeks[this.current_month]++; this.monthWeeks[this.currentMonth]++;
if(month_change) { if(monthChange) {
this.current_month = (this.current_month + 1) % 12; this.currentMonth = (this.currentMonth + 1) % 12;
this.months.push(this.current_month + ''); this.months.push(this.currentMonth + '');
this.month_weeks[this.current_month] = 1; this.monthWeeks[this.currentMonth] = 1;
} }
addDays(current_week_sunday, 7); addDays(currentWeekSunday, 7);
} }
this.render_month_labels(); this.render_month_labels();
} }
get_week_squares_group(current_date, index) { get_week_squares_group(currentDate, index) {
const no_of_weekdays = 7; const noOfWeekdays = 7;
const square_side = 10; const squareSide = 10;
const cell_padding = 2; const cellPadding = 2;
const step = 1; const step = 1;
const today_time = this.today.getTime(); const todayTime = this.today.getTime();
let month_change = 0; let monthChange = 0;
let week_col_change = 0; let weekColChange = 0;
let data_group = makeSVGGroup(this.dataGroups, 'data-group'); let dataGroup = makeSVGGroup(this.dataGroups, 'data-group');
for(var y = 0, i = 0; i < no_of_weekdays; i += step, y += (square_side + cell_padding)) { for(var y = 0, i = 0; i < noOfWeekdays; i += step, y += (squareSide + cellPadding)) {
let data_value = 0; let dataValue = 0;
let colorIndex = 0; let colorIndex = 0;
let current_timestamp = current_date.getTime()/1000; let currentTimestamp = currentDate.getTime()/1000;
let timestamp = Math.floor(current_timestamp - (current_timestamp % 86400)).toFixed(1); let timestamp = Math.floor(currentTimestamp - (currentTimestamp % 86400)).toFixed(1);
if(this.data[timestamp]) { if(this.data[timestamp]) {
data_value = this.data[timestamp]; dataValue = this.data[timestamp];
} }
if(this.data[Math.round(timestamp)]) { if(this.data[Math.round(timestamp)]) {
data_value = this.data[Math.round(timestamp)]; dataValue = this.data[Math.round(timestamp)];
} }
if(data_value) { if(dataValue) {
colorIndex = getMaxCheckpoint(data_value, this.distribution); colorIndex = getMaxCheckpoint(dataValue, this.distribution);
} }
let x = 13 + (index + week_col_change) * 12; let x = 13 + (index + weekColChange) * 12;
let dataAttr = { let dataAttr = {
'data-date': getDdMmYyyy(current_date), 'data-date': getDdMmYyyy(currentDate),
'data-value': data_value, 'data-value': dataValue,
'data-day': current_date.getDay() 'data-day': currentDate.getDay()
}; };
let heatSquare = makeHeatSquare('day', x, y, square_side, let heatSquare = makeHeatSquare('day', x, y, squareSide,
this.legend_colors[colorIndex], dataAttr); this.legendColors[colorIndex], dataAttr);
data_group.appendChild(heatSquare); dataGroup.appendChild(heatSquare);
let next_date = new Date(current_date); let nextDate = new Date(currentDate);
addDays(next_date, 1); addDays(nextDate, 1);
if(next_date.getTime() > today_time) break; if(nextDate.getTime() > todayTime) break;
if(next_date.getMonth() - current_date.getMonth()) { if(nextDate.getMonth() - currentDate.getMonth()) {
month_change = 1; monthChange = 1;
if(this.discrete_domains) { if(this.discreteDomains) {
week_col_change = 1; weekColChange = 1;
} }
this.month_start_points.push(13 + (index + week_col_change) * 12); this.monthStartPoints.push(13 + (index + weekColChange) * 12);
} }
current_date = next_date; currentDate = nextDate;
} }
return [data_group, month_change]; return [dataGroup, monthChange];
} }
render_month_labels() { render_month_labels() {
// this.first_month_label = 1; // this.first_month_label = 1;
// if (this.first_week_start.getDate() > 8) { // if (this.firstWeekStart.getDate() > 8) {
// this.first_month_label = 0; // this.first_month_label = 0;
// } // }
// this.last_month_label = 1; // this.last_month_label = 1;
// let first_month = this.months.shift(); // let first_month = this.months.shift();
// let first_month_start = this.month_start_points.shift(); // let first_month_start = this.monthStartPoints.shift();
// render first month if // render first month if
// let last_month = this.months.pop(); // let last_month = this.months.pop();
// let last_month_start = this.month_start_points.pop(); // let last_month_start = this.monthStartPoints.pop();
// render last month if // render last month if
this.months.shift(); this.months.shift();
this.month_start_points.shift(); this.monthStartPoints.shift();
this.months.pop(); this.months.pop();
this.month_start_points.pop(); this.monthStartPoints.pop();
this.month_start_points.map((start, i) => { this.monthStartPoints.map((start, i) => {
let month_name = this.month_names[this.months[i]].substring(0, 3); let month_name = this.monthNames[this.months[i]].substring(0, 3);
let text = makeText('y-value-text', start+12, 10, month_name); let text = makeText('y-value-text', start+12, 10, month_name);
this.domainLabelGroup.appendChild(text); this.domainLabelGroup.appendChild(text);
}); });
@ -2548,19 +2566,19 @@ class Heatmap extends BaseChart {
).map(el => { ).map(el => {
el.addEventListener('mouseenter', (e) => { el.addEventListener('mouseenter', (e) => {
let count = e.target.getAttribute('data-value'); let count = e.target.getAttribute('data-value');
let date_parts = e.target.getAttribute('data-date').split('-'); let dateParts = e.target.getAttribute('data-date').split('-');
let month = this.month_names[parseInt(date_parts[1])-1].substring(0, 3); let month = this.monthNames[parseInt(dateParts[1])-1].substring(0, 3);
let g_off = this.chartWrapper.getBoundingClientRect(), p_off = e.target.getBoundingClientRect(); let gOff = this.chartWrapper.getBoundingClientRect(), pOff = e.target.getBoundingClientRect();
let width = parseInt(e.target.getAttribute('width')); let width = parseInt(e.target.getAttribute('width'));
let x = p_off.left - g_off.left + (width+2)/2; let x = pOff.left - gOff.left + (width+2)/2;
let y = p_off.top - g_off.top - (width+2)/2; let y = pOff.top - gOff.top - (width+2)/2;
let value = count + ' ' + this.count_label; let value = count + ' ' + this.countLabel;
let name = ' on ' + month + ' ' + date_parts[0] + ', ' + date_parts[2]; let name = ' on ' + month + ' ' + dateParts[0] + ', ' + dateParts[2];
this.tip.setValues(x, y, name, value, [], 1); this.tip.setValues(x, y, {name: name, value: value, valueFirst: 1}, []);
this.tip.showTip(); this.tip.showTip();
}); });
}); });
@ -2714,7 +2732,7 @@ class AxisChart extends BaseChart {
this.config.xAxisMode = args.axisOptions.xAxisMode || 'span'; this.config.xAxisMode = args.axisOptions.xAxisMode || 'span';
this.config.yAxisMode = args.axisOptions.yAxisMode || 'span'; this.config.yAxisMode = args.axisOptions.yAxisMode || 'span';
this.config.xIsSeries = args.axisOptions.xIsSeries || 1; this.config.xIsSeries = args.axisOptions.xIsSeries || 0;
this.config.formatTooltipX = args.tooltipOptions.formatTooltipX; this.config.formatTooltipX = args.tooltipOptions.formatTooltipX;
this.config.formatTooltipY = args.tooltipOptions.formatTooltipY; this.config.formatTooltipY = args.tooltipOptions.formatTooltipY;
@ -2810,7 +2828,7 @@ class AxisChart extends BaseChart {
return; return;
} }
s.yExtremes = new Array(s.datasetLength).fill(9999); s.yExtremes = new Array(s.datasetLength).fill(9999);
s.datasets.map((d, i) => { s.datasets.map(d => {
d.yPositions.map((pos, j) => { d.yPositions.map((pos, j) => {
if(pos < s.yExtremes[j]) { if(pos < s.yExtremes[j]) {
s.yExtremes[j] = pos; s.yExtremes[j] = pos;
@ -2824,9 +2842,9 @@ class AxisChart extends BaseChart {
if(this.data.yMarkers) { if(this.data.yMarkers) {
this.state.yMarkers = this.data.yMarkers.map(d => { this.state.yMarkers = this.data.yMarkers.map(d => {
d.position = scale(d.value, s.yAxis); d.position = scale(d.value, s.yAxis);
if(!d.label.includes(':')) { // if(!d.label.includes(':')) {
d.label += ': ' + d.value; // d.label += ': ' + d.value;
} // }
return d; return d;
}); });
} }
@ -2928,7 +2946,7 @@ class AxisChart extends BaseChart {
} }
let labels = new Array(s.datasetLength).fill(''); let labels = new Array(s.datasetLength).fill('');
if(this.valuesOverPoints) { if(this.config.valuesOverPoints) {
if(stacked && d.index === s.datasets.length - 1) { if(stacked && d.index === s.datasets.length - 1) {
labels = d.cumulativeYs; labels = d.cumulativeYs;
} else { } else {
@ -3037,12 +3055,15 @@ class AxisChart extends BaseChart {
let s = this.state; let s = this.state;
if(!s.yExtremes) return; if(!s.yExtremes) return;
let formatY = this.config.formatTooltipY;
let formatX = this.config.formatTooltipX;
let titles = s.xAxis.labels; let titles = s.xAxis.labels;
if(this.formatTooltipX && this.formatTooltipX(titles[0])) { if(formatX && formatX(titles[0])) {
titles = titles.map(d=>this.formatTooltipX(d)); titles = titles.map(d=>formatX(d));
} }
let formatY = this.formatTooltipY && this.formatTooltipY(this.y[0].values[0]); formatY = formatY && formatY(s.yAxis.labels[0]) ? formatY : 0;
for(var i=s.datasetLength - 1; i >= 0 ; i--) { for(var i=s.datasetLength - 1; i >= 0 ; i--) {
let xVal = s.xAxis.positions[i]; let xVal = s.xAxis.positions[i];
@ -3053,19 +3074,37 @@ class AxisChart extends BaseChart {
let values = this.data.datasets.map((set, j) => { let values = this.data.datasets.map((set, j) => {
return { return {
title: set.title, title: set.name,
value: formatY ? this.formatTooltipY(set.values[i]) : set.values[i], value: formatY ? formatY(set.values[i]) : set.values[i],
color: this.colors[j], color: this.colors[j],
}; };
}); });
this.tip.setValues(x, y, titles[i], '', values); this.tip.setValues(x, y, {name: titles[i], value: ''}, values, i);
this.tip.showTip(); this.tip.showTip();
break; break;
} }
} }
} }
renderLegend() {
let s = this.data;
this.statsWrapper.textContent = '';
if(s.datasets.length > 1) {
s.datasets.map((d, i) => {
let stats = $.create('div', {
className: 'stats',
inside: this.statsWrapper
});
stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i>
${d.name}
</span>`;
});
}
}
makeOverlay() { makeOverlay() {
if(this.overlayGuides) { if(this.overlayGuides) {
this.overlayGuides.forEach(g => { this.overlayGuides.forEach(g => {
@ -3079,7 +3118,7 @@ class AxisChart extends BaseChart {
type: c.unitType, type: c.unitType,
overlay: undefined, overlay: undefined,
units: c.units, units: c.units,
} };
}); });
if(this.state.currentIndex === undefined) { if(this.state.currentIndex === undefined) {
@ -3105,19 +3144,26 @@ class AxisChart extends BaseChart {
} }
bindOverlay() { bindOverlay() {
// on event, update overlay this.parent.addEventListener('data-select', () => {
this.parent.addEventListener('data-select', (e) => {
this.updateOverlay(); this.updateOverlay();
}); });
} }
bindUnits(units_array) { bindUnits() {
// units_array.map(unit => { this.dataUnitComponents.map(c => {
// unit.addEventListener('click', () => { c.units.map(unit => {
// let index = unit.getAttribute('data-point-index'); unit.addEventListener('click', () => {
// this.setCurrentDataPoint(index); let index = unit.getAttribute('data-point-index');
// }); this.setCurrentDataPoint(index);
// }); });
});
});
// Note: Doesn't work as tooltip is absolutely positioned
this.tip.container.addEventListener('click', () => {
let index = this.tip.container.getAttribute('data-point-index');
this.setCurrentDataPoint(index);
});
} }
updateOverlay() { updateOverlay() {
@ -3136,16 +3182,12 @@ class AxisChart extends BaseChart {
} }
getDataPoint(index=this.state.currentIndex) { getDataPoint(index=this.state.currentIndex) {
// check for length let s = this.state;
let data_point = { let data_point = {
index: index index: index,
label: s.xAxis.labels[index],
values: s.datasets.map(d => d.values[index])
}; };
// let y = this.y[0];
// ['svg_units', 'yUnitPositions', 'values'].map(key => {
// let data_key = key.slice(0, key.length-1);
// data_point[data_key] = y[key][index];
// });
// data_point.label = this.xAxis.labels[index];
return data_point; return data_point;
} }
@ -3186,7 +3228,14 @@ class AxisChart extends BaseChart {
// addDataset(dataset, index) {} // addDataset(dataset, index) {}
// removeDataset(index = 0) {} // removeDataset(index = 0) {}
// updateDatasets(datasets) {} updateDatasets(datasets) {
this.data.datasets.map((d, i) => {
if(datasets[i]) {
d.values = datasets[i];
}
});
this.update(this.data);
}
// updateDataPoint(dataPoint, index = 0) {} // updateDataPoint(dataPoint, index = 0) {}
// addDataPoint(dataPoint, index = 0) {} // addDataPoint(dataPoint, index = 0) {}

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
.chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .graph-focus-margin{margin:0 5%}.chart-container>.title{margin-top:25px;margin-left:25px;text-align:left;font-weight:400;font-size:12px;color:#6c7680}.chart-container .graphics{margin-top:10px;padding-top:10px;padding-bottom:10px;position:relative}.chart-container .graph-stats-group{-ms-flex-pack:distribute;-webkit-box-flex:1;-ms-flex:1;flex:1}.chart-container .graph-stats-container,.chart-container .graph-stats-group{display:-webkit-box;display:-ms-flexbox;display:flex;justify-content:space-around}.chart-container .graph-stats-container{-ms-flex-pack:distribute;padding-top:10px}.chart-container .graph-stats-container .stats{padding-bottom:15px}.chart-container .graph-stats-container .stats-title{color:#8d99a6}.chart-container .graph-stats-container .stats-value{font-size:20px;font-weight:300}.chart-container .graph-stats-container .stats-description{font-size:12px;color:#8d99a6}.chart-container .graph-stats-container .graph-data .stats-value{color:#98d85b}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .percentage-graph .progress{margin-bottom:0}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path,.chart-container .multiaxis-chart .line-horizontal,.chart-container .multiaxis-chart .y-axis-guide{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.chart-container .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.chart-container .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#36414c;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.chart-container .graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.chart-container .graph-svg-tip ol,.chart-container .graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.chart-container .graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.chart-container .graph-svg-tip strong{color:#dfe2e5;font-weight:600}.chart-container .graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.chart-container .graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.chart-container .graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.chart-container .graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.chart-container .graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}.chart-container .indicator,.chart-container .indicator-right{background:none;font-size:12px;vertical-align:middle;font-weight:700;color:#6c7680}.chart-container .indicator i{content:"";display:inline-block;height:8px;width:8px;border-radius:8px}.chart-container .indicator:before,.chart-container .indicator i{margin:0 4px 0 0}.chart-container .indicator-right:after{margin:0 0 0 4px} .chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .graph-focus-margin{margin:0 5%}.chart-container>.title{margin-top:25px;margin-left:25px;text-align:left;font-weight:400;font-size:12px;color:#6c7680}.chart-container .graphics{margin-top:10px;padding-top:10px;padding-bottom:10px;position:relative}.chart-container .graph-stats-group{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-pack:distribute;justify-content:space-around;-webkit-box-flex:1;-ms-flex:1;flex:1}.chart-container .graph-stats-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:10px}.chart-container .graph-stats-container:after,.chart-container .graph-stats-container:before{content:"";display:block}.chart-container .graph-stats-container .stats{padding-bottom:15px}.chart-container .graph-stats-container .stats-title{color:#8d99a6}.chart-container .graph-stats-container .stats-value{font-size:20px;font-weight:300}.chart-container .graph-stats-container .stats-description{font-size:12px;color:#8d99a6}.chart-container .graph-stats-container .graph-data .stats-value{color:#98d85b}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .percentage-graph .progress{margin-bottom:0}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path,.chart-container .multiaxis-chart .line-horizontal,.chart-container .multiaxis-chart .y-axis-guide{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.chart-container .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.chart-container .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#36414c;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.chart-container .graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.chart-container .graph-svg-tip ol,.chart-container .graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.chart-container .graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.chart-container .graph-svg-tip strong{color:#dfe2e5;font-weight:600}.chart-container .graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.chart-container .graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.chart-container .graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.chart-container .graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.chart-container .graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}.chart-container .indicator,.chart-container .indicator-right{background:none;font-size:12px;vertical-align:middle;font-weight:700;color:#6c7680}.chart-container .indicator i{content:"";display:inline-block;height:8px;width:8px;border-radius:8px}.chart-container .indicator:before,.chart-container .indicator i{margin:0 4px 0 0}.chart-container .indicator-right:after{margin:0 0 0 4px}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,76 +1,100 @@
// Composite Chart // Composite Chart
// ================================================================================ // ================================================================================
let report_count_list = [17, 40, 33, 44, 126, 156, let reportCountList = [152, 222, 199, 287, 534, 709,
324, 333, 478, 495, 527]; 1179, 1256, 1632, 1856, 1850];
let bar_composite_data = { let lineCompositeData = {
labels: ["2007", "2008", "2009", "2010", "2011", "2012", labels: ["2007", "2008", "2009", "2010", "2011", "2012",
"2013", "2014", "2015", "2016", "2017"], "2013", "2014", "2015", "2016", "2017"],
yMarkers: [ yMarkers: [
{ {
label: "Marker 1", label: "Average 100 reports/month",
value: 420, value: 1200,
},
{
label: "Marker 2",
value: 250,
} }
], ],
yRegions: [
{
label: "Region Y 1",
start: 100,
end: 300
},
],
datasets: [{ datasets: [{
"name": "Events", "name": "Events",
"values": report_count_list, "values": reportCountList
// "formatted": report_count_list.map(d => d + " reports")
}] }]
}; };
let line_composite_data = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: [{
"values": [37, 36, 32, 33, 12, 34, 52, 45, 58, 57, 64, 35],
// "values": [36, 46, 45, 32, 27, 31, 30, 36, 39, 49, 40, 40],
// "values": [-36, -46, -45, -32, -27, -31, -30, -36, -39, -49, -40, -40],
}]
};
let more_line_data = [ let fireball_5_25 = [
[4, 0, 3, 1, 1, 2, 1, 2, 1, 0, 1, 1], [4, 0, 3, 1, 1, 2, 1, 1, 1, 0, 1, 1],
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 3, 3, 2, 1, 3, 0, 1, 2, 7, 10, 4],
[2, 3, 3, 2, 1, 4, 0, 1, 2, 7, 11, 4], [5, 6, 2, 4, 0, 1, 4, 3, 0, 2, 0, 1],
[7, 7, 2, 4, 0, 1, 5, 3, 1, 2, 0, 1], [0, 2, 6, 2, 1, 1, 2, 3, 6, 3, 7, 8],
[0, 2, 6, 2, 2, 1, 2, 3, 6, 3, 7, 10], [6, 8, 7, 7, 4, 5, 6, 5, 22, 12, 10, 11],
[9, 10, 8, 10, 6, 5, 8, 8, 24, 15, 10, 13], [7, 10, 11, 7, 3, 2, 7, 7, 11, 15, 22, 20],
[9, 13, 16, 9, 4, 5, 7, 10, 14, 22, 23, 24], [13, 16, 21, 18, 19, 17, 12, 17, 31, 28, 25, 29],
[20, 22, 28, 19, 28, 19, 14, 19, 51, 37, 29, 38], [24, 14, 21, 14, 11, 15, 19, 21, 41, 22, 32, 18],
[29, 20, 22, 16, 16, 19, 24, 26, 57, 31, 46, 27], [31, 20, 30, 22, 14, 17, 21, 35, 27, 50, 117, 24],
[36, 24, 38, 27, 15, 22, 24, 38, 32, 57, 139, 26], [32, 24, 21, 27, 11, 27, 43, 37, 44, 40, 48, 32],
[37, 36, 32, 33, 12, 34, 52, 45, 58, 57, 64, 35], [31, 38, 36, 26, 23, 23, 25, 29, 26, 47, 61, 50],
[36, 46, 45, 32, 27, 31, 30, 36, 39, 58, 82, 62],
// [36, 46, 45, 32, 27, 31, 30, 36, 39, 49, 40, 40]
// [-36, -46, -45, -32, -27, -31, -30, -36, -39, -49, -40, -40]
]; ];
let fireball_2_5 = [
[22, 6, 6, 9, 7, 8, 6, 14, 19, 10, 8, 20],
[11, 13, 12, 8, 9, 11, 9, 13, 10, 22, 40, 24],
[20, 13, 13, 19, 13, 10, 14, 13, 20, 18, 5, 9],
[7, 13, 16, 19, 12, 11, 21, 27, 27, 24, 33, 33],
[38, 25, 28, 22, 31, 21, 35, 42, 37, 32, 46, 53],
[50, 33, 36, 34, 35, 28, 27, 52, 58, 59, 75, 69],
[54, 67, 67, 45, 66, 51, 38, 64, 90, 113, 116, 87],
[84, 52, 56, 51, 55, 46, 50, 87, 114, 83, 152, 93],
[73, 58, 59, 63, 56, 51, 83, 140, 103, 115, 265, 89],
[106, 95, 94, 71, 77, 75, 99, 136, 129, 154, 168, 156],
[81, 102, 95, 72, 58, 91, 89, 122, 124, 135, 183, 171],
];
let fireballOver25 = [
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
[1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2],
[3, 2, 1, 3, 2, 0, 2, 2, 2, 3, 0, 1],
[2, 3, 5, 2, 1, 3, 0, 2, 3, 5, 1, 4],
[7, 4, 6, 1, 9, 2, 2, 2, 20, 9, 4, 9],
[5, 6, 1, 2, 5, 4, 5, 5, 16, 9, 14, 9],
[5, 4, 7, 5, 1, 5, 3, 3, 5, 7, 22, 2],
[5, 13, 11, 6, 1, 7, 9, 8, 14, 17, 16, 3],
[8, 9, 8, 6, 4, 8, 5, 6, 14, 11, 21, 12]
];
let monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
let barCompositeData = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: [
{
name: "Over 25 reports",
values: fireballOver25[9],
},
{
name: "5 to 25 reports",
values: fireball_5_25[9],
},
{
name: "2 to 5 reports",
values: fireball_2_5[9]
}
]
};
let c1 = document.querySelector("#chart-composite-1"); let c1 = document.querySelector("#chart-composite-1");
let c2 = document.querySelector("#chart-composite-2"); let c2 = document.querySelector("#chart-composite-2");
let bar_composite_chart = new Chart (c1, { let lineCompositeChart = new Chart (c1, {
title: "Fireball/Bolide Events - Yearly (reported)", title: "Fireball/Bolide Events - Yearly (reported)",
data: bar_composite_data, data: lineCompositeData,
type: 'line', type: 'line',
height: 180, height: 190,
colors: ['green'], colors: ['green'],
isNavigable: 1, isNavigable: 1,
isSeries: 1, isSeries: 1,
// valuesOverPoints: 1, valuesOverPoints: 1,
lineOptions: { lineOptions: {
dotSize: 8 dotSize: 8
@ -79,25 +103,33 @@ let bar_composite_chart = new Chart (c1, {
// regionFill: 1 // regionFill: 1
}); });
let line_composite_chart = new Chart (c2, { let barCompositeChart = new Chart (c2, {
data: line_composite_data, data: barCompositeData,
type: 'bar', type: 'bar',
height: 180, height: 190,
colors: ['#46a9f9'], colors: ['violet', 'light-blue', '#46a9f9'],
isSeries: 1, isSeries: 1,
valuesOverPoints: 1, valuesOverPoints: 1,
xAxisMode: 'tick' axisOptions: {
xAxisMode: 'tick'
},
barOptions: {
stacked: 1
},
}); });
bar_composite_chart.parent.addEventListener('data-select', (e) => { lineCompositeChart.parent.addEventListener('data-select', (e) => {
line_composite_chart.updateDataset(more_line_data[e.index]); let i = e.index;
barCompositeChart.updateDatasets([
fireballOver25[i], fireball_5_25[i], fireball_2_5[i]
]);
}); });
// Demo Chart (bar, linepts, scatter(blobs), percentage) // Demo Chart (bar, linepts, scatter(blobs), percentage)
// ================================================================================ // ================================================================================
let type_data = { let typeData = {
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm", labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm",
"12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"], "12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"],
@ -166,15 +198,13 @@ let type_data = {
] ]
}; };
let type_chart = new Chart("#chart-types", { let typeChart = new Chart("#chart-types", {
// title: "My Awesome Chart", title: "My Awesome Chart",
data: type_data, data: typeData,
type: 'bar', type: 'bar',
height: 250, height: 250,
colors: ['purple', 'magenta', 'light-blue'], colors: ['purple', 'magenta', 'light-blue'],
isSeries: 1, isSeries: 1,
xAxisMode: 'tick',
yAxisMode: 'span',
valuesOverPoints: 1, valuesOverPoints: 1,
// maxLegendPoints: 6, // maxLegendPoints: 6,
// maxSlices: 3, // maxSlices: 3,
@ -184,86 +214,45 @@ let type_chart = new Chart("#chart-types", {
}, },
tooltipOptions: { tooltipOptions: {
formatTooltipX: d => (d + '').toUpperCase(), formatTooltipX: d => (d + '').toUpperCase(),
formatTooltipY: d => d + ' pts' formatTooltipY: d => d + ' pts',
} }
}); });
Array.prototype.slice.call(
document.querySelectorAll('.chart-type-buttons button')
).map(el => {
el.addEventListener('click', (e) => {
let btn = e.target;
let type = btn.getAttribute('data-type');
let newChart = type_chart.getDifferentChart(type);
if(newChart){
type_chart = newChart;
}
Array.prototype.slice.call(
btn.parentNode.querySelectorAll('button')).map(el => {
el.classList.remove('active');
});
btn.classList.add('active');
});
});
// Trends Chart
// Aggregation chart
// ================================================================================ // ================================================================================
let trends_data = { let aggrChart = new Chart("#chart-aggr", {
labels: [1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, data: typeData,
1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, type: 'pie',
1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016] ,
datasets: [
{
"values": [132.9, 150.0, 149.4, 148.0, 94.4, 97.6, 54.1, 49.2, 22.5, 18.4,
39.3, 131.0, 220.1, 218.9, 198.9, 162.4, 91.0, 60.5, 20.6, 14.8,
33.9, 123.0, 211.1, 191.8, 203.3, 133.0, 76.1, 44.9, 25.1, 11.6,
28.9, 88.3, 136.3, 173.9, 170.4, 163.6, 99.3, 65.3, 45.8, 24.7,
12.6, 4.2, 4.8, 24.9, 80.8, 84.5, 94.0, 113.3, 69.8, 39.8]
}
]
};
let plotChartArgs = {
title: "Mean Total Sunspot Count - Yearly",
data: trends_data,
type: 'line',
height: 250, height: 250,
colors: ['blue'], colors: ['purple', 'magenta', 'light-blue'],
isSeries: 1, isSeries: 1,
lineOptions: {
hideDots: 1,
heatline: 1,
},
axisOptions: {
xAxisMode: 'tick',
yAxisMode: 'span',
xIsSeries: 1
}
};
new Chart("#chart-trends", plotChartArgs); maxLegendPoints: 6,
maxSlices: 10,
barOptions: {
stacked: 1
},
tooltipOptions: {
formatTooltipX: d => (d + '').toUpperCase(),
formatTooltipY: d => d + ' pts',
}
});
Array.prototype.slice.call( Array.prototype.slice.call(
document.querySelectorAll('.chart-plot-buttons button') document.querySelectorAll('.aggr-type-buttons button')
).map(el => { ).map(el => {
el.addEventListener('click', (e) => { el.addEventListener('click', (e) => {
let btn = e.target; let btn = e.target;
let type = btn.getAttribute('data-type'); let type = btn.getAttribute('data-type');
let config = {};
config[type] = 1;
if(['regionFill', 'heatline'].includes(type)) { let newChart = aggrChart.getDifferentChart(type);
config.hideDots = 1; if(newChart){
aggrChart = newChart;
} }
// plotChartArgs.init = false;
plotChartArgs.lineOptions = config;
new Chart("#chart-trends", plotChartArgs);
Array.prototype.slice.call( Array.prototype.slice.call(
btn.parentNode.querySelectorAll('button')).map(el => { btn.parentNode.querySelectorAll('button')).map(el => {
el.classList.remove('active'); el.classList.remove('active');
@ -337,6 +326,71 @@ chart_update_buttons.querySelector('[data-update="remove"]').addEventListener("c
update_chart.removeDataPoint(); update_chart.removeDataPoint();
}); });
// Trends Chart
// ================================================================================
let trends_data = {
labels: [1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976,
1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986,
1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016] ,
datasets: [
{
values: [132.9, 150.0, 149.4, 148.0, 94.4, 97.6, 54.1, 49.2, 22.5, 18.4,
39.3, 131.0, 220.1, 218.9, 198.9, 162.4, 91.0, 60.5, 20.6, 14.8,
33.9, 123.0, 211.1, 191.8, 203.3, 133.0, 76.1, 44.9, 25.1, 11.6,
28.9, 88.3, 136.3, 173.9, 170.4, 163.6, 99.3, 65.3, 45.8, 24.7,
12.6, 4.2, 4.8, 24.9, 80.8, 84.5, 94.0, 113.3, 69.8, 39.8]
}
]
};
let plotChartArgs = {
title: "Mean Total Sunspot Count - Yearly",
data: trends_data,
type: 'line',
height: 250,
colors: ['blue'],
isSeries: 1,
lineOptions: {
hideDots: 1,
heatline: 1,
},
axisOptions: {
xAxisMode: 'tick',
yAxisMode: 'span',
xIsSeries: 1
}
};
new Chart("#chart-trends", plotChartArgs);
Array.prototype.slice.call(
document.querySelectorAll('.chart-plot-buttons button')
).map(el => {
el.addEventListener('click', (e) => {
let btn = e.target;
let type = btn.getAttribute('data-type');
let config = {};
config[type] = 1;
if(['regionFill', 'heatline'].includes(type)) {
config.hideDots = 1;
}
// plotChartArgs.init = false;
plotChartArgs.lineOptions = config;
new Chart("#chart-trends", plotChartArgs);
Array.prototype.slice.call(
btn.parentNode.querySelectorAll('button')).map(el => {
el.classList.remove('active');
});
btn.classList.add('active');
});
});
// Event chart // Event chart
// ================================================================================ // ================================================================================
@ -398,28 +452,24 @@ events_chart.parent.addEventListener('data-select', (e) => {
data_div.querySelector('img').src = "./assets/img/" + name.toLowerCase() + ".jpg"; data_div.querySelector('img').src = "./assets/img/" + name.toLowerCase() + ".jpg";
}); });
// Aggregation chart
// ================================================================================
// Heatmap // Heatmap
// ================================================================================ // ================================================================================
let heatmap_data = {}; let heatmapData = {};
let current_date = new Date(); let current_date = new Date();
let timestamp = current_date.getTime()/1000; let timestamp = current_date.getTime()/1000;
timestamp = Math.floor(timestamp - (timestamp % 86400)).toFixed(1); // convert to midnight timestamp = Math.floor(timestamp - (timestamp % 86400)).toFixed(1); // convert to midnight
for (var i = 0; i< 375; i++) { for (var i = 0; i< 375; i++) {
heatmap_data[parseInt(timestamp)] = Math.floor(Math.random() * 5); heatmapData[parseInt(timestamp)] = Math.floor(Math.random() * 5);
timestamp = Math.floor(timestamp - 86400).toFixed(1); timestamp = Math.floor(timestamp - 86400).toFixed(1);
} }
new Chart("#chart-heatmap", { new Chart("#chart-heatmap", {
data: heatmap_data, data: heatmapData,
type: 'heatmap', type: 'heatmap',
legend_scale: [0, 1, 2, 4, 5], legendScale: [0, 1, 2, 4, 5],
height: 115, height: 115,
discrete_domains: 1 discreteDomains: 1
}); });
Array.prototype.slice.call( Array.prototype.slice.call(
@ -428,10 +478,10 @@ Array.prototype.slice.call(
el.addEventListener('click', (e) => { el.addEventListener('click', (e) => {
let btn = e.target; let btn = e.target;
let mode = btn.getAttribute('data-mode'); let mode = btn.getAttribute('data-mode');
let discrete_domains = 0; let discreteDomains = 0;
if(mode === 'discrete') { if(mode === 'discrete') {
discrete_domains = 1; discreteDomains = 1;
} }
let colors = []; let colors = [];
@ -443,12 +493,12 @@ Array.prototype.slice.call(
} }
new Chart("#chart-heatmap", { new Chart("#chart-heatmap", {
data: heatmap_data, data: heatmapData,
type: 'heatmap', type: 'heatmap',
legend_scale: [0, 1, 2, 4, 5], legendScale: [0, 1, 2, 4, 5],
height: 115, height: 115,
discrete_domains: discrete_domains, discreteDomains: discreteDomains,
legend_colors: colors legendColors: colors
}); });
Array.prototype.slice.call( Array.prototype.slice.call(
@ -471,22 +521,22 @@ Array.prototype.slice.call(
colors = ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c']; colors = ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c'];
} }
let discrete_domains = 1; let discreteDomains = 1;
let view_mode = document let view_mode = document
.querySelector('.heatmap-mode-buttons .active') .querySelector('.heatmap-mode-buttons .active')
.getAttribute('data-mode'); .getAttribute('data-mode');
if(view_mode === 'continuous') { if(view_mode === 'continuous') {
discrete_domains = 0; discreteDomains = 0;
} }
new Chart("#chart-heatmap", { new Chart("#chart-heatmap", {
data: heatmap_data, data: heatmapData,
type: 'heatmap', type: 'heatmap',
legend_scale: [0, 1, 2, 4, 5], legendScale: [0, 1, 2, 4, 5],
height: 115, height: 115,
discrete_domains: discrete_domains, discreteDomains: discreteDomains,
legend_colors: colors legendColors: colors
}); });
Array.prototype.slice.call( Array.prototype.slice.call(

View File

@ -44,67 +44,51 @@
<div class="col-sm-10 push-sm-1"> <div class="col-sm-10 push-sm-1">
<div class="dashboard-section"> <div class="dashboard-section">
<h6 class="margin-vertical-rem"> <h6 class="margin-vertical-rem">Create a chart</h6>
<!--Bars, Lines or <a href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts" target="_blank">Percentages</a>-->
Create a chart
</h6>
<p class="step-explain">Install</p>
<pre><code class="hljs console"> npm install frappe-charts</code></pre>
<p class="step-explain">And include it in your project</p>
<pre><code class="hljs javascript"> import Chart from "frappe-charts/dist/frappe-charts.min.esm"</code></pre>
<p class="step-explain">... or include it directly in your HTML</p>
<pre><code class="hljs html"> &lt;script src="https://unpkg.com/frappe-charts@0.0.8/dist/frappe-charts.min.iife.js"&gt;&lt;/script&gt;</code></pre>
<p class="step-explain">Make a new Chart</p>
<pre><code class="hljs html"> &lt!--HTML--&gt; <pre><code class="hljs html"> &lt!--HTML--&gt;
&lt;div id="chart"&gt;&lt;/div&gt;</code></pre> &lt;div id="chart"&gt;&lt;/div&gt;</code></pre>
<pre><code class="hljs javascript"> // Javascript <pre><code class="hljs javascript"> // Javascript
let data = { let chart = new Chart( "#chart", { // or DOM element
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm", data: {
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm",
"12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"], "12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"],
datasets: [ datasets: [
{ {
label: "Some Data", label: "Some Data", type: 'bar',
values: [25, 40, 30, 35, 8, 52, 17, -4] values: [25, 40, 30, 35, 8, 52, 17, -4]
}, },
{ {
label: "Another Set", label: "Another Set", type: 'bar',
values: [25, 50, -10, 15, 18, 32, 27, 14] values: [25, 50, -10, 15, 18, 32, 27, 14]
}, },
{ {
label: "Yet Another", label: "Yet Another", type: 'line',
values: [15, 20, -3, -15, 58, 12, -17, 37] values: [15, 20, -3, -15, 58, 12, -17, 37]
} }
] ]
}; },
let chart = new Chart({
parent: "#chart", // or a DOM element
title: "My Awesome Chart", title: "My Awesome Chart",
data: data, type: 'axis-mixed', // or 'bar', 'line', 'pie', 'percentage'
type: 'bar', // or 'line', 'scatter', 'pie', 'percentage'
height: 250, height: 250,
colors: ['#7cd6fd', 'violet', 'blue']
colors: ['#7cd6fd', 'violet', 'blue'],
// hex-codes or these preset colors;
// defaults (in order):
// ['light-blue', 'blue', 'violet', 'red',
// 'orange', 'yellow', 'green', 'light-green',
// 'purple', 'magenta', 'grey', 'dark-grey']
format_tooltip_x: d => (d + '').toUpperCase(),
format_tooltip_y: d => d + ' pts'
});</code></pre> });</code></pre>
<div id="chart-types" class="border"></div> <div id="chart-types" class="border"></div>
<div class="btn-group chart-type-buttons margin-vertical-px mx-auto" role="group"> <!-- <div class="btn-group chart-type-buttons margin-vertical-px mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary active" data-type='bar'>Bar Chart</button> <button type="button" class="btn btn-sm btn-secondary active" data-type='bar'>Bar Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='line'>Line Chart</button> <button type="button" class="btn btn-sm btn-secondary" data-type='line'>Line Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='pie'>Pie Chart</button> <button type="button" class="btn btn-sm btn-secondary" data-type='pie'>Pie Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button> <button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button>
</div> -->
<div id="chart-aggr" class="border"></div>
<div class="btn-group aggr-type-buttons margin-vertical-px mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary active" data-type='pie'>Pie Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button>
</div> </div>
<p class="text-muted"> <!-- <p class="text-muted">
<a target="_blank" href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts">Why Percentage?</a> <a target="_blank" href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts">Why Percentage?</a>
</p> </p> -->
</div> </div>
</div> </div>
@ -113,42 +97,12 @@
<h6 class="margin-vertical-rem"> <h6 class="margin-vertical-rem">
Update Values Update Values
</h6> </h6>
<pre><code class="hljs javascript"> // Update entire datasets
chart.updateData(
[
{values: new_dataset_1_values},
{values: new_dataset_2_values}
],
new_labels
);
// Add a new data point
chart.add_data_point(
[new_value_1, new_value_2],
new_label,
index // defaults to last index
);
// Remove a data point
chart.remove_data_point(index);</code></pre>
<div id="chart-update" class="border"></div> <div id="chart-update" class="border"></div>
<div class="chart-update-buttons mt-1 mx-auto" role="group"> <div class="chart-update-buttons mt-1 mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary" data-update="random">Random Data</button> <button type="button" class="btn btn-sm btn-secondary" data-update="random">Random Data</button>
<button type="button" class="btn btn-sm btn-secondary" data-update="add">Add Value</button> <button type="button" class="btn btn-sm btn-secondary" data-update="add">Add Value</button>
<button type="button" class="btn btn-sm btn-secondary" data-update="remove">Remove Value</button> <button type="button" class="btn btn-sm btn-secondary" data-update="remove">Remove Value</button>
</div> </div>
<pre><code class="hljs javascript margin-vertical-px"> ...
// Include specific Y values in input data to be displayed as lines
// (before passing data to a new chart):
data.specific_values = [
{
label: "Altitude",
line_type: "dashed", // or "solid"
value: 38
}
]
...</code></pre>
</div> </div>
</div> </div>
@ -157,12 +111,6 @@
<h6 class="margin-vertical-rem"> <h6 class="margin-vertical-rem">
Plot Trends Plot Trends
</h6> </h6>
<pre><code class="hljs javascript"> ...
xAxisMode: 'tick', // for short label ticks
// or 'span' for long spanning vertical axis lines
yAxisMode: 'span', // for long horizontal lines, or 'tick'
isSeries: 1, // to allow for skipping of X values
...</code></pre>
<div id="chart-trends" class="border"></div> <div id="chart-trends" class="border"></div>
<div class="btn-group chart-plot-buttons mt-1 mx-auto" role="group"> <div class="btn-group chart-plot-buttons mt-1 mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary" data-type="hideDots">Line</button> <button type="button" class="btn btn-sm btn-secondary" data-type="hideDots">Line</button>
@ -170,13 +118,13 @@
<button type="button" class="btn btn-sm btn-secondary active" data-type="heatline">HeatLine</button> <button type="button" class="btn btn-sm btn-secondary active" data-type="heatline">HeatLine</button>
<button type="button" class="btn btn-sm btn-secondary" data-type="regionFill">Region</button> <button type="button" class="btn btn-sm btn-secondary" data-type="regionFill">Region</button>
</div> </div>
<pre><code class="hljs javascript margin-vertical-px"> ... <!-- <pre><code class="hljs javascript margin-vertical-px"> ...
type: 'line', // Line Chart specific properties: lineOptions: 'line', // Line Chart specific properties:
hideDots: 1, // Hide data points on the line; default 0 hideDots: 1, // Hide data points on the line; default 0
heatline: 1, // Show a value-wise line gradient; default 0 heatline: 1, // Show a value-wise line gradient; default 0
regionFill: 1, // Fill the area under the graph; default 0 regionFill: 1, // Fill the area under the graph; default 0
...</code></pre> ...</code></pre> -->
</div> </div>
</div> </div>
@ -204,8 +152,7 @@
</div> </div>
</div> </div>
<pre><code class="hljs javascript margin-vertical-px"> ... <pre><code class="hljs javascript margin-vertical-px"> ...
type: 'bar', // Bar Chart specific properties: isNavigable: 1, // Navigate across data points; default 0
isNavigable: 1, // Navigate across bars; default 0
... ...
chart.parent.addEventListener('data-select', (e) => { chart.parent.addEventListener('data-select', (e) => {
@ -214,22 +161,6 @@
</div> </div>
</div> </div>
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<h6 class="margin-vertical-rem">
Simple Aggregations
</h6>
<div id="chart-aggr" class="border"></div>
<div class="chart-aggr-buttons mt-1 mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary" data-aggregation="sums">Show Sums</button>
<button type="button" class="btn btn-sm btn-secondary" data-aggregation="average">Show Averages</button>
</div>
<pre><code class="hljs javascript margin-vertical-px"> chart.show_sums(); // and `hide_sums()`
chart.show_averages(); // and `hide_averages()`</code></pre>
</div>
</div>
<div class="col-sm-10 push-sm-1"> <div class="col-sm-10 push-sm-1">
<div class="dashboard-section"> <div class="dashboard-section">
<h6 class="margin-vertical-rem"> <h6 class="margin-vertical-rem">
@ -249,16 +180,16 @@
parent: "#heatmap", parent: "#heatmap",
type: 'heatmap', type: 'heatmap',
height: 115, height: 115,
data: heatmap_data, // object with date/timestamp-value pairs data: heatmapData, // object with date/timestamp-value pairs
discrete_domains: 1 // default: 0 discreteDomains: 1 // default: 0
start: start_date, start: startDate,
// A Date object; // A Date object;
// default: today's date in past year // default: today's date in past year
// for an annual heatmap // for an annual heatmap
legend_colors: ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c'], legendColors: ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c'],
// Set of five incremental colors, // Set of five incremental colors,
// beginning with a low-saturation color for zero data; // beginning with a low-saturation color for zero data;
// default: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'] // default: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127']
@ -267,6 +198,54 @@
</div> </div>
</div> </div>
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<h6 class="margin-vertical-rem">All available options:</h6>
<pre><code class="hljs javascript"> // Javascript
let data = {
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm",
"12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"],
datasets: [
{
label: "Some Data", type: 'bar',
values: [25, 40, 30, 35, 8, 52, 17, -4]
},
{
label: "Another Set", type: 'bar',
values: [25, 50, -10, 15, 18, 32, 27, 14]
},
{
label: "Yet Another", type: 'line',
values: [15, 20, -3, -15, 58, 12, -17, 37]
}
]
};
let chart = new Chart( "#chart", { // or DOM element
title: "My Awesome Chart",
data: data,
type: 'axis-mixed', // or 'bar', 'line', 'pie', 'percentage'
height: 250,
colors: ['#7cd6fd', 'violet', 'blue']
});</code></pre>
</div>
</div>
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<h6 class="margin-vertical-rem">Install</h6>
<p class="step-explain">Install via npm</p>
<pre><code class="hljs console"> npm install frappe-charts</code></pre>
<p class="step-explain">And include it in your project</p>
<pre><code class="hljs javascript"> import Chart from "frappe-charts/dist/frappe-charts.min.esm"</code></pre>
<p class="step-explain">... or include it directly in your HTML</p>
<pre><code class="hljs html"> &lt;script src="https://unpkg.com/frappe-charts@0.0.8/dist/frappe-charts.min.iife.js"&gt;&lt;/script&gt;</code></pre>
</div>
</div>
<div class="col-sm-10 push-sm-1"> <div class="col-sm-10 push-sm-1">
<div class="dashboard-section"> <div class="dashboard-section">
<!-- Closing --> <!-- Closing -->

View File

@ -50,10 +50,11 @@ export default class AggregationChart extends BaseChart {
renderLegend() { renderLegend() {
let s = this.state; let s = this.state;
this.statsWrapper.textContent = '';
this.legendTotals = s.sliceTotals.slice(0, this.config.maxLegendPoints); this.legendTotals = s.sliceTotals.slice(0, this.config.maxLegendPoints);
let x_values = this.formatted_labels && this.formatted_labels.length > 0 let xValues = s.labels;
? this.formatted_labels : s.labels;
this.legendTotals.map((d, i) => { this.legendTotals.map((d, i) => {
if(d) { if(d) {
let stats = $.create('div', { let stats = $.create('div', {
@ -62,7 +63,7 @@ export default class AggregationChart extends BaseChart {
}); });
stats.innerHTML = `<span class="indicator"> stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i> <i style="background: ${this.colors[i]}"></i>
<span class="text-muted">${x_values[i]}:</span> <span class="text-muted">${xValues[i]}:</span>
${d} ${d}
</span>`; </span>`;
} }

View File

@ -2,11 +2,11 @@ import BaseChart from './BaseChart';
import { dataPrep, zeroDataPrep, getShortenedLabels } from '../utils/axis-chart-utils'; import { dataPrep, zeroDataPrep, getShortenedLabels } from '../utils/axis-chart-utils';
import { Y_AXIS_MARGIN } from '../utils/constants'; import { Y_AXIS_MARGIN } from '../utils/constants';
import { getComponent } from '../objects/ChartComponents'; import { getComponent } from '../objects/ChartComponents';
import { getOffset, fire } from '../utils/dom'; import { $, getOffset, fire } from '../utils/dom';
import { calcChartIntervals, getIntervalSize, getValueRange, getZeroIndex, scale } from '../utils/intervals'; import { calcChartIntervals, getIntervalSize, getValueRange, getZeroIndex, scale } from '../utils/intervals';
import { floatTwo } from '../utils/helpers'; import { floatTwo } from '../utils/helpers';
import { makeOverlay, updateOverlay } from '../utils/draw'; import { makeOverlay, updateOverlay } from '../utils/draw';
import { MIN_BAR_PERCENT_HEIGHT, DEFAULT_AXIS_CHART_TYPE, BAR_CHART_SPACE_RATIO, LINE_CHART_DOT_SIZE } from '../utils/constants'; import { MIN_BAR_PERCENT_HEIGHT, BAR_CHART_SPACE_RATIO, LINE_CHART_DOT_SIZE } from '../utils/constants';
export default class AxisChart extends BaseChart { export default class AxisChart extends BaseChart {
constructor(parent, args) { constructor(parent, args) {
@ -28,7 +28,7 @@ export default class AxisChart extends BaseChart {
this.config.xAxisMode = args.axisOptions.xAxisMode || 'span'; this.config.xAxisMode = args.axisOptions.xAxisMode || 'span';
this.config.yAxisMode = args.axisOptions.yAxisMode || 'span'; this.config.yAxisMode = args.axisOptions.yAxisMode || 'span';
this.config.xIsSeries = args.axisOptions.xIsSeries || 1; this.config.xIsSeries = args.axisOptions.xIsSeries || 0;
this.config.formatTooltipX = args.tooltipOptions.formatTooltipX; this.config.formatTooltipX = args.tooltipOptions.formatTooltipX;
this.config.formatTooltipY = args.tooltipOptions.formatTooltipY; this.config.formatTooltipY = args.tooltipOptions.formatTooltipY;
@ -88,7 +88,7 @@ export default class AxisChart extends BaseChart {
positions: yPts.map(d => zeroLine - d * scaleMultiplier), positions: yPts.map(d => zeroLine - d * scaleMultiplier),
scaleMultiplier: scaleMultiplier, scaleMultiplier: scaleMultiplier,
zeroLine: zeroLine, zeroLine: zeroLine,
} };
// Dependent if above changes // Dependent if above changes
this.calcDatasetPoints(); this.calcDatasetPoints();
@ -124,7 +124,7 @@ export default class AxisChart extends BaseChart {
return; return;
} }
s.yExtremes = new Array(s.datasetLength).fill(9999); s.yExtremes = new Array(s.datasetLength).fill(9999);
s.datasets.map((d, i) => { s.datasets.map(d => {
d.yPositions.map((pos, j) => { d.yPositions.map((pos, j) => {
if(pos < s.yExtremes[j]) { if(pos < s.yExtremes[j]) {
s.yExtremes[j] = pos; s.yExtremes[j] = pos;
@ -138,9 +138,9 @@ export default class AxisChart extends BaseChart {
if(this.data.yMarkers) { if(this.data.yMarkers) {
this.state.yMarkers = this.data.yMarkers.map(d => { this.state.yMarkers = this.data.yMarkers.map(d => {
d.position = scale(d.value, s.yAxis); d.position = scale(d.value, s.yAxis);
if(!d.label.includes(':')) { // if(!d.label.includes(':')) {
d.label += ': ' + d.value; // d.label += ': ' + d.value;
} // }
return d; return d;
}); });
} }
@ -170,7 +170,6 @@ export default class AxisChart extends BaseChart {
} }
setupComponents() { setupComponents() {
let s = this.state;
let componentConfigs = [ let componentConfigs = [
[ [
'yAxis', 'yAxis',
@ -243,7 +242,7 @@ export default class AxisChart extends BaseChart {
} }
let labels = new Array(s.datasetLength).fill(''); let labels = new Array(s.datasetLength).fill('');
if(this.valuesOverPoints) { if(this.config.valuesOverPoints) {
if(stacked && d.index === s.datasets.length - 1) { if(stacked && d.index === s.datasets.length - 1) {
labels = d.cumulativeYs; labels = d.cumulativeYs;
} else { } else {
@ -352,12 +351,15 @@ export default class AxisChart extends BaseChart {
let s = this.state; let s = this.state;
if(!s.yExtremes) return; if(!s.yExtremes) return;
let formatY = this.config.formatTooltipY;
let formatX = this.config.formatTooltipX;
let titles = s.xAxis.labels; let titles = s.xAxis.labels;
if(this.formatTooltipX && this.formatTooltipX(titles[0])) { if(formatX && formatX(titles[0])) {
titles = titles.map(d=>this.formatTooltipX(d)); titles = titles.map(d=>formatX(d));
} }
let formatY = this.formatTooltipY && this.formatTooltipY(this.y[0].values[0]); formatY = formatY && formatY(s.yAxis.labels[0]) ? formatY : 0;
for(var i=s.datasetLength - 1; i >= 0 ; i--) { for(var i=s.datasetLength - 1; i >= 0 ; i--) {
let xVal = s.xAxis.positions[i]; let xVal = s.xAxis.positions[i];
@ -368,19 +370,37 @@ export default class AxisChart extends BaseChart {
let values = this.data.datasets.map((set, j) => { let values = this.data.datasets.map((set, j) => {
return { return {
title: set.title, title: set.name,
value: formatY ? this.formatTooltipY(set.values[i]) : set.values[i], value: formatY ? formatY(set.values[i]) : set.values[i],
color: this.colors[j], color: this.colors[j],
}; };
}); });
this.tip.setValues(x, y, titles[i], '', values); this.tip.setValues(x, y, {name: titles[i], value: ''}, values, i);
this.tip.showTip(); this.tip.showTip();
break; break;
} }
} }
} }
renderLegend() {
let s = this.data;
this.statsWrapper.textContent = '';
if(s.datasets.length > 1) {
s.datasets.map((d, i) => {
let stats = $.create('div', {
className: 'stats',
inside: this.statsWrapper
});
stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i>
${d.name}
</span>`;
});
}
}
makeOverlay() { makeOverlay() {
if(this.overlayGuides) { if(this.overlayGuides) {
this.overlayGuides.forEach(g => { this.overlayGuides.forEach(g => {
@ -394,7 +414,7 @@ export default class AxisChart extends BaseChart {
type: c.unitType, type: c.unitType,
overlay: undefined, overlay: undefined,
units: c.units, units: c.units,
} };
}); });
if(this.state.currentIndex === undefined) { if(this.state.currentIndex === undefined) {
@ -406,7 +426,7 @@ export default class AxisChart extends BaseChart {
let currentUnit = d.units[this.state.currentIndex]; let currentUnit = d.units[this.state.currentIndex];
d.overlay = makeOverlay[d.type](currentUnit); d.overlay = makeOverlay[d.type](currentUnit);
this.drawArea.appendChild(d.overlay); this.drawArea.appendChild(d.overlay);
}) });
} }
@ -420,26 +440,33 @@ export default class AxisChart extends BaseChart {
} }
bindOverlay() { bindOverlay() {
// on event, update overlay this.parent.addEventListener('data-select', () => {
this.parent.addEventListener('data-select', (e) => {
this.updateOverlay(); this.updateOverlay();
}); });
} }
bindUnits(units_array) { bindUnits() {
// units_array.map(unit => { this.dataUnitComponents.map(c => {
// unit.addEventListener('click', () => { c.units.map(unit => {
// let index = unit.getAttribute('data-point-index'); unit.addEventListener('click', () => {
// this.setCurrentDataPoint(index); let index = unit.getAttribute('data-point-index');
// }); this.setCurrentDataPoint(index);
// }); });
});
});
// Note: Doesn't work as tooltip is absolutely positioned
this.tip.container.addEventListener('click', () => {
let index = this.tip.container.getAttribute('data-point-index');
this.setCurrentDataPoint(index);
});
} }
updateOverlay() { updateOverlay() {
this.overlayGuides.map(d => { this.overlayGuides.map(d => {
let currentUnit = d.units[this.state.currentIndex]; let currentUnit = d.units[this.state.currentIndex];
updateOverlay[d.type](currentUnit, d.overlay); updateOverlay[d.type](currentUnit, d.overlay);
}) });
} }
onLeftArrow() { onLeftArrow() {
@ -451,16 +478,12 @@ export default class AxisChart extends BaseChart {
} }
getDataPoint(index=this.state.currentIndex) { getDataPoint(index=this.state.currentIndex) {
// check for length let s = this.state;
let data_point = { let data_point = {
index: index index: index,
label: s.xAxis.labels[index],
values: s.datasets.map(d => d.values[index])
}; };
// let y = this.y[0];
// ['svg_units', 'yUnitPositions', 'values'].map(key => {
// let data_key = key.slice(0, key.length-1);
// data_point[data_key] = y[key][index];
// });
// data_point.label = this.xAxis.labels[index];
return data_point; return data_point;
} }
@ -501,7 +524,14 @@ export default class AxisChart extends BaseChart {
// addDataset(dataset, index) {} // addDataset(dataset, index) {}
// removeDataset(index = 0) {} // removeDataset(index = 0) {}
// updateDatasets(datasets) {} updateDatasets(datasets) {
this.data.datasets.map((d, i) => {
if(datasets[i]) {
d.values = datasets[i];
}
});
this.update(this.data);
}
// updateDataPoint(dataPoint, index = 0) {} // updateDataPoint(dataPoint, index = 0) {}
// addDataPoint(dataPoint, index = 0) {} // addDataPoint(dataPoint, index = 0) {}

View File

@ -143,7 +143,10 @@ export default class BaseChart {
setTimeout(() => {this.update();}, this.initTimeout); setTimeout(() => {this.update();}, this.initTimeout);
} }
this.renderLegend(); if(!onlyWidthChange) {
this.renderLegend();
}
this.setupNavigation(init); this.setupNavigation(init);
} }

View File

@ -13,15 +13,15 @@ export default class Heatmap extends BaseChart {
this.domain = options.domain || ''; this.domain = options.domain || '';
this.subdomain = options.subdomain || ''; this.subdomain = options.subdomain || '';
this.data = options.data || {}; this.data = options.data || {};
this.discrete_domains = options.discrete_domains || 1; this.discreteDomains = options.discreteDomains === 0 ? 0 : 1;
this.count_label = options.count_label || ''; this.countLabel = options.countLabel || '';
let today = new Date(); let today = new Date();
this.start = options.start || addDays(today, 365); this.start = options.start || addDays(today, 365);
let legend_colors = (options.legend_colors || []).slice(0, 5); let legendColors = (options.legendColors || []).slice(0, 5);
this.legend_colors = this.validate_colors(legend_colors) this.legendColors = this.validate_colors(legendColors)
? legend_colors ? legendColors
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127']; : ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
// Fixed 5-color theme, // Fixed 5-color theme,
@ -32,6 +32,12 @@ export default class Heatmap extends BaseChart {
this.setup(); this.setup();
} }
setMargins() {
super.setMargins();
this.leftMargin = 10;
this.translateY = 10;
}
validate_colors(colors) { validate_colors(colors) {
if(colors.length < 5) return 0; if(colors.length < 5) return 0;
@ -54,21 +60,21 @@ export default class Heatmap extends BaseChart {
this.start = new Date(); this.start = new Date();
this.start.setFullYear( this.start.getFullYear() - 1 ); this.start.setFullYear( this.start.getFullYear() - 1 );
} }
this.first_week_start = new Date(this.start.toDateString()); this.firstWeekStart = new Date(this.start.toDateString());
this.last_week_start = new Date(this.today.toDateString()); this.lastWeekStart = new Date(this.today.toDateString());
if(this.first_week_start.getDay() !== 7) { if(this.firstWeekStart.getDay() !== 7) {
addDays(this.first_week_start, (-1) * this.first_week_start.getDay()); addDays(this.firstWeekStart, (-1) * this.firstWeekStart.getDay());
} }
if(this.last_week_start.getDay() !== 7) { if(this.lastWeekStart.getDay() !== 7) {
addDays(this.last_week_start, (-1) * this.last_week_start.getDay()); addDays(this.lastWeekStart, (-1) * this.lastWeekStart.getDay());
} }
this.no_of_cols = getWeeksBetween(this.first_week_start + '', this.last_week_start + '') + 1; this.no_of_cols = getWeeksBetween(this.firstWeekStart + '', this.lastWeekStart + '') + 1;
} }
calcWidth() { calcWidth() {
this.baseWidth = (this.no_of_cols + 3) * 12 ; this.baseWidth = (this.no_of_cols + 3) * 12 ;
if(this.discrete_domains) { if(this.discreteDomains) {
this.baseWidth += (12 * 12); this.baseWidth += (12 * 12);
} }
} }
@ -82,21 +88,20 @@ export default class Heatmap extends BaseChart {
'data-groups', 'data-groups',
`translate(0, 20)` `translate(0, 20)`
); );
// Array.prototype.slice.call(
// this.container.querySelectorAll('.graph-stats-container, .sub-title, .title') this.container.querySelector('.title').style.display = 'None';
// ).map(d => { this.container.querySelector('.sub-title').style.display = 'None';
// d.style.display = 'None'; this.container.querySelector('.graph-stats-container').style.display = 'None';
// }); this.chartWrapper.style.marginTop = '0px';
// this.chartWrapper.style.marginTop = '0px'; this.chartWrapper.style.paddingTop = '0px';
// this.chartWrapper.style.paddingTop = '0px';
} }
calc() { calc() {
let data_values = Object.keys(this.data).map(key => this.data[key]); let dataValues = Object.keys(this.data).map(key => this.data[key]);
this.distribution = calcDistribution(data_values, this.distribution_size); this.distribution = calcDistribution(dataValues, this.distribution_size);
this.month_names = ["January", "February", "March", "April", "May", "June", this.monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December" "July", "August", "September", "October", "November", "December"
]; ];
} }
@ -110,118 +115,118 @@ export default class Heatmap extends BaseChart {
this.domainLabelGroup.textContent = ''; this.domainLabelGroup.textContent = '';
this.dataGroups.textContent = ''; this.dataGroups.textContent = '';
let current_week_sunday = new Date(this.first_week_start); let currentWeekSunday = new Date(this.firstWeekStart);
this.week_col = 0; this.weekCol = 0;
this.current_month = current_week_sunday.getMonth(); this.currentMonth = currentWeekSunday.getMonth();
this.months = [this.current_month + '']; this.months = [this.currentMonth + ''];
this.month_weeks = {}, this.month_start_points = []; this.monthWeeks = {}, this.monthStartPoints = [];
this.month_weeks[this.current_month] = 0; this.monthWeeks[this.currentMonth] = 0;
this.month_start_points.push(13); this.monthStartPoints.push(13);
for(var i = 0; i < no_of_weeks; i++) { for(var i = 0; i < no_of_weeks; i++) {
let data_group, month_change = 0; let dataGroup, monthChange = 0;
let day = new Date(current_week_sunday); let day = new Date(currentWeekSunday);
[data_group, month_change] = this.get_week_squares_group(day, this.week_col); [dataGroup, monthChange] = this.get_week_squares_group(day, this.weekCol);
this.dataGroups.appendChild(data_group); this.dataGroups.appendChild(dataGroup);
this.week_col += 1 + parseInt(this.discrete_domains && month_change); this.weekCol += 1 + parseInt(this.discreteDomains && monthChange);
this.month_weeks[this.current_month]++; this.monthWeeks[this.currentMonth]++;
if(month_change) { if(monthChange) {
this.current_month = (this.current_month + 1) % 12; this.currentMonth = (this.currentMonth + 1) % 12;
this.months.push(this.current_month + ''); this.months.push(this.currentMonth + '');
this.month_weeks[this.current_month] = 1; this.monthWeeks[this.currentMonth] = 1;
} }
addDays(current_week_sunday, 7); addDays(currentWeekSunday, 7);
} }
this.render_month_labels(); this.render_month_labels();
} }
get_week_squares_group(current_date, index) { get_week_squares_group(currentDate, index) {
const no_of_weekdays = 7; const noOfWeekdays = 7;
const square_side = 10; const squareSide = 10;
const cell_padding = 2; const cellPadding = 2;
const step = 1; const step = 1;
const today_time = this.today.getTime(); const todayTime = this.today.getTime();
let month_change = 0; let monthChange = 0;
let week_col_change = 0; let weekColChange = 0;
let data_group = makeSVGGroup(this.dataGroups, 'data-group'); let dataGroup = makeSVGGroup(this.dataGroups, 'data-group');
for(var y = 0, i = 0; i < no_of_weekdays; i += step, y += (square_side + cell_padding)) { for(var y = 0, i = 0; i < noOfWeekdays; i += step, y += (squareSide + cellPadding)) {
let data_value = 0; let dataValue = 0;
let colorIndex = 0; let colorIndex = 0;
let current_timestamp = current_date.getTime()/1000; let currentTimestamp = currentDate.getTime()/1000;
let timestamp = Math.floor(current_timestamp - (current_timestamp % 86400)).toFixed(1); let timestamp = Math.floor(currentTimestamp - (currentTimestamp % 86400)).toFixed(1);
if(this.data[timestamp]) { if(this.data[timestamp]) {
data_value = this.data[timestamp]; dataValue = this.data[timestamp];
} }
if(this.data[Math.round(timestamp)]) { if(this.data[Math.round(timestamp)]) {
data_value = this.data[Math.round(timestamp)]; dataValue = this.data[Math.round(timestamp)];
} }
if(data_value) { if(dataValue) {
colorIndex = getMaxCheckpoint(data_value, this.distribution); colorIndex = getMaxCheckpoint(dataValue, this.distribution);
} }
let x = 13 + (index + week_col_change) * 12; let x = 13 + (index + weekColChange) * 12;
let dataAttr = { let dataAttr = {
'data-date': getDdMmYyyy(current_date), 'data-date': getDdMmYyyy(currentDate),
'data-value': data_value, 'data-value': dataValue,
'data-day': current_date.getDay() 'data-day': currentDate.getDay()
}; };
let heatSquare = makeHeatSquare('day', x, y, square_side, let heatSquare = makeHeatSquare('day', x, y, squareSide,
this.legend_colors[colorIndex], dataAttr); this.legendColors[colorIndex], dataAttr);
data_group.appendChild(heatSquare); dataGroup.appendChild(heatSquare);
let next_date = new Date(current_date); let nextDate = new Date(currentDate);
addDays(next_date, 1); addDays(nextDate, 1);
if(next_date.getTime() > today_time) break; if(nextDate.getTime() > todayTime) break;
if(next_date.getMonth() - current_date.getMonth()) { if(nextDate.getMonth() - currentDate.getMonth()) {
month_change = 1; monthChange = 1;
if(this.discrete_domains) { if(this.discreteDomains) {
week_col_change = 1; weekColChange = 1;
} }
this.month_start_points.push(13 + (index + week_col_change) * 12); this.monthStartPoints.push(13 + (index + weekColChange) * 12);
} }
current_date = next_date; currentDate = nextDate;
} }
return [data_group, month_change]; return [dataGroup, monthChange];
} }
render_month_labels() { render_month_labels() {
// this.first_month_label = 1; // this.first_month_label = 1;
// if (this.first_week_start.getDate() > 8) { // if (this.firstWeekStart.getDate() > 8) {
// this.first_month_label = 0; // this.first_month_label = 0;
// } // }
// this.last_month_label = 1; // this.last_month_label = 1;
// let first_month = this.months.shift(); // let first_month = this.months.shift();
// let first_month_start = this.month_start_points.shift(); // let first_month_start = this.monthStartPoints.shift();
// render first month if // render first month if
// let last_month = this.months.pop(); // let last_month = this.months.pop();
// let last_month_start = this.month_start_points.pop(); // let last_month_start = this.monthStartPoints.pop();
// render last month if // render last month if
this.months.shift(); this.months.shift();
this.month_start_points.shift(); this.monthStartPoints.shift();
this.months.pop(); this.months.pop();
this.month_start_points.pop(); this.monthStartPoints.pop();
this.month_start_points.map((start, i) => { this.monthStartPoints.map((start, i) => {
let month_name = this.month_names[this.months[i]].substring(0, 3); let month_name = this.monthNames[this.months[i]].substring(0, 3);
let text = makeText('y-value-text', start+12, 10, month_name); let text = makeText('y-value-text', start+12, 10, month_name);
this.domainLabelGroup.appendChild(text); this.domainLabelGroup.appendChild(text);
}); });
@ -233,19 +238,19 @@ export default class Heatmap extends BaseChart {
).map(el => { ).map(el => {
el.addEventListener('mouseenter', (e) => { el.addEventListener('mouseenter', (e) => {
let count = e.target.getAttribute('data-value'); let count = e.target.getAttribute('data-value');
let date_parts = e.target.getAttribute('data-date').split('-'); let dateParts = e.target.getAttribute('data-date').split('-');
let month = this.month_names[parseInt(date_parts[1])-1].substring(0, 3); let month = this.monthNames[parseInt(dateParts[1])-1].substring(0, 3);
let g_off = this.chartWrapper.getBoundingClientRect(), p_off = e.target.getBoundingClientRect(); let gOff = this.chartWrapper.getBoundingClientRect(), pOff = e.target.getBoundingClientRect();
let width = parseInt(e.target.getAttribute('width')); let width = parseInt(e.target.getAttribute('width'));
let x = p_off.left - g_off.left + (width+2)/2; let x = pOff.left - gOff.left + (width+2)/2;
let y = p_off.top - g_off.top - (width+2)/2; let y = pOff.top - gOff.top - (width+2)/2;
let value = count + ' ' + this.count_label; let value = count + ' ' + this.countLabel;
let name = ' on ' + month + ' ' + date_parts[0] + ', ' + date_parts[2]; let name = ' on ' + month + ' ' + dateParts[0] + ', ' + dateParts[2];
this.tip.setValues(x, y, name, value, [], 1); this.tip.setValues(x, y, {name: name, value: value, valueFirst: 1}, []);
this.tip.showTip(); this.tip.showTip();
}); });
}); });

View File

@ -67,7 +67,7 @@ export default class PercentageChart extends AggregationChart {
? this.formattedLabels[i] : this.state.labels[i]) + ': '; ? this.formattedLabels[i] : this.state.labels[i]) + ': ';
let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1); let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%"); this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip(); this.tip.showTip();
} }
}); });

View File

@ -2,7 +2,7 @@ import AggregationChart from './AggregationChart';
import { getComponent } from '../objects/ChartComponents'; import { getComponent } from '../objects/ChartComponents';
import { getOffset } from '../utils/dom'; import { getOffset } from '../utils/dom';
import { getPositionByAngle } from '../utils/helpers'; import { getPositionByAngle } from '../utils/helpers';
import { makePath, makeArcPathStr } from '../utils/draw'; import { makeArcPathStr } from '../utils/draw';
import { lightenDarkenColor } from '../utils/colors'; import { lightenDarkenColor } from '../utils/colors';
import { transform } from '../utils/animation'; import { transform } from '../utils/animation';
import { FULL_ANGLE } from '../utils/constants'; import { FULL_ANGLE } from '../utils/constants';
@ -39,7 +39,7 @@ export default class PieChart extends AggregationChart {
this.center = { this.center = {
x: this.width / 2, x: this.width / 2,
y: this.height / 2 y: this.height / 2
} };
this.radius = (this.height > this.width ? this.center.x : this.center.y); this.radius = (this.height > this.width ? this.center.x : this.center.y);
s.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0); s.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
@ -102,7 +102,7 @@ export default class PieChart extends AggregationChart {
return { return {
sliceStrings: s.sliceStrings, sliceStrings: s.sliceStrings,
colors: this.colors colors: this.colors
} };
}.bind(this) }.bind(this)
] ]
]; ];
@ -132,7 +132,7 @@ export default class PieChart extends AggregationChart {
let title = (this.formatted_labels && this.formatted_labels.length > 0 let title = (this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels[i] : this.state.labels[i]) + ': '; ? this.formatted_labels[i] : this.state.labels[i]) + ': ';
let percent = (this.state.sliceTotals[i] * 100 / this.state.grandTotal).toFixed(1); let percent = (this.state.sliceTotals[i] * 100 / this.state.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%"); this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip(); this.tip.showTip();
} else { } else {
transform(path,'translate3d(0,0,0)'); transform(path,'translate3d(0,0,0)');

View File

@ -51,6 +51,9 @@ export default class SvgTip {
fill() { fill() {
let title; let title;
if(this.index) {
this.container.setAttribute('data-point-index', this.index);
}
if(this.titleValueFirst) { if(this.titleValueFirst) {
title = `<strong>${this.titleValue}</strong>${this.titleName}`; title = `<strong>${this.titleValue}</strong>${this.titleName}`;
} else { } else {
@ -97,13 +100,14 @@ export default class SvgTip {
} }
} }
setValues(x, y, titleName = '', titleValue = '', listValues = [], titleValueFirst = 0) { setValues(x, y, title = {}, listValues = [], index = -1) {
this.titleName = titleName; this.titleName = title.name;
this.titleValue = titleValue; this.titleValue = title.value;
this.listValues = listValues; this.listValues = listValues;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.titleValueFirst = titleValueFirst; this.titleValueFirst = title.valueFirst || 0;
this.index = index;
this.refresh(); this.refresh();
} }

View File

@ -1,4 +1,4 @@
export const VERT_SPACE_OUTSIDE_BASE_CHART = 40; export const VERT_SPACE_OUTSIDE_BASE_CHART = 50;
export const TRANSLATE_Y_BASE_CHART = 20; export const TRANSLATE_Y_BASE_CHART = 20;
export const LEFT_MARGIN_BASE_CHART = 60; export const LEFT_MARGIN_BASE_CHART = 60;
export const RIGHT_MARGIN_BASE_CHART = 40; export const RIGHT_MARGIN_BASE_CHART = 40;
@ -16,7 +16,7 @@ export const MIN_BAR_PERCENT_HEIGHT = 0.01;
export const LINE_CHART_DOT_SIZE = 4; export const LINE_CHART_DOT_SIZE = 4;
export const DOT_OVERLAY_SIZE_INCR = 4; export const DOT_OVERLAY_SIZE_INCR = 4;
export const DEFAULT_CHAR_WIDTH = 8; export const DEFAULT_CHAR_WIDTH = 7;
// Universal constants // Universal constants
export const ANGLE_RATIO = Math.PI / 180; export const ANGLE_RATIO = Math.PI / 180;

View File

@ -31,4 +31,9 @@ export function addDays(date, numberOfDays) {
date.setDate(date.getDate() + numberOfDays); date.setDate(date.getDate() + numberOfDays);
} }
// export function getMonthName() {} export function getMonthName(i) {
let monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
return monthNames[i];
}

View File

@ -180,7 +180,7 @@ function makeVertLine(x, label, y1, y2, options={}) {
dy: FONT_SIZE + 'px', dy: FONT_SIZE + 'px',
'font-size': FONT_SIZE + 'px', 'font-size': FONT_SIZE + 'px',
'text-anchor': 'middle', 'text-anchor': 'middle',
innerHTML: label innerHTML: label + ""
}); });
let line = createSVG('g', { let line = createSVG('g', {
@ -337,7 +337,7 @@ export function yRegion(y1, y2, width, label) {
let labelSvg = createSVG('text', { let labelSvg = createSVG('text', {
className: 'chart-label', className: 'chart-label',
x: width - getStringWidth(label, 4.5) - LABEL_MARGIN, x: width - getStringWidth(label+"", 4.5) - LABEL_MARGIN,
y: 0, y: 0,
dy: (FONT_SIZE / -2) + 'px', dy: (FONT_SIZE / -2) + 'px',
'font-size': FONT_SIZE + 'px', 'font-size': FONT_SIZE + 'px',
@ -369,6 +369,8 @@ export function datasetBar(x, yTop, width, color, label='', index=0, offset=0, m
height: height || meta.minHeight // TODO: correct y for positive min height height: height || meta.minHeight // TODO: correct y for positive min height
}); });
label += "";
if(!label && !label.length) { if(!label && !label.length) {
return rect; return rect;
} else { } else {
@ -385,6 +387,7 @@ export function datasetBar(x, yTop, width, color, label='', index=0, offset=0, m
}); });
let group = createSVG('g', { let group = createSVG('g', {
'data-point-index': index,
transform: `translate(${x}, ${y})` transform: `translate(${x}, ${y})`
}); });
group.appendChild(rect); group.appendChild(rect);
@ -403,6 +406,8 @@ export function datasetDot(x, y, radius, color, label='', index=0, meta={}) {
r: radius r: radius
}); });
label += "";
if(!label && !label.length) { if(!label && !label.length) {
return dot; return dot;
} else { } else {
@ -420,6 +425,7 @@ export function datasetDot(x, y, radius, color, label='', index=0, meta={}) {
}); });
let group = createSVG('g', { let group = createSVG('g', {
'data-point-index': index,
transform: `translate(${x}, ${y})` transform: `translate(${x}, ${y})`
}); });
group.appendChild(dot); group.appendChild(dot);
@ -481,9 +487,10 @@ export let makeOverlay = {
} }
let overlay = unit.cloneNode(); let overlay = unit.cloneNode();
let radius = unit.getAttribute('r'); let radius = unit.getAttribute('r');
overlay.setAttribute('r', radius + DOT_OVERLAY_SIZE_INCR); let fill = unit.getAttribute('fill');
overlay.style.fill = '#000000'; overlay.setAttribute('r', parseInt(radius) + DOT_OVERLAY_SIZE_INCR);
overlay.style.opacity = '0.4'; overlay.setAttribute('fill', fill);
overlay.style.opacity = '0.6';
if(transformValue) { if(transformValue) {
overlay.setAttribute('transform', transformValue); overlay.setAttribute('transform', transformValue);

View File

@ -28,8 +28,13 @@
} }
.graph-stats-container { .graph-stats-container {
display: flex; display: flex;
justify-content: space-around; justify-content: space-between;
padding-top: 10px; padding: 10px;
&:before,
&:after {
content: '';
display: block;
}
.stats { .stats {
padding-bottom: 15px; padding-bottom: 15px;
} }