I know this has been asked before, but I'm kinda lost here.
I've got an element from which I log the typeof:
typeof msg['PID']['PID.13'] // outputs "xml"
So following this answer I logged the children.length, of which I expect it to be a number:
typeof msg['PID']['PID.13'].children.length // also outputs "xml"
But the typeof the children.length is also xml. How can this be?
It's Javascript hidden in a system (Mirth) in which logging is a problem (at least I still haven't found out how it works) so I'm having a hard time debugging this.
Does anybody know how I can get the children count of the element? All tips are welcome!
[EDIT]
As suggested I also tried the output of msg['PID']['PID.13'].children.length, but that seems to be empty.
First thing that seems pretty strange to me is: typeof msg['PID']['PID.13'] // 'xml'. So, in case you get some xml from the server, you can parse it like so:
var parser = new DOMParser(),
doc = parser.parser.parseFromString(xml, 'text/xml'); //xml is a xml string
typeof doc // 'object'
Than, to count the occurrences of some elements/children, you can use xpath:
var count = doc.evaluate('count(//someelement)', doc.documentElement, null, XPathResult.NUMBER_TYPE, null).numberValue;
You can even run:
doc.querySelectorAll('someelement').length
and those methods from the comments will work, too:
doc.documentElement.children.length
So I guess the xml object you have in that object is not a real XMLDocument, that is why I guess those properties like msg['PID']['PID.13'].children.length »seam to be empty«.
UPDATE
As pointed out in the answer of #Nick Rupley you might be dealing with an Instance of E4X, and as documented here, in the Archive of obsolete content, it is obsolete in firefox and does not appear at all on caniuse.com. So if your code is running in a Browser, you need to change it to one of the variants mentioned above. Otherwise you can find documentation about the usage on the first linked resource on mdn.
What you have there is an E4X XML (or XMLList) object. So do this instead:
msg['PID']['PID.13'].children().length()
So, msg['PID']['PID.13'] is xml. Can you post it as text here?
If that xml was something like <children><length><value>5</value></length></children> then, perhaps, msg['PID']['PID.13'].children could have been interpreted by js as if it was msg['PID']['PID.13']['children'] which is identical js expression. Similarly, dependending on what type of object that is, it could return empty xml node for all invalid nodes, that is:
typeof msg['PID']['PID.13'].children.a.b.c.d.length
would also return xml.
Related
I was reviewing some code and I saw something like this:
if (result.indexOf('?') === -1) {
result += '?';
}
result += '&' + SOMETHING;
Clearly this can result in an URL like this http://example.com?&a=b
The author of the code sees nothing unusual in the code but ?& bothers me. I could not find any restrictions in the RFC for URI to prove him wrong (or maybe I missed it).
Clearly in the network tab of Chrome dev tools it appears as an empty pair:
Should URL like this bother me or am i just paranoid?
This case will be interpreted as an empty value by most servers, so yes, it is indeed valid. What's going to happen is that the server checks between ? and every & and then separates the values at = accordingly.
So when there is nothing between a ? and a & (or two &'s), the values will both be empty. Missing ='s will affect whether the value is "" or null, but it will not make the query invalid.
Watch out with this, because some parsers might not find this to be valid, so you may get problems when using custom parsers (in JavaScript for example).
I wrote up a blog post about some of these edge cases years ago.
tl;dr: yes, ?&example is valid
What's important about it is that you're defining a key of "" with a value of null.
You can pretty much guarantee that almost no libraries support those empty string keys, so don't rely on them working, but as far as having a URL along the lines of ?&foo=bar, you should be fine when accessing the foo key.
A function in my WP plugin has just randomly (as far as I can tell) stopped working.
Here's the code in question:
window.send_to_editor = function(html) {
var classes = jQuery('img',html).attr('class');
var items = classes.split(" ");
... more stuff here
}
I've confirmed that the html variable is indeed an img html tag. Here's what firebug shows when I do a console.log of the object (console.log(jQuery('img',html));):
Object[]
context -> undefined
jquery -> "1.11.2"
length -> 0
prevObject -> Object[img.alignnone.size-full.wp-image-1234 name.jpg]
And the error it shows is classes is undefined.
I figure there's something wrong with the object I get, but this used to work recently and I'm not aware of any changes in the site that could have caused this.
I'd appreciate any input on this.
EDIT:
More info. This happens with two plugins which are supposed to be unrelated (made by different people). It happens when, after uploading an image to the server (or selecting a previously uploaded picture) you try to insert it into the post.
As I said before this error has appeared out of nowhere, it was working as intended a couple days ago. The only thing I can think of that has changed since then is the domain name, but I can't see how that could be related.
The jQuery selector always returns a jQuery object, but when the length is 0 then no elements were found matching the selector that you provided. In your example you've confirmed that nothing is selected as the length of the jQuery object is 0. Perform a check whether an element was selected like this:
var $els = jQuery('img',html),
classes;
if ($els.length) {
classes = $els.attr("class");
}
Keep in mind that your DOM query is limited by what you pass in as the html parameter. If you simply want to find the images on the page do: var $els = jQuery('img');
I finally managed to fix this; the key was parsing the html string variable into proper HTML, using jQuery.parseHTML(). Thanks to everyone who helped!
Can someone offer some troubleshooting tips here? My PostXML() return value is NULL for a very small subset of data results. This works for 99.9% of usage. I think the failed data may have special characters perhaps, but comparing to a similar dataset, its identical and passes OK? The oXMLDoc.xml in File.asp contains a valid XML string while debugging, but its null when it gets back to my JS call.
Is there any known issues with what looks like a valid XML element getting trashed in the Microsoft.XMLHTTP object?
function PostXML(sXML)
{
var oHTTPPost = new ActiveXObject("Microsoft.XMLHTTP");
oHTTPPost.Open("POST","File.asp", false);
oHTTPPost.send(sXML);
// documentElement is null???
return oHTTPPost.responseXML.documentElement;
}
File.asp
<%
' oXMLDoc.xml contains valid XML here, but is NULL in the calling JS
Response.ContentType = "text/xml"
Response.Write oXMLDoc.xml
%>
Check the response headers. The content type needs to be application/xml.
XMLHttpRequest is available in current IEs. I suggest using the ActiveX only as a fallback.
You can override the content mimetype on it:
xhr = new XMLHttpRequest();
xhr.overrideMimeType("application/xml");
...
This might by possible on the ActiveX object, too. But I am not sure.
Another possibility is using the DOMParser to convert a received string into an Document instance.
Found the issue.
Using IE Dev/Debugger, I found xEFxBFxBF in one of the string attributes. This product uses MS SQL Server and the query output did not reflect these characters even if copy/pasted into Notepad++. I'm assuming Ent Manager filters out unsupported characters... /=
Thanks for the help people!
Ouch man.
Is it possible to use jQuery instead?
The other thing I know is that if the return xml is a little off (poorly formatted xml, case sensitive, non-legal characters) the javascript will trash the return value.
With jQuery you have better debugging options to see the error.
I have a very specific problem concerning a regular expression matching in Javascript. I'm trying to match a piece of source code, more specifically a portion here:
<TD WIDTH=100% ALIGN=right>World Boards | Olympa - Trade | <b>Bump when Yasir...</b></TD>
The part I'm trying to match is boardid=106121">Olympa - Trade</a>, the part I actually need is "Olympa". So I use the following line of JS code to get a match and have "Olympa" returned:
var world = document.documentElement.innerHTML.match('/boardid=[0-9]+">([A-Z][a-z]+)( - Trade){0,1}<\/a>/i')[1];
the ( - Trade) part is optional in my problem, hence the {0,1} in the regex.
There's also no easier way to narrow down the code by e.g. getElementsByTagName, so searching the complete source code is my only option.
Now here's the funny thing. I have used two online regex matchers (of which one was for JS-regex specifically) to test my regex against the complete source code. Both times, it had a match and returned "Olympa" exactly as it should have. However, when I have Chrome include the script on the actual page, it gives the following error:
Error in event handler for 'undefined': Cannot read property '1' of null TypeError: Cannot read property '1' of null
Obviously, the first part of my line returns "null" because it does not find a match, and taking [1] of "null" doesn't work.
I figured I might not be doing the match on the source code, but when I let the script output document.documentElement.innerHTML to the console, it outputs the complete source code.
I see no reason why this regex fails, so I must be overlooking something very silly. Does anyone else see the problem?
All help appreciated,
Kenneth
You're putting your regular expression inside a string. It should not be inside a string.
var world = document.documentElement.innerHTML.match(/boardid=[0-9]+">([A-Z][a-z]+)( - Trade){0,1}<\/a>/i)[1];
Another thing — it appears you have a document object, in which case all this HTML is already parsed for you, and you can take advantage of that instead of reinventing a fragile wheel.
var element = document.querySelector('a[href*="boardid="]');
var world = element.textContent;
(This assumes that you don't need <=IE8 support. If you do, there remains a better way, though.)
(P.S. ? is shorthand for {0,1}.)
I'm getting an xml file and want to get data from it.
The source of the xml doesn't really matter but what I;ve got to get a certain field is:
tracks = xmlDoc.getElementsByTagName("track");
variable = tracks.item(i).childNodes.item(4).childNodes.item(0).nodeValue;
Now this works like a charm, EXCEPT when there is no value in the node. So if the structure is like this:
<xml>
<one>
<two>nodeValue</two>
</one>
<one>
<two></two>
</one>
</xml>
the widget will crash on the second 'one' node, because there is no value in the 'two' node. The console says:
TypeError: tracks.item(i).childNodes.item(4).childNodes.item(0) has no properties
Any ideas on how to get the widget to just see empty as an empty string (null, empty, or ""), instead of crashing? I'm guessing something along the lines of data, getValue(), text, or something else.
using
var track= xmlDoc.getElementsByTagName('track')[0];
var info= track.getElementsByTagName('artist')[0];
var value= info.firstChild? info.firstChild.data : '';
doesn't work and returns "TypeError: track has no properties". That's from the second line where artist is called.
Test that the ‘two’ node has a child node before accessing its data.
childNodes.item(i) (or the JavaScript simple form childNodes[i]) should generally be avoided, it's a bit fragile relying on whitespace text nodes being in the exact expected place.
I'd do something like:
var tracks= xmlDoc.getElementsByTagName('track')[0];
var track= tracks.getElementsByTagName('one')[0];
var info= track.getElementsByTagName('two')[0];
var value= info.firstChild? info.firstChild.data : '';
(If you don't know the tagnames of ‘one’ and ‘two’ in advance, you could always use ‘getElementsByTagName('*')’ to get all elements, as long as you don't need to support IE5, where this doesn't work.)
An alternative to the last line is to use a method to read all the text inside the node, including any of its child nodes. This doesn't matter if the node only ever contains at most one Text node, but can be useful if the tree can get denormalised or contain EntityReferences or nested elements. Historically one had to write a recurse method to get this information, but these days most browsers support the DOM Level 3 textContent property and/or IE's innerText extension:
var value= info.textContent!==undefined? info.textContent : info.innerText;
without a dtd that allows a one element to contain an empty two element, you will have to parse and fiddle the text of your xml to get a document out of it.
Empty elements are like null values in databases- put in something, a "Nothing" or "0" value, a non breaking space, anything at all- or don't include the two element.
Maybe it could be an attribute of one, instead of an element in its own right.
Attributes can have empty strings for values. Better than phantom elements .
Yahoo! Widgets does not implement all basic javascript functions needed to be able to use browser-code in a widget.
instead of using:
tracks = xmlDoc.getElementsByTagName("track");
variable = tracks.item(i).childNodes.item(4).childNodes.item(0).nodeValue;
to get values it's better to use Xpath with a direct conversion to string. When a string is empty in Yahoo! Widgets it doesn't give any faults, but returns the 'empty'. innerText and textContent (the basic javascript way in browsers, used alongside things like getElementsByTagName) are not fully (or not at all) implemented in the Yahoo! Widgets Engine and make it run slower and quite awfully react to xmlNodes and childNodes. an easy way however to traverse an xml Document structure is using 'evaluate' to get everything you need (including lists of nodes) from the xml.
After finding this out, my solution was to make everything a lot easier and less sensitive to faults and errors. Also I chose to put the objects in an array to make working with them easier.
var entries = xmlDoc.evaluate("lfm/recenttracks/track");
var length = entries.length;
for(var i = 0; i < length; i++) {
var entry = entries.item(i);
var obj = {
artist: entry.evaluate("string(artist)"),
name: entry.evaluate("string(name)"),
url: entry.evaluate("string(url)"),
image: entry.evaluate("string(image[#size='medium'])")
};
posts[i] = obj;
}