Two ways to run JavaScript in Jupyter Notebook:

  • Client side javascript using IPython built-in magic commands;
  • Server side Node javascript using Javascript kernel for the Jupyter notebook.

“The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text.”

Javascript kernel for the Jupyter notebook

The Jupyter notebook can execut code in a number of programming languages. The execution of code is carried out by means of a kernel. There is a list of available kernels. The SoS kernel provides multi-language support within a single notebook. Javascript kernel is Ijavascript.

The IJavascript kernel executes Javascript code inside a Node.js session and provides access to the Node.js standard library and to any installed npm modules. The IJavascript kernel, by default, runs a Node.js session in the current working folder.

To run the Node.js session in a different folder:

ijsinstall --working-dir=/path/to/working/dir

IJavascript is an npm package and requires:

  • Node.js
  • npm

The packages should be installed in the same directory as the notebook. To install it use npm.

To initialize npm in the notebook directory and install the required packages to support it navigate to the directory and run the following command in your terminal to create a package for a project:

npm init --yes

The --yes argument runs through all of the prompts that you would otherwise have to fill out or skip. It creates a package.json to keep track of installed packages.

Example of Windows installation (Anaconda Distribution)

In the Anaconda prompt run:

conda install nodejs

npm install -g ijavascript

ijsinstall

Then run jupyter notebook in terminal to load Jupyter Notebook. The Javascript (Node) kernel should be available while creating a new Jupyter Notebook.

ijsinstall registers the IJavascript kernel with Jupyter, so that the Jupyter notebook can invoke it.


Javascript kernel example

In [1]:
var msg = ["Hello", "World!"].join(", ");
In [2]:
msg
Out[2]:
'Hello, World!'
In [3]:
console.log(msg);
 
Hello, World!
In [4]:
console.error(msg);
 
Hello, World!
In [5]:
$$.html("<div style='background-color:red; width:250px;height:50px'></div>");
Out[5]:
 
 

Client side javascript in a node.js environment using jsdom

jsdom is a pure-JavaScript implementation of many web standards and provides a playground for D3’s select().enter().append() pattern.

d3 and jsdom modules should be installed in the current notebook folder.

In [6]:
var d3 = require("d3");
var jsdom = require("jsdom");
In [7]:
var dom0 = new jsdom.JSDOM("<svg></svg>",{QuerySelector:true});

var selectSvg = dom0.window.document.querySelector("svg");

d3.select(selectSvg)
    .append("rect")
    .attr("width", 80)
    .attr("height", 80)
    .style("fill", "blue");

$$.html(dom0.serialize());
Out[7]: 
 
In [8]:
const dom = new jsdom.JSDOM(`<!DOCTYPE html><div id="id1"></div>`);
In [9]:
var data = [1, 2, 4, 8, 4, 2, 1];
var selectDiv = dom.window.document.querySelector("div");
var svg = d3.select(selectDiv).append('svg')
            .attr('width', 500)
            .attr('height', 200);
svg.selectAll('circle')
            .data(data)
            .enter()
            .append('circle')
            .attr("cx", function(d, i) {return 65 * (i + 1);})
            .attr("cy", function(d, i) {return 100 + 40 * (i % 2 - 1);})
            .style("fill", "#15a415")
            .attr("r", function(d) {return 3*d;});
$$.html(dom.serialize());
Out[9]: 
 

Built-in javascript magic command

Magic commands or magic functions are one of the enhancements of IPython. Magics control the behaviour of IPython.

There are two types of magic commands:

  1. Line magics
  2. Cell magics

Line magics operate on a single line of a code cell.

Cell magics operate on the entire code cell in which they are called.

Client side javascript using Jupyter magics

JavaScript isn’t supported by default. It is necessary to use a special command to tell the cell about running a JavaScript code in it. For JavaScript, the magic command is %%javascript.

 

To see the available magics, type and run the following:

%lsmagic
In [1]:
%lsmagic
Out[1]:
Available line magics:
%alias  %alias_magic  %autoawait  %autocall  %automagic  %autosave  %bookmark  %cd  %clear  %cls  %colors  %conda  %config  %connect_info  %copy  %ddir  %debug  %dhist  %dirs  %doctest_mode  %echo  %ed  %edit  %env  %gui  %hist  %history  %killbgscripts  %ldir  %less  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %ls  %lsmagic  %macro  %magic  %matplotlib  %mkdir  %more  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %pip  %popd  %pprint  %precision  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %ren  %rep  %rerun  %reset  %reset_selective  %rmdir  %run  %save  %sc  %set_env  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

Available cell magics:
%%!  %%HTML  %%SVG  %%bash  %%capture  %%cmd  %%debug  %%file  %%html  %%javascript  %%js  %%latex  %%markdown  %%perl  %%prun  %%pypy  %%python  %%python2  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

Automagic is ON, % prefix IS NOT needed for line magics.
In [2]:
%%js?
 

Ways to run JavaScript in a Python Jupyter

  1. Running JavaScript in a Python Jupyter cell by writing:

    %%javascript
    [some JavaScript]
  2. By importing the IPython library:

    from IPython.display import Javascript

    Link to IPython library
    And then run arbitrary JavaScript, client-side like this:

    Javascript("""
    [some JavaScript]
    """)
  3. Running an external JavaScript file like this:
    Javascript(filename='someFileName.js')

 

IPython’s %%javascript magic runs code client-side and sets a global JQuery-selected variable, element, to refer to the output cell.

Creating arbitrary DOM elements in a cell.

To create SVG canvases and add SVG shapes to that canvas write code like this:

%%javascript
element.append("<div></div>");
In [3]:
%%javascript
element.append("<div>Hello ;-)</div>");
 
Hello ;-)

Javascript Example:
In [4]:
%%html
<div id="javasciptId"></div>
Numbers
 
  • Figure 1: 33
  • Figure 2: 44
  • Figure 3: 55
  • Figure 4: 66
  • Figure 5: 77
Average number is 55
 
In [5]:
%%javascript

var selected = document.getElementById("javasciptId");
var numbers = new Array();
numbers[1]=33;
numbers[2]=44;
numbers[3]=55;
numbers[4]=66;
numbers[5]=77;
selected.innerHTML = "<b>Numbers</b>";
selected.innerHTML += "<ul>";
var num=0;
var sum=0;
var average=0;
for(var i in numbers){
    selected.innerHTML += "<li>Figure "+i+": "+numbers[i];
    num++;
    sum=sum+numbers[i];
}
selected.innerHTML += "</ul>";
var average = Math.round(sum/num);
selected.innerHTML += "Average number is "+average;
 

Using the JavaScript visualisation library D3 in a Python Notebook

To import D3 library, use RequireJS:

In [6]:
%%javascript
require.config({ 
     paths: { 
     d3: 'https://d3js.org/d3.v5.min'
}});
 

To use D3 in subsequent cells, use RequireJS again:

%%javascrip
require(['d3'], function(d3) {   
     console.log(d3);
});
 

Accessing the output cell

element is the jQuery powered wrapper for the current output cell:

In [7]:
%%javascript
element.text('hello world');
 hello world

D3 in an IPython Notebook

element.get(0) is the DOM (Document Object Model) node that can be handed to d3.select().

D3 - Example 1

Since element is a global variable and overwritten when new cells are run, to make sure you’re referring to the correct output cell wrap this in a closure like so:

In [8]:
%%javascript
 (function(element) {
     require(['d3'], function(d3) {   
        d3.select(element.get(0)).append('text').text('hello world');
     })
 })(element);
 hello world
 

D3 - Example 2

In [9]:
%%javascript
(function(element) {
    require(['d3'], function(d3) {   
        var data = [1, 2, 4, 8, 4, 2, 1]

        var svg = d3.select(element.get(0)).append('svg')
            .attr('width', 500)
            .attr('height', 200);
        svg.selectAll('circle')
            .data(data)
            .enter()
            .append('circle')
            .attr("cx", function(d, i) {return 65 * (i + 1);})
            .attr("cy", function(d, i) {return 100 + 40 * (i % 2 - 1);})
            .style("fill", "#f7e80c")
            .transition().duration(2000)
            .attr("r", function(d) {return 2*d;})
        ;
    })
})(element);
 
 

Passing data from ipython to javascript

In Python, to get data into javascript code:

  1. Import the json module
  2. Serialize data with json.dumps()
  3. Pass the string into JavaScript
In [1]:
#Import the json module:
import json
#Create data:
data = [10, 20, 30, 40, 50]
#Convert the Python data to a json formatted string
as_json = json.dumps(data)
print(type(data))  # prints '<class 'dict'>'
print(type(as_json))  # prints '<class 'str'>'
#pass string into JavaScript
from IPython.display import Javascript
Javascript("""
console.log(%s);
""" % as_json)
 
<class 'list'>
<class 'str'>
Out[1]:
 
 

JSON string can be exported to an external json file and referenced in JavaScript cell.

References and further reading:

  1. A gallery of interesting Jupyter Notebooks
  2. Built-in magic commands
  3. JavaScript Charts on Jupyter Notebooks
  4. D3 JavaScript visualisation in a Python Jupyter notebook
  5. Custom D3.js Visualization in a Jupyter Notebook
  6. Using D3.js in Jupyter notebook
  7. Embedding D3 in an IPython Notebook
  8. IJavascript
  9. Ijavascript kernell Installation
  10. Data Science for Javascript Developers
  11. jsdom - a pure-JavaScript implementation of web standards
  12. Web Scraping and Parsing HTML in Node.js with jsdom
  13. Client side javascript in a node.js environment using jsdom
  14. How to output SVG in a Jupyter notebook using jsdom, D3 and Ijavascript
  15. Talking to Python from JavaScript (and Back Again!)
  16. IPython Notebook: Javascript/Python Bi-directional Communication