It is simple example HTML for demonstration my issue
<!DOCTYPE html>
<html>
<body>
<div>
<label>This value comes from internal</label>
<div>
<div name='internal'>$11.11</div>
</div>
<div>
<label>This value comes from external</label>
<div>
<input type ='text' name='internal' readonly='true'>
</div>
</div>
</body>
</html>
//Display in Web Browser
This value comes from internal
11.11
This value comes from external
55.55
I want to get $55.55, but I searched "//*[text()='$55.55']" with inspector but I could not find any $55.55
and I figured out this $55.55 value comes from external JS and changed DOM and display.
This value displayed on browser but I could not get Xpath of input value
How can I get Xpath get this value "$55.55"
Thank you
Well, I dont know if I correctly understand your question, but if your goal is to get the input's value you can do something easy as, without the need of XPath:
var myInputValue = document.querySelector('input[name=internal]').value;
console.log(myInputValue);
Related
Need to check format of the value of a textfield inside the Javascript.
I am using thymeleaf for rendering the page.
To achieve this I plan to use th:id and use this inside Javascript (similar to document.getElementById and read the value. But I donot know how to get the value of the textfield inside the javascript as I am doing an iteration..
Below is the scenario
While iterating through a Map<String,Field> (where Field is a class containing two elements fieldValueList (List) and timeField(boolean) check for the format of the textField entered in the page, (format of the textfield should be hh:mm:ss) need to be done in javascript. I used id for reading the value, but donot know how to get the value of the textfield inside the javascript.
The code for the page is
<fieldSet th:each="fieldKey,fieldKeyIndex : *{recipeFieldMap.keySet()}">
<div class="fieldDiv" th:each="fieldVal,field : *{recipeFieldMap[__${fieldKey}__].fieldValueList}">
<span class="fieldSpan" th:if="*{recipeFieldMap[__${fieldKey}__].timeField}">
<input type="text" th:id="|text_${fieldKeyIndex.index}_${field.index}|" th:field="*{recipeFieldMap[__${fieldKey}__].fieldTimeValueList[__${field.index}__].displayStr}" onchange="checkTimeStr()">
<script th:inline="javascript">
/*<![CDATA[*/
function checkTimeStr() {
// Something like this.. to read the value
//var value = document.getElementById('/* text_${groupKeyIndex.index}_${field.index} */').value;
//alert(value)
}
/*]]>*/
</script>
</span>
<span class="fieldSpan" th:unless="*{recipeFieldMap[__${fieldKey}__].timeField}">
<input type="text" th:field="*{recipeFieldMap[__${fieldKey}__].fieldValueList[__${field.index}__]}">
</span>
</div>
</fieldSet>
enter image description here
try this:
<script th:inline="javascript">
[[${field.index}]]
</script>
The documentation on source binding has an aside which states:
Important: A single root element should be used in the template when
binding to an array. Having two first level DOM elements will result
in an erratic behavior.
However, I'm finding that this is the case even for non arrays.
I have the following HTML, which sets up two div's populated by two templates. The only difference is that the working template wraps that databound spans in a div.
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2013.3.1119/js/kendo.all.min.js"></script>
<title>JS Bin</title>
<script id="broken-template" type="text/x-kendo-template">
Foo: <span data-bind="text: foo"></span><br/>
Foo Again: <span data-bind="text: foo"></span>
</script>
<script id="working-template" type="text/x-kendo-template">
<div>
Foo: <span data-bind="text: foo"></span><br/>
Foo Again: <span data-bind="text: foo"></span>
</div>
</script>
</head>
<body>
<div id="broken-div" data-template="broken-template" data-bind="source: this">
</div>
<br/>
<br/>
<div id="working-div" data-template="working-template" data-bind="source: this">
</div>
</body>
</html>
And the JavaScript simply creates a view model with a single property and binds it to both divs:
var viewModel = kendo.observable({foo: "bar"});
kendo.bind($("#broken-div"), viewModel);
kendo.bind($("#working-div"), viewModel);
In both cases, only the first root element and it's children are being bound properly. This suggests that every time I databind to template with more than one element I need to make sure it is wrapped in a single root.
Is this behavior documented somewhere? Is there a bug in Kendo or in my sample code? An explanation for why Kendo requires a single root would be great to hear as well.
(Sample code as a jsfiddle)
It's not documented except in the one place you mentioned. Such is the state of Kendo UI documentation - it's less than complete. I've been using Kendo UI for three years and as far as I can tell you, this is its default behavior and not a bug. Unfortunately, it's one of the many quirks you simply learn (stumble upon) from experience.
I am trying to get the value of an element attribute from this site via importXML in Google Spreadsheet using XPath.
The attribute value i seek is content found in the <span> with itemprop="price".
<div class="left" style="margin-top: 10px;">
<meta itemprop="currency" content="RON">
<span class="pret" itemprop="price" content="698,31 RON">
<p class="pret">Pretul tau:</p>
698,31 RON
</span>
...
</div>
I can access <div class="left"> but i can't get to the <span> element.
Tried using:
//span[#class='pret']/#content i get #N/A;
//span[#itemprop='price']/#content i get #N/A;
//div[#class='left']/span[#class='pret' and #itemprop='price']/#content i get #N/A;
//div[#class='left']/span[1]/#content i get #N/A;
//div[#class='left']/span/text() to get the text node of <span> i get #N/A;
//div[#class='left']//span/text() i get the text node of a <span> lower in div.left.
To get the text node of <span> i have to use //div[#class='left']/text(). But i can't use that text node because the layout of the span changes if a product is on sale, so i need the attribute.
It's like the span i'm looking for does not exist, although it appears in the development view of Chrome and in the page source and all XPath work in the console using $x("").
I tried to generate the XPath directly form the development tool by right clicking and i get //*[#id='produs']/div[4]/div[4]/div[1]/span which does not work. I also tried to generate the XPath with Firefox and plugins for FF and Chrome to no avail. The XPath generated in these ways did not even work on sites i managed to scrape with "hand coded XPath".
Now, the strangest thing is that on this other site with apparently similar code structure the XPath //span[#itemprop='price']/#content works.
I struggled with this for 4 days now. I'm starting to think it's something to do with the auto-closing meta tag, but why doesn't this happen on the other site?
Perhaps the following formulas can help you:
=ImportXML("http://...","//div[#class='product-info-price']//div[#class='left']/text()")
Or
=INDEX(ImportXML("http://...","//div[#class='product-info-price']//div[#class='left']"), 1, 2)
UPDATE
It seems that not properly parse the entire document, it fails. A document extraction, something like:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<div class="product-info-price">
<div class="left" style="margin-top: 10px;">
<meta itemprop="currency" content="RON">
<span class="pret" itemprop="price" content="698,31 RON">
<p class="pret">Pretul tau:</p>
698,31 RON
</span>
<div class="resealed-info">
ยป Vezi 1 resigilat din aceasta categorie
</div>
<ul style="margin-left: auto;margin-right: auto;width: 200px;text-align: center;margin-top: 20px;">
<li style="color: #000000; font-size: 11px;">Rata de la <b>28,18 RON</b> prin BRD</li>
<li style="color: #5F5F5F;text-align: center;">Pretul include TVA</li>
<li style="color: #5F5F5F;">Cod produs: <span style="margin-left: 0;text-align: center;font-weight: bold;" itemprop="identifier" content="mol:GA-Z87X-UD3H">GA-Z87X-UD3H</span> </li>
</ul>
</div>
<div class="right" style="height: 103px;line-height: 103px;">
<form action="/?a=shopping&sa=addtocart" method="post" id="add_to_cart_form">
<input type="hidden" name="product-183641" value="on"/>
<img src="/templates/marketonline/images/pag-prod/buton_cumpara.jpg"/>
</form>
</div>
</div>
</html>
works with the following XPath query:
"//div[#class='product-info-price']//div[#class='left']//span[#itemprop='price']/#content"
UPDATE
It occurs to me that one option is that you can use Apps Script to create your own ImportXML function, something like:
/* CODE FOR DEMONSTRATION PURPOSES */
function MyImportXML(url) {
var found, html, content = '';
var response = UrlFetchApp.fetch(url);
if (response) {
html = response.getContentText();
if (html) content = html.match(/<span class="pret" itemprop="price" content="(.*)">/gi)[0].match(/content="(.*)"/i)[1];
}
return content;
}
Then you can use as follows:
=MyImportXML("http://...")
At this time, the referred web page in the first link doesn't include a span tag with itemprop="price", but the following XPath returns 639
//b[#itemprop='price']
Looks to me that the problem was that the meta tag was not XHTML compliant but now all the meta tags are properly closed.
Before:
<meta itemprop="currency" content="RON">
Now
<meta itemprop="priceCurrency" content="RON" />
For web pages that are not XHTML compliant, instead of IMPORTXML another solution should be used, like using IMPORTDATA and REGEXEXTRACT or Google Apps Script, the UrlFetch Service and the match JavasScript function, among other alternatives.
Try smth like this:
print 'content by key',tree.xpath('//*[#itemprop="price"]')[0].get('content')
or
nodes = tree.xpath('//div/meta/span')
for node in nodes:
print 'content =',node.get('content')
But i haven't tried that.
I have this view:
<script type="text/x-handlebars" data-template-name="articlesOne">
<div class="main">
<div id="articlesOne">
<h2 id="article-title">{{App.ArticlesOneController.article.title}}</h2>
<h3 id="article-lead">{{App.ArticlesOneController.article.lead}}</h3>
<div id="article-body">{{App.ArticlesOneController.article.body}}</div>
</div>
</div>
</script>
When I change the App.ArticlesOneController.article.title property to, say <p>Pragraph</p>, the browser displays the plain text, not parsed as HTML.
I would like to display that in HTML, due to building an editor on that div. How should I do that?
You should try triple brackets with {{{App.ArticlesOneController.article.title}}}. I think this link is useful for you: Show property which includes html tags
In a GSP (Groovy Server Page), I'm using <g:submitToRemote update="..."> to update a <div> after the server-side call.
According to the tag's documentation and other sources on the web, the target <div> can be placed arbitrarily at the page. In my testings, however, I find that the <div> needs to surround the <g:submitToRemote> tag.
If it does not, the <div> will be updated with some "random" contents (i.e., parts of the form that surround the <g:submitToRemote> tag).
Consider the following GSP code:
<html>
<head>
<g:javascript library="prototype" />
</head>
<body>
<div id="updateMe_NOT_WORKING">${message}</div>
<g:form>
<div id="updateMe_WORKING">
<g:submitToRemote value="Click Me"
action="someAction" update="updateMe_NOT_WORKING" />
</div>
</g:form>
</body>
</html>
That's on Grails 1.3.4.
What am I missing? - Thanks
According to my testings, g:submitToRemote's action attribute must not point to the current controller's current action (as this will insert/duplicate the current view into the current view).
It works if you specify an alternate action in g:submitToRemote - i.e.,
<g:submitToRemote value="Click Me"
action="ajaxAction" update="updateMe" />
If this action provides a model - i.e.,
def ajaxAction = { [message: 'foo'] }
then there needs to be a corresponding GSP - that, in this case, should state,
$message
Alternatively, the action can use the render method - like this,
def ajaxAction = { render 'foo' }
I'll leave this issue open for some time, in case there might be additional responses, and, if there aren't, will accept this answer as the solution.
Thanks
I think the problem is that you don't specify the controller for your action. Try adding controller="..." into your g:submitToRemote tag. Or at least specify it in g:form.
I'm sure that the <div> doesn't need to be wrapped.