notebook
notebook copied to clipboard
Can't save the notebook programmatically from JavaScript by simulating a click on the save button
Description
When simulating a click on the save button element or its parent using JavaScript, the notebook is not saved.
This is needed in an R client library for otter-grader, where we need to programmatically save a notebook before exporting it into a zip file for submission. We have similar functionality in our Python client which was migrated to ipylab but there is no analog that I can find in R, so we need to use JavaScript to perform the save.
The issue also occurs in JupyterLab and from my understanding notebook v7 is basically a reskin of JupyterLab so I wasn't sure which repo to open this under, but the user who opened our bug about this (https://github.com/ucbds-infra/otter-grader/issues/767) is using notebook, so I figured I'd open it here. Please let me know if it should be moved.
Reproduce
- Create a new notebook with a R kernel
- Run
IRdisplay::display_javascript("
// the save button has the data-command=\"docmanager:save\" attribute
document.querySelector('[data-command=\"docmanager:save\"]').click()
")
- Note that the notebook is not saved
This can also be reproduced in the browser's console by just running the JS:
document.querySelector('[data-command="docmanager:save"]').click()
Expected behavior
When a click is simulated on the button element with JavaScript, the notebook should be saved.
Context
- Operating System and version: MacOS 14.2.1
- Browser and version: Firefox 121.0.1
- Jupyter Notebook version: 7.0.7
Output of jupyter --version
:
IPython : 8.14.0
ipykernel : 6.25.1
ipywidgets : 8.1.0
jupyter_client : 7.4.9
jupyter_core : 5.3.1
jupyter_server : 2.12.5
jupyterlab : 4.0.11
nbclient : 0.8.0
nbconvert : 7.8.0
nbformat : 5.9.2
notebook : 7.0.7
qtconsole : not installed
traitlets : 5.9.0
Troubleshoot Output
See attachment: troubleshoot.txt
Command Line Output
See attachment: jupyter logs.txt
Browser Output
>> document.querySelector('[data-command="docmanager:save"]').click() undefined
In triage, I'm accepting this issue. Your use case might be better suited to a Jupyter Notebook extension that actually runs the "save" command, rather than relying on JavaScript and queries for a specific button that might change in the future.
@chrispyles - the action on the button is actually triggered on mousedown
event not on click. As you are emulating the event, you are not generating the mousedown
event as it happens when a user is really clicking.
@chrispyles - the action on the button is actually triggered on
mousedown
event not on click. As you are emulating the event, you are not generating themousedown
event as it happens when a user is really clicking.
@fcollonval I tried emulating mousedown with document.querySelector('[data-command="docmanager:save"]').dispatchEvent(new MouseEvent('mousedown'))
and that also does not work. Am I missing some required params in the event or is there a sequence of events (e.g. mousedown then mouseup) that needs to happen?
When run with --expose-app-in-browser
, this should work:
window.jupyterapp.commands.execute('docmanager:save');
From within an extension:
const plugin: JupyterFrontEndPlugin<void> = {
id: 'some-integration:plugin',
description: 'A JupyterLab extension',
autoStart: true,
requires: [],
activate: async (app: JupyterFrontEnd) => {
app.commands.execute('docmanager:save');
}
};