Electron Adventures: Episode 4: Image Gallery with Dynamic HTML
Tags: electron, javascript
Published: 2021-07-28 22:42:47

## Electron Adventures: Episode 4: Image Gallery with Dynamic HTML

Let's do something a little more advanced with Electron - generate some HTML dynamically, and load it into the browser window.

There's no direct functionality for this, but we can use `data` URLs.

(I had to change all references to `data` URLs in code to `da+ta` as dev.to crashes if I use actual code; link to the actual code at the end of the post)

### Load data URL into the web view

```javascript
let { app, BrowserWindow } = require("electron")

let html = `
<!DOCTYPE html>
<html>
  <body>
    <h1>Welcome To The Internet!</h1>
  </body>
</html>
`

function createWindow() {
  let win = new BrowserWindow({})
  win.maximize()
  win.loadURL(`da`+`ta:text/html;charset=utf-8,${encodeURI(html)}`)
}

app.on("ready", createWindow)

app.on("window-all-closed", () => {
  app.quit()
})
```

### ARGV parsing

Well, we managed to pass generated HTML, but it's not doing anything interesting yet.

Let's pick a directory to display images from. The way we run Electron apps, argv starts with `electron`, `.`, so only third arg is the image directory.

```javascript
let imageDir
let argv = process.argv

if (argv.length >= 3) {
  imageDir = argv[2]
} else {
  imageDir = `${__dirname}/images`
}
```

For testing I included a folder with some US state flags in the repo, in `images`.

We can check that this part worked, by displaying it in the browser:

```javascript
let html = `
<!DOCTYPE html>
<html>
  <body>
    <h1>Image Gallery - ${imageDir}</h1>
  </body>
</html>
```

You can run this either as:

```shell
$ npx electron . /path/to/images
$ npx electron .
```

### Find all images in directory

We can use `fs` and `path` to get all the images in a directory.

```javascript
let fs = require("fs")
let path = require("path")

let findImages = (dir) => {
  let files = fs.readdirSync(dir)
  files.sort()
  return files
    .filter(x => /\.(png|jpg|jpeg|gif)/i.test(x))
    .map(x => path.join(dir, x))
}
```

### Display images

We're almost there. Let's change the HTML to display the images. Also switching it all to dark mode, as I had enough of all white screen.

```javascript
let html = `
<!DOCTYPE html>
<html>
  <head>
    <style>
      body { background-color: black; color: white; }
      img { padding: 10px; }
    </style>
  </head>
  <body>
    <h1>Image Gallery</h1>
    ${ findImages(imageDir).map(x => `<img src="file://${x}" />`).join("") }
  </body>
</html>
`
```

### Web security

This should work but it doesn't. Let's try to figure out why.

In Electron you can go to View menu and select "Toggle Developer Tools". Or use appropriate keyboard shortcut like Cmd-Option-I. You get all the usual Chrome debugging tools!

In this case we can see that our image requests were all blocked. This makes sense. Letting `data` URLs load arbitrary `file:` URLs doesn't sound terribly safe.

As this is just a tutorial one-off, let's disable web security rules without thinking too much about the consequences of that.

```javascript
function createWindow() {
  let win = new BrowserWindow({webPreferences: { webSecurity: false }})
  win.maximize()
  win.loadURL(`da` + `ta:text/html;charset=utf-8,${encodeURI(html)}`)
}
```

Electron app security is a big topic. If you're writing an Electron app, and not just a PWA, you likely do it because you need access to something the browser won't let you have. And if so, you're largely leaving browser's protection, and you're now responsible for security of your app.

### Result

And here's what we got:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qg55jqc80def2fhv2vlw.png)

[All the code for the episode is here](https://github.com/taw/electron-adventures/tree/master/episode-04-image-gallery-with-dynamic-html).

See you in the next episode!