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>
window.frames
, .contentDocument
, & .contentWindow.document
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.
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.
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>
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);
}