I am trying to load a Highcharts module (called “dumbbell”) in all the possible ways I can think of, and although I was able to get it to work, it only worked temporarily (strangely enough). The moment I clicked “Enable link sharing”, it broke and I couldn’t get it to work again.
I tried to require each, and although the first two “work” (i.e. load without error), the last one complains of a missing k.arearange. Arearange is something added to Highcharts by highcharts-more.js.
The problem is that these scripts really want to be loaded together. So the only way I could think of doing that was:
Highcharts = {
const HC = await (await fetch('https://code.highcharts.com/highcharts.js')).text();
const more = await (await fetch('https://code.highcharts.com/highcharts-more.js')).text();
const dumbbell = await (await fetch('https://code.highcharts.com/modules/dumbbell.js')).text();
const all = HC + '\n' + more + '\n' + dumbbell;
const blob = new Blob([all], {type: 'application/javascript'});
const obj = await require(URL.createObjectURL(blob)).catch(() => window.Highcharts);
return obj.Highcharts;
}
Believe it or not, this actually worked… for a little while… but then it stopped working. It started to complain that TypeError: obj is undefined. The Javascript console mentions errors like:
Firefox: Content Security Policy: The page’s settings blocked the loading of a resource at inline (“script-src”).
Safari: Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy.
… as well as mentions about Unrecognized Content-Security-Policy directive 'prefetch-src' and Unrecognized Content-Security-Policy directive 'worker-src'.
Can anyone please recommend a more reliable way of getting these scripts loaded?
PS: Here’s a sample JSFiddle for what I’m trying to get working in Observable.
I don’t know if this is simplest (best?) way to do this, but seems to work.
The Hmore(HC); line is what extends the Highcharts object with the functionality in highcharts-more.js which is required for the dumbbell module to work.
I’ll now try to re-implement this functionality in D3
Yep, that’s roughly what I was going to suggest. Though I would recommend loading it from npm rather than Highcharts’ servers because on npm it will be versioned, which protects your notebook from breaking if Highcharts ever changes its API.
In the D3 dumbbell implementation, is it easy to make it so that the labels are listed as in the Highcharts example, as Y-axis labels, right-justified? … and bonus points for adding tooltips to the little circles displaying the actual corresponding percentage value. Pretty please!
The dot plot example I linked demonstrates labeling the values (the dots) directly. Instead of showing the state name in the label, you’d show the value. Though personally I find it more important to label the names, because with lots of data, it’s difficult to trace a line from the y-axis to the correct dot.
As for using the title attribute, there are lots of examples, but to pick one at random:
In short, you append a title element to the thing you want to have a tooltip, and then set the text of the title element to be the desired tooltip text.
Thank you * 100! I got everything working as you indicated!!
Is there a way I can privately share my notebook with you?
Another question, if you don’t mind (and if I share my notebook you’ll see what I’m talking about):
I added y-axis data labels (like the state names in your example), but my labels are very long and I would need to set a very large left margin for them to fully show up (they’re being cut off at the beginning). I’m wondering whether there is a way to show these labels with an overflow indicator (like the ellipsis “…”) when the label doesn’t fit in a particular margin.
I found this reference about how to generate overflow labels for D3, but it applies to text() nodes, but the text on the yAxis in my notebook isn’t built like that, so not sure if/how this approach would apply.
I’m not aware of an “easy” way to get text-overflow: ellipsis working in SVG, but I suspect you could using computed text metrics and binary search to do it manually. Here are a couple examples of text metrics:
You could also use foreignObject or an HTML overlay, but that’s not exactly easy either. I’ll try to put together an ellipsis example in SVG tomorrow.