{"id":13935665,"url":"https://github.com/jorgehpo/notebookJS","last_synced_at":"2025-07-19T20:33:31.633Z","repository":{"id":52825713,"uuid":"357050653","full_name":"jorgehpo/notebookJS","owner":"jorgehpo","description":"notebookJS: seamless JavaScript integration in Python Notebooks","archived":false,"fork":false,"pushed_at":"2022-12-25T22:31:58.000Z","size":1252,"stargazers_count":172,"open_issues_count":1,"forks_count":11,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-04-28T23:33:33.748Z","etag":null,"topics":["interaction","javascript","jupyter-notebook","python","visualization","widget"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jorgehpo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-12T03:55:17.000Z","updated_at":"2024-04-22T14:44:06.000Z","dependencies_parsed_at":"2023-01-30T22:45:36.959Z","dependency_job_id":null,"html_url":"https://github.com/jorgehpo/notebookJS","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jorgehpo%2FnotebookJS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jorgehpo%2FnotebookJS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jorgehpo%2FnotebookJS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jorgehpo%2FnotebookJS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jorgehpo","download_url":"https://codeload.github.com/jorgehpo/notebookJS/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226677198,"owners_count":17666017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["interaction","javascript","jupyter-notebook","python","visualization","widget"],"created_at":"2024-08-07T23:01:58.279Z","updated_at":"2024-11-27T03:31:01.601Z","avatar_url":"https://github.com/jorgehpo.png","language":"Python","readme":"# notebookJS: seamless JavaScript integration in Python Notebooks \n\n[![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/)\n[![Open In Collab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1g8WOn9oZ5G_3-Y8DYmpV1MIj59dnd81u?usp=sharing)\n[![PyPI version](https://badge.fury.io/py/notebookjs.svg)](https://pypi.org/project/notebookjs)\n\u003c!--- PyPI badge made with https://badge.fury.io/for/py/notebookjs ---\u003e\n\n\u003cimg src=\"https://raw.githubusercontent.com/jorgehpo/notebookJS/main/Images/notebookJS.png\" \n     align=\"left\" \n     hspace=\"10\" \n     vspace=\"6\"\n     width=\"100\"\n     height=\"120\"\u003e\n\n*notebookJS* enables the execution of custom JavaScript code in Python Notebooks (Jupyter Notebook and Google Colab). This Python library can be useful for implementing and reusing  interactive Data Visualizations in the Notebook environment.\n\n*notebookJS* takes care of downloading and handling Javascript libraries and CSS stylesheets from the web. Furthermore, it supports bidirectional communication between Python and JavaScript. User interactions in HTML/JavaScript can trigger Python callbacks that process data on demand and send the results back to the front-end code.\n\nImplementation details in [our paper](https://ieeexplore.ieee.org/iel7/5992/9387473/09391750.pdf?casa_token=v05VFeWM3gwAAAAA:ra4uhd2Xpsd6lllS62Woz1IOjaSOZJGGhh4jpF_ZXOlm1Kq4HTBFHJU7Z-Ez6DDQOUE_djlI5Gk).\n\nSee our [blog post](https://jorgehpo.medium.com/introducing-notebookjs-seamless-integration-between-python-and-javascript-in-computational-e654ec3fbd18).\n\n[![ScatterPlot](https://user-images.githubusercontent.com/14821895/114492279-478ae380-9be6-11eb-8750-30ec3a206816.gif)](https://github.com/jorgehpo/notebookJS/tree/main/Examples/7_D3_scatterplot)\n\n\n## Install\n\nTo install, run:\n`pip install notebookjs`\n\nOr clone this repository and run:\n`python setup.py install`\n\n## API\n\n### execute_js\nThis method executes a javascript function and sets up the infrastructure for bidirectional communication between Python and Javascript using callbacks. \n\n```python\nexecute_js(\n    library_list,\n    main_function,\n    data_dict={},\n    callbacks={},\n    css_list=[],\n)\n```\n\n**Parameters**\n\n- library_list : list of str. \n    List of strings containing either 1) URL to a javascript library, 2) javascript code, 3) javascript [bundle](https://github.com/jorgehpo/notebookJS/tree/main/Examples/5_Webpack_BaseballAnnotator_Bidirectional) (Plain JS only - No support for ES6 Modules)\n- main_function : str. \n    Name of the main function to be called. The function will be called with two parameters: \n    \u003cdiv_id\u003e, for example \"#my_div\", and \u003cdata_dict\u003e.\n- data_dict : dict. \n    Dictionary containing the data to be passed to \u003cmain_function\u003e\n- callbacks : dict. \n    Dictionary of the form {\u003ccallback_str_id\u003e : \u003cpython_function\u003e}. The javascript library can\n    use callbacks to talk to python.\n- css_list : list of str. \n    List of strings containing either 1) URL to a CSS stylesheet or 2) CSS styles\n\n**Main Function**\n\n*main_function* is the javascript function that will be run when execute_js is called. It has the following signature:\n```Javascript\nfunction main_function(div_id, data_dict)\n```\n\n**Example of Main Function**\n\nAs a simple example, we can use D3 to add a circular div to the output cell:\n\n```Javascript\nfunction draw_circle(div_id, data){\n  // Function that draws a circle of color \u003cdata.color\u003e inside the div \u003cdiv_id\u003e using D3\n  d3.select(div_id)\n    .append(\"div\")\n    .style(\"width\", \"50px\")\n    .style(\"height\", \"50px\")\n    .style(\"background-color\", data.color)\n    .style(\"border-radius\", \"50px\")\n}\n```\n\n**Callbacks**\n\n*callbacks* contains a dictionary that maps an identifier string to a Python function. Data is passed to/from callbacks using json/dicts.\n\nFor example, the following callback computes the number to the power of 2.\n\n``` Python\ndef compute_power_2(data){\n    n = data.n\n    n2 = n**2\n    return {\"power2\": n2}\n}\n\ncallbacks = {\n    \"compute_power_2\": compute_power_2\n}\n\nexecute_js(..., callbacks=callbacks)\n```\n\nIn Javascript, we can call this callback with the class *CommAPI*. *CommAPI* is automatically injected in the Javascript by *notebookJS*.\n\n``` Javascript\nlet comm = new CommAPI(\"compute_power_2\", (ret)=\u003e{alert(\"The returned value is \" + ret.power2)})\n\ncomm.call({n: 3}) \n// An alert will be shown with the message: \"The returned value is 9\"\n```\n\nJupyter Notebook and Google Colab have different APIs for sending data to/from Javascript/Python. *CommAPI* abstracts the different APIs in a single convenient class.\n\n**Warning**: Callbacks between Python and JS are only available in Jupyter and Colab notebooks. Jupyter Lab is not supported currently.\n\n### save_html\nThis method creates a standalone HTML bundle (containing all data, JS and CSS resources) and saves it to disk. It accepts all parameters of execute_js, with the addition of *html_dest*, the path to the output file. For example, *html_dest=\"./output.html\"*\n\n```python\nsave_html(,\n    html_dest,\n    library_list,\n    main_function,\n    data_dict={},\n    callbacks=None,\n    css_list=[],\n)\n```\n\n**Warning:** callbacks do not work in standalone HTML files. This parameter only exists to make *execute_js* and *save_html* interoperable.\n\n## Examples\n\n### Hello World - Python Callbacks\n\nIn this example, we show how to display \"hello world\" in multiple languages using Javascript and Python. The Javascript is responsible for updating the front end and requesting a new message from Python. Python returns a random message every time the callback is invoked.\n\n![Hello World Output Gif](https://user-images.githubusercontent.com/14821895/114482788-2d94d500-9bd5-11eb-9ec3-7ee5c5d62a86.gif)\n\n**Javascript to update the div with a hello world message**\n```Python\nhelloworld_js = \"\"\"\nfunction helloworld(div_id, data){\n    comm = new CommAPI(\"get_hello\", (ret) =\u003e {\n      document.querySelector(div_id).textContent = ret.text;\n    });\n    setInterval(() =\u003e {comm.call({})}, 1000);\n    comm.call({});\n}\n\"\"\"\n```\n\n**Defining the Python Callback**\n```Python\nimport random\ndef hello_world_random(data):\n  hello_world_languages = [\n      \"Ola Mundo\", # Portuguese\n      \"Hello World\", # English\n      \"Hola Mundo\", # Spanish\n      \"Geiá sou Kósme\", # Greek\n      \"Kon'nichiwa sekai\", # Japanese\n      \"Hallo Welt\", # German\n      \"Namaste duniya\", # Hindi\n      \"Ni hao, shijiè\" # Chinese\n  ]\n  i = random.randint(0, len(hello_world_languages)-1)\n  return {'text': hello_world_languages[i]}\n```\n\n**Invoking the function helloworld in notebook**\n```Python\nfrom notebookjs import execute_js\nexecute_js(helloworld_js, \"helloworld\", callbacks={\"get_hello\": hello_world_random})\n```\n\nSee this [colab notebook](https://colab.research.google.com/drive/1g8WOn9oZ5G_3-Y8DYmpV1MIj59dnd81u?usp=sharing) for a live demo.\n\n### Radial Bar Chart - Running D3 code in the Notebook\n\nPlotting a Radial Bar Chart with data loaded from Python. Adapted from this [bl.ock](https://bl.ocks.org/AntonOrlov/6b42d8676943cc933f48a43a7c7e5b6c).  See [Examples/3_RadialBarChart](https://github.com/jorgehpo/notebookJS/blob/main/Examples/3_RadialBarChart/).\n\n```Python\n# Loading libraries\nd3_lib_url = \"https://d3js.org/d3.v3.min.js\"\n\nwith open(\"radial_bar.css\", \"r\") as f:\n    radial_bar_css = f.read()\n    \nwith open (\"radial_bar_lib.js\", \"r\") as f:\n    radial_bar_lib = f.read()\n\n# Loading data\nimport pandas as pd\nenergy = pd.read_csv(\"energy.csv\")\n\n# Plotting the Radial Bar Chart\nfrom notebookjs import execute_js\nexecute_js(library_list=[d3_lib_url, radial_bar_lib], main_function=\"radial_bar\", \n             data_dict=energy.to_dict(orient=\"records\"), css_list=[radial_bar_css])\n```\n\n![Radial Bar Chart](https://user-images.githubusercontent.com/14821895/114483438-536ea980-9bd6-11eb-8502-77f7a8864322.gif)\n\n### More examples\n\nPlease see the [Examples/](https://github.com/jorgehpo/notebookJS/blob/main/Examples/) folder for more examples.\n\n## Reference\n\nIf you use *notebookJS*, please reference our related work:\n\n\"*Interactive Data Visualization in Jupyter Notebooks*. JP Ono, J Freire, CT Silva - Computing in Science \u0026 Engineering, 2021\"\n\nBibtex:\n```\n@article{ono2021interactive,\n  title={Interactive Data Visualization in Jupyter Notebooks},\n  author={Ono, Jorge Piazentin and Freire, Juliana and Silva, Claudio T},\n  journal={Computing in Science \\\u0026 Engineering},\n  volume={23},\n  number={2},\n  pages={99--106},\n  year={2021},\n  publisher={IEEE}\n}\n```\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjorgehpo%2FnotebookJS","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjorgehpo%2FnotebookJS","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjorgehpo%2FnotebookJS/lists"}