I am using Selenium to test a site, the idea is to get all rows from a table, select the visible buttons then click them. Once clicked an event is triggered and with AJAX data is loaded right under the rows.
The following code works perfectly inside the Firefox console. Actually clicks so fast that items are all loaded at once (there are max 10 rows so I would not bother to add a wait event).
function button_visible(row) {
var opacity = row.style.opacity;
if (opacity == "" || opacity == 1) {
return true;
} else {
return false;
}
}
var table = document.querySelectorAll('div>.table');
for (x = 1; x < table.length; x++) {
row = table.item(x);
var row_buttons = row.querySelectorAll('icon-button');
for (var i = 0; i < row_buttons.length; i++) {
if (button_visible(row_buttons.item(i))) {
row_buttons.item(i).click();
}
}
}
Running this JavaScript from Selenium doesn't not work:
js='function button_visible(row) {var opacity = row.style.opacity; if (opacity === "" || opacity == 1) {return true;} else {return false;}} var table = document.querySelectorAll('div>.table'); for (x = 1; x < table.length; x++) {var row = table.item(x); var row_buttons = row.querySelectorAll('icon-button'); for (var i = 0; i < row_buttons.length; i++) {if(button_visible(row_buttons.item(i))){ row_buttons.item(i).click();}}}'
driver.execute_script(js)
Added come console.log's, they show up in the console but the click event is not triggered at all. Funny enough, after trying to run the code with Selenium, running the JavaScript from console does not work as well.
I also tried to return these rows as an array and click with Selenium but this just makes things complicated as I get stale element exception. To make sure it works I need to re-fetch the table rows after each click etc.
I cannot even think a reason why this would not work. Any opinions?
Try the following:
driver.execute_script("""
function button_visible(row) {
var opacity = row.style.opacity;
if (opacity == "" || opacity == 1) {
return true;
} else {
return false;
}
}
var table = document.querySelectorAll('div>.table');
for (x = 1; x < table.length; x++) {
row = table.item(x);
var row_buttons = row.querySelectorAll('icon-button');
for (var i = 0; i < row_buttons.length; i++) {
if (button_visible(row_buttons.item(i))) {
row_buttons.item(i).click();
}
}
}
""")
PS: For running multiline JS in Selenium (Python) should be used """ (start and end).
Hope it helps you!
Related
I'm using vanilla JS to try and disable/re-enable form elements depending on the value of one of the form elements selected.
function editableFormElements() {
let formElements = document.getElementById('NewCaseForm').elements;
let assignedTo = document.getElementById('assignedTo');
if(assignedTo.value == "pending")
{
for(x = 0; x < formElements.length; x++){
formElements[x].disabled = true;
}
}
else{
for(x = 0; x < formElements.length; x++){
formElements[x].disabled = false;
}
}
assignedTo.disabled = false;
}
document.getElementById('assignedTo').addEventListener('change', editableFormElements);
I always want the 'assignedTo' element to be enabled, so I'm setting disabled to false again at the end of the function. The problem is, this doesn't seem to work. That form element remains disabled. What am I missing here?
Good! I have a problem and you do not run my code at the end of the loop, the above and what is inside the loop works fine, the problem is that after the loop is still not executing the code. Any idea why it can be?
This is my code:
var arrayp = new Array();
function botonAdelante(tabl, pasos)
{
var padreTabla = document.getElementById(tabl).rows;
var cont = 0;
for(var j = 0; j < padreTabla.length; j++)
{
var hijoTd = document.getElementById(pasos+ "-producto-" +j);
var childArray = hijoTd.children;
for(var i = 0; i < childArray.length; i++)
{
var check = document.getElementById(pasos+ "-CheckBox-" +j);
if(check.type == 'checkbox' && check.checked==true)
{
arrayp[cont] = check.value;
var algo = arrayp[cont];
alert(arrayp[cont]);
alert(arrayp);
cont++;
continue;
};
}
}
alert("It is in this part of the code does not work");
}
Clarification: "continue" found at the end of long and if it will not work either.
The continue is confusing used like this, but I have a feeling your code is probably throwing an error because the cont might exceed the array length. Regardless of whether this fixes it or not I'd at least add a check to ensure that it doesn't throw an exception.
Please check for exceptions being thrown through web dev tools (F12 in Chrome).
for(var i = 0; i < childArray.length; i++)
{
var check = document.getElementById(pasos+ "-CheckBox-" +j);
if(check.type == 'checkbox' && check.checked==true && arrayp.length <= cont)
{
arrayp[cont] = check.value;
var algo = arrayp[cont];
alert(arrayp[cont]);
alert(arrayp);
cont++;
continue;
};
}
I've learned an enormous amount of scripting for InDesign CS6 thanks to all of the helpful folks here! Now, it's a problem with setting the printPreferences for a document. Here is the code I have:
with(document.printPreferences) {
activePrinterPreset = outputPreset;
pageRange = outputRange;
for (var j = 0; j < allInks.length; j++) {
document.inks.item(allInks[j]).printInk = false;
}
for (var k = 0; k < printInks.length; k++) {
if (printInks[k].toString() === "Black") {
$.writeln("Found Black!");
printBlack = true;
$.writeln("Set Black!");
} else {
document.inks.item(printInks[k]).printInk = true;
}
}
if (offsetJob) {
// If it's an offset job, we might need to change page sizes.
if (productType === "HI-N13W") {
paperSize = PaperSizes.custom;
paperHeight = 12.5;
paperWidth = 8.5;
} else if (productType.subString(3,5) === "PC") {
paperSize = PaperSizes.custom;
paperHeight = 8;
paperWidth = 12.5;
} else if (couldBeBothJobs.toString().indexOf(productType.subString(3,5)) > -1) {
paperSize = "US Letter";
} else {
paperSize = PaperSizes.custom;
paperHeight = 8;
paperWidth = 25;
}
}
}
In the second for loop, you'll see that I have first turned off ALL of the inks in the document for printing. I then only turn on the ones in the printInks array. If, however, the word "Black" exists in the array, there isn't an Ink for it, so instead, I want to set the built-in printPreference "printBlack". (This complements the other three—printCyan, printMagenta, and printYellow.)
It's just supposed to be a boolean value, according to the InDesign CS6 Object Model Reference. However, whenever the script gets to that point, it halts. Pasting just that small bit of code to a fresh document, just so I can see the error message, gets me this:
The property is not applicable in the current state.
What does this mean? And more importantly, how can I fix it? I know that trapping has to be off before this property can be set, but I've definitely made sure that it is off.
After asking this question on the Adobe Community Forums, I was told that some of the Print Preferences cannot be set directly on the document, but must instead be set on a Print Preset, which, in turn, is then set as the Active Print Preset. Thus, I just re-built the preset I needed and assigned it to a new, temporary one. The following is the result:
try {
tempPreset.name;
}
catch(eNoSuchPreset) {
tempPreset = app.printerPresets.add({name:"tempPreset"});
}
// Let's turn off all of the spot colors before everything else.
for (var j = 0; j < allInks.length; j++) {
document.inks.item(allInks[j]).printInk = false;
}
with(document.printPreferences) {
tempPreset.printer = Printer.POSTSCRIPT_FILE;
tempPreset.ppd = "OYO Imagesetter";
tempPreset.pagePosition = PagePositions.CENTERED;
tempPreset.paperSize = PaperSizes.CUSTOM;
tempPreset.paperHeight = "12.5 in";
tempPreset.paperWidth = "6.5 in";
tempPreset.colorOutput = ColorOutputModes.SEPARATIONS;
tempPreset.trapping = Trapping.OFF;
tempPreset.screening = "60 lpi / 600 dpi";
tempPreset.sendImageData = ImageDataTypes.OPTIMIZED_SUBSAMPLING;
pageRange = outputRange;
// Now let's turn off all of the CMYK colors.
tempPreset.printCyan = false;
tempPreset.printMagenta = false;
tempPreset.printYellow = false;
tempPreset.printBlack = false;
// Then we turn back on BLACK if it exists.
for (var k = 0; k < printInks.length; k++) {
if (printInks[k] === "Black") {
tempPreset.printBlack = true;
} else {
document.inks.item(printInks[k]).printInk = true;
}
}
// If this is a four-color process job, then turn back on all of the process colors.
if (processJob) {
tempPreset.printCyan = true;
tempPreset.printMagenta = true;
tempPreset.printYellow = true;
tempPreset.printBlack = true;
}
// That concludes OYO seps.
}
var mydpp = document.printPreferences;
mydpp.activePrinterPreset = "tempPreset";
That gets my 99% of the way to completing this script. YAY!!
Can we get the count of total radiobuttonlist items from .aspx page. I have to call a javascript function onclientclick of a button and i want to loop through the total number of radiobuttonlist items. So can anyone tell me that can we get it from .aspx page. Because in my scenario i can not use code behind for this.
function ClearRBL() {
for (i = 0; i < RBLCOUNT; i++) {
document.getElementById('rblWorkerList_' + [i]).checked = false;
}
}
How can i get RBLCOUNT here from .aspx page only? If not possible then in Javascript please.
I don't know how the aspx side would work, but if you want to do it just in JavaScript you could do something like the following that doesn't need to know the total number of elements in advance:
function ClearRBL() {
var i = 0,
rbl;
while (null != (rbl = document.getElementById('rblWorkerList_' + i++)))
rbl.checked = false;
}
The above assumes that the element ids end in numbers beginning with 0 counting up by 1s; the while loop will keep going until document.getElementById() doesn't find a matching element (in which case it returns null). A less cryptic way of writing it is as follows:
function ClearRBL() {
var i = 0,
rbl = document.getElementById('rblWorkerList_' + i);
while (null != rbl) {
rbl.checked = false;
i++;
rbl = document.getElementById('rblWorkerList_' + i);
}
}
P.S. When the while loop finishes i will be equal to the number of radio buttons, which may be useful if you want to do something with that number afterwards.
Try this:- This is not exactly what you want but hope it will help you.
function GetRBLSelectionID(RadioButtonListID) {
var RB1 = document.getElementById(RadioButtonListID);
var radio = RB1.getElementsByTagName("input");
var isChecked = false;
var retVal = "";
for (var i = 0; i < radio.length; i++) {
if (radio[i].checked) {
retVal = radio[i].id;
break;
}
}
return retVal;
}
you can give a name all radio button and then get them like this.
var RBLCOUNT= document[groupName].length;
or
var RBLCOUNT= 0;
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; ++i) {
if(inputs[i].type =="radio"){
RBLCOUNT++;
}
}
I just created a javascript function as mentioned by Karthik Harve and found the total number of rows generated dynamically as below: -
function ClearRBL() {
var rblLen = document.getElementById('rblWorkerList');
for (i = 0; i < rblLen.rows.length; i++) {
document.getElementById('rblWorkerList_' + [i]).checked = false;
}
}
It's working on both Mozila and IE.
Thanks alot to all who tried to help.
I have a long table with many many columns and it looks really ugly for the users. What I wanted to do was create a simple button that would act as a switch, to turn on and off some of the columns.
Some of the columns are not needed, so what I did was add a class to every that wasn't needed, eg: ....
Now, what I thought I could do was this:
var hidden = 1;
function toggleTable(){
element_array = document.getElementsByClassName('disabled');
for(i = 0; i < element_array.length; i++){
if(hidden == 1){
element_array[i].style.display = 'none';
}else{
element_array[i].style.display = '';
}
}
if(hidden == 1) hidden = 0;
else hidden = 1;
}
This works for the most part in Firefox, but some quick tests in IE(7+8) and I get the following:
Message: Object doesn't support this property or method
Obviously indicating that IE doesn't want to let me simply change "display: none;" for something like table columns/rows.
I can't think of any workarounds. Ideally I'd like a fully cross-compatible solution to toggling the display of certain table columns,but if it's not compatible in the older browsers (eg: IE6) then that would also be OK.
The error that you're getting is not because IE doesn't want to set the display property, it's because the getElementsByClassName method isn't implemented in IE. If you want an implementation of that methods you can use this one which was written by Dustin Diaz.
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
node = document;
if ( tag == null )
tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}
Then you would re-write your method as follows.
var hidden = 1;
function toggleTable(){
var element_array = getElementsByClass('foo');
for(i = 0; i < element_array.length; i++){
if(hidden == 1){
element_array[i].style.display = 'none';
}else{
element_array[i].style.display = '';
}
}
if(hidden == 1) hidden = 0;
else hidden = 1;
}
toggleTable();
And what about jQuery.toggle()?
$(".disabled").toggle();