clear iframe content (including it's JS global scope)
Asked Answered
N

1

4

I'm creating an iframe dynamically like this:

let code = "<html><head><title> hello world <\/title><\/head><body><h1> hello world <\/h1><script>const h1 = document.querySelector('h1'); h1.style.color = 'red'<\/script><\/body><\/html>"

const iframe = document.createElement('iframe')
document.body.appendChild(iframe)

const content = iframe.contentDocument || iframe.contentWindow.document
content.open()
content.write(code)
content.close()

then later I change it's contents like this:

code = "<html><head><title> bye world <\/title><\/head><body><h1> bye world <\/h1><script>const h1 = document.querySelector('h1'); h1.style.color = 'red'<\/script><\/body><\/html>"
content.open()
content.write(code)
content.close()

but I get the following error: SyntaxError: redeclaration of const h1 because of the JavaScript being injected into the iframe.

is there someway to clear the global variable scope within the iframe before i write new code to it? I've tried iframe.contentWindow.location.replace('about:blank') as well as iframe.src = 'about:blank' but this doesn't clear it's internal JS variable scope. (I get the same error)

I realize I could trash the entire iframe and make a new one, but I'm going to be replacing the code a couple of times a second and I'm hoping for a less costly approach to update it.

Nunuance answered 24/6, 2020 at 1:26 Comment(3)
I have exactly the same problem, because I'm trying to get around a situation where mobile browsers are asking for mic permissions once for every iframe. So I wanted to just replace the content of the frame, but ran into the same SyntaxError: redeclaration.Mescal
@Mescal dang, i hadn't thought of that, but in my use case i'm also going to likely hit that same issue (as i do plan on using APIs that now require explicit user permissions)... i really do hope there's a way around this :(Nunuance
See Iframe document write doesn't update JavaScript for some solutions.Spineless
N
0

You can surround the const and let declarations in your dynamic content variable with curly braces {} creating a block scope. That is a simple way to get around the redeclaration error.

// Note the added braces {} within the <script>
let code = "<html><head><title> hello world <\/title><\/head><body><h1> hello world <\/h1><script>{ const h1 = document.querySelector('h1'); h1.style.color = 'red' }<\/script><\/body><\/html>"

Probably better is to first remove any iframe already present in the DOM, then recreate the iframe when you have content to add.

const updateIframe = (code) => {
  const iframe = document.createElement('iframe')

  document.body.querySelector('iframe')?.remove()
  document.body.appendChild(iframe)

  const content = iframe.contentDocument || iframe.contentWindow.document

  content.open()
  content.write(code)
  content.close()
}
Nikaniki answered 10/5, 2024 at 0:50 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.