Frank
Frank

Reputation: 800

how to add an element in the outer body tag and exclude iframe body tags

I try to add an button via Tampermonkey to websites. That button should only appear in the outer body and not in iframes.

So, for example, this is before the Tampermokey runs...

<html>
  <head>...</head>
  <body>
    ...
    ...
    <iframe src="https://xyz.abc", id="myID">
      <html>
        <head>...</head>
        <body>
          ...
          ...
        </body>
      </html>
    </iframe>
  </body>
</html

I try to add an button like this:

var zNode = document.createElement('div');
            zNode.innerHTML = '<button id="myButton" type="button">' +
                'submit</button>';
            zNode.setAttribute('id', 'myContainer');
var first = document.getElementsByTagName('body')[0];
            first.appendChild(zNode);
            
// add an event handler, etc...

But this piece of code is not ignoring the body tag in the iframe and my button appears in both body tags.

<html>
  <head>...</head>
  <body>
    <div id="myContainer"><button id="myButton" 
      type="button">Clear Session</button></div>
    ...
    <iframe src="https://xyz.abc", id="myID">
      <html>
        <head>...</head>
        <body>
          <div id="myContainer"><button id="myButton" 
            type="button">Clear Session</button></div>
          ...
        </body>
      </html>
    </iframe>
  </body>
</html

What I would like to archive is to add the button only in the outer body (not as part of the iFrame). Please notice, I cannot modify the webpage, I can only try to adapt my code by Tampermonkey... Are you able to support me here please? Thanks

Upvotes: 1

Views: 1097

Answers (1)

zer00ne
zer00ne

Reputation: 43910

Update 2

If the pages are dynamically generated, varies in content, and/or what and how things are loaded cannot be controlled, etc., try adding the button with .insertAdjacentHTML() method. Also adding elements to body isn't the best choice of locations because it's at the top of the hierarchy of HTML and there should be only few elements there.

const win = document.querySelector('iframe');

win.insertAdjacentHTML('beforebegin', `<div class="box">
  <button class='clr'>
    Clear Session
  </button>
</div>`);
<iframe srcdoc="<html><head></head><body>There's no button in this iFrame.</body></html>" width='200' height='100' frameborder='2'></iframe>

Update 1

  1. Use .class instead of #id.
  • A fundamental rule concerning HTML is that of the attribute #id. #ids must be unique on the page, meaning it is invalid HTML if there are more than one element assigned as #myContainer for example. Under normal circumstances should there be more than one #id, methods such as .querySelector() or .getElementById() will find the first element and ignore any other duplicates because it's assumed that there is only one #myContainer.
  1. iFrame HTML is invalid
  • In the OP code there's a unusual layout where there is two #myContainers and they are in separate documents which inadvertantly makes them both behave as valid. But the OP code is invalid because iFrames syntax is very wrong:

    • OP Invalid HTML (iFrame is an just an inline element)

      <iframe><html><body>...</body></html></iframe>
      
    • Valid HTML (iFrame src attribute is a url of the page)

      <iframe src='https://sub.dom.com/path/to/page.html'></iframe>
      
    • Valid HTML (iFrame source is htmlString of srcdoc attribute)

      <iframe srcdoc='<html><body>...</body></html>'></iframe>
      
  • If the iFrame was valid, then everything within the iFrame couldn't be affected unless:

  • Op code has an invalid iFrame which is just an inline element with no special features.

  1. Use .querySelector()
  • The method .getElementsByTagName('body')[0] actually collects all body elements and the bracket notation with the value of zero: [0] indicates the first body in the document, thus both bodys are affected.

Check the HTML with F12 and make sure that zNode (assuming zNode is an element) is appended to the iframe. From what little code posted, it looks as if you couldn't have added anything to an iframe because there is an extra property needed:

document.querySelector('iframe').contentDocument;

In the example below the following is used to reference the body of parent document:

document.body 

const mark = document.createElement('mark');
mark.textContent = 'This is in body of parent document';
document.body.appendChild(mark);
<iframe srcdoc="<!DOCTYPE html><html><head></head><body><p>Inside iFrame</body></html>" style='display: block; width: 50vw; height: 25vh; border: 3px inset grey; margin: 10px auto'></iframe>

Upvotes: 2

Related Questions