Is it possible to create table using Repeater control which has rows wrapped in ItemContainer controls? Something along the line:
<table id="products">
<thead>
<tr>
<td>Name</td>
<td>Description</td>
<td>Type</td>
<td>Billing Periodicity</td>
<td>Average Life Time (in months)</td>
<td>Is default</td>
</tr>
</thead>
<tbody id="tableBody" data-win-control="WinJS.UI.Repeater" data-win-bind="winControl.data: products">
<tr data-win-control="WinJS.UI.ItemContainer">
<td data-win-bind="textContent: name"></td>
<td data-win-bind="textContent: description"></td>
<td data-win-bind="textContent: type"></td>
<td data-win-bind="textContent: costPeriodicity"></td>
<td data-win-bind="textContent: averageLifeTime"></td>
<td data-win-bind="textContent: isDefault"></td>
</tr>
</tbody>
</table>
Given example throws exception at runtime:
Unable to get property 'children' of undefined or null reference
I' d like to use ItemContainer's functionality to make table rows clickable. Is my approach to the issue invalid? Is ItemContainer control wrong to use in that scenario?
Side note - if I apply ItemContainer control to table cells (td), evertything runs smoothly (they behave like windows8 - like clickable objects).
You incorrectly declared data source for repeater, it should be declared as win-options not -win-bind, when you change it to:
<tbody data-win-control="WinJS.UI.Repeater" data-win-options="{data: products}">
it should work with no problems.
Related
I am attempting to scrape a link from a td cell adjacent to another td labeling the type or description of the link using puppeteer. There are no classes or id distinguishing these td cells other than the text content
<tr>
<td scope="row">1</td>
<td scope="row">10-Q</td>
<td scope="row">nflx-093018x10qxdoc.htm</td>
<td scope="row">10-Q</td>
<td scope="row">1339833</td>
</tr>
<tr class="blueRow">
<td scope="row">2</td>
<td scope="row">EXHIBIT 31.1</td>
<td scope="row">nflx311_q32018.htm</td>
<td scope="row">EX-31.1</td>
<td scope="row">14914</td>
</tr>
<tr>
<td scope="row">3</td>
<td scope="row">EXHIBIT 31.2</td>
<td scope="row">nflx312_q32018.htm</td>
<td scope="row">EX-31.2</td>
<td scope="row">14553</td>
</tr>
<tr class="blueRow">
<td scope="row">4</td>
<td scope="row">EXHIBIT 32.1</td>
<td scope="row">nflx321_q32018.htm</td>
<td scope="row">EX-32.1</td>
<td scope="row">12406</td>
</tr>
the link after td containing '10Q'
XPath expressions
This is where XPath expression are great:
//td[contains(., '10-Q')]/following-sibling::td[1]/a[1]
This XPath expression queries for a td element containing the text 10-Q. Then it will take the following td element and return the first link (a) inside. Alternatively, you could use //td[text()='10-Q']/ in the beginning, if you don't just want the element to contain the text, but to exactly match it.
Usage within puppeteer
To get the element with puppeteer, use the page.$x function. To extract information (like href) from the queried node, use page.evaluate.
Putting all together, the code looks like this:
const [linkHandle] = await page.$x("//td[contains(., '10-Q')]/following-sibling::td[1]/a[1]");
const address = await page.evaluate(link => link.href, linkHandle);
You can do this with vanila javascript,
// find all tr elements
[...document.querySelectorAll('tr')]
// check which one of them includes the word
.find(e=>e.innerText.includes('10-Q'))
// get the link inside
.querySelector('a')
With puppeteer $eval, this can be simplified,
page.$$eval('tr', eachTr=> eachTr.find(e=>e.innerText.includes('10-Q')).querySelector('a'))
Or page.evaluate,
page.evaluate(()=> {
// find all tr elements
return [...document.querySelectorAll('tr')]
// check which one of them includes the word
.find(e=>e.innerText.includes('10-Q'))
// get the link inside
.querySelector('a')
// do whatever you want to do with this
.href
})
Readable solution.
I have seen questions pertaining to accordion but not entirely to my specific need. My table is populated using spacebars, more specific a nested each loop like this:
<tbody>
{{#each piece in pieces}}
<tr id="{{piece._id}}" class="itemList table-warning">
<th class="name tText">{{piece.name}} {{piece._id}}</th>
<td class="pdf tText" style="text-align: center"><a class ="pdf" href="{{piece.pdf}}" target="_blank"><i class="fa fa-file-text-o" aria-hidden="true"></i></a></td>
<td class="audio tText" style="text-align: center"><a class="audio" href="{{piece.audio}}" target="_blank"><i class="fa fa-volume-up" aria-hidden="true"></i></a></td>
<td class="format tText">{{piece.instrumentation}}</td>
<th class="price tText" >${{piece.price}}</th>
<td><input class ="qty" type ="number" name ="quantity" value="0" min="0"></td>
</tr>
<!-- Row that is being clicked-->
<tr class="partsList">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<tr class="partList">
<td colspan="3"></td>
<td class="pname tText">{{piece.name}}: {{part.pname}}</td>
<td class="price tText">${{part.pprice}}</td>
<td><input class="qty" type="number" name="quantity" value="0" min="0"></td>
</tr>
{{/each}}
{{/each}}
</tbody>
I have a click function like so:
'click .partsList': function(e){
e.preventDefault();
$('.partList').nextUntil('tr.itemList').toggle();
}
The accordion function works, however it works with every instance of the each loop. i.e. every tr class ="partsList" will accordion at the same time on click.
To my understanding of the each loop, I can access the _id of a document using {{piece._id}}. If I set the table row id to equal that however, it only reads the _id of the FIRST document in the collection.
What I need is on click for the <tr class="partList"> to accordion based on _id. Or perhaps you would go about this a different way than bootstrap tables?
Please let me know if my question needs clarification.
You could filter the clicked .partslist using a data-* attribute. This causes jQuery to select only this specific items. Note that you need to attach the data-* attribute to the row that is clicked and to the rows that should collapse:
<tbody>
{{#each piece in pieces}}
...
<!-- Row that is being clicked-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partsList" data-id="{{piece._id}}">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partList" data-target="{{piece._id}}">
...
</tr>
{{/each}}
{{/each}}
</tbody>
'click .partsList': function(e, templateInstance){
e.preventDefault();
// get the data-id attribute of the clicked row
const targetId = templateInstance.$(e.currentTarget).data('id')
// skip if this row is not intended to toggle
if (!targetId) return
// toggle based on data-target attribute
templateInstance.$(`.partList[data-target="${targetId}"]`).nextUntil('tr.itemList').toggle();
}
I have a table with sorting columns and I need to assert if the numbers in the columns are descending when the column has an arrow down and ascending when the column has an arrow up. I tried it this way, but receive an error when I verify the expression
<tr> //they start from an ascending order so I have to click the arrow to change it
<td>click</td>
<td>//div/div/div/div/table/thead/tr/th[3]</td>
<td></td>
</tr>
<tr>
<td>pause</td>
<td>3000</td>
<td></td>
</tr>
<tr>
<td>verifyElementPresent</td>
<td>//div/div/div/div/table/thead/tr/th[contains(#class,'sorting_desc')]/label</td>
<td></td>
</tr>
<tr>
<td>storeText</td>
<td>//table[#id='ecmMaskList_3_1230628']/tbody/tr/td[3]</td>
<td>descendent</td>
</tr>
<tr>
<td>storeEval</td>
<td>var s = false; s = eval((storedVars['descendent']) >0);</td>
<td>s</td>
</tr>
<tr>
<td>verifyExpression</td>
<td>${s} </td>
<td></td>
</tr>
I tried to set S to true and got the error : [error] Actual value 'true ' did not match ''. The same when it´s on false.
Does anyone know how I can store the value of the last row and then check if it´s the right one when the arrow id down? My values are dynamic, and this is why I thought it would be more flexible to just say >0, since when they are ascending they always start from 0.
Any help is much appreciated
Never mind, I found the solution here https://groups.google.com/forum/#!topic/selenium-users/dzQWVAyDLH4
.
I just deleted my storeVal and verifyExpresion commands and replaced them with verifyVal | storedVars['descendent'] > 0. That did the trick
I'm trying to dynamically update a HTML table via Comet. I've got something like the following:
class EventsComet extends CometClient[Event] {
def server = Event
def render = {
println("Binding on: " + defaultHtml)
data.flatMap( event =>
bind("event", "name" -> event.name.toString, "date" -> event.startDate.toString)
)
}
}
And:
<lift:comet type = "EventsComet">
<table>
<thead>
<tr>
<th>Name</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr>
<td><event:name />Test Name</td>
<td><event:date />Oct. 25, 2012</td>
</tr>
</tbody>
</table>
</lift:comet>
This prints out the entire table over and over again, one for each event rendered by EventsComet. The println statement outputs the entire table node.
So I tried variations:
<table>
<thead>
<tr>
<th>Race</th>
<th>Track</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<lift:comet type = "EventsComet">
<tr>
<td><event:name />Test Name</td>
<td><event:date />Oct. 25, 2012</td>
</tr>
</lift:comet>
</tbody>
</table>
As expected, the HTML5 parser strips out the [lift:comet] tags and no binding occurs.
So I tried switching the rows to:
<tr lift:comet = "EventsComet">
<td><event:name />Test Name</td>
<td><event:date />Oct. 25, 2012</td>
</tr>
...as is shown in a snippet example here, but with this syntax my CometClient is not being instantiated at all.
Can anyone advise on the proper syntax?
EventsComet itself works fine; it can keep lists of events up to date without problem. I only run into issue using tables (and presumably other highly-nested structures I've not tried yet?).
Thank you. This is all rather frustrating for such a simple problem, and makes me want to just start implementing my templates in a strongly-typed templating language instead of using bindings.
The proper syntax seems to be:
<tr class="lift:comet?type=EventsComet">
<td><event:name />Test Name</td>
<td><event:date />Oct. 25, 2012</td>
</tr>
From this thread:
https://groups.google.com/forum/?fromgroups=#!topic/liftweb/NUDU1_7PwmM
Sometimes I'm getting duplicate rows (inserted above the table header at that), but I'd imagine this is related to my comet actor itself.
I have a HTML Table which in which i want to manipulate using JQuery
Table:
<tr><td>----Parent One
<Table id="ChildID" >----Child One
First TR1<TR>
<TD><div class=ExternalClass00FA6D5A488C4B2582667D6D8DF15F79>Value 1</div></TD>
<TD class="ms-disc-bordered-noleft">Value 2</TD>
<TD class="ms-disc-bordered-noleft">Value 3</TD>
<TD class="ms-disc-bordered-noleft">
Value 4
</TD></TR>
..........
Second TR2<TR>
<TD><div class=ExternalClass00FA6D5A488C4B2582667D6D8DF15F79>Value 1</div></TD>
<TD class="ms-disc-bordered-noleft">Value 2</TD>
<TD class="ms-disc-bordered-noleft">Value 3</TD>
<TD class="ms-disc-bordered-noleft">
Value 4
</TD></TR>
........and so on
</TABLE>---Child One
</td></tr></TABLE>---Parent One
i am trying to pick "Value 4" the last having string "FolderCTID" in href and insertBefore "Value 1" with div class that starts with "ExternalClass".
I want to insertBefore the each element in the row to the corresponding element in the same row
I am using following code:
$('a[href*="FolderCTID"]').insertBefore($('div[class^="ExternalClass"]'));
But it is inserting all the elements for every row....i think i should make something to specify the entities and loop around** each end of the entity...
Please help me on this
then you may want this,
try this , and let me know,
$('a[href*="FolderCTID"]').each(
function(){
$(this).parents('tr').find('div[class^="ExternalClass"]').before(this);
}
);
$('a[href*="FolderCTID"]').each(
function(){
$(this).siblings(':first').insertBefore(this);
}
)
may this help.