Xpages - Repeat control with SSJS - xpages

I am building a history tracker, that continues to work with legacy code in non xpage apps. For xpage apps, I simply call the below function. This works fine:
function AddObjectivesHistoryItem(doc, dt, action, username){
var ArrDocHistory:array = doc.getItemValueArray("History");
if(ArrDocHistory.length < 1){
// This should always return an object as it is created when an objectives
document is first
// created but do this check to be safe and create an array if for some
reason it doesnt exist
ArrDocHistory = [dt+"|"+action+"|"+username];
}else{
// append new value to the array
ArrDocHistory.push(dt+"|"+action+"|"+username);
}
return ArrDocHistory;
}
The issue I have, is splitting and displaying the 3 data types. I have a 3 computed fields, which is date, username and status in a table within a repeat control, code, including first column and computed field below, this should be all values prior to the first pipe delimiter for each multi value.:
<table class="table table-hover">
<thead>
<tr>
<th>Date</th>
<th>Action</th>
<th>Username</th>
</tr>
</thead>
</table>
<table class="table table-hover">
<xp:repeat value="#{document1.History}" var="row">
<tbody>
<tr>
<td>
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:var ArrDocHistory:array = document1.getItemValueArray("History");
print ("LEN: " + ArrDocHistory.length);
var test:array = new Array();
for (i=0; i<ArrDocHistory.length; i++){
var split = ArrDocHistory[i].split("|");
test.push(split[0]);
//return split[i]
}
return test}]]></xp:this.value>
</xp:text></td>
However, what this displays is all the values, in a line, seperated with a comma. For example, "value1, value2, value3" where as I expected, and need, and can't seem to be able to get each value to display on its own, in a new row. For example:
value1
value2
value3
I know I'm doing something silly, but am currently suffering from tunnel vision so any pointers greatly appreciated.

You are returning Test, to a single computed field. Change your repeat to return the array 'test', (it gets the value like you do, than split it to the array you have). Than the computed field returns one of the elements of test.
Put a page break after the computed field to see it the way you want.

Related

Return value from an HTML class/scope?

I have a webpage that I'm trying to return a value from, however I can't find the right way to grab it with Selenium.
Here's the relevant HTML part:
<table class="table table-striped">
<tbody>
<tr class="hidden-sm hidden-xs">
<th scope="row"><a style="cursor: pointer"
onClick="document.formShip.P_IMO.value='9526942';document.formShip.submit();">
9526942</a>
</th>
I'm trying to get 9526942.
I've tried:
imo = driver.find_element_by_xpath("//*[contains(text(), 'document.formShip.P_IMO.value')]")
and looked around here, but don't know what element this is. I tried looking for the class hidden-sm hidden-xs, to no avail:
imo = driver.find_element_by_class_name('hidden-sm hidden-xs')
if you want to get the text you need to use .text. The .text method can be used with a webelement which some text in that.
in your first example which you tried, you are passing a different parameter with text(). usually when you use text(), you need to pass the value which is there between closing and open tags (the text which you see on the screen)
you simply try this.
imo = driver.find_element_by_xpath(.//tr[#class='hidden-sm hidden-xs']).text

Loop in table with Watir

Stuck with watir trying to create a loop to click in all the links included in a table. Currently the table has this format:
<table id="test">
<tbody><tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Link</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>http://facebook.com</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>http://google.com</td>
</tr>
</tbody></table>
And my current attempt looks like:
browser.table(:id => "test").rows do |tr|
tr.each do |td|
td.links.click
end
end
This code above does nothing in the browser & neither returns something in the terminal (no errors, no outputs).
Also tried a different approach using columns:
columns = browser.table(:id => "test").strings.transpose
browser.columns.each do |t|
t.click
browser.back
end
That outputs this error: jsfiddle.rb:24:in <main>': undefined methodcolumns' for # (NoMethodError)
The newer versions of Watir, version 6.0, automatically attempts to relocate stale elements. As a result, as long as the initial page does not change each time you reload it, you no longer need to save some sort of reference data before clicking the links.
It simply becomes:
my_table = browser.table(:id, 'test')
my_table.links.each do |link|
link.click
browser.back
end
This should work to click on each link in the table:
my_table = browser.table(:id, 'test')
table_links = my_table.links.map(&:text)
table_links.each do |link_text|
my_table.link(:text, link_text).click
browser.back
end
Largely based on Justin Ko's answer here.

Adding new xElement after ALL found Descendants

I have an xDocument with multiple various xElements.
I can successfully find a specific xElement by searching via it's xAttributes & then Add a new xElement after it using the code below:
xDocument.Descendants("td").LastOrDefault(e => ((string)e.Attribute("ID")) == "3").Add(new XElement("b", "Just a test."));
The problem is that I wish to Add this new xElement after all found instances of the Descendants, not just LastOrDefault or FirstOrDefault.
My xDocument is created dynamically & there is no way before hand to know how many 'td' xElements with 'ID' = '3' that there are going to be.
Any help would be appreciated.
Thanks
ADDED CODE AS REQUESTED
<html> .... etc....
<body>
<table>
<tr>
<td>Image</td>
<td>Description</td>
<td>Date</td>
</tr>
<tr>
<td ID="1">*.jpg</td>
<td ID="2">some image</td>
<td ID="3">01/01/1901</td> <--CHANGING THIS PART OF CODE-->
<--THIS TABLE ROW REPEATS AN UNDETERMINED NUMBER
OF TIMES RELATING TO THE NUMBER OF FILES CONTAINED IN WHATEVER DIRECTORY IS BEING SEARCHED USING A FOREACH LOOP IN ANOTHER PART OF
THE CODE-->
</tr>
</table>
</body>
</html>
So I am trying to add a tag between the <td> with ID = 3.
This <b> tag also contains a string variable i.e.
new xElement("b", DateTaken)
& needs to be created at runtime and not hard coded as it relates to each loaded image at the start of the table row.
So I am trying to add this <b> tag to every occurrence of <td> with ID=3 & not just the first or the last.
Hope this extra info helps.

Tal condition string contains

Trying to change table data based on conditions.
<td tal:condition="string.stringname != '-shadow'"><strong>Stuff</strong></td>
<td tal:condition="string.stringname == '-shadow'"><em>Stuff</em></td>
string.stringname may have -shadow at the very end of the string, and it may not. I'm trying to get tal to display either table data based on whether one or the other is true. The page will need to display both cases, if both cases are met of course. tal:condition doesnt seem to be able to search if a string contains something, only if something is explicitly true or false.
Use str.endswith() to test if a string ends with a given substring:
<td tal:condition="not string.stringname.endswith('-shadow')"><strong>Stuff</strong></td>
<td tal:condition="string.stringname.endswith('-shadow')"><em>Stuff</em></td>

Alternating row colors in ExpressionEngine table

I have some code that creates a table that alternates row colors based on the row value of the entry.
<table class="authorList" cellspacing="0">
{exp:channel:entries channel="team" disable="categories|member_data|pagination" orderby="team-last-name" sort="asc"}
{if team-not-with-us != 'y'}
<tr class="{switch="odd|even"} authorInfo">
<th class="authorName">
{if team-bio != ''}<a href="{site_url}about/the-team/{url_title}">{/if}
{title}
{if team-bio != ''}</a>{/if}
</th>
<td class="position">{team-position}</td>
</tr>
{/if}
{/exp:channel:entries}
</table>
The problem is when I delete an entry, I end up having two odd or two even numbers in a row, leaving me with two like-colored rows side by side.
While the switch function is convenient, it is referencing the row count within the database. I don't believe I can apply it to reference the actual row count in the if statement which would solve my problem. (Correct me if I'm wrong.)
I know how to make this change with php:
<?php $oddevenrow = 0; ?>
{if team-not-with-us != 'y'}
<?php $oddevenrow++; ?>
<?php ($oddeven = ($oddevenrow % 2 ? 'odd' : 'even')); ?>
<tr class="<?php echo $oddeven; ?> authorInfo">
But I'm not allowed to turn PHP on in the EE install.
Is there something similar I can do in EE?
Thanks!
You're looking for the switch tag.
{switch="odd|even"}
But it looks like you already knew that. It looks like you're requiring the variable team-not-with-us to != 'y'. Because you're doing that validation after results have been returned you'll end of with multiple odd or even rows next to each other. The easy way to avoid this is to use the channel:entries search param. Example: search:team-not-with-us="not y"
<table class="authorList" cellspacing="0">
{exp:channel:entries
channel="team"
disable="categories|member_data|pagination"
orderby="team-last-name"
sort="asc"
search:team-not-with-us="not y"
}
<tr class="{switch="odd|even"} authorInfo">
<th class="authorName">
{if team-bio != ''}<a href="{site_url}about/the-team/{url_title}">{/if}
{title}
{if team-bio != ''}</a>{/if}
</th>
<td class="position">{team-position}</td>
</tr>
{/exp:channel:entries}
</table>
You might want to try asking the EE peeps at https://expressionengine.stackexchange.com/ The {count} tag should work. That simply counts every entry that (in your case) is in the Team Channel and is not Y in your "team-not-with-us" field group, which I'm assuming is a switch or a select box or something.
What does your outputted code look like?

Resources