Xpath evaluation in javascript not working relative to some element - javascript

The code below will reach the "before" and "between" alerts, but not the "after" alert.
alert("before")
var test = document.evaluate('.//*',document,document.createNSResolver(document),XPathResult.ANY_TYPE,null)
alert(element.tagName)//alerts "TABLE"
alert("between")
test = document.evaluate('.//*',element,document.createNSResolver(document),XPathResult.ANY_TYPE,null)
alert("after")
This is written as part of a selenium extension. and alert(document) in the code gives a different result than alert(document) when run in firebug. [object XULDocument] vs [object HTMLDocument].

Your second test has an undefined variable element.

solved.
document does not refer to the HTML document in selenium extensions. however each element has a reference to the document which owns it. in this case
test = document.evaluate('.//*',element,document.createNSResolver(document),
XPathResult.ANY_TYPE,null)
becomes
test = element.ownerDocument.evaluate('.//*',element,
element.ownerDocument.createNSResolver(element.ownerDocument),
XPathResult.ANY_TYPE,null)
and so on...

A variant of Zackkenyon answer, without the resolver seems to work.
var rangee = table.ownerDocument.evaluate("./tbody/tr", table, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

Related

innerHTML and outerHTML property on HTMLElement return undefined with no error

Goal: Take a HTML as string, edit some attributes of image tags in it, return the HTML as string.
My function is along following lines:
private resolveImagesInHTML (body: string): string {
let htmlParser = new domParser.DOMParser(); // from react-native-html-parser
let parsedDOM: HTMLDocument = htmlParser.parseFromString('<html>' + body + '</html>', 'text/html');
// ------- code to modify DOM goes here -------
return parsedDOM.documentElement.innerHTML;
}
Issue: If I print parsedDOM or parsedDOM.documentElement in my debug console,
it correctly displays the modified HTML content. Surprisingly,
innerHTML or outerHTML property throws no error but returns
'undefined'.
My obvious guess was that I might have messed up the format of HTML while modifying my code but even if I comment everything inside my function except the three lines above, the behavior is still the same.
What could I possibly be doing wrong here?
Thanks, I am pretty new to React-Native and typescript so I won't be surprised if I am missing some trivial and obvious thing here.
htmlParser.parseFromString
returns something that looks like the DOM, that has some methods in common with the DOM but not all of them. It does not have .innerHTML. Real browser DOM have it.
From what is written here https://www.npmjs.com/package/react-native-html-parser innerHTML is not available
So why does it not throw an Error ? Because that is how JavaScript Objects work.
console.log({}.innerHTML) // No Error
How to force an error ?
There are 2 solutions, One is to use strict mode and enable strict mode warnings in the console. The other is wrap things with Proxys that checks for hasOwnProperty for example.

Getting element from DOM with jQuery

EDIT:
JSFIDDLE here. I am trying to mirror DESKTOP 1 to MOBILE 1 elements (same for #2) in the fiddle. The error is shown in console.
Got to DESKTOP 1 and select NEW RATE from the list. Have the console opened to see the issue. Thanks!
I get an element from my layout with this command:
var eqTaxSelect = $('table#mob-tab-' + num).find('select.tax_rate').get();
I then try to toggle it:
toggleField($(eqTaxSelect), $(eqTaxSelect).nextElementSibling); <-- FAILS
function toggleField(hideObj, showObj) {
hideObj.style.display = 'none'; <-- FAILS HERE
showObj.style.display = 'inline';
showObj.focus();
}
with:
Uncaught TypeError: Cannot set property 'nextElementSibling' of undefined
What am I doing wrong when assigning the element to my variable? This function works for this inside click event listeners for example.
Thanks!
The HTML I am toggling came from this forum, essentially a select with a hidden input so new entries can be added as well as using an entry from the options list.
What am I doing wrong when assigning the element to my variable?
You are passing jQuery() objects, where toggleField expects DOM elements. jQuery() does not have a .nextElementSibling method. Remove calls to jQuery() at
toggleField($(eqTaxSelect), $(eqTaxSelect).nextElementSibling);
replace with
toggleField(eqTaxSelect, eqTaxSelect.nextElementSibling);
to pass DOM elements to toggleField.
test with
console.log(eqTaxSelect)
see on inspector (CTRL+SHIF+I CHROME). if this is ok,
just do this
toggleField(eqTaxSelect, eqTaxSelect.nextElementSibling)
withouth "$"
The reason why your statement
toggleField(eqTaxSelect, eqTaxSelect.nextElementSibling);
fails is because of the way you are populating the eqTaxSelect
var eqTaxSelect = $('table#mob-tab-' + num).find('select.tax_rate').get();
It should be modified as
var eqTaxSelect = $('table#mob-tab-' + num).find('select.tax_rate').get(0);
reason being, get() without an index returns an array and the way you are operating, you are expecting an single dom element.
jQuery documentation for get()

Print Element names in Console Use Firebug

I want to listing all input elements in console of firebug so in console window write the followings:
var inputs = $(":input");
console.log(inputs);
but when I press the Run in console appear null
also when I write just var inputs = $(":input"); the console show Undefined I sure the page have a lot of input elements, where is the problem?
There is nothing wrong with the provided snippet.
Though, without specifying what to write (using console.log) firebug will print whatever the last statement returned, when declaring a variable using var the result is always undefined.
var inputs = $(":input"); // firebug printing 'undefined' is valid
var abc = 123; // results in the same thing
Please make sure that the website in question actually uses jQuery (bound to global $), and that there really are input elements present in the DOM.
Also make sure that the jQuery version running is of a version later/equal to 1.0 (:input selector didn't exists until then).
If it has jQuery it probably is of a more recent version, how ever; without you providing us with additional information there is no way to guarantee it.
simply go to the firebug console and wrtie as #refp mentioned the page in question must have jquery included
$(":input")
press run

document.evaluate won't work from content script

var allTags = document.evaluate("//*[contains(#src,'"+imgSrc+"')]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
This is the code that gives errors, it gives:
Uncaught Error: TYPE_ERR: DOM XPath Exception 52
Could someone tell me what the problem is?
I don't have a precise answer, but I can guess and give a workaround.
First the work around: change UNORDERED_NODE_SNAPSHOT_TYPE to a type that don't create a snapshot(unless you need it that way) and returns multiple nodes like UNORDERED_NODE_ITERATOR_TYPE(or ANY_TYPE).
And my guess: After reading the spec it say for this function 'TYPE_ERR: Raised if the result cannot be converted to return the specified type.'. It may be the case it can't allocate the resources to create a snapshot or something like this(the workaround assumes that).
Edit:
The real problem is most likely not the call to document.evaluate is that in your code you do allTags.iterateNext and this call expects allTags to be a *_NODE_ITERATOR_TYPE and not a *_NODE_SNAPSHOT_TYPE, using allTags.snapshotItem don't cause an error to be thrown. I wrote a sample at jsfiddle, it changes the borders after 2 seconds using the call to evaluate in your question and iterate over the elements in the proper way.

JavaScript will alert nodeValue, but when trying to display the text, it's null or causes errors

I have been having tremendous trouble getting this to work. There is no reason (to my knowledge) that this shouldn't work.
var xpath = '/course/module[#id=\''+modId+'\']/child::*';
var getData = sxe(xmldoc, xpath);
var result = getData.iterateNext();
The function returns the xpath. Just looks cleaner. This works 100%.
while (results)
{
var text = result.getElementsByTagName('title')[0].nodeValue;
document.write(text); // returns null
}
For the example, I use document.write, it returns null, but in my actual script, it usually says childNodes or whatever method I'm trying to access the data (I thought this would help) it never returns it. It causes an error and breaks it. When I use alert(), I get the exact text I want, everything works perfectly!
What is happening?!
try
var text = result.getElementsByTagName('title')[0].text; //concatenates the text of all descendant nodes
or
var text = result.getElementsByTagName('title')[0].firstChild.nodeValue;
I fixed it. Some of my XML data was missing a title attribute. This caused an error when trying to pass it to a variable, but alerting something that doesn't exist just ... doesn't alert it. So, it makes sense to why it works now.

Categories

Resources