I have been at this for hours and I cannot make any progress.
I do not know how to do the following, I am used to arrays and loops, not nokogiri objects.
I want to select the table element immediately after the h2 containing span with id == "filmography"
<h2><span id ="filmography>...
<table> # What I want to find
<tr>
<td>...
So far I have used
objects = page.xpath("//h2" | "//table")
to have an array of nokogiri objects and I test each for id == "Filmography" and would work with the next object, however the elements returned are not in order as they appear on the page they are in the order all h2's then all tables.
Could I somehow have all 'h2's and 'table's as element objects in the order they appear on the page, and test the child object 'span' for its id attribute?
All advice appreciated, as I am thoroughly stuck.
This looks like it should work:
page.xpath('h2//span[#id="filmography"]').first.next_element
Nokogiri supports CSS selectors, which make this easy:
doc.at('span#filmography table').to_html
=> "<table><tr>\n<td>...</td>\n </tr></table>"
doc.at('#filmography table').to_html
=> "<table><tr>\n<td>...</td>\n </tr></table>"
at returns the first matching node, using either a CSS or XPath selector.
The "NodeSet" equivalent is search, which returns a NodeSet, which is like an Array, but would force you to use first after it, which only really makes for a longer command:
doc.search('span#filmography table').first.to_html
doc.search('#filmography table').first.to_html
Because the span tag contains an id parameter, you're safe to use at and only look for #filmography, since IDs are unique in a page.
Related
I have a UI macro that fetches a list of records and displays them into a table above some form fields. I'm not using an embedded list because I want the table to read-only and so far, haven't found a way to make an embedded list read.
In my macro I have :
<g2:evaluate var="jvar_records" object="true" >
var gr = new GlideRecord(Tables.PTC);
gr.query();
gr;
</g2:evaluate>
<j2:while test="$[jvar_records.next()]">
<tr class="$[jvar_class]">
<td>$[jvar_records.getValue('arrival_date')]</td>
<td>$[jvar_records.getValue('departure_date')]</td>
<td>$[jvar_records.getDisplayValue('certifier')]</td>
<td>$[jvar_records.getDispalayValue('trip.depart_reason_code')]</td>
</tr>
</j2:while>
The field certifier and trip are Reference fields, that I want to get the dispaly value of. But they keep coming back as empty in the macro. It works in a background-script just fine.
If I just get the value jvar_records.getValue('certifier') it correctly gives me the sys_id.
What am I missing?
Am relatively certain that, outside of the <g2: evaluate> tag, Jelly is constrained to client side API. Client side GlideRecord doesn't have a getDisplayValue function.
What I would do is have your g2:evaluate actually loop through the records and build an array of normal JavaScript objects with just the values you will need, then return that array of objects as opposed to returning the GlideRecord object with query results.
I am trying to scrape dynamic content with Watir and I am stuck.
Basically, I know that I can use
browser.element(css: ".some_class").wait_until_present
in order to scrape only when "some_class" is loaded.
The problem is that it is only giving me the first element having this class name and I want all of them.
I also know I can use
browser.spans(css: ".some_class")
in order to collect ALL the classes having this name, the problem is that I can't combine it with "wait_until_present" (it gives me an error). And spans on his own is not working because the content is not loaded yet, the page is using javascript
Is there a way to combine both? That means waiting for the class_name to be loaded AND select all the elements matching this class name, not just the first one?
I've been stuck for ages...
Thanks a lot for your help
There currently isn't anything in Watir for waiting for a collection of elements (though I had been recently thinking about adding something). For now, you just have to manually wait for an element to appears and then get the collection.
The simplest one is to call both of your lines:
browser.element(css: ".some_class").wait_until_present
browser.spans(css: ".some_class")
If you wanted to one-liner it, you could use #tap:
browser.spans(css: ".some_class").tap { |c| c[0].wait_until_present }
#=> Watir::SpanCollection
Note that if you are just checking the class name, you might want to avoid writing the CSS-selector. Not only is it easier to read without it, it won't be as performant.
browser.spans(class: "some_class").tap { |c| c[0].wait_until_present }
I'm loading data using jQuery (AJAX), which is then being loaded into a table (so this takes place after page load).
In each table row there is a 'select' link allowing users to select a row from the table. I then need to grab the information in this row and put it into a form further down the page.
$('#selection_table').on('click', '.select_link', function() {
$('#booking_address').text = $(this).closest('.address').text();
$('#booking_rate').text = $(this).closest('.rate').val();
});
As I understand it, the 'closest' function traverses up the DOM tree so since my link is in the last cell of each row, it should get the elements 'address' and 'rate from the previous row (the classes are assigned to the correct cells).
I've tried debugging myself using quick and dirty 'alert($(this).closest(etc...' in many variations, but nothing seems to work.
Do I need to do something differently to target data that was loaded after the original page load? where am I going wrong?
You are making wrong assumptions about .closest() and how .text() works. Please make a habit of studying the documentation when in doubt, it gives clear descriptions and examples on how to use jQuery's features.
.closest() will traverse the parents of the given element, trying to match the selector you have provided it. If your .select_link is not "inside" .address, your code will not work.
Also, .text() is a method, not a property (in the semantical way, because methods are in fact properties in Javascript). x.text = 1; simply overrides the method on this element, which is not a good idea, you want to invoke the method: x.text(1);.
Something along these lines might work:
var t = $(this).closest('tr').find('.address').text();
$('#booking_address').text(t);
If #booking_address is a form element, use .val() on it instead.
If it does not work, please provide the HTML structure you are using (edit your question, use jsFiddle or a similar service) and I will help you. When asking questions like this, it is a good habit anyways to provide the relevant HTML structure.
You can try using parent() and find() functions and locate the data directly, the amount of parent() and find() methods depends on your HTML.
Ex. to get previous row data that would be
$('#selection_table').on('click', '.select_link', function(){
$('#booking_address').text = $(this).parent().parent().prev().find('.address').text();
});
Where parent stands for parent element (tr), then prev() as previous row and find finds the element.
Is there a demo of the code somewhere? Check when are you calling the code. It should be after the 'success' of AJAX call.
I am trying to test a list on a web page using Cucumber and Ruby.
The list changes (dependant on user input) basically, I want to grab all the item into an array - I then wan to ensure that the list is in alphabetical order. Ideas anybody
Use capybara's all method to find elements on page:
elements_array = page.all(:css, 'li')
See corresponding API docs.
Assuming you're using Capybara and CSS selectors, this will give you an array contains text of each element in the list:
list_items = page.all('li').collect(&:text)
If you're using RSpec you can confirm they are sorted with:
list_items.sort.should == list_items
(you might write a be_sorted RSpec matcher to make that cleaner).
How do I tell the Zend_Form that I want an element (and it's ID-label, etc) to use another ID value instead of the element's name?
I have several forms in a page. Some of them have repeated names. So as Zend_Form creates elements' IDs using names I end up with multiple elements with the same ID, which makes my (X)HTML document invalid.
What is the best solution to fix this, given that I really have to stick with using the same element names (they are a hash common to all forms and using the Zend_Form Hash Element is really out of question)?
Zend_Form_Element has a method called setAttribs that takes an array. You may be able to do something like $element->setAttribs(array('id' => "some_id"));
or you can do $element->setAttrib('id', 'some_id');
Thanks, Chris Gutierrez.
However, as I said, I needed to get ride of the default decorator generated IDs like -label. Wiht the $element->setAttribs() it is not possible, however.
So based on http://framework.zend.com/issues/browse/ZF-7125 I just did the following:
$element->clearDecorators();
$element->setAttrib('id', 'some_id');
$element->addDecorator("ViewHelper");
Whoever sees this: please note this was enough for what I needed. But may not be for you (the default settings has more than the viewHelper decorator).