CreateElement inside div without id

How can I use document.createElement(“iframe”) and place that iframe within the div I’m running the js in when it has no id/class etc?

eg.

<div>
<script>
var newiframe = document.createElement("iframe")
....
</script>
</div>

Stating the obvious, but you would need another way to target it, maybe relative to a parent with an id or class.

As an example something like this perhaps…

<body>
  <div></div>
  <div id='section1'> <!-- targeting section1 as parent -->
    <div></div> <!-- [0] first div -->
    <div><!-- [1] second div -->
      <script>
        const iframe = document.createElement('iframe')
        const thisDiv = document.querySelectorAll('#section1 div')[1] // [second div inside section]
        const script = thisDiv.querySelector('script') // get the child element script

        // replace this script with the iframe
        thisDiv.replaceChild(iframe, script)
      </script>
    </div>
  </div>
</body>

Daft question, but is there a reason the script has to be inside a particular div?

The problem is I have no idea about divs outside the unnamed div that I’m wanting to add this iframe into. It has to be inside this div as it’s containing the iframe.

Can you give the script a unique id?

<body>
  <div></div>
  <div id='section1'>
    <div></div>
    <div>
      <script data-id='appendIframe'>
        const iframe = document.createElement('iframe')
        const script = document.querySelector("script[data-id='appendIframe']")

        // replace this script with the iframe
        script.parentNode.replaceChild(iframe, script)
      </script>
    </div>
  </div>
</body>
1 Like

Unfortunately not as this code is out of my hands. These are embeddable on remote webpages. I just have access to the div around the iframe I’m inserting.

Ok, learning exercise here

I’m not sure how reliable this is. Other contributors may have a better idea

<body>
  <div></div>
  <div>
    <script>
      // empty script here
    </script>
    <div></div>
    <div id='target-div'> <!-- just so I can see when I inspect element -->
      <script>
        const iframe = document.createElement('iframe')
        // get all scripts to this point of the rendered page
        const scripts = document.querySelectorAll('script')
        // pick the last one
        const thisScript = scripts[scripts.length-1]

        // replace this script with the iframe
        thisScript.parentNode.replaceChild(iframe, thisScript)
      </script>
    </div>
  </div>
  <script>
    // Another script here
  </script>
</body>
2 Likes

FWIW, it won’t work if the script is getting loaded asynchronously… there’s also document.currentScript, which works for async scripts as well but not for old IE. ^^

2 Likes

That works thanks. In terms of getting it to work if called async, is there a way to detect and serve alternative code to suit? Or detect old IE instead?

Also, do you know how to set the no borders and scollbars attributes on an iframe? This doesn’t work: iframe.setAttribute(‘style.border’, 0);

EDIT: Fixed no borders with iframe.frameBorder = 0 and no scroll with iframe.scrolling =“no”

Iframes aren’t something I have used in about 20 years, so best someone else helps you there.

Not sure how to solve the async vs no async issue.

One option for isolating IE is to use <script src='iescript.js' nomodule> and for modern browsers <script src='script.js' type='module'>. MDN link

1 Like

Or you might simply check if document.currentScript is actually defined; if it’s not, do something else:

if (!document.currentScript) {
  // Do something else
}

BTW note that when using type="module" scripts, document.currentScript won’t be defined either; in this case you have to use the import.meta to find the current script:

const currentScript = [...document.scripts]
  .find(script => script.src === import.meta.url)

… which again will only work if the code was not actually imported as a module. <:o)

JFTR this should have been:

iframe.setAttribute('style', 'border: 0')

Or better, since this will keep other existing other styles:

iframe.style.border = '0'
1 Like

Thanks. iframe.frameBorder = 0 seems to work, is that OK to use?

In terms of async vs sync, is this OK:

if (document.currentScript.async) {
	var thisScript = document.currentScript;
} else {
	var scripts = document.querySelectorAll('script');
	var thisScript = scripts[scripts.length-1];  
}

Well, it’s actually deprecated and the MDN recommends to use border styles instead.

This is a misunderstanding; document.currentScript will work as expected for async scripts – it will just not work for IE at all. So you could use the else code as an IE fallback, but then again you might rather do nothing or display an error message if your script is possibly async.