I have this HTML
<p>
<!-- templateDebugMode: start template: articleLists/indexHeadline.html -->
<!-- templateDebugMode: start template: articleLists/indexHeadline.html - templateCell: articleRow -->
December 18th 2017 : News item 1<br>
<!-- /templateDebugMode: end template: articleLists/indexHeadline.html - templateCell: articleRow -->
<!-- templateDebugMode: start template: articleLists/indexHeadline.html - templateCell: articleRow -->
December 18th 2017 : News item 2<br>
<!-- /templateDebugMode: end template: articleLists/indexHeadline.html - templateCell: articleRow -->
<!-- templateDebugMode: start template: articleLists/indexHeadline.html - templateCell: articleRow -->
November 29th 2017 : News item 3<br>
<!-- /templateDebugMode: end template: articleLists/indexHeadline.html - templateCell: articleRow -->
<!-- /templateDebugMode: end template: articleLists/indexHeadline.html -->
</p>
I tried splitting on the <br> but using this answer found the comments to be reliable:
//*[preceding-sibling::comment()[1][contains(., 'start template: articleLists/indexHeadline.html')]]
[following-sibling::comment()[1][contains(., 'end template: articleLists/indexHeadline.html')]]
This gets me the links (which I can get with a simpler expression) but not the date (text) preceding it. How can I extract this too for each entry? The data I'm looking to collect for each news item is:
Date
Link
Link text
You can get required output with below XPath expressions
//p/text()[string-length(.)>0] # for date
//p/a/#href # for link
//p/a/text() # for link text
If you still want to use those comments in XPath:
//p/text()[preceding-sibling::comment()[1][contains(., 'start template: articleLists/indexHeadline.html')]]
[following-sibling::comment()[1][contains(., 'end template: articleLists/indexHeadline.html')]] # for date
//p/a[preceding-sibling::comment()[1][contains(., 'start template: articleLists/indexHeadline.html')]]
[following-sibling::comment()[1][contains(., 'end template: articleLists/indexHeadline.html')]]/#href # for links
//p/a[preceding-sibling::comment()[1][contains(., 'start template: articleLists/indexHeadline.html')]]
[following-sibling::comment()[1][contains(., 'end template: articleLists/indexHeadline.html')]]/text() # for link text
Related
Let's have this xpath:
<div>
<!-- ... -->
<div> <!--I want this element-->
<!-- ... -->
<sometag>
<a></a>
</sometag>
<!-- ... -->
</div>
<!-- ... -->
</div>
I have this xpath //div[.//a], which selects both divs.
How to write the xpath which selects the nearest div of his child(a). Without link it by that sometag.
You can try to locate the a elements first and then select nearest ancestor div from there:
//a/ancestor::div[1]
xpathfiddle demo
I have page front matter with multiple levels. My page front matter looks like this:
grids:
- template: section
background_image: "/uploads/2018/05/01/q-mark.png"
rows:
- template: row
stack-columns: tablet-s
cols:
- template: column
title: "Column-1 Title"
- template: section
background_image: "/uploads/2018/05/01/lk.png"
rows:
- template: row
stack-columns: tablet-s
cols:
- template: column
title: "Column-2 Title"
rows:
- template: row
stack-columns: tablet-l
cols:
- template: column
title: "Column-3 Title"
I can display the first-level template name for both of my grids:
{{ range .Params.grids }}
{{ .template }}
{{ end }}
How can I return the template name of rows and cols within the loop?
I figured it out. You can use a nested range to access parameters with multiple levels:
{{ range .Params.grids }}
<p>Grid template name: {{ .template }}</p>
{{ range .rows }}
<p><strong>row template name: </strong>{{ .template }}</p>
{{ range .cols }}
<p><em>col template name:</em> {{ .template }}</p>
{{ end }}
{{ end }}
{{ end }}
This displays:
Grid template name: section
row template name: row
col template name: column
Grid template name: section
row template name: row
col template name: column
For example we have codes like :
<!-- ko ifnot: product().bannerImageVideoLink -->
<img data-bind="attr: {src: product().largeImageURLs()[0] }">
<!-- /ko -->
Is there any way to debug into the code in html so that I can see what inside product() is ?
I always use a browser add-on for this like:
Knockout context debugger extension for Chrome dev tools
FireKnockout add-on for Firefox
Install the extension, browse up to the point where you want to debug your app, select the element in the browser's dev-tools and find the current state in detail in the extension tab.
how about ko.toJSON
from http://knockoutjs.com/documentation/json-data.html
Note that ko.toJSON accepts the same arguments as JSON.stringify. For
example, it can be useful to have a “live” representation of your view
model data when debugging a Knockout application. To generate a nicely
formatted display for this purpose, you can pass the spaces argument
into ko.toJSON and bind against your view model like
run snippet below
var product = {
'foo': 'bar',
'largeImageUrls': ['image1', 'image2', 'image3', 'image4'],
'bannerImageVideoLink': true
}
function viewModel() {
var self = this;
this.product = ko.observable(ko.mapping.fromJS(product));
};
var vm = new viewModel();
$(document).ready(function() {
ko.applyBindings(vm);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<!-- ko ifnot: product().bannerImageVideoLink -->
<img data-bind="attr: {src: product().largeImageURLs()[0] }">
<!-- /ko -->
debugger....
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
The way I do this is by calling a function which uses the browsers debugger like this...
<!-- ko if: function(){debugger;}() --><!-- /ko -->
so if you add that just before your code like this...
<!-- ko if: function(){debugger;}() --><!-- /ko -->
<!-- ko ifnot: product().bannerImageVideoLink -->
<img data-bind="attr: {src: product().largeImageURLs()[0] }">
<!-- /ko -->
...then run the page with the chrome developer tools window open. Your browser will hit a breakpoint on that line. You can then inspect the $data variable in your console. This variable will contain the data being bound by knockout which in this case is the model.
You can see this in action by looking at this jsfiddle with your dev tools window open (F12)
https://jsfiddle.net/fa3x9o2s/
On my personal site, I style the post list on my home page based on the post's category. So if I have the front matter:
---
layout: post
title: "My Post"
date: 2016-01-26
category: code
---
Because the category is code, the div below will render to have a css class card-code and style the post excerpt accordingly.
{% for post in site.posts %}
<div class="col-1-2">
<!-- This Line! -->
<div class="paper-card card-{{ post.category }}">
<!-- other code -->
</div>
</div>
{% endfor %}
To try to make my life simpler, I set the default category for posts to be general in my _config.yml file:
default:
-
scope:
path: ""
type: "posts"
values:
category: "general"
However, {{ post.category }} comes up with nothing for these posts (i.e., card-). Any ideas why this ain't working?
Reading the documentation at Front Matter Defaults the section should be called defaults not default.
Try this in your _config.yaml
defaults:
-
scope:
path: ""
type: "posts"
values:
category: "general"
Here's example from Steve Sanderson's blog demonstrating a containerless IF statement in knockout:
<h3>Products</h3>
<ul>
<li><strong>Here is a static header item</strong></li>
<!-- ko foreach: products -->
<li>
<em data-bind="text: name"></em>
<!-- ko if: manufacturer -->
— made by <span data-bind="text: manufacturer.company"></span>
<!-- /ko -->
</li>
<!-- /ko -->
</ul>
How would I make the IF statement more complex. I am trying the following and it doesn't work (always returns false):
<!-- ko if: PlanStateName == 'Draft' -->
<div>This plan is a draft!</div>
<!-- /ko -->
How would one accomplish this?
So it turns out I made a rookie mistake. Here's the working code:
<!-- ko if: PlanStateName() == 'Draft' -->
<div>This plan is a draft!</div>
<!-- /ko -->
Since the variables are wrappered by knockout, the parentheses on PlanStateName are required to access the underlying data.
You need to surround the logical statement with {}.
See http://jsfiddle.net/photo_tom/nvYdf/55/