Can not data bind to table using knockout - data-binding

//AJAX Webservice Call
ManualRegDiseaseData = $.parseJSON(rows.d);
var VM = new testView(ManualRegDiseaseData);
ko.applyBindings(VM);
var testView = function (DiseaseData) {
var self = this;
self.disease = ko.observableArray();
self.benefitData = ko.observableArray();
var sampleBenefit = [{ "Benefit": "Room", "Detail": "Ordinary", "Desc": "not herbal", "TotalDays": "2", "Remaining": "1000", "Claimed": "400", "Approved": "350", "Excess": "50" },
{ "Benefit": "Medicine", "Detail": "All", "Desc": "herbal", "TotalDays": "1", "Remaining": "2000", "Claimed": "800", "Approved": "600", "Excess": "100" }];
$.each(sampleBenefit, function (x, rowType) {
var obj = new BenefitObject();
obj.Benefit(rowType.Benefit);
obj.Detail(rowType.Detail);
obj.Desc(rowType.Desc);
obj.TotalDays(rowType.TotalDays);
obj.Remaining(rowType.Remaining);
obj.Claimed(rowType.Claimed);
obj.Approved(rowType.Approved);
obj.Excess(rowType.Excess);
self.benefitData.push(obj);
})
$.each(DiseaseData, function (x, rowType) {
var obj = new DiseaseObject();
obj.DiseaseCode(rowType.DiseaseCode);
obj.DiseaseName(rowType.DiseaseName);
self.disease.push(obj);
})
}
<table id="tblDisplayBenefit" class="">
<thead>
<tr>
<th>No.</th>
<th>Benefit </th>
<th>Detail </th>
<th>Description </th>
<th>Total Days </th>
<th>Remaining Inner Limit </th>
<th>Claimed </th>
<th>Approved </th>
<th>Excess </th>
<th>Reduce Max Limit </th>
</tr>
</thead>
<tbody data-bind="foreach: benefitData">
<tr>
<td data-bind="value: Benefit"></td>
<td data-bind="value: Detail"></td>
<td data-bind="value: Desc"></td>
<td data-bind="value: TotalDays"></td>
<td data-bind="value: Remaining"></td>
<td data-bind="value: Claimed"></td>
<td data-bind="value: Approved"></td>
<td data-bind="value: Excess"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="6" style="text-align: right">Total</td>
<td>Total Claimed</td>
<td>Total Approved</td>
<td>Total Excess</td>
</tr>
</tfoot>
</table>
Those are my JS snippet code and my html, the problem is, I can not data bind the sample JSON variable into my table. It seems I can not push my data into benefitData object.
I have been doing console.log the rowType, the Json data is readable through the console.log.
I dont know, this must be a simple data binding, yet I dont know where is the fault part.
I cant figure this out.
Thanks in advance for the suggestion!

Use text binding instead of value for text int the table cells:
<td data-bind="text: Benefit"></td>
<td data-bind="text: Detail"></td>
<td data-bind="text: Desc"></td>
<td data-bind="text: TotalDays"></td>
<td data-bind="text: Remaining"></td>
<td data-bind="text: Claimed"></td>
<td data-bind="text: Approved"></td>
<td data-bind="text: Excess"></td>
Js Fiddle
According to knockout documentation
The value binding links the associated DOM element’s value with a
property on your view model. This is typically useful with form
elements such as input, select and textarea.
In other words it works with form elements and makes two-way binding, so when you change the value knockout automatically updates your ViewModel.
On the other hand, text binding
Typically this is useful with elements like span or em that
traditionally display text, but technically you can use it with any
element.
So you should use text binding here, because <td> element has static content.

Related

#each helper to populate a table

I'm fairly new to meteor and I'm trying to iterate over a cursor using #each to populate a table. Here's my code:
<template name="choral">
<div class="container" style="padding-top: 25px">
<div class="table-responsive">
<form id="orderForm">
<table class="table table-borderless table-dark">
<thead class="thead-light">
<tr>
<th>Title:</th>
<th>See the Music:</th>
<th>Hear the Music:</th>
<th>Format:</th>
<th>Price (per copy):</th>
<th>Quantity:</th>
</tr>
</thead>
<tbody>
{{#each piece in pieces}}
<tr>
<td id="name">{{piece.name}}</td>
<td id="pdf">PDF</td>
<td id="audio">AUDIO</td>
<td id="format">FORMAT</td>
<td id="price">{{piece.score}}</td>
<td id="qty"><input type ="number" name ="quantity" min="5"></td>
</tr>
{{/each}}
</tbody>
<tfoot>
<tr>
<td colspan="5"></td>
<td><button class="button" type ="submit">Add to Cart</button></td>
</tr>
</tfoot>
</table>
</form>
</div>
</div>
my js.
Template.choral.helpers({
pieces: function(){
return choralm.find({});
}
});
I'm outputting a blank row between the #each tag. I publish the collection server side and subscribe. I'm just not sure where to look. Any ideas?
My publishment and subscription:
Meteor.publish('choralList', function() {
return choralm.find();
});
Template.choral.onCreated( function(){
Meteor.subscribe('choralList');
});
As far as I can see you are subscribing to your data but you are not "telling" your template, that the subscription is finished and it should redraw.
Therefore your template immediately renders while the subscription is ongoing and thus uses the yet empty collection data.
In order to inform your template that data has been updated you can use it's internal Tracker and store the information in a reactive data-source (for my example I use ReactiveDict instead of ReactiveVar).
import { ReactiveDict } from 'meteor/reactive-dict';
Template.choral.onCreated( function (){
// inside onCreated, this refers to the
// current template instance
const instance = this;
// let's attach a ReactiveDict to the instance
instance.state = new ReactiveDict();
// use the internal Tracker
instance.autorun(() => {
// subscribe and store a flag, once ready
const choralListSub = Meteor.subscribe('choralList');
if (choralListSub.ready()) {
instance.state.set('subscriptionComplete', true);
}
});
});
Next you add a helper, that returns the reactive value for 'subscriptionComplete':
Template.choral.helpers({
pieces(){
return choralm.find({});
},
subscriptionComplete() {
// we use 'state', our ReactiveDict,
// which we added as prop in onCreated
return Template.instance().state.get('subscriptionComplete');
}
});
And finally we let our template draw the data, once our subscription is complete. Until the subscription is complete (note the {{else}} block), we display a message about the loading status:
<template name="choral">
<div class="container" style="padding-top: 25px">
{{#if subscriptionComplete}}
<div class="table-responsive">
<form id="orderForm">
<table class="table table-borderless table-dark">
<thead class="thead-light">
<tr>
<th>Title:</th>
<th>See the Music:</th>
<th>Hear the Music:</th>
<th>Format:</th>
<th>Price (per copy):</th>
<th>Quantity:</th>
</tr>
</thead>
<tbody>
{{#each piece in pieces}}
<tr>
<td id="name">{{piece.name}}</td>
<td id="pdf">PDF</td>
<td id="audio">AUDIO</td>
<td id="format">FORMAT</td>
<td id="price">{{piece.score}}</td>
<td id="qty"><input type ="number" name ="quantity" min="5"></td>
</tr>
{{/each}}
</tbody>
<tfoot>
<tr>
<td colspan="5"></td>
<td><button class="button" type ="submit">Add to Cart</button></td>
</tr>
</tfoot>
</table>
</form>
</div>
{{else}}
<div>Loading template...</div>
{{/if}}
</div>
</template>
Related resources
TemplateInstance.autorun
http://blazejs.org/api/templates.html#Blaze-TemplateInstance-autorun
https://docs.meteor.com/api/tracker.html
Reactive stores
https://guide.meteor.com/data-loading.html#stores
Subscription readyness
https://guide.meteor.com/data-loading.html#readiness
Helpers
http://blazejs.org/guide/spacebars.html#Built-in-Block-Helpers

Checkbox not being rendered with correct gentelella css when added via javascript

I'm trying to add some rows data in a datatable, first via Pug and then later on via javascript.
I add the first rows getting data via controller call, and then adding it via pug parse:
<div class="x_content">
<table id="datatable-buttons" class="table table-striped table-bordered bulk_action">
<thead>
<tr>
<th>
<th>Aprovado</th>
</th>
<th>Nome</th>
<th>Email</th>
<th>Data de nascimento</th>
<th>Cidade</th>
<th>Gênero</th>
<th>Escolaridade</th>
<th>Instituição de ensino</th>
<th>Semestre</th>
<th>Token</th>
<th>Selection Status</th>
</tr>
</thead>
<tbody>
for candidate in candidates
- var formatedCandidate = candidateService.formatCandidateForDataTable(candidate, newTrueCheckbox, newFalseCheckbox);
<tr>
<td>
<th>
if formatedCandidate.isCandidateApproved
<input type="checkbox" id="check-all" class="flat" checked>
else
<input type="checkbox" id="check-all" class="flat">
</th>
</td>
<td>
= formatedCandidate.name
</td>
<td>
= formatedCandidate.email
</td>
<td>
= formatedCandidate.bornDate
</td>
<td>
= formatedCandidate.city
</td>
<td>
= formatedCandidate.gender
</td>
<td>
= formatedCandidate.educationLevel
</td>
<td>
= formatedCandidate.educationInstitution
</td>
<td>
= formatedCandidate.educationSemester
</td>
<td>
= formatedCandidate.token
</td>
<td>
= formatedCandidate.selectionStatus
</td>
</tr>
</tbody>
</table>
This way, it manages to render the checkbox with the right style:
Later on, I try to update the rows via a "reload" button, getting data via a get request and then adding rows via javascript:
$.get("candidates/getCandidatesForTable", function(candidatesArray){
candidateTable.clear().draw();
candidatesArray.forEach((candidate, index) => {
debugger;
if (candidate[1]) {
candidate[1] = `<th>
<input type="checkbox" id="check-all" class="flat" checked/>
</th>`;
} else {
candidate[1] = `<th>
<input type="checkbox" id="check-all" class="flat"/>
</th>`;
}
candidateTable.row.add(candidate).draw();
});
});
Although I inserted the HTML code via javascript using the same properties as it was added via pug, the checkbox was rendered different: it is rendered, but the css style is now gone:
How should I add the a checkbox via javascript and still get the correct css styling?

Can CSS rules be dynamically added to Sharepoint 2010 Web Part Controls?

It's possible to add HTML elements dynamically in a WebPart's CreateChildControls() method, like so:
protected override void CreateChildControls()
{
base.CreateChildControls();
. . .
HtmlGenericControl _breakingSpace = new HtmlGenericControl("br");
this.Controls.Add(_breakingSpace);
}
Is it possible to also add CSS rules programatically? For example, I want to make "labels" (LiteralControls) block elements so that their width value can be set. Is something like the following pseudocode possible?
CSSRule displayInlineBlock = new CSSRule("display: inline-block");
CSSRule width20em = new CSSRule("width: 20em");
reqDateStr.ApplyCSSRule(displayInlineBlock);
reqDateStr.ApplyCSSRule(width20em);
?
I've tried applying those CSS rules inline to the Literal Control itself like this:
LiteralControl reqDateStr = new LiteralControl("<span class=\"finaff-webform-field-label\" style=\"display: inline-block\"; width:200px\">Requester Date:</span>");
...but it doesn't work any differently than what I had before, which was:
LiteralControl reqDateStr = new LiteralControl("<span class=\"finaff-webform-field-label\">Requester Date:</span>");
You can see how the form looks here
UPDATE
In answer to ceej's inquiry as to what HTML is generated, here it is, straight from the browser's "Show Source" ("inline" is there, but seems to have no effect):
<h1>UCSC - Direct Payment Form</h1>
<table>
<tr>
<td colspan="4"><h2 class="finaff-webform-field-label">Section 1: Payment Information</h2></td>
<td colspan="2"><h2 class="finaff-webform-field-label">Section 2: Requester Information</h2></td>
</tr>
<tr>
<td><span class="finaff-webform-field-label" style="display: inline-block"; width:200px">Requester Date:</span></td>
<td><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl11" type="text" value="4/23/2015" class="finaff-webform-field-input" /></td>
<td><span class="finaff-webform-field-label">Payment Amount:</span></td>
<td><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl14" type="text" class="finaff-webform-field-input" /></td>
<td><span class="finaff-webform-field-label">Requester Name:</span></td>
<td><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl17" type="text" class="finaff-webform-field-input" /></td>
</tr>
<tr>
<td><span class="finaff-webform-field-label">Payee Name:</span></td>
<td colspan="3"><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl21" type="text" size="64" class="finaff-webform-field-input" /></td>
<td><span class="finaff-webform-field-label">Dept / Div Name:</span></td>
<td><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl24" type="text" class="finaff-webform-field-input" /></td>
</tr>
<tr>
<td><span class="finaff-webform-field-label">Remit Address:</span></td>
<td colspan="3"><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl28" type="text" size="64" class="finaff-webform-field-input" /></td>
<td><span class="finaff-webform-field-label">Phone:</span></td>
<td><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl31" type="text" class="finaff-webform-field-input" /></td>
</tr>
<tr height="2em">
<td><span class="finaff-webform-field-label"> OR</span></td>
</tr>
<tr>
<td><span class="finaff-webform-field-label">Mail Stop:</span></td>
<td colspan="3"><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl37" type="text" size="64" class="finaff-webform-field-input" /></td>
<td><span class="finaff-webform-field-label">Email:</span></td>
<td><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl40" type="text" class="finaff-webform-field-input" /></td>
</tr>
<tr>
<td><span class="finaff-webform-field-label">Last 4 Digits SSN or ITIN:</span></td>
<td><input name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl44" type="text" class="finaff-webform-field-input" /></td>
</tr>
<tr>
<td colspan="5"><input id="ctl00_ctl24_g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c_ctl47" type="checkbox" name="ctl00$ctl24$g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c$ctl47" /><label for="ctl00_ctl24_g_5f7ce2fb_5653_4cc9_b9b8_b00ee0d0910c_ctl47"><span class="finaff-webform-field-label">204 submitted or on file. <strong>NOTE:</strong> If not on file, complete a Payee_Setup_204</span></label></td>
</tr>
</table>
This should be possible. What is the generated HTML that is produced? Is the in-line style actually being output? Is the HTML malformed?
I think it might be as simple as having incorrectly specified the style in your line that applies the styles inline in the constructor of the LiteralControl. You are closing the style after inline-block - should this not be `style=\"display: inline-block; width:200px\? This would make the complete line
LiteralControl reqDateStr = new LiteralControl("<span class=\"finaff-webform-field-label\" style=\"display: inline-block; width:200px\">Requester Date:</span>");
You can certainly add dynamic controls within a web part and it should be done in the CreateChildControls method. Personally I would use a LiteralControl rather than an HtmlGenericControl for putting static text or mark up such as <br> on the page.
As for CSS and styling - most web controls have a CssClass property and a Style property. However, the control you have chosen (LiteralControl) does not. Have you considered using a Label control? This will generate a <span> and you can set the Style property. You would have something like
var reqDateStr = new Label
{
CssClass= "finaff-webform-field-label",
Text = "Requester Date:"
};
reqDateStr.Style.Add("display", "inline-block");
reqDateStr.Style.Add("width", "200px");
this.Controls.Add(reqDateStr);
You can even set an AssociatedControlId property, which will result in a <label for="textboxId"> being output. The value should be the Id of the input control, e.g. your text box. This might be desirable in your scenario.
Hope this helps...

Multiple foreach in Durandal

I am all new to Durandal and have been playing around with it for a few hours now. It seems very promising - but now I have run into a problem, I cannot figure out - and cannot find a solution with Google.
I have a view with three tables of data - creditCardLines, cashLines and drivingReimbursementLines. They fetch data from three different data sources - and the user can add new lines to cashLines and drivingReimbursementLines (left out the forms).
Problem: In the viewmodel, I can easily bind a list for data to the first foreach - but I cannot figure out how to bind data to the second and third.
In the activate function I make an ajax call to my server API to get the data for the first foreach - and then returns the promise, when this finishes. How do I get data for the second and third foreach here?
ViewModel:
define(function () {
var submit = function () {
this.displayName = 'Expenses';
this.creditCardLines = ko.observableArray();
var me = this;
this.activate = function () {
return $.get('/submit/GetCreditCardLines').then(function (creditCardLines) {
me.creditCardLines(creditCardLines.Data);
});
};
};
return submit;
});
View:
<section>
<h2 data-bind="html:displayName"></h2>
<h3>CreditCard lines</h3>
<table class="table">
<tbody data-bind="foreach: creditCardLines">
<tr>
<td class="date" data-bind="text: Date"></td>
<td data-bind="text: Description"></td>
<td data-bind="text: Amount"></td>
<td><input type="checkbox" data-bind="checked: ApprovedEmployee" /></td>
</tr>
</tbody>
</table>
<h3>Cash lines</h3>
<table class="table">
<tbody data-bind="foreach: cashLines">
<tr>
<td class="date" data-bind="text: Date"></td>
<td data-bind="text: Description"></td>
<td data-bind="text: Amount"></td>
</tr>
</tbody>
</table>
<!-- TODO: Generate form to add new lines -->
<h3>Driving reimbursement lines</h3>
<table class="table">
<tbody data-bind="foreach: drivingReimbursementLines">
<tr>
<td class="date" data-bind="text: Date"></td>
<td data-bind="text: Description"></td>
<td data-bind="text: Distance"></td>
<td data-bind="text: Rate"></td>
<td data-bind="text: Amount"></td>
</tr>
</tbody>
</table>
<!-- TODO: Generate form to add new lines -->
<!-- Approve and save all lines as a quote with lines -->
<input type="submit" value="Submit quote" />
</section>
This is how I've been dealing with multiple jQuery deferred calls in my view models:
return $.when(
$.get('/submit/GetCreditCardLines'),
$.get('/submit/GetCashLines'),
$.get('/submit/GetReimbursementLines'))
.then(function (creditCardLines, cashLines, reimbursementLines)
{
processCreditCardLines(creditCardLines);
processCashLines(cashLines);
processReimbursementLines(reimbursementLines);
})
.fail(function (status)
{
// Do whatever you need to if it fails
});
You don't need the process methods if you don't want them, but if you're doing anything complicated, I think it's neater to have them.
You should check out BreezeJS. It has an option to make a single Ajax call to pull multiple lookups.
Take a look at the BreezeJS docs for a detailed explanation: http://www.breezejs.com/documentation/lookup-lists

How can I select from only one table with Web::Scraper?

I want to extract the text only for heading Node Object Methods from a webpage. The specific HMTL part is as follows:
<h2>Node Object Properties</h2>
<p>The "DOM" column indicates in which DOM Level the property was introduced.</p>
<table class="reference">
<tr>
<th width="23%" align="left">Property</th>
<th width="71%" align="left">Description</th>
<th style="text-align:center;">DOM</th>
</tr>
<tr>
<td>attributes</td>
<td>Returns a collection of a node's attributes</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>baseURI</td>
<td>Returns the absolute base URI of a node</td>
<td style="text-align:center;">3</td>
</tr>
<tr>
<td>childNodes</td>
<td>Returns a NodeList of child nodes for a node</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>firstChild</td>
<td>Returns the first child of a node</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>lastChild</td>
<td>Returns the last child of a node</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>localName</td>
<td>Returns the local part of the name of a node</td>
<td style="text-align:center;">2</td>
</tr>
<tr>
<td>namespaceURI</td>
<td>Returns the namespace URI of a node</td>
<td style="text-align:center;">2</td>
</tr>
<tr>
<td>nextSibling</td>
<td>Returns the next node at the same node tree level</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>nodeName</td>
<td>Returns the name of a node, depending on its type</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>nodeType</td>
<td>Returns the type of a node</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>nodeValue</td>
<td>Sets or returns the value of a node, depending on its
type</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>ownerDocument</td>
<td>Returns the root element (document object) for a node</td>
<td style="text-align:center;">2</td>
</tr>
<tr>
<td>parentNode</td>
<td>Returns the parent node of a node</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>prefix</td>
<td>Sets or returns the namespace prefix of a node</td>
<td style="text-align:center;">2</td>
</tr>
<tr>
<td>previousSibling</td>
<td>Returns the previous node at the same node tree level</td>
<td style="text-align:center;">1</td>
</tr>
<tr>
<td>textContent</td>
<td>Sets or returns the textual content of a node and its
descendants</td>
<td style="text-align:center;">3</td>
</tr>
</table>
<h2>Node Object Methods</h2>
<p>The "DOM" column indicates in which DOM Level the method was introduced.</p>
<table class="reference">
<tr>
<th width="33%" align="left">Method</th>
<th width="61%" align="left">Description</th>
<th style="text-align:center;">DOM</th>
</tr>
<tr>
<td>appendChild()</td>
<td>Adds a new child node, to the specified node, as the last child node</td>
<td style="text-align:center;">1 </td>
</tr>
<tr>
<td>cloneNode()</td>
<td>Clones a node</td>
<td style="text-align:center;">1 </td>
</tr>
<tr>
<td>compareDocumentPosition()</td>
<td>Compares the document position of two nodes</td>
<td style="text-align:center;">1 </td>
</tr>
<tr>
<td>getFeature(<span class="parameter">feature</span>,<span class="parameter">version</span>)</td>
<td>Returns a DOM object which implements the specialized APIs
of the specified feature and version</td>
<td style="text-align:center;">3 </td>
</tr>
<tr>
<td>getUserData(<span class="parameter">key</span>)</td>
<td>Returns the object associated to a key on a this node. The
object must first have been set to this node by calling setUserData with the
same key</td>
<td style="text-align:center;">3 </td>
</tr>
<tr>
<td>hasAttributes()</td>
<td>Returns true if a node has any attributes, otherwise it
returns false</td>
<td style="text-align:center;">2 </td>
</tr>
<tr>
<td>hasChildNodes()</td>
<td>Returns true if a node has any child nodes, otherwise it
returns false</td>
<td style="text-align:center;">1 </td>
</tr>
<tr>
<td>insertBefore()</td>
<td>Inserts a new child node before a specified, existing, child node</td>
<td style="text-align:center;">1 </td>
</tr>
</table>
In Perl if I write the following:
my $data = scraper {
process "table.reference > tr > td > a", 'renners[]' => 'TEXT';
}
for my $i (0 .. $#{$res2->{renners}}) {
print $res2->{renners}[$i];
print "\n";
}
I get the text for all the tags i.e.:
attributes
baseURI
.
.
.
.
insertBefore()
wheras I need the text of tag <a> only for Node Object Methods i.e.:
appendChild()
.
.
.
insertBefore()
In short I want to print the NODE object methods only. What should I modify in the code?
Web::Scraper can use nth_of_type to choose the right table. There are two tables with the same class, so you can say table.reference:nth-of-type(2):
use v5.22;
use feature qw(postderef);
no warnings qw(experimental::postderef);
use Web::Scraper;
my $html = do { local $/; <DATA> };
my $methods = scraper {
process "table.reference:nth-of-type(2) > tr > td > a", 'renners[]' => 'TEXT';
};
my $res = $methods->scrape( $html );
say join "\n", $res->{renners}->#*;
And here's a Mojo::DOM:
use Mojo::DOM;
my $html = do { local $/; <DATA> };
my $dom = Mojo::DOM->new( $html );
say $dom
->find( 'table.reference:nth-of-type(2) > tr > td > a' )
->map( 'text' )
->join( "\n" );
I tried looking for a selector solution that could recognize the text in the h2, but my kung fu is weak here.
Web::Query provides an almost identical solution to the Mojo::DOM solution proposed by brian d foy.
use Web::Query;
my $html = do { local $/; <DATA> };
wq($html)
->find('table.reference:nth-of-type(2) > tr > td > a')
->each(sub {
my ($i, $e) = #_;
say $e->text();
});
However it looks like Mojo::DOM is the more robust library. For Web::Query to correctly match with its selector I had to edit the input provided in the question to add a root node surrounding all the other content.
__DATA__
<html>
...
</html>
You can use XPath to extract data from the very next table after the heading Node Object Methods, like so
use Web::Scraper;
my $html = do { local $/; <DATA> };
my $methods = scraper {
process '//h2[.="Node Object Methods"]/following-sibling::table[1]//tr/td[1]',
'renners[]' => 'TEXT';
};
my $res = $methods->scrape( $html );
say join "\n", #{ $res->{renners} };
The output will be
appendChild()
cloneNode()
compareDocumentPosition()
getFeature(feature,version)
getUserData(key)
hasAttributes()
hasChildNodes()
insertBefore()

Resources