ChE Junkie ChE Junkie - 1 year ago 236
Javascript Question

How to: Select Radio Option Button in iFrame Using CasperJS?

I am new to JavaScript, new to CasperJS, etc. However, I have watched a couple of YouTube videos and worked through some examples using CasperJS. From this vantage I thought I had a fairly good grasp of the basics and was ready for my first project, which I am currently now stuck on. How to click a radio option button?

I do not know if it is something unique to the site I am working with or some additional holes in my understanding, but nothing I try seems to work. I would greatly appreciate any input; I have been stumbiling in the dark for far to long...

Since I am new to this, I will give details incase there are some things I have done wrong, or should consider doing etc. Thanks!

The Problem

When I open the site URL: I am greeted by four options:
enter image description here
So I right-click on the control and use DevTools to get information on the elements:

<input name="selection" value="Upload" id="ID1" type="radio" onclick="this.form.submit()">
<input name="selection" value="MolinspirationJME" id="ID2" type="radio" onclick="this.form.submit()">
<input name="selection" value="Insert" id="ID3" type="radio" onclick="this.form.submit()">
enter code here
<input name="selection" value="DDBSearch" id="ID4" type="radio" checked="checked" onclick="this.form.submit()">

Here I am interested in DDBSearch (option no. 4). I have yet to do an example with radio buttons, and I originally thought that I could just do somehting like e.g. value=true, but then I see that value is actually a text string, so I click on the button to see what its active state looks like:

<input name="selection" value="DDBSearch" id="ID4" type="radio" checked="checked" onclick="this.form.submit()">

So I know that I need to somehow activate the property checked, but I have been unable to do so by XPath, ID, Name, etc. Not knowing what the problem was I tried to report more error information using other examples from the web.

Casper Constructor Options

I setup my casper object as follows:

var casper = require("casper").create({
verbose:true, // log messages will be printed out to the console
pageSettings:{ // the WebPage instance used by Casper will use these settings.
loadImages: false,
loadPlugins: false,
webSecurityEnabled: false
onDie: function(){
console.log("Script complete.");
// Display message every time any page successfully initializes:
onPageInitialized: function(){
console.log("\rPage initialized.\r");
waitTimeout: 10000,
stepTimeout: 10000,
onWaitTimeout: function(){ // invoked when you are waiting for an element to be visible, e.g. after clicking a button, and waitTimeout has been exceeded.
this.echo("** Wait-TimeOut **");
onStepTimeout: function(){ // NOT REALLY SURE WHAT THIS IS USED FOR ???
this.echo("** Step-TimeOut **");

Trying to catch additional error information by using code like e.g.

casper.on('remote.message', log);
casper.on('error', logError);
casper.on('complete.error', logError);
casper.on('page.error', logError);

Requiring additional functions:

function log(msg){
console.log('Remote msg>: ', msg);

function logError(msg,traceback){

Not really sure where I got this from, or how it really works, but it looked like it should report additional error information, so I went for broke.

Verify Page Structure

I read somewhere that you should verify the structure of the page first, so I based it on the form opeform, which the radio options are contained within. At this point I also noticed that the additional input fields that I am really tring to get to (after option no. 4 is selected) are just hidden on the page--not sure if this is important or not?

Seems to me that it would be easier to work with the hidden elements of the form; thereby, bypassing the radio option issue that I am currently having? (Just a thought burning in the background for now..)

<form name="opeform" method="post" action="">
<table border="0" style="white-space: nowrap; font-size:10pt;width: 560px; text-align: left;" cellpadding="2" cellspacing="2">
<h3>Input Method</h3><input name="selection" value="Upload" id="ID1" type="radio" onclick="this.form.submit()"><b>Upload</b> a Mol- or CTC-file directly from your hard drive<br>
<input name="selection" value="MolinspirationJME" id="ID2" type="radio" onclick="this.form.submit()"><b>Molinspiration JME</b> allows to draw and edit molecules (Java required)<br>
<input name="selection" value="Insert" id="ID3" type="radio" onclick="this.form.submit()"><b>Insert</b> the content of a Molfile in a textfield<br>
<input name="selection" value="DDBSearch" id="ID4" type="radio" onclick="this.form.submit()"><b>DDB Search</b> (retrieves a structure from the chemical structure database ChemDB)</td>
<input type="hidden" id="ID9" name="molstruct" value="">

So I use the CasperJS assert system to make sure that the form opeformis in place before continuing:

var selector = "#unifacga";
console.log("\r>>> Check if the element exists.");
console.log(">>> If the element does not exist, the test (i.e. our script) will fail, otherwise it will simply continue.\r");
function pass () {
console.log("\r",">>> Element found");
console.log("1: ",this.evaluate(function(sel){return !!document.querySelector(sel)},selector));
console.log("2: ",this.evaluate(function(sel){return document.querySelector(sel).textContent;},selector));
console.log(">>> Continue.","\r");
function fail () {
this.die(">>> Did not load element... something is wrong T_T","\r");

Up to this point everything is roses an sunshine...

Try No.1 - Radio Option Select by XPATH

I first tried using XPath, because this is what a lot of examples use for clicking buttons:

var x = require("casper").selectXPath;
// //*[@id="ID4"] is the XPath statement.
// input type that has the attribute id as radio.

For which I get an error like:
enter image description here
It says nonexistant selector, but the syntax looks right (as far as I can tell), and the ID is most definately "ID4" (as shown above from DevTools).

Try No.2 - Radio Option Select by ID (and Name)

So I next tried to work with the object by ID (and name):


Now I get a different error:
enter image description here
So now I get a type error. Looks like the getElementByID method as I have used it may not return the object or something? Any other variation like e.g. getElementByName results in similar errors...

Try No.3 - Casper.Click

I also tried

casper.then(function() {'input[id="ID4"][checked="checked"]');

Which results in another error like XPath:
enter image description here

In Conclusion

I am not sure how to resolve the issue. Seems like everything I try to select radio option 4 results in some type of error; however, I do not know enough about JavaScript and CasperJS to troubleshoot any furhter than I already have. Other solutions that I have tried from online, so far, have not worked for me. Any help would be greately appretiated.

Answer Source

Use my function click2iframe, and don't forget --web-security=no option, e.g. ./casperjs --web-security=no snap.js

function click2iframe(sel_of_the_iframe,sel_in_the_iframe){
var event=document.createEvent('MouseEvents'),element=document.querySelector(sel_of_the_iframe).contentDocument.querySelector(sel_in_the_iframe);event.initMouseEvent('click',1,1,window,1,0,0,0,0,0,0,0,0,0,null); element.dispatchEvent(event);
var casper = require('casper').create();

Bonus example: click3_iframe function, if you need to click on an element which is located in the 3rd iframe:

<iframe id="1"><iframe id="2"><iframe id="3">
<a id="some_id" href="">some text</a>

function click3_iframe(sel_of_the_iframe,sel_of_the_iframe2,sel_of_the_iframe3,sel_in_the_iframe){
var event=document.createEvent('MouseEvents'),
event.initMouseEvent('click',1,1,window,1,0,0,0,0,0,0,0,0,0,null); element.dispatchEvent(event);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download