On my journey to learn d3, I often have difficulties passing from vanilla JS (standard js right?) to observable code and vice versa. Problems rise when I have external data or when I need to update the chart (zoom, pan ect…)
So my question is:
Is there a well defined methodology to port code from let’s say https://bl.ocks.org/ to observable and vice versa ?
I don’t know of a “well-defined” methodology, but I did put some tips at the end of the above notebook. For me the most important thing was to understand how the code that I’m porting works inside and out before trying to adapt it to Observable’s runtime.
Thank you very much Bryan. You are of great help. Seen a correction after trying several hours is useful. I continued with your solution. Rephrasing and clarifying the code. I now understand that the cell should return a DOM element that will be inserted in the div attached to the cell. But I’m left with what looks like subtleties to the beginner that I am.
For example, why the following 2 selects are not returning the exact same DOM element ?
foo = html<button id="fooId">Change data</button>
d3.select(foo)
d3.select("#fooid")
Same for : DOM.svg(width, height) and html<svg width=width, height=height></svg>
Also in your correction you wrote const div = html'<div>;
With just with one div as in the html doc example where it’s written : html<h1>Hello, world!
with just one h1.
Is that just a short cut to html<div></div> ?
Here’s my (possibly inaccurate) understanding. When select is given a string, it searches the current DOM tree using the string as a CSS selector. foo hasn’t yet been appended to the DOM tree so you get the null selection. Hopefully someone will jump in and correct me if this is way off.
In the second one you probably mean:
html`<svg width="width" height="height"></svg>`
These will create slightly different svg elements, check the Observable stdlib docs. DOM.svg also specifies a viewBox in the svg element it creates.
Yep, the html function conveniently closes all HTML tags in the string.
Great, your explanation for the foo makes a lot of sens if the three lignes are in the same cell but if each is in a different cell then foo may be rendered when select search the DOM tree.
But in the latter case there is still a difference with the _parents
Observable doesn’t run cells in top-down order; it uses references to compute topological order. See this notebook:
If you use document.querySelector, you’re reaching through the DOM rather than using an explicit reference, and the behavior of your notebook will be nondeterministic.
Ok, I got that. I even made a draft translation of your notebook how Observable Runs(fr) to make sur I had read it.
From your answer I understand that d3.select(bouton2) is by construction an orphan DOM element, so my mistake was to use a document.querySelector and not remove its parents. That would make sense…
If a cell references a variable bouton2, the referencing cell will wait until the cell that defines bouton2 runs (and adds the button to the DOM) before running. Thus the referencing cell will see the bouton2 as an HTMLButtonElement that has been added to the DOM. In addition, the referencing cell will re-run automatically whenever the defining cell runs, for example if you change the definition or if the definition depends on some other changing value.
On the other hand, if a cell says
document.querySelector("#monBouton2")
it might run before the bouton2 cell runs, or it might not, meaning it’s uncertain whether it will find a matching element. Additionally, such a cell would not re-run automatically when the bouton2 definition changes, because Observable can’t see the dependency between the two cells.
This is likely just a coincidence. The order is not guaranteed. And equally important, cells are re-evaluated only if a cell they reference changes (other than running them explicitly). Dependencies should be explicit.
Didn’t mean to imply it was something to be relied on. But I’ve added, removed and reordered cells, and the order always remained the same. Just something I though was curious.