I am trying to loop through a series of pages (javascript) from the following webpage:
http://nh.mypublicnotices.com/PublicNotice.asp?Page=SEARCHRESULTS
I found all of the elements that I need to loop through, but I am unable to click on it. What would be the best way to loop through these javascript elements:
from selenium.webdriver.support.select import Select
next_page=driver.find_elements_by_xpath('//[#id="PublicNoticeContent"]/table[2]/tbody/tr/td/table[2]/tbody/tr[6]/td/table/tbody/tr/td/table/tbody/tr[1]/td/a')
for i in next_page:
link=i.get_attribute("href")
Select(link)
Select.click()
You need to repeat your materials on Select and working with a class.
link=i.get_attribute("href")
Select(link)
This code has just grabbed what had better be a SELECT tag, but it certainly looks as if you've grabbed only an href. You tried to create a Select object from that link ... but then, having created it, you failed to save it: you threw it away.
Select.click()
I'm not at all sure how you expect this to work: this invokes click as a direct call of a class method, but Select has no such method, so this will fail because teh attribute doesn't exist: an error message you failed to provide in your posting.
Start with this: once you work through your tutorial materials and learn to extract the proper SELECT tag from a URL i ... perhaps
select_tag = i.find_element_by_tag_name(“select”)).select_by_index(0)
clickable = Select(select_tag)
clickable.click()
You click on the object you created, not on the class.
Does that help get you going? You still need to figure out how to code that first line in your application.
Related
I'm a beginner in using Nightwatch and I'm stuck with the following:
I've got a table that has a <tbody> and multiple <tr>s in it. I need to check if a specific word is in one of the cells in the first column.
First, I tried getting the whole table using document.GetElements... but it appears this is not supported by Nightwatch. Currently, I'm looking for a solution without using Nightwatch custom command.
P.S. I can't create tags yet, so it'd be awesome if someone could create one, like table-to-array or something like that.
You can execute javascript code into the browser using execute command (Documentation here). So you can do something like this:
client.execute(function(){
/*your js to get the DOM element and check if the element has the text you want*/
return true //or false if didnt find it
},[],function(response){
console.log(response.value)//this will contain your returned value
client.assert.equal(response.value, true, "Text not found on table")
})
Updated
I'm using:
Selenium 2.53.1
Firefox and IE11
I've been trying to click on all elements with the same selector, for example, I want to click on all the ones with the title "What I Want":
<div id="first_question">
<a class="gibberish1" title="What I Want"></a>
<a class="gibberish2" title="What I Want"></a>
<a class="gibberish3" title="What I Want"></a>
</div>
Here is what I have working so far:
browser.findElements(by.xpath("//a[#title='What I Want']")).then(function(all_tests){
for (var i = 0; i < all_tests.length; i++) {
console.log(all_tests.length);
all_tests[i].click();
}
});
It's able to recognize that I have three elements, and if I call each individual one directly then I'm able to see it click on the button. However, when I want to loop so it clicks on each button, I get an error:
"StaleElementReferenceError: Element is no longer attached to the DOM."
I also added a wait of 5 seconds in, but that didn't deter the same issue from popping up.
What am I doing wrong? I'm new to Selenium and I'm trying to figure this out in Javascript, instead of Java which is what I find examples for this situation.
You need to find them one by one, on page reload your objects will be lost and you will get stale element exception.
1) find all links
2) save an attribute/attributes in a list/array that can help you identify each link
3) create a loop where for each attribute you are searching for the element and click it
Moving my comment to an answer...
The first issue is that your code attempts are clicking a collection rather than an individual element. There are several ways to do this, one of which is doing a for loop and accessing the individual elements inside the loop, e.g. all_tests[i].click();.
The second issue with stale elements is because the DOM is being changed either through refreshing the page or navigating to a new page. If the issue is that clicking is causing navigation, you can loop through all the A tags and store the hrefs in a string array. Then you can loop through that string array and navigate to each stored href, etc.
Another way to handle this is to scrape the page using the index rather than storing the collection outside the loop. A simple example of this is
This is Java/pseudocode that you will have to translate into whatever language you are using but the concept should work.
for (int i = 0; i < driver.findElements(locator).length; i++)
{
// scrapes the page each iteration to avoid the stale element exception
driver.findElements(locator)[i].click();
// do stuff and get back to the original page, if navigated
}
I think first print the all_tests, check the output and the changes in
the for loop could work
for element in all_tests: element.click()
And to handle StaleElementReferenceError, can check here:
StaleElementReferenceException on Python Selenium
NOTE: Not Tested but handled the same concern.
1: What I want to do is check if a page contains a specific class with a specific string, and if it does, send an event to Google Tag Manager.
2: I also need a macro to check if a certain element exists on a page and if it does, fire the tag above.
What I have been able to get together so far is the supposed tag:
<html>
<head></head>
<body>
...
<a class="myClass">Captured value</a>
...
</body>
</html>
My tag to be fired using JavaScript would look something like this:
<script>
var x = document.getElementsByClassName("myClass")[0].innerHTML;
if (x.match ("Captured value")) {
dataLayer.push({'event':'captured'});
}
</script>
So this tag will fire if it sees the above anchor with that specific class. Using the above code though, I keep getting errors:
Uncaught Type Error: Cannot read property 'innerHTML' of undefined(anonymous function)
#VM490:2InjectedScript._evaluateOn
#VM479:883InjectedScript._evaluateAndWrap
#VM479:816InjectedScript.evaluate
#VM479:682
How would I write a cleaner code to not generate an error if the class doesn't exist?
Regarding number two, how would I write a function with a return statement? I just can't figure this one out. I have tried something along the lines of:
function () {
var t = document.getElementsByClassName("myClass")[0].innerHTML;
var y = dataLayer.push({'event':'trigger'})
if (t.match ("Captured value")) {
return y;
}
I want to use a macro to check if the class exists on a page with the correct value, which in turn I can use as a trigger to fire the first tag. To use macros in GTM, I need to return a value. I just can't figure out how to check for the class value and have my tag fire upon its validation.
Another way to go is of course to write a custom HTML tag to fire on all pages and have the JavaScript look for, validate and send the event. I currently do not possess the JavaScript aptitude to figure out how that would look though.
Any suggestions are highly appreciated.
With your second block of code, I would first make it a self-invoking function
<script>
(function(){
...
}()
</script>
that checkes for the presence of the class in question and also checks for the required text. Use 'indexOf' rather than 'matches' (so you do not need to deal with regex). If those two conditions are true, then push your event to the dataLayer. Fire this tag when event equals gtm.dom, along with any other conditions you think should apply, and that should do it.
Google Tag Manager has a perfectly usable DOM element variable for this. Go to variables (assuming GTM v2), "new", "DOM Element", Selection Method "CSS selector", selector ".myClass" (from your example).
Set up a trigger "page view", trigger type "DOM ready", fire on "yourDOMelement eq. "Captured value".
Unless I misunderstand your needs you should not havbe to write any custom javascript.
My approach was all backwards. I attempted to use a JavaScript solution while I could just use a custom JS inside of Tag Manager to check for a defined value and fire a trigger if it resolved to true.
The methodology I was thinking about was about right I guess, but the way about doing it was over complicating things.
What I did was add a custom JavaScript macro named cjs.return class (using v1 for this said container) and added the following code:
function (){
x = document.getElementsByClassName("myClass")[0].innerHTML;
return x;
}
This function returned either undefined or "Captured value" depending on if it was the right page or not. I then set up a new rule to trigger my tag if:
event equals gtm.dom
cjs.return class equals Captured value
This new rule triggered my tag, which in turn could send the data on the specific set of pages I wanted it to fire on.
Thanks to both Eike and nyuen for answering to give me a clearer picture of what I did wrong.
I'm a total newbie to Onsen UI and I managed to make my first little app (static that is) with a few pages, popovers, lists, etc.
But when I try to add dynamic stuff in there, it does not want to cooperate.
When I click my side menu, it calls menu.setMainPage and in the callback I want to modify the content of the list (lets say iterate a JSON request and add a ons-list-item for each of them). However, they do not look styled with Onsen UI icing.
I guess it's because the menu.setMainPage has already parsed the ons-page and showed it in the browser.
Is there a way to do a load page, update the dom, and then pass it to be displayed?
I have a simila problem with an popover that contains a list. I want to add items in that list, but my jQuery append never work. Same reason I suppose.
Thanks!
Sounds like you're not running ons.compile() on the dynamic elements. The custom elements must be compiled after they've been added to the DOM to get the correct style and behavior.
I made a short example to illustrate it:
ons.bootstrap();
var addItem = function() {
var $myList = $("#my-list"),
$item = $("<ons-list-item>").text(Math.random());
$myList.append($item[0]);
ons.compile($item[0]);
};
If you attach the addItem function to a click handler you can add items dynamically to an <ons-list>.
This is a running example on codepen:
http://codepen.io/argelius/pen/gbxNEg
im working on a Asp.net MVc application to create a scheduler application for workers.
The schedule is auto-generate using a JavaScript library called: Dhtmlx Scheduler.
upon populating the data, it creates some Html and places the content.
I would like to retrieve the content and was wondering if it's possible by obtaining the info from its class.
Pic for reference:
I am trying to retrieve the "Abel Toribio" so i can do a reverse search in my database for his name and eventually display a tooltip over that td with further information about the person.
So far I have tried:
var engName = document.getElementsByClassName("dhx_matrix_scell");
alert(engName[0].getData());
alert(engName[0].getContent());
alert(engName[0].getText());
alert(engName[0].getValue());
They all seem to give me undefined.
Thanks!
engName[0].innerHTML - for contents inside the tag 'html'.
engName[0].outerHTML - for contents inside the tag wrapped in the tag.
engName[0].textContent - for contents inside the tag 'text'.
As you tagged jquery as well,for tooltip purpose, you can write mouseover event using jquery this way :
$(".dhx_matrix_scell").on("mouseover",function(){
alert($(this).text());
// do something here
});
if you want to get all, you can get them like this:
$.each(".dhx_matrix_scell",function(){
alert($(this).text());
});