Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions highcharts-api/highcharts/17-data-module/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

<head>

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>

</head>

Expand All @@ -24,4 +27,4 @@

</body>

<script src="main.js"></script>
<script src="main.js"></script>
144 changes: 143 additions & 1 deletion highcharts-api/highcharts/17-data-module/main.js
Original file line number Diff line number Diff line change
@@ -1 +1,143 @@
const data = document.getElementById('csv').innerHTML;
const data = document.getElementById('csv').innerHTML;
const T_UNITS = [ 'C', 'F' ];
let currentTUnit = 1;

const toMinutes = value => {
const [h, m] = value.split(':').map(Number);
return h * 60 + m;
};

const toTimeStr = minutes => {
const h = Math.floor(minutes / 60),
m = minutes % 60;
const toStr = v => String(v).padStart(2, '0');
return `${toStr(h)}:${toStr(m)}`;
};

const chart = Highcharts.chart('container', {
chart: {
events: {
load() {
const chart = this;

chart.tUnitSwitchBtn = chart.renderer
.button(T_UNITS[currentTUnit], 0, 0, function() {
const temperatureSeries = [];
chart.series.forEach(s => {
if (s.name === 'tempC') temperatureSeries[0] = s;
if (s.name === 'tempF') temperatureSeries[1] = s;
});

temperatureSeries[currentTUnit].hide();
currentTUnit ^= 1;
temperatureSeries[currentTUnit].show();

this.attr({ text: T_UNITS[currentTUnit] });

chart.yAxis[0].update({
title: {
text: T_UNITS[currentTUnit]
},
labels: {
format: `{value}°${T_UNITS[currentTUnit]}`
}
});
})
.add();
}
}
},
title: {
text: 'Temperature'
},
yAxis: [{
title: { text: T_UNITS[currentTUnit] },
height: '45%',
lineWidth: 2,
labels: {
format: `{value}°${T_UNITS[currentTUnit]}`
}
Comment on lines +57 to +59

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Whenever you can, use format instead of formatter (better e.g. for JSON configs)
labels: {
    format: `{value}°${T_UNITS[currentTUnit]}`
},

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Format will not work here because when you press the button: currentTUnit variable changes and axis text must change as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then perhaps you should update the yAxis.labels.format on a button click as well? Only a few lines of additional code, but it'll work for more specific cases.

You don't have to change it now, but please keep it in mind - format is usually better than formatter. We had many users on support with problems when the formatter wasn't working in specific cases, e.g. when the chart config had to be a JSON string (no functions, only strings).
Soon you'll work with Highcharts core code, and build API and documentation, and you'll have to use format only.

ps. I can see the .attr() on the yAxis text - using yAxis.update({ title: { text: ... } }) is also better because you store all real values on the chart (with .attr, you only change DOM)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. I'll keep that in mind.

}, {
title: { text: 'Rainfall' },
height: '45%',
top: '55%',
offset: 0,
lineWidth: 2,
labels: {
formatter() {
return toTimeStr(this.value);
}
}
}],
legend: {
enabled: false
},
data: {
csv: data,
firstRowAsNames: true,
itemDelimiter: ',',
parsed(columns) {
columns.forEach(col => {
const colName = col[0];
if (colName === 'rainStart' || colName === 'rainEnd') {
for (let i = 1; i < col.length; i++) {
col[i] = toMinutes(col[i]);
}
}
});
},
complete(options) {
let tempF = {
visible: T_UNITS[currentTUnit] === 'F'
};
let tempC = {
visible: T_UNITS[currentTUnit] === 'C'
};
let rainfall = {
yAxis: 1,
type: 'columnrange',
name: 'rainfall',
pointStart: 0,
data: [],
tooltip: {
pointFormatter() {
return `
<span style="color:${this.color}">●</span>
${this.series.name}: <b>${toTimeStr(this.low)} – ${toTimeStr(this.high)}</b><br/>
`;
}
}
};

options.series.forEach(s => {
switch (s.name) {
case 'tempC':
tempC = { ...tempC, ...s };
break;

case 'tempF':
tempF = { ...tempF, ...s };
break;

case 'rainStart':
rainfall.pointStart = s.pointStart;
s.data.forEach((data, i) => {
rainfall.data[i] ||= [];
rainfall.data[i][0] = data[0];
rainfall.data[i][1] = data[1];
});
break;

case 'rainEnd':
s.data.forEach((data, i) => {
rainfall.data[i] ||= [];
rainfall.data[i][2] = data[1];
});
break;
}
});

options.series = [ tempC, tempF, rainfall ];
}
}
});