I need to select the element labeled "Save" in the following HTML:
<td id="glActionAreaItem_0" tabindex="401" widgetid="glActionAreaItem_0">
<a class="actionItem" dojoattachevent="onclick:_onClick" tabindex="401" href="javascript:void(0);"> Reset </a>
</td>
<td id="ActionAreaItem_1" tabindex="402" widgetid="glActionAreaItem_1">
<a class="actionItem" dojoattachevent="onclick:_onClick" tabindex="402" href="javascript:void(0);"> Save </a>
</td>
I need to grab the Save object, but there are very few unique fields between the Reset and Save objects, and I don't want to rely on the tabindex cause we are not guaranteed that will stay 402 forever.
Is it possible to use the 'Save' label as the XPath? How would I go about doing that? Or perhaps I can use the id="glActionAreaItem_1" and somehow get that objects children, would that give me the Save object? Sorry, thinking out loud.
Dim btn_Save
'page is the HTML page
Set btn_Save = page.FindChildByXPath("//a[#tabindex='402']:, True)
I need another way to get the btn_Save object, not using the tabindex property because it is not going to be 402 always.
Here is another way to get the Save object.
Set lnk_Save = page.FindChildByXPath("//td[#id='glActionAreaItem_1']//a[#class='actionItem']", True)
Yes, you can select an element based on its string value in XPath.
This XPath will select the a element whose string value is "Save":
//a[normalize-space(.) = 'Save']
That way it won't matter whether #tabindex or any other attribute changes.
(normalize-space() will trim away leading and trailing whitespace and consolidate internal space (not applicable here).)
Related
I'm creating a sample textbox for search like this (I'm using VB) in my webpage:
Dim txtSearchFilter As New HtmlGenericControl("input")
With txtSearchFilter
.ID = "txtSearchFilter"
.Attributes.Add("placeholder","Filter")
.Attributes.Add("type","search")
.Attributes.Add("maxlength","80")
End With
It's great, because this is the HTML5 style box which has some useful features, such as the "x" on the right side of the box to clear the text entry. However, from the code behind, I can't retrieve the text that was entered. I've tried:
txtSearchFilter.InnerText
txtSearchFilter.InnerHtml
txtSearchFilter.Attributes("value")
Request.Form("txtSearchFilter")
But none of these work. Is there a way to get the value?
P.S., SO prevents me from selecting the HTML5 tag and, instead, puts in the HTML tag even though I selected the HTML5 tag.
Add a name attribute to the input element.
txtSearchFilter.Attributes.Add("name", "txtSearchFilter")
Then on postback, you can retrieve the value by Request.Form(name_attribute). Example based on the above code :
Dim value as String = Request.Form("txtSearchFilter")
I have this code in HTML:
<table cellspacing = "0" cellpadding = "0" width = "100%" border="0">
<td class="TOlinha2"><span id="Co">140200586125</span>
I already have a VBA function that accesses a web site, logs in and goes to the right page. Now I'm trying to take the td tags inside a table in HTML. The value I want is 140200586125, but I want a lot of td tags, so I intend to use a for loop to get those tds and put them in a worksheet.
I have tried both:
.document.getElementByClass()
and:
.document.getElementyById()
but neither worked.
Appreciate the help. I'm from Brazil, so sorry about any English mistakes.
There is not enough HTML to determine if the TOlinha2 is a consistent class name for all the tds within the table of interest; and is limited only to this table. If it is then you can indeed use .querySelectorAll
You could use the CSS selector:
ie.document.querySelectorAll(".TOlinha2")
Where "." stands for className.
You cannot iterate over the returned NodeList with a For Each Loop. See my question Excel crashes when attempting to inspect DispStaticNodeList. Excel will crash and you will lose any unsaved data.
You have to loop the length of the nodeList e.g.
Dim i As Long
For i = 0 To Len(nodeList) -1
Debug.Print nodeList(i).innerText
Next i
Sometimes you need different syntax which is:
Debug.Print nodeList.Item(i).innerText
You can seek to further narrow this CSS selector down with more qualifying elements such as, the element must be within tbody i.e. a table, and preceeded by a tr (table row) and have classname .TOLinha2
ie.document.querySelectorAll("tbody tr .TOlinha2")
Since you mentioned you need to retrieve multiple <td> tags, it would make more sense to retrieve the entire collection rather than using getElementById() to get them one-at-a-time.
Based on your HTML above, this would match all <span> nodes within a <td> with a class='TOlinha2':
Dim node, nodeList
Set nodeList = ie.document.querySelectorAll("td.TOlinha2 > span")
For Each node In nodeList
MsgBox node.innerText ' This should return the text within the <span>
Next
<a class="spf-link current" href="/orders/returns?offset=0&limit=25">
<span class="pg-helpText">Page</span>
1
</a>
I need to read the value '1' in my test. When I do a get text using css-selector .spf-link.current, it gets me "Page 1". I only need '1'. How do I exclude the text from the span tag.
You will need Javascript childNodes to get the text from the nodes.
The childNodes property returns a collection of a node's child nodes,
as a NodeList object.
The nodes in the collection are sorted as they appear in the source
code and can be accessed by index numbers. The index starts at 0.
WebElement element = driver.findElement(By
.cssSelector(".spf-link.current"));
String node_text=(String)((JavascriptExecutor)driver)
.executeScript("return arguments[0].childNodes[2].nodeValue",element);
This should give you the value 1 as node_text when you run the JavascriptExecutor. Other way is to split the text Page 1 on the basis of space. But, i would prefer childNodes.
Let me know if you have any queries.
Try the following:
//span[#class="pg-helpText" and contains(text(), 'Page')]/following-sibling::span/span
It is not normal to customize untagged text between tags.
I recommend you to change the value to your desired result:
<a class="spf-link current" href="/orders/returns?offset=0&limit=25">1</a>
...and when you want to show it in other place, do it as var ThePage = "Page " + [the page number]
Other solution is to include it into another tag as a div or as another span with a different class or id.
I am automating some things for work with Selenium and I am attempting to drag a drop a list in sorted order. So I have a list of the link names and am looping through so that for each item I can drag and drop the [drag] element to the top of the page.
I can't figure out how to grab that [drag] handle element using the link_text ("Audit: " in this case).
I've tried selecting the desired element with the link_text locator and then using .attribute("id") to get the id which should be the same for the link and for the [drag] handle. The problem is that I am getting a blank string for the id instead of "evaluation_422"
reversed.each do |form|
puts form
eval = browser.find_element(link_text: "#{form}")
id = eval.attribute("id")
puts id
#returns blank string
end
Any help is greatly appreciated! Below is the HTML I am trying to reference.
<li id="evaluation_422" class="evaluation">
<div class="right">
<span class="handle">[drag]</span>
<a href="/evaluations/422/edit">
<span>Audit: </span>
</a>
Okay so I finally solved this issue by grabbing the href of the link which happened to contain the number of the evaluation, so I was able to select the correct handle element using this:
reversed.each do |form|
href = browser.find_element(link_text: form).attribute("href")
eval_num = href.gsub("https://thisistheurl.com/evaluations/","").gsub("/edit","")
handle = browser.find_element(xpath: ".//*[#id='evaluation_#{eval_num}']/span")
top = browser.find_element(class_name: "evaluation")
browser.action.drag_and_drop(handle, top).perform
end
I have a simple HTML page with an Unordered list. Is it possible to have an input field where you could add more to the list and it would be saved after you submitted it. What I would like to add would be the content inside of an <li> tag as well as the <li> tags themselves.
Thanks,
Here is a jsfiddle with a demo of what I think you want to achieve: http://jsfiddle.net/mvJNq/25/
Note that I can not answer as to how you should do this on the server, as that depends on how your serverside code, database etc is set up. However, if all you want is to display it as HTML and not have it saved as the user navigates away, you won't need the Submit button at all - then you just need the "Add" functionality.
Yes, it is possible - no, it will not be pretty. Here is what you would do:
create your base form with any default list items/inputs
use jQuery/JavaScript to bind an event handler to a button that you click when you want to add another item (alternatively, you could skip this step and just have another item appear by default)
on your event (be it checking that all input boxes have user-entered text, or the click event in step two) add another list item using jQuery.append(...)
ensure that you have a hidden input field to be used as a "counter" to keep track of the total number of list items and increment the value of this counter each time you add a new list item (note: you may need to use the ParseInt() method, depending on how you design the code for this field)
the page that is receiving the form's inputs should first read the hidden field so that it knows how many items to add, and then you should loop through the items (for or while loop) to add them correctly
Note: I don't know what Server-Side language you are using to handle receiving the form so step 5 is a fairly generic and universally viable option
Sure, it's possible.
The complexity of this comes in when you want to "save" the items. If the user leaves the page and comes back later will that data be available? If so, you will need a database like mySQL or similar. The li tags can be stored as well, but why?
If you just need that information available in that session you can store in a JavaScript variable and have it loop through the variable and spit them out as <li>'s
If you did want to use an add button instead of submit:
$('#addButton').click(function(){
var savedContent = $('#input').val();
}
To create + insert the <li>you can use javascript to create the element and append it to the ul. If you have more than one ul change the index:
var content = document.createElement('li');
content.innerText = savedContent;
document.getElementsByTagName('ul')[0].appendChild(content);