Embedding only parts of notebook

I would like to embed the map and radio options found in this notebook on a webpage, so that a lay person can view and interact with the map without being scared off by the code parts.

I have tried embedding the entire notebook as described in the Rendering cells section of this notebook, but that results in the following with all of the ‘unwanted’ information displayed at the bottom:

I have also tried embedding just the cells I want using the methods described in the Embedding a cell on a web page section of this notebook, however the view of cells only display the selected value (e.g., classification = “Obese”) and not the radio buttons to make a selection.

Is there a way to achieve what I would like as crudely shown in the image below (where I have crossed out the parts I don’t want to appear on the webpage)?

It’s definitely possible. You will want to use the second technique, but write a custom inspector that only applies to the cell names you want to display:

For cells like viewof X , that means you probably only want to inspect the viewof X cell and not the X cell.

Here’s a fragment of something you might use in your embedding code based on the notebook you linked:

 // list the cells you want displayed in HTML elements here
const displayedCells = ["chart", "viewof ageGroup", "viewof classification", 
  "viewof colorScheme"];
const main = new Runtime().module(notebook, name => {
  if (displayedCells.includes(name)) {
    return new Inspector(container);
  } else return true; // this ensures that all notebook cells are run, even if they aren't displayed
})

I think you may also need to give a name the title cell and the style cell in your notebook and then add them to the displayedCells array so that they can be properly appended to the HTML of the page.

If you don’t mind sharing the code you’re using to embed, I (or someone else) could probably quickly give some more specific pointers as to what you need to change.

So I was trying to use some of the code found in this question, but it does not work.

The Runtime. statement is slightly different from yours, but I am not sure how to modify it. What documentation should I be looking at to understand how Runtime works / what it expects?

<html>
    <body>
    
    <div class="wrapper">
		<div id="chart"></div>
		<div id="ageGroup"></div>
		<div id="classification"></div>
		<div id="colorScheme"></div>
    </div>
   
    </body>
    
    <script type="module">
       // Load the Observable runtime and inspector
      import {Inspector, Runtime} from "https://unpkg.com/@observablehq/notebook-runtime@2?module";
          //  Load your notebook, compiled as an ES module.
      import notebook from "https://api.observablehq.com/@bjl2n/bmi-classification-prevalence-mapping.js?v=3";
      const renders = {"chart": "#chart", 
		       "viewof ageGroup": "#ageGroup",
		       "viewof classification": "#classification",
		       "viewof colorScheme": "#colorScheme"};
  
  for (let i in renders)
    renders[i] = document.querySelector(renders[i]);

  Runtime.load(notebook, (variable) => {
    if (renders[variable.name])
      return new Inspector(renders[variable.name]);
  });
    </script>

</html>

I think the most up-to-date docs are at the Github repository.

Here’s a modification of your code along the lines of what I posted above. The main difference is that the forum post you were looking at was using an older version (v2) of the notebook runtime.

Do let me know if you have any questions:

<html>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@observablehq/inspector@3/dist/inspector.css">
    <body>

    <div class="wrapper">
		<div id="chart"></div>
		<div id="ageGroup"></div>
		<div id="classification"></div>
		<div id="colorScheme"></div>
    </div>

    </body>

    <script type="module">
       // Load the Observable runtime and inspector
      import {Runtime, Inspector} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js";
          //  Load your notebook, compiled as an ES module.
      import notebook from "https://api.observablehq.com/@bjl2n/bmi-classification-prevalence-mapping.js?v=3";
      const renders = {"chart": "#chart",
       "viewof ageGroup": "#ageGroup",
       "viewof classification": "#classification",
       "viewof colorScheme": "#colorScheme"};

      for (let i in renders)
        renders[i] = document.querySelector(renders[i]);
      const main = new Runtime().module(notebook, (name) => {
        if (renders[name])
          return new Inspector(renders[name]);
        else return true;
      });
    </script>

</html>

See the result here!

2 Likes

Thanks for the link to the documentation - for some reason I did not know what to look for and where to look.

The code works just as I wanted, thank you!

2 Likes

Glad it worked!

By the way, I just realized that I forgot to implement what I said re: the title cell and style cell. Here’s a fork of your notebook with the title and style cells named:

Here’s the new embedding code.

<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@observablehq/inspector@3/dist/inspector.css">
  </head>
  <body>
    <div class="wrapper">
      <div id="title"></div>
      <div id="chart"></div>
      <div id="ageGroup"></div>
      <div id="classification"></div>
      <div id="colorScheme"></div>
    </div>
  </body>
  <script type="module">
    // Load the Observable runtime and inspector
    import {Runtime, Inspector} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js";
    //  Load your notebook, compiled as an ES module. 
    // (REPLACE THIS WITH A LINK TO YOUR NOTEBOOK IF YOU MERGE MY FORK)
    import notebook from "https://api.observablehq.com/d/a149515eab6eb6ed.js?v=3";
    const renders = {
      "title": "#title",
      "chart": "#chart",
      "viewof ageGroup": "#ageGroup",
      "viewof classification": "#classification",
      "viewof colorScheme": "#colorScheme",
      "hoverStyle": "head",
    };

    for (const name in renders)
      renders[name] = document.querySelector(renders[name]);
    const main = new Runtime().module(notebook, (name) => {
      if (renders[name])
        return new Inspector(renders[name]);
      else return true;
    });
  </script>
</html>

See it live here!

2 Likes

Forgot to reply to this. Naming the style cell was the answer to the next question that I had, but you had already answered it, thanks!

Thanks
great and very usefull post … so it’s very important to give a name to each cell !

I’m going to briefly revive this old thread to leave a link to this handy new embed code generator notebook:

Pick your cells, order them the way you want, and it’ll write the embed code for you.

2 Likes

There is also a Markdown / Observable mashup available (demo here: https://raw.githack.com/hpcc-systems/Visualization/master/demos/storyboard/index.html)

Basically just write your Markdown document as normal and put any “live” code inside ```…``` sections.