javascript/jQuery can't find element with messed up id - javascript

I'm trying to access an element in MS CRM 2011 with the following id:
account|NoRelationship|Form|B_GenerateInvoice-Large
I can see this element in the IE developer tools:
Unfortunately I always get null when trying to find this element.
I've tried the following:
alert(document.getElementById('account|NoRelationship|Form|B_GenerateInvoice-Large'));
alert($("[id='account|NoRelationship|Form|B_GenerateInvoice-Large]").html());
alert($(jq("account|NoRelationship|Form|B_GenerateInvoice-Large")).html()); // jq() adds the '#' and escapes special characters
alert($("#account|NoRelationship|Form|B_GenerateInvoice-Large").html());
alert(document.getElementById("#account\\|NoRelationship\\|Form\\|B_GenerateInvoice-Large"));
alert($("#account\\|NoRelationship\\|Form\\|B_GenerateInvoice-Large").html());
These all fail to find the element.
Am I missing something obvious here?
Solution:
The javascript was inside an iframe while the element was outside of the iframe..
I did not manage to solve it.

The jQuery Manual on Selectors states:
If you wish to use any of the
meta-characters ( such as
!"#$%&'()*+,./:;<=>?#[]^`{|}~ ) as a
literal part of a name, you must
escape the character with two
backslashes: \\. For example, if you
have an element with id="foo.bar", you
can use the selector $("#foo\\.bar").
The W3C CSS specification contains the
complete set of rules regarding valid CSS selectors.
So try this one:
$('#account\\|NoRelationship\\|Form\\|B_GenerateInvoice-Large')...
jsFiddle Demo
EDIT: I have successfully tested my Fiddle in Chrome, Firefox 4, IE9, IE8 and IE7, it works fine.

It may be a bug in browser, since HTML5 specification allows any character except spaces in id attribute
ID #
Any string, with the following restrictions:
must be at least one character long
must not contain any space characters
however, it is encrouaged not to put any weired character in id attribute, only number, letter and underscore there:)

From the jQuery documentation:
If you wish to use any of the meta-characters ( such as !"#$%&'()*+,./:;<=>?#[]^`{|}~ ) as a literal part of a name, you must escape the character with two backslashes: \. For example, if you have an element with id="foo.bar", you can use the selector $("#foo\.bar").
So this should work:
alert($("#account\\|NoRelationship\\|Form\\|B_GenerateInvoice-Large").html());
And it does, indeed: http://jsfiddle.net/Cdz9w/

What version of HTML is the page declaring that it's using? Because that's a valid HTML5 id, but it's an invalid HTML4.01 and earlier id. (It's also an invalid CSS id, which is vaguely relevant if you use something like jQuery to look it up, as jQuery uses CSS selectors.)
The fiddle in #bazmegakapa's answer works for me on Chrome, but perhaps your page is declaring a different version of HTML, or perhaps a less-advanced browser doesn't like it, etc.

Related

jQuery Escaping Special Characters Fails

I am trying to make a jQuery selector to select, by an arbitrary id, an html element. The ids may contains special characters that need to be escaped. An example is test_E///_AAAAA
I am basically doing exactly what is going on in this working fiddle (which uses v 1.11.0, where I am using v 1.11.3 and have also tested with 2.1.3)
However, in my scaled up environment, it doesn't work. I get Syntax error, unrecognized expression: #test_E\\/\\/\\/_AAAAA
There must be some obscure factoid about jQuery that is the difference between this working and not working. I, being a novice, have no hope of identifying it.
I notice that I am not alone though. A commentator on this thread had the same issue.
The code files are thousands of lines long, and I'm probably prohibited from posting more than a couple lines by my employer. I'm just looking for a hint, a clue, a shot in the dark about what would cause a perfectly reasonable selection string to be rejected.
You just need enough backslashes :)
ID:
The ID of the element is test_E\\/\\/\\/_AAAAA. Note that backslashes don't have any special meaning in HTML, so there really are six backslashes in the ID.
jQuery selector: Backslashes, forward slashes, and several other characters have special meaning in jQuery selectors, so we need to escape them with a backslash. The selector therefore needs to be #test_E\\\\\/\\\\\/\\\\\/_AAAAA. This tells jQuery to look for an element whose ID contains test_E, then two backslashes, then one forward slash, and so on.
JavaScript string literal: To represent that selector using a JavaScript string literal, each backslash needs to be escaped. So the string literal would be "#test_E\\\\\\\\\\/\\\\\\\\\\/\\\\\\\\\\/_AAAAA".
var selectionString = "#test_E\\\\\\\\\\/\\\\\\\\\\/\\\\\\\\\\/_AAAAA";
snippet.log("actual id: " + $("p")[0].id);
snippet.log("selection string given to jQuery: " + selectionString);
snippet.log("text: " + $(selectionString).text());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<p id="test_E\\/\\/\\/_AAAAA">This is a test :)</p>
As you can see, this is extremely ugly, hard to understand, and hard to get right. I highly recommend avoiding such IDs. Another option is to use good old document.getElementById(), which only requires the string literal escapes:
$(document.getElementById('test_E\\\\/\\\\/\\\\/_AAAAA')).text()
The code in the fiddle doesn't work either. I have tried it in IE, Firefox and Chrome, and neither of them finds the element.
You need to escape a slash to use it in a # selector. If you use a backslash, you have to escape it twice, once to put it in a string, and once for the selector.
To match the id test\A you need the selector #test\\A which as a string is "#test\\\\A".
To match the id test/A you need the selector #test\/A which as a string is "#test\\/A".
To match the id test_E\\/\\/\\/_AAAAA you need the selector #test_E\\\\\/\\\\\/\\\\\/_AAAAA which as a string is "#test_E\\\\\\\\\\/\\\\\\\\\\/\\\\\\\\\\/_AAAAA".
Demo: https://jsfiddle.net/Guffa/463849xj/4/
Generally you should avoid unusual characters in an identity. Even if you can make it work, there is still a risk that some browser handles it differently.
Update:
The error message is shown with the selector unescaped, so as the error message shows the selector #test_E\\/\\/\\/_AAAAA it means that you actually use the string "#test_E\\\\/\\\\/\\\\/_AAAAA". That leaves the slashes unescaped, which causes the syntax error.

Selecting elements with exotic id [duplicate]

This question already has answers here:
jquery exotic id selection
(2 answers)
Closed 9 years ago.
I'm working on a legacy system that uses square brackets in id parameters. E.g.:
<select id="mySelect[]">
<option value="1">Yadda</option>
<option value="2">Yadda</option>
<option value="3">Yadda</option>
</select>
jQuery (being javaScript) quite rightly complains when I try to use this id in, say,
$("#mySelect[]").append(options);
Given the fact that I can't change the legacy code and therefore I'm stuck with the existing id's (which may or may not be valid in any context), what would be a good way to work around this mess and let me select my elements?
While using meta characters you have to escapse those.
$("#mySelect\\[\\]").append(options);
Jquery selector docs saying that
To use any of the meta-characters ( such as !"#$%&'()*+,./:;<=>?#[]^`{|}~ ) as a literal part of a name, it must be escaped with with two backslashes: \.
If you don't want to escape it, you can use the selector
$( document.getElementById('mySelect[]')
Try this way:
$("#mySelect\\[\\]").append(options);
You need to escape [ and ] as they are reserved jquery chars used in selectors.
Have a look at the jquery docs
To use any of the meta-characters ( such as !"#$%&'()*+,./:;<=>?#[]^`{|}~ ) as a literal part of a name, it must be escaped with with two backslashes: \. For example, an element with id="foo.bar", can use the selector $("#foo\.bar").
and a fiddle here
Plus ofcourse you could do this $('[id="mySelect[]"]') But since it is an attribute selector performance wise this will be slower and you lose the advantage of using the id selector, but handy if you are in no way to escape the chars.
Try this jsfiddle link.
Both of the below work fine:
console.log($('[id^=mySelect]'));
console.log($('#mySelect\\[\\]'));

IE8 window.open name - doesn't like JavaScript encoding?

I'm calling window.open() like this:
window.open('blank.html', 'New_Window\x3a_Jamie', 'width=800,height=800');
What I've done in the code is taken the window's name and JavaScript encoded it using the Microsoft Web Protection library. I'm also replacing spaces with underscores because I read that IE doesn't like spaces in window names. FYI the original string was "New Window: Jamie" and it looks like the ":" gets encoded as "\x3a". The window opens in FireFox just fine, but the window does not open in IE8. Does IE8 just not like this encoding, or the character or what? Are there rules around what characters can appear in the window name for IE8?
Are there rules around what characters can appear in the window name for IE8?
Yes. Although it doesn't seem to be documented, IE has always required that a window name be composed of alphanumerics and underscore. A colon won't be accepted, whether read from an encoded string literal or not.
If you really needed to map an arbitrary string to a unique name-safe version you'd have to do something like encoding every non-alphanumeric character into an escape sequence, eg:
function encodeToName(s) {
return s.replace(/[^A-Za-z0-9]/g, function(match) {
var c= match[0].charCodeAt(0).toString(16);
return '_'+(new Array(5-c.length).join('0'))+c;
});
}
alert(encodeToName('New Window: Jamie'));
// 'New_0020Window_003A_0020Jamie'
I agree with casablanca though, it seems very unlikely you should actually need to do this. The user is never going to get to see the window name, so w1 is just as good. It's rare enough that you need window names at all.
I think it wants the window name to be something that'd work as an identifier. Thus, "New_Window_Jamie" would probably be OK.
Do you really need a window name? From the docs:
Such string can be used to be the target of links and forms when the target attribute of an <a> element or of a <form> is specified. This string parameter should not contain any blank space.
That's about the only use of specifying a name, and though I don't see any restrictions apart from "no spaces", it would be safe to just stick to letters, digits and underscores.

When do I need to escape metacharectars? (jQuery Selectors)

According to the jQuery docs, I need to escape metacharacters that occur in my selector strings, when they occur as a literal. However, I couldn't find very many specific examples of when and when not to escape selectors. So when and when don't I need to escape metacharacters, when they are to be interpreted as a literal, in:
Attribute selectors? ie
$("[attr=value]")
Id selectors? ie
$("#id")
Class selectors? ie
$(".class");
And, is there a way to write a function that replaces metachars in selector strings, while still preserving the beginning character? ie:
// replace all meta chars, preserving the id selection?
$("#id.rest$of*string")
// replace all meta chars, preserving the attribute selection?
// going back to my previous question, do I even need to escape the metachars in this situation?
$("[attr=blah.dee#foo*yay]")
The reason I ask this question, is because I'm working with a website that happens to have some really nasty selectors. And I don't have control over the website, so I can't go change the selectors to be nicer to work with.
THANKS!!
From the jQuery docs:
If you wish to use any of the meta-characters (#;&,.+*~':"!^$=>|/ ) as a literal part of a name, you must escape the character with two backslashes ...
All of these must be escaped:
id
class name
attribute name
attribute value
element name
The first four are obvious, and here's an example for the fifth. Element names in XML can contain a "." character for instance and still be valid.
<user.name>John Doe</user.name>
If you had to select all elements of user.name, then that . must be escaped
$(xml).find("user\\.name");
Rather than blatantly stealing someone else's answer, I'll point you to it: jQuery selector value escaping, where jQuery's selector parsing method is described in detail.
The short answer: you may be in trouble since jQuery's selector parser is not 100% standards-complaint. Per the suggestion in the linked answer, you may be able to workaround by calling the regular DOM methods (document.getElementById()), which will work with funny selectors, and then pass the raw DOM element to the jQuery selector.
$(document.getElementById("id.rest$of*string"));

Find DOM element by ID when ID contains square brackets?

I have a DOM element with an ID similar to:
something[500]
which was built by my Ruby on Rails application. I need to be able to get this element via jQuery so that I can traverse my way up the DOM to delete the parent of it's parent, which has a variable ID that I don't have access to beforehand.
Does anyone know how I could go about this? The following code doesn't seem to be working:
alert($("#something["+id+"]").parent().parent().attr("id"));
Upon further inspection, the following:
$("#something["+id+"]")
returns an object, but when I run ".html()" or ".text()" on it, the result is always null or just an empty string.
You need to escape the square brackets so that they are not counted as attribute selectors. Try this:
alert($("#something\\["+id+"\\]").parent().parent().attr("id"));
See Special Characters In Selectors, specifically the second paragraph:
To use any of the meta-characters (such as !"#$%&'()*+,./:;<=>?#[\]^``{|}~) as a literal part of a name, it must be escaped with with two backslashes: \\. For example, an element with id="foo.bar", can use the selector $("#foo\\.bar"). The W3C CSS specification contains the complete set of rules regarding valid CSS selectors. Also useful is the blog entry by Mathias Bynens on CSS character escape sequences for identifiers.
You can also do
$('[id="something['+id+']"]')
An id cannot include square brackets. It is forbidden by the spec.
Some browsers might error correct and cope, but you should fix you data instead of trying to deal with bad data.
Square brackets have special meaning to jQuery selectors, the attribute filters specifically.
Just escape these and it will find your element fine
$( "#something\\[" + id + "\\]" )
Try this:
alert($("#something\\["+id+"\\]").parent()[0].parent()[0].attr("id"));
You can escape them using \\ or you could do something like this...
$(document.getElementById("something[" + id + "]"))
"Any of the meta-characters
!"#$%&'()*+,./:;<=>?#[\]^`{|}~
as a literal part of a name, it must be escaped with with two backslashes: \\.
For example, an element with id="foo.bar", can use the selector
$("#foo\\.bar")
" [source: jquery doc], and an element with id="foo[bar]" (even though not valid for W3C but recognised by JQuery), can use the selector
$("#foo\\[bar\\]")
(Just an asnwer like the many others, but all together :))

Categories

Resources