[IPython-dev] WebGL example in IPython notebook based on three.js

David Powell DavidAnthonyPowell+python at gmail.com
Mon Jan 19 21:17:09 EST 2015

> Did you consider or explore using require.js to load the three.js
> library?  You can reference and load the library once, and then not have to
> inline it within each cell.
My reason for not using require is because I need parts of three.js (e.g
orbit controls) which are not part of the main library, but are instead
included as examples, and hence are not hosted on CDNs.
Also, my code for injecting javascript libraries is in a separate function
which only needs to be called once at the start of the notebook, so it
shouldn't need to be included more than once.

> Aside for folks fiddling with Javscript libraries & the Web notebook:
> the obvious approach of dropping a <script> reference in an HTML cell or
> result isn't robust.  When the cell is reexecuted, the browser will load
> the library again, overwriting the original library name space.  However,
> the first instance of the library will likely still be there because of
> lingering references.  So you'll have a variable "foo" of type X in the old
> library instance, and you'll pass it into a function call (new library
> instance) and things will fail in strange ways because all the type tests
> in the new library instance fail.  And you will drive yourself crazy
> because you'll be in the JS console and wonder why foo is clearly of type
> "X", but "isinstanceof X" is giving False.
> That's why David's JS code has this test:
> https://github.com/DavidPowell/OpenModes/blob/master/openmodes/static/three_js_plot.js#L175
>        if ( *camera instanceof THREE.Camera === false* || !
> document.body.contains(three_container)) {
>             console.log("Animation loop failed: stopping");
>             return;
>         }
I agree that it's a horrible hack, I'm definitely looking for a more
elegant long-term solution. This hack here isn't strictly needed for the
code to work, but if it's missing, then the browser's javascript console
will spew out error messages 60 times per second, which makes debugging
javascript essentially impossible. I think I minimise some of the problems
you describe by injecting the javascript libraries once at the start,
rather than with every plot.

> See my example of using require.js for three.js, here:
> http://nbviewer.ipython.org/github/payne92/notebooks/blob/master/00%20Javascript%20In%20Notebooks.ipynb
 I did find your examples online, but had real trouble getting your
approach to work with the additional javascript from the three.js examples.
So in the end I just went back to this simpler approach of directly
injecting code.

> For the dev team, this raises the issue of:  what's the best idiom for JS
> in a cell to access the output area?  (See SO question:
> http://stackoverflow.com/questions/20019690/how-to-access-current-cell-output-area-with-javascript-in-ipython-web-notebook
> )
> On a "live" notebook, the Javascript *element *variable is fine.  But as
> you can see with my notebook (above) vs David's, the element variable
> approach doesn't survive nbconvert -- my Javascript examples break because
> element doesn't exist in an nbconvert(ed) notebook.
> David made things work by generating (effectively) a UID as part of his
> HTML cell result that the corresponding Javascript can pick up.
> As we see Javascript used more with the Web notebook, folks are going to
> consistently run into this pattern.  I think the notebook could provide
> some "standard" way to reference the output area for the cell, that
> survives nbconvert.

I agree, you've exactly described the problems I ran into, and the reason
why I generate html with a <script> tag rather than javascript output.

> What do you think?
> -andy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ipython-dev/attachments/20150120/763e1e1e/attachment.html>

More information about the IPython-dev mailing list