Search code examples
javascriptiframeradio-button

Cannot select the radio button using javascript when the page is in an iframe


I have an iframe on the first page that contains a second page. The iframe does not have an id so I'll have to assign one to it using javascript. After I assign the id I try to use javascript to click the radio button that have the value 'female' in it. However when I do, I get an error in the console that says: "ERROR: Execution of script 'categorize faces' failed! Cannot read property 'click' of null". What am I doing wrong?

var myframe = document.getElementsByTagName("iframe")[0];
myframe.id = "newID";
document.getElementById("newID").contentWindow.document.querySelector("input[value='female']").click();

First Page:

<iframe src="http://chatwithibot.com/test2.php"></iframe>

Second Page:

<form action="/testx.php" method = "POST">
<input type="radio" name="gender" value="male"> Male<br>
<input type="radio" name="gender" value="female"> Female<br>
<input type="radio" name="gender" value="other"> Other
<input type="submit" value="Submit">
</form> 

Solution

  • window.frames, .contentDocument, & .contentWindow.document

    Iframe Exists when Page Loaded (Not Dynamic)

    See Demo 1

    Assuming that we are referencing the first (or only) iframe on the page:

    window.frames[0]
    document.getElementsByTagName('iframe')[0].contentDocument; // interchangeable
    document.querySelector('iframe').contentWindow.document; // interchangeable
    

    Store any one of the three lines from the example above into a variable, then treat that variable as document.

    var iframeDoc = window.frames[0];
    var iframeInput = iframeDoc.querySelector('#input2');
    

    That in a nutshell is how to access a tag from parent page to a child page via iframe programmatically. If a user's interaction is involved such the user clicking a radio button of the child page then the iframe's document should be registered to the click event using .addEventListener() or an Onevent Property.

    iframeDoc.addEventListener('click', eventHandler);
    

    The Event Handler is a function called when iframeDoc is clicked.

    function eventHandler(event) {
      console.log(event.target.value);
    }
    

    eventHandler() passes the Event Object and then references the property Event.target. event.target is a direct reference to the clicked tag (ex. a radio button). The .value property is suffixed to event.target to get the value of the clicked tag.


    Iframe is Dynamically Inserted Into DOM

    See Demo 2

    When a tag is dynamically added to the DOM it cannot be registered to any event. A workaround is to use the Event Delegation pattern by registering an ancestor tag (ex. body) of the dynamic tag (ex. iframe). The eventHandler must "drill down" into the iframe document from an ancestor tag on the parent page. See Demo 2 for the gruesome details.


    Demo 1

    Static Iframe

    Note: due to security measures on SO, iframes are crippled. The iframe in this demo is using srcdoc to roughly represent what the OP (Original Post) code has.

    var xFrame = window.frames[0];
    
    xFrame.onclick = extractValue;
    
    function extractValue(e) {
      console.log(e.target.value);
    }
    <iframe srcdoc='<form action="/testx.php" method="POST"><input type="radio" name="gender" value="male"> Male<br><input type="radio" name="gender" value="female"> Female<br><input type="radio" name="gender" value="other"> Other<br><br><input type="submit" value="Submit"></form>'></iframe>


    Plunker

    Demo 2

    Dynamic Iframe

    Note: a working demo can be reviewed at this Plunker

    /* 
    || This is to simulate the iframe being dynamically inserted into the DOM.
    || This is not required for OP (Original Post) specific circumstance.
    */
    document.body.insertAdjacentHTML('afterbegin', `<iframe src='test2.html'></iframe>`);
    
    /* BEGINNING OF REQUIRED CODE */
    /*
    || Register the body to the click event
    || function extractValue() is the event handler called when body is clicked.
    */
    document.body.addEventListener('click', extractValue);
    
    /* Event Handler */
    /*
    || Reference the Document Object inside iframe
    || Reference the form tag inside Document Object of iframe
    || Reference all radio buttons name='gender' in the form tag
    || Reference the selected radio button
    || Log the selected radio button's value
    */
    function extractValue(e) {
      var xFrame = window.frames[0];
      var xForm = xFrame.forms[0];
      var xRads = xForm.elements['gender'];
      var selected = xRads.checked;
      console.log(selected.value);
    }