From 0f12f436ce90da603a492406f05edbe26e0f93db Mon Sep 17 00:00:00 2001 From: Jan Poeschko Date: Sat, 1 Dec 2018 11:16:23 +0100 Subject: [PATCH] add documentation about notebook loading phases and corresponding events --- README.md | 1 + docs/NotebookAPI.md | 27 ++++++++++++++++++++++++++- docs/NotebookLoadingPhases.md | 23 +++++++++++++++++++++++ docs/ServerSideRendering.md | 2 +- 4 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 docs/NotebookLoadingPhases.md diff --git a/README.md b/README.md index 7b481ae..7f6224b 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ and then use the global variable `WolframNotebookEmbedder`. * [Library interface](./docs/LibraryInterface.md) * [Notebook API](./docs/NotebookAPI.md) * [Server-side rendering](./docs/ServerSideRendering.md) +* [Notebook loading phases](./docs/NotebookLoadingPhases.md) * [Troubleshooting](./docs/Troubleshooting.md) ## Examples diff --git a/docs/NotebookAPI.md b/docs/NotebookAPI.md index b9d9d70..9f8f501 100644 --- a/docs/NotebookAPI.md +++ b/docs/NotebookAPI.md @@ -2,7 +2,7 @@ This is the documentation of [methods](#methods) on the object returned by [`embed`](./LibraryInterface.md) to control a notebook from JS code. Each method takes a JS object with *parameters* and returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) resolving to a *response* object. Parameters with a default value (specified as "= `...`") are optional. In case of an error, the returned promise is rejected with a standard [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object with a `message` property; the potential error messages are listed for each command. -The API also exposes some [events](#events) that can be subscribed to using the API method `addEventListener(eventName, callback)`. The `callback` will receive a JS object with the specified *fields* as its single argument. Event listeners can be removed with `removeEventListener(eventName, callback)`. +The API also exposes some [events](#events) that can be subscribed to using the API method `addEventListener(eventName, callback)`. The `callback` will receive a JS object with the specified *fields* as its single argument. Event listeners can be removed with `removeEventListener(eventName, callback)`. Some events are marked as *singular*, which means that they will usually fire exactly once, and an event listener added after they have already fired will still be executed (right away). Some methods and events marked with "[INTERNAL]" are **internal** and not part of the official API. **Do not rely on internal methods or events in production code.** They might be changed or disappear at any time. @@ -606,6 +606,31 @@ Inserts a function template at current cursor position based on the symbol's lis ## Events +### Initial render progress + +See [notebook loading phases](./NotebookLoadingPhases.md) for more information. + +#### first-paint-done (singular) + +Fired when either static HTML is shown for the notebook (see [servers-side rendering](./ServerSideRendering.md)) or the notebook starts rendering individual cells. + ++ Fields + + + `showingStaticHTML` (`boolean`) ... Whether the notebook is showing a piece of static HTML. + +#### initial-render-progress + +Fired when progress is made during the initial render phase. + ++ Fields + + + `cellsRendered` (`number`) ... Number of cells that have already been "live-rendered". + + `cellsTotal` (`number`) ... Total number of cells that are visible in the notebook. + +#### initial-render-done (singular) + +Fired when the initial render phase is done, i.e. all visible cells have been live-rendered. + ### Selection #### selection-change diff --git a/docs/NotebookLoadingPhases.md b/docs/NotebookLoadingPhases.md new file mode 100644 index 0000000..995ad52 --- /dev/null +++ b/docs/NotebookLoadingPhases.md @@ -0,0 +1,23 @@ +# Notebook Loading Phases + +## Rendering phases + +Notebooks depend on various things that are loaded asynchronously, e.g. the actual notebook content, CSS, JS, fonts, and (potentially) results from kernel evaluations. While things are loading, static pieces of HTML are rendered if available (see [server-side rendering](./ServerSideRendering.md)). Rendering generally goes through the following phases: + +1. Nothing is displayed initially. +2. Once critical CSS and fonts are loaded: Static HTML is displayed, if available; the event `first-paint-done` with `{showingStaticHTML: true}` is fired. +3. Once the main JS code and notebook content data is loaded: Static HTML is reused as a whole (albeit in a slightly different container structure); the event `initial-render-progress` with `{cellsRendered: 0, cellsTotal: -1}` is fired. +4. Once other dependencies such as the notebook stylesheet is loaded and notebook-level options are resolved (possibly relying on kernel evaluations): Static HTML for individual cells is rendered; the event `initial-render-progress` with `{cellsRendered: 0, cellsTotal: N}` is fired with the actual number `N` of initially visible cells. If no static HTML was available initially, the event `first-paint-done` is fired at this point. The notebook also starts fetching static HTML for cells that were not present in the initial static HTML. +5. Each cell might require additional dependencies (e.g. fonts), resolution of `Dynamic` option values, or resolution of `Dynamic` content, etc. Once a cell becomes ready, it is "live-rendered", while other non-ready cells are still rendered using static HTML; the event `initial-render-progress` with `{cellsRendered: M, cellsTotal: N}` is fired accordingly. +6. Once all cells have been live-rendered: the event `initial-render-done` is fired. + +If no static HTML is available for the notebook as a whole or for individual cells, a loading background is displayed in their place until they are live-rendered. + +## Progress indicator + +By default, notebooks show a (blue) progress indicator at the top during the initial render phase. It can be turned off by setting the option `showRenderProgress: false`. The progress indicator distinguishes between two groups of phases: + +1. (phase 1-3 above) An indeterminate progress indicator is shown. +2. (phase 4-6 above) A determinate progress indicator is shown, based on the number of rendered vs. total cells, as long as there are at least three cells in the notebook. If there are less then three cells, another indeterminate progress indicator is shown (since a determinate progress indicator would jump too much and not give a real impression of progress). + +Once the initial render phase is over, the progress indicator is hidden. diff --git a/docs/ServerSideRendering.md b/docs/ServerSideRendering.md index bac494e..7a711ec 100644 --- a/docs/ServerSideRendering.md +++ b/docs/ServerSideRendering.md @@ -1,4 +1,4 @@ -# Server-side rendering +# Server-Side Rendering In some cases, you might want to include (static) HTML for a notebook on your page so it can be rendered even before the necessary JavaScript code is loaded and executed. This reduces the time until the user sees the notebook, and it also helps search engines to index your notebook content. Once your JS code executes, you can [embed](./LibraryInterface.md) the notebook into the same container node, and it will transition seamlessly from the static view to "live" (interactive) rendering. The same happens on [wolframcloud.com](https://www.wolframcloud.com) as well.