Element refreshing in #FindBy with Selenium and java - pageobjects

We have HTML code that has elements which can be expanded or collapsed (depending on what they currently are). They can be expanded only one level. It looks sort of like this
<a href = "#" title = "Expand" id = ...>Row 1 </a>
<a href = "#" title = "Expand" id = ...>Row 2 </a>
<a href = "#" title = "Collapse" id = ...>Row 3 </a>
<a href = "#" id = ...>Subrow 3.1 </a>
<a href = "#" id = ...>Subrow 3.2 </a>
<a href = "#" title = "Expand" id = ...>Row 4 </a>
<a href = "#" title = "Collaps" id = ...>Row 5 </a>
<a href = "#" id = ...>Subrow 5.1 </a>
<a href = "#" id = ...>Subrow 5.2 </a>
There are many more, and it is a bit more complicated than this but you get the picture. Using page object I made a list
#FindBy(xpath = "//a[contains(#title, 'Expand') or contains(#title, 'Collapse')]")
private List<WebElement> expandCollapseElements
And then a method to expand them for instance:
public void expand() {
for (WebElement ele : expndCollapseElements) {
if (ele.getAttribute("title").equals("Expand")) {
ele.click();
}
}
}
In the actual code I also tried waiting until the title changed so I know it worked. Anyway, the problem is that once I expand an element, all the elements underneath apparently become stale. I know when you use #FindBy it refinds the element each time. But I am wondering when the element is refreshed. It seems like it is just done once at the beginning of the loop. Is that true? When is the element list refreshed? And is there a better way to do this? I tried making a new list containing the list and reversing it which kind of worked but not really. The matter is further complicated by the fact that these rows are displayed in its own scrollable div where you need to sacroll to see some of the elements. So any thoughts?

Suggestion: That's the difference between foreach and for.
Try to use "For loop" only.

Related

iMacros - How do I TAG URL with unique surrounding html?

I need to extract "https://www.somesite.com/Some.Name.123" from the code below.
That code segment is repeated many times, and I need the URLs ..Some.Name.X.
There are other code segments between each of the ones I'm interested in, with very different surrounding html. I don't need the ..Some.Name.x URLs in those other segments.
The following is unique to what URLs I need: "<a class="-cx-PRIVATE-uiImageBlock__image"
<div class="clearfix pvm">
<a class="-cx-PRIVATE-uiImageBlock__image -cx-PRIVATE-uiImageBlock__largeImage lfloat"
aria-hidden="true" tabindex="-1" href="https://www.somesite.com/Some.Name.123">
I don't know how to tag that preceding HTML with iMacros, or how to do that with jQuery as the structure will a bit different each time, but you could to this.
Save the web pages with iMacros. Write a program (c, etc.) to read each of the saved files and write the URLs that follow "cx-PRIVATE-uiImageBlock__image" to a file. Add that list of URLs to an iMacro, or have iMacros read the file, and then process each URL from iMacros.
You need to use some scripting.
My answer makes use of jQuery
var listoflinks = []; //array containing your links
$('a[href*="somesite.com"]').each(function () { // for each link that contains somesite.com in href
var j = $(this).attr('href'); //put the whole href in a variable
listoflinks.push(j); // put all values in an array
});
you'll end up with an array that contains all the href values you're looking for.
If you want to see an example and/or you want to play around with the script you can go here:
http://jsfiddle.net/flish/rESjg/
Edited
Your code is still not clear enough, but hopefully this may help
<a class="sibling a" href="link">sibling a</a><br />
<div class="sibling div"><br />
<a class="child a" href="start-with-link/correct-link">Child a</a><br />
</div><br />
Above is the markup I've used. What this means is that I have considered that you have the following elements:
a // with a sibking div
div // with a child a
a // and all of them have appropriate classes
For this markup you can use the following code (jQuery, of course)
var listoflinks = []; //array containing your links
$('a[class="sibling a"]').siblings('div[class="sibling div"]').children('a[class="child a"]').each(function () {
if ((($(this).attr("href")).substring(0,15))=="start-with-link"){
var i = $(this).attr("href");
listoflinks.push(i);
}
});
View detailed example at http://jsfiddle.net/flish/HMXDk/
Be that as it may, you can add more sibling and children elements in case you have other html entities you forgot to mention
<a class="-cx-PRIVATE-uiImageBlock__image" ------------------ <div class="clearfix pvm"> <a class="-cx-PRIVATE-uiImageBlock__image -cx-PRIVATE-uiImageBlock__largeImage lfloat" aria-hidden="true" tabindex="-1" href="somesite.com/some.name.123">
For example, what means ------------------ in your code above?

Typo3 FCE refer filetype of field uri inside class attribute

xI would like to insert the filetype of the inserted file into a a href class:
a href class"icon-filetype-"
i have something like this now:
10 = TEXT
10.field = field_uri
10.wrap = icon-filetype-|
but than i get the hole url inside the class :D
thans for time
(btw, i used these sites as reference, so maybe i give you a start with it:
Typo3 FCE refer a field inside a container field
and http://typo3.org/extension-manuals/rs_linklayout/1.3.1/view/1/3/ )
this is the mapping i use:
<ul class="section-container">
<li>
<a class="" href="#" target="_blank"><span>Item 1</span><span class="size"></span></a>
</li>
</ul>
did not test this code:
10 = TEXT
10.field = field_uri
10.split {
token = .
# if you get an different part or some parts added, this optionsplit is wrong
cObjNum = |*||*| 1 || 2
# render nothing means remove this part
1 = TEXT
1.value =
# render only the filetype
2 = TEXT
2.current = 1
}
10.wrap = icon-filetype-|

XHTML DOM - How to split a tag on IE?

Let's assume I have a part of an html document containing the following code (basic structure) :
<p>
<span class="1">This is my first content</span>
<span class="2">This is my second content</span>
</p>
I'd like to allow the user to select a part of the text and apply a new class to it.
Let's say the user selects "is my first" in the first span, and applies class "3".
I'd like to have the following result :
<p>
<span class="1">This </span>
<span class="3">is my first</span>
<span class="1"> content</span>
<span class="2">This is my second content</span>
</p>
I've managed to do this on Firefox by using the execCommand "InsertHTML", but I can't find a way to do this in IE (before IE9)
The only result I have is a nested span element, like below :
<p>
<span class="1">This <span class="3">is my first</span> content</span>
<span class="2">This is my second content</span>
</p>
Do you have any idea of how I could achieve this ?
Any help would be much appreciated !
By the way, if this looks too simple to you, how would you handle the case of a user selecting a portion of text that spans over 2 or more spans ? over 2 or more ps ?
you can get the selected segment using selection range. I would recommend using rangy, which is a cross browser range module.
Here's some "untested" code using jQuery and Rangy to hopefully point you in the right direction, for your first case:
var splitTag=function(class){
var sel = rangy.getSelection();
// this is your selection, in your example "is my first"
var r0 = sel.getRangeAt(0);
// create a new range
var r1 = rangy.createRange();
// this would be your <p>
var p = r0.endContainer.parentNode;
// set the new range to start at the end of your phrase and to end at <p>
r1.setStart(r0.endContainer, r0.endOffset);
r1.setEnd(p, p.length-1);
// extract the content of your first selection "is my first"
var r0Txt=r0.toHtml();
// make it into an span, with class set to "class argument" which would be 3
var newContent=$("<span/>").html(r0Txt).attr("class", class);
r0.deleteContents();
// insert the new node before r1
r1.insertNode(newContent[0]);
sel.removeAllRanges();
}
this should get you the result for your first situation. for selections across multiple paragraphs, here's a modification of the code:
var splitTag=function(class){
var sel = rangy.getSelection();
var r0 = sel.getRangeAt(0);
var r1 = rangy.createRange();
var p = r0.endContainer.parentNode;
r1.setStart(r0.endContainer, r0.endOffset);
r1.setEnd(p, p.length-1);
var r0Txt=r0.toHtml();
if(!r0.startContainer===r0.endContainer){
// the selection spans multiple dom's
// set the class of all spans in the highlight to 3
var newContent=$(r0Txt).find("span").attr("class",class);
}else{
var newContent=$("<span/>").html(r0Txt).attr("class", class);
}
r0.deleteContents();
r1.insertNode(newContent[0]);
sel.removeAllRanges();
}

How to select something with its tags? And 1 more question about tag ignoring

i have to parse google and other search systems search results, and i want to take something with tag, for example i have:
<span class="tl">
<h3 class="r">
<a class="l noline" onmousedown="return rwt(this,'','','','1','AFQjCNE3QDnLsIkujVElxf1vT7LocQ-YYw','','0CCQQFjAA')" target="_blank" href="http://l2.ru/">
<em>Lineage</em>
2. Oficial servers l2, la2,
<em>lineage</em>
2.
</a>
</h3>
<button class="vspib"></button>
</span>
and i want to take all inner content of tag, including , like
<a class="l noline" onmousedown="return rwt(this,'','','','1','AFQjCNE3QDnLsIkujVElxf1vT7LocQ-YYw','','0CCQQFjAA')" target="_blank" href="http://l2.ru/">
<em>Lineage</em>
2. Oficial servers l2, la2,
<em>lineage</em>
2.
</a>
something like
TFHpple *googleParser = [[TFHpple alloc] initWithHTMLData:googleData];
NSArray *linksWithItsNames = [googleParser search:#"//span[#class='tl'/h3[#class='r']"];
TFHppleElement *googleLinkWithItsName = [linksWithItsNames objectAtIndex:0];
NSString *googleFirstLink = [googleLinkWithItsName content];
[myWebView loadHTMLString:googleFirstLink baseURL:requestURL];
And in the end i want to show in my WebView link with its name, that contains in (so i want to ignore all b, em, br etc. tags inside ), and with its #href.
I just saw 1 question - Ignoring / skipping known or all subordinated tags with XPath but don't understand how should i ignore inner tags and how can i take inner text with its tags as a string.
Thank you
TouchXML: an xml parser that will let you access any tag you want.

Dojo events: getting it to work with dynamically added DOM elements

I have a method of a class as follows:
add_file: function(name, id, is_new){
// HTML: <div class="icon mime zip">name.zip <a>x</a></div>
var components = name.split('.');
var extension = components[components.length-1];
this.container.innerHTML += "<div id='"+id+"' class='icon mime "+extension+"'>"+name+" <a id='remove-"+id+"' href='#remove'>x</a></div>";
// Add event to a tag
dojo.connect(dojo.byId('remove-'+id), 'onclick', function(ev){
// here i am
});
},
All is working well, until I run this method more than once. The first time the event is registered correctly, and clicking the 'x' will run the "here i am" function. However, once I add more than one node (and yes, the ID is different), the event is registered to the last node, but removed from any previous ones.
In affect I have this:
<div id="field[photos]-filelist">
<div id="file1" class="icon mime jpg">file1.jpg <a id="remove-file1" href="#remove">x</a></div>
<div id="file2" class="icon mime jpg">file2.jpg <a id="remove-file2" href="#remove">x</a></div>
</div>
...and the remove link only works for the last node (remove-file2 in this case).
The problem is you are using the innerHTML +=
That is going to take the existing html, convert it to plain markup, and then completely create new nodes from the markup. In the process, all of the nodes with events get replaced with nodes that look exactly the same but are not connected to anything.
The correct way to do this is to use dojo.place(newNodeOrHTML, refNode, positionString)
var myNewHTML = "<div id='"+id+"' class='icon mime "+extension+"'>"+name+" <a id='remove-"+id+"' href='#remove'>x</a></div>"
//This won't work as is breaks all the connections between nodes and events
this.container.innerHTML += myNewHTML;
//This will work because it uses proper dom manipulation techniques
dojo.place(myNewHTML, this.container, 'last');