How to insert an attached image into a DIV from a javascript function and set the size

I’m carrying on from my learnings in a recent forum post: howTo reference an attached image in observable slide preso - #4 by aaronkyle

I’m trying to write javascript that will update the image and size in a DIV, and so far I’m not successful writing the image into an empty DIV, I’m only successful when I put the script inside the HTML cell.

This is my sample notebook: https://observablehq.com/d/b1449a98c382035d

Using the array of StoryImages, I’m able to render an attached image in an HTML cell and set the size:

html`<img src="${await storyImages[0].url}" style="height: 100px">`

I’m also able to do something similar in an HTML cell inside a DIV

<DIV id=i2>`${await storyImages[0].img}`  </DIV>

But I still can’t figure out how to use javascript to insert the image into a DIV let alone get it sized properly.

const str = "`${await storyImages[0].url}`";
document.getElementById("i0").innerHTML = str;
storyImages = [
{
  "index":"1",
  "img":FileAttachment("1.jpeg").image(),
  "url":FileAttachment("1.jpeg").url()
},
{
  "index":"2",
  "img":FileAttachment("2.png").image()
},
  {
  "index":"3",
  "img":FileAttachment("3.png").image()
}
  
]

Thank you,
Bruce

Your sample notebook doesn’t appear to be available. I suppose it’s not shared at the moment. Regardless, it’s pretty easy to produce a notebook that inserts and resizes an image into a cell. The basic idea might look like so:

adjust = {
  d3.select(imgDiv).selectAll("img").remove();
  d3.select(imgDiv)
    .append("img")
    .attr("width", width)
    .attr("src", img_url);
}

Note that width could be the built in reactive variable or anything that you set it to. Here’s an example where width is set by a slider:

@mcmcclur thank you for your assistance but I’m struggling to adapt your code. I shared my notebook in case that helps.

In an HTML Cell I have:

<DIV id="i0">  </DIV>

In a JS cell I have:

adjust = function adjust() {
  const i0 =  storyImages[0];
  const width = 50;
  var imgDiv = document.getElementById("i0");
  d3.select(imgDiv).selectAll("img").remove();
  d3.select(imgDiv)
    .append("img")
    .attr("width", width)
    .attr("src", i0.url);
  return 0;
}

Thanks again

Note that you can pass any attribute to FileAttachment.image(), for example

FileAttachment("1.jpeg").image({width: 100})

To insert a FileAttachment inside your text, use

some text

${ await FileAttachment("1.jpeg").image({width: 100, style: "max-width:640px"}) }

some more text

But I would suggest that you set the image width globally instead, by adding an HTML cell to your notebook with the following content:

<style>
  img { max-width: 640px }
</style>

Please also note that notebook cells are displayed inside the notebook’s <body>, so you cannot use elements like <HTML>, <HEAD> or <BODY> again.


If I may, I’d also suggest to switch from HTML cells to Markdown cells, which will offer a much friendlier editing experience. Instead of

    <B>1</B>

    <p>Sophia sat in her garage workshop, surrounded by piles of scraps and spare parts. She was a brilliant inventor and dreamer, but no one seemed to appreciate or understand her.</p>
   
    <BR>
    <p>At school, she was always getting into trouble for daydreaming and ignoring her lessons. And at home, her parents were always nagging her to help with chores and take care of her younger siblings.</p>

you’d only have to write

## 1

Sophia sat in her garage workshop, surrounded by piles of scraps and spare parts. She was a brilliant inventor and dreamer, but no one seemed to appreciate or understand her.
   
At school, she was always getting into trouble for daydreaming and ignoring her lessons. And at home, her parents were always nagging her to help with chores and take care of her younger siblings.

(similar to what you use here on the forum).

Thanks again @mootari.

  • The HTML Style Block is an easy approach for setting the value globally.
  • It makes sense that I can’t repeat the HTML tags - it would be cool if the notebooks could catch simple errors like that :slight_smile: But it also seemed benign unless I’m missing something?
  • I took another look at Markdown, I do see advantages in some capabilities and the shorthand / compact format. The downside for me, as a new user who will create some notebooks and come back 6 months later, is that the syntax isn’t obvious and human readable like HTML. I need to learn to write like a computer and keep the cheat sheet in another window while I’m working in a notebook.
  • I just found your notebook here, which will definitely come in handy for me: How To List FileAttachments Dynamically / Fabian Iwand | Observable
  • I’m curious if there is something invalid about the approach I was trying with an empty DIV in HTML and to select it in javascript with getElementByID? My current layout is resolved by setting the max-width, but in the future I may want to implement some dynamic sizing following the example mcclure showed above.

That’s a surprising perspective, considering that Markdown was created precisely to be human readable. I’m not sure what features of Markdown you looked at, but most markup options should be very intuitive.

Cells aren’t necessarily executed in the order in which they appear in the notebook. If you have an HTML cell

<div id="my-cell"></div>

and another cell

document.getElementById("my-cell").append(/* ... */)

chances are the second cell runs before the first, and the element won’t exist in the DOM yet.

The proper way to refer to elements in other cells is by cell name:

myCell = htl.html`<div></div>`
myCell.append(/* ... */)

Note that Observable’s Runtime handles dependencies between cells, but it can only do so if cells declare these dependencies explicitly. The general assumption here is that data flows in one direction only - if a parent cell’s value changes, only cells that depend on that cell need to rerun. For that reason we discourage the use of side effects (i.e., a cell changing the contents of a parent cell).


I also encourage you to describe the problem that you’re trying to solve as broadly and abstract as possible. Oftentimes we seek a specific solution because we are unaware of alternative approaches.

:+1: