Uncaught Error: Syntax error, unrecognized expression: # Something - javascript

So I have the following code inside a React Component
handleClick: function(e) {
e.preventDefault();
var post = new AisisWriter.Models.Post()
var title = this.stripHtml($('#post-title').val());
var content = this.stripHtml($('#post-content').val());
post.set({title: title, content: content});
post.save().then(this.created, this.failed);
},
stripHtml: function(content){
if($(content)[0] !== undefined){
return $(content)[0].textContent;
}
return content;
},
The essential point is that I am trying to strip out any HTML that you try and send back, but keep other symbols such as # and so on for Markdown.
Any ways, the #post-content contains the following: # Something and apparently Jquery doesn't like it: Uncaught Error: Syntax error, unrecognized expression: # Something
How can I get around this?
JSBin of the issue

let me start with the solution first:
function stripHtml(){
content = strip($('#content').val());
alert(content);
}
function strip(content){
var content2 = jQuery.parseHTML(content);
if(content2[0].data !== undefined){
// This will remove all the html assuming there is any
return content2[0].data;
}
// Return the content if their is no html
return content;
}
to explain, starting with jQuery >= 1.9 documentation:
jQuery(htmlString) versus jQuery(selectorString)
Prior to 1.9, a string would be considered to be an HTML string if it
had HTML tags anywhere within the string. This has the potential to
cause inadvertent execution of code and reject valid selector strings.
As of 1.9, a string is only considered to be HTML if it starts with a
less-than ("<") character. The Migrate plugin can be used to restore
the pre-1.9 behavior.
If a string is known to be HTML but may start with arbitrary text that
is not an HTML tag, pass it to jQuery.parseHTML() which will return an
array of DOM nodes representing the markup. A jQuery collection can be
created from this, for example: $($.parseHTML(htmlString)). This would
be considered best practice when processing HTML templates for
example. Simple uses of literal strings such as
$("Testing").appendTo("body") are unaffected by this change.
Bottom line: HTML strings passed to jQuery() that start with something
other than a less-than character will be interpreted as a selector.
Since the string usually cannot be interpreted as a selector, the most
likely result will be an "invalid selector syntax" error thrown by the
Sizzle selector engine. Use jQuery.parseHTML() to parse arbitrary
HTML.
and due to that you need to use jQuery.parseHTML function first and access your object (0) data element which contains the required text.

Related

JS - querySelector returns an illegal or invalid string error - but valid string for class name in console.log

I have the below code:
var parentdepth=depth-1;
var parentclass=classes[parentdepth];
console.log(parentclass); // prints 0-check
//el=e.querySelector('.'+parentclass);
console.log(parentclass); has no problem and prints the parent class name, but when I command the el=e.querySelector('.'+parentclass);, below error appears:
SyntaxError: An invalid or illegal string was specified
Note that console.log(e) is <section class="to y-12 y-3 0-check">.
Also, note that my goal is to append a child inside the class which matches 0-check in its name.
Your class name starts with a digit, and the CSS parser doesn't like that digit starting the class name in the selector string. You can use such a class name, but you'll need to express it differently, specifically as the JavaScript string "\\40-class". That'll result in the CSS selector parser seeing .\40-class, and that will not cause an error. It will correctly match an element like
<span class=0-check>Hello World</span>
It's interesting to note that the HTML markup itself will not cause an error, because the HTML parser doesn't care what the attribute value looks like.
From your question, it seems that you might be trying to test whether an element matches the selector. If so, then .querySelector() is not the API to use anyway; you want .matches() (which in older browsers was prefixed and called "matchesSelector"). So,
var matches = e.matches("." + parentclass);
That function returns a boolean.

jQuery / Javascript substitution 'Syntax error, unrecognized expression'

I am implementing jQuery chaining - using Mika Tuupola's Chained plugin - in my rails project (using nested form_for partials) and need to dynamically change the chaining attribute:
The code that works without substitution:
$(".employee_title_2").remoteChained({
parents : ".employee_title_1",
url : "titles/employee_title_2",
loading : "Loading...",
clear : true
});
The attributes being substituted are .employee_title_1 and .employee_title_2:
var t2 = new Date().getTime();
var A1 = ".employee_title_1A_" + t2;
var B2 = ".employee_title_2B_" + t2;
In ruby speak, I'm namespacing the variables by adding datetime.
Here's the code I'm using for on-the-fly substitution:
$(`"${B2}"`).remoteChained({
parents : `"${A1}"`,
url : "titles/employee_title_2",
loading : "Loading...",
clear : true
});
Which throws this error:
Uncaught Error: Syntax error, unrecognized expression:
".employee_title_2B_1462463848339"
The issue appears to be the leading '.' How do I escape it, assuming that's the issue? Researching the error message Syntax error, unrecognized expression lead to SO question #14347611 - which suggests "a string is only considered to be HTML if it starts with a less-than ('<) character" Unfortunately, I don't understand how to implement the solution. My javascript skills are weak!
Incidentally, while new Date().getTime(); isn't in date format, it works for my purpose, i.e., it increments as new nested form fields are added to the page
Thanks in advance for your assistance.
$(`"${B2b}"`).remoteChained({
// ^ ^
// These quotes should not be here
As it is evaluated to a string containing something like:
".my_class"
and to tie it together:
$('".my_class"')...
Same goes for the other place you use backtick notation. In your case you could simply use:
$(B2).remoteChained({
parents : A1,
url : "titles/employee_title_2",
loading : "Loading...",
clear : true
});
The back tick (``) syntax is new for Javascript, and provides a templating feature, similar to the way that Ruby provides interpolated strings. For instance, this Javascript code:
var who = "men";
var what = "country";
var famous_quote = `Now is the time for all good ${who} to come to the aid of their #{what}`;
is interpolated in exactly the same way as this Ruby code:
who = "men"
what = "country"
famous_quote = "Now is the time for all good #{who} to come to the aid of their #{what}"
In both cases, the quote ends up reading, "Now is the time for all good men to come to the aid of their country". Similar feature, slightly different syntax.
Moving on to jQuery selectors, you have some flexibility in how you specify them. For instance, this code:
$(".my_class").show();
is functionally equivalent to this code:
var my_class_name = ".my_class";
$(my_class_name).show();
This is a great thing, because that means that you can store the name of jQuery selectors in variables and use them instead of requiring string literals. You can also build them from components, as you will find in this example:
var mine_or_yours = (user_selection == "me") ? "my" : "your";
var my_class_name = "." + mine_or_yours + "_class";
$(my_class_name).show();
This is essentially the behavior that you're trying to get working. Using the two features together (interpolation and dynamic jQuery selectors), you have this:
$(`"${B2}"`).remote_chained(...);
which produces this code through string interpolation:
$("\".employee_title_2B_1462463848339\"").remote_chained(...);
which is not correct. and is actually the cause of the error message from jQuery, because of the embedded double quotes in the value of the string. jQuery is specifically complaining about the extra double quotes surrounding the value that you're passing to the selector.
What you actually want is the equivalent of this:
$(".employee_title_2B_1462463848339").remote_chained(...);
which could either be written this way:
$(`${B2}`).remote_chained(...);
or, much more simply and portably, like so:
$(B2).remote_chained(...);
Try this little sample code to prove the equivalence it to yourself:
if (`${B2}` == B2) {
alert("The world continues to spin on its axis...");
} else if (`"${B2}"` == B2) {
alert("Lucy, you've got some 'splain' to do!");
} else {
alert("Well, back to the drawing board...");
}
So, we've established the equivalency of interpolation to the original strings. We've also established the equivalency of literal jQuery selectors to dynamic selectors. Now, it's time to put the techniques together in the original code context.
Try this instead of the interpolation version:
$(B2).remoteChained({
parents : A1,
url : "titles/employee_title_2",
loading : "Loading...",
clear : true
});
We already know that $(B2) is a perfectly acceptable dynamic jQuery selector, so that works. The value passed to the parents key in the remoteChained hash simply requires a string, and A1 already fits the bill, so there's no need to introduce interpolation in that case, either.
Realistically, nothing about this issue is related to Chained; it just happens to be included in the statement that's failing. So, that means that you can easily isolate the failing code (building and using the jQuery selectors), which makes it far easier to debug.
Note that the Javascript syntax was codified just last year with ECMAScript version 6, so the support for it is still a mixed bag. Check your browser support to make sure that you can use it reliably.

DOMstring parser

I have a DOMstring object, text of some web page which I get from server using XMLHttpRequest. I need to cut a substring from it, which lies between some specific tags. Is there any easy way to do this? Such methods as substring() or slice() won't work in my case, because content of the web page is dynamic, so I can't specify the beginning and the end of substring (I only know that it's surrounded by <tag> and </tag>).
yourString.subtring(yourString.indexOf('<tag>') + 5, yourString.indexOf('</tag>'));
This should work, assuming you know the name of the surrounding tags.
A DOMString is just implemented as a string in most (all?) JavaScript browser environments so you can use any parsing technique you like, including regular expressions, DOMParser, and the HTML parser provided by libraries such as jQuery. For example:
function extractText(domString) {
var m = (''+domString).match(/<tag>(.*?)<\/tag>/i);
return (m) ? m[0] : null;
}
Of course, this is a terrible idea; you should really use a DOM parser, for example, with jQuery:
$('tag', htmlString).html();
[Edit] To clarify the above jQuery example, it's the equivalent of doing something like below:
function extractText2(tagName, htmlString) {
var div = document.createElement('div'); // Build a DOM element.
div.innerHTML = htmlString; // Set its contents to the HTML string.
var el = div.getElementsByTagName(tagName) // Find the target tag.
return (el.length > 0) ? el[0].textContent : null; // Return its contents.
}
extractText2('tag', '<tag>Foo</tag>'); // => "Foo"
extractText2('x', '<x><y>Bar</y></x>'); // => "Bar"
extractText2('y', '<x><y>Bar</y></x>'); // => "Bar"
This solution is better than a regex solution since it will handle any HTML syntax nuances on which the regex solution would fail. Of course, it likely needs some cross-browser testing, hence the recommendation to a library like jQuery (or Prototype, ExtJS, etc).
Assuming the surrounding tag is unique in the string...
domString.match(/.*<tag>(.*)<\/tag>.*/)[0]
or
/.*<tag>(.*)<\/tag>.*/.exec(domString)[0]
Seems like it should do the trick
As #Gus but improved, if you only have text and the tags are repited:
"<tag>asd</tag>".match(/<tag>[^<]+<\/tag>/);

Create 2d array from string

I have the following string :
[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],]
How can I create a 2d array of strings from it ?
EDIT
I've removed html tags since they're not the problem here. Also I'd like to do it without using any additional libs to keep it lightweight.
Except from the HTML tags in it, it would be valid JSON. You could remove the HTML tags and parse it using any library that handles JSON, like jQuery:
var arr = $.parseJSON(theString.replace(/<br\/>/g,''));
It would also be valid Javascript code with the HTML tags removed, so if you have full control over where the string comes from so that you are certain that it can never contain any harmful code, you could use the eval function to execute the string:
// Warning: 'eval' is subject to code injection vulnerabilities
var arr = eval(theString.replace(/<br\/>/g,''));
You will need to remove the <br/> from the string. Then you should be able to do:
var my2darray = eval(mystring);

space or not outputting in jQuery

I have the following being extracted from an XML and being put into a jQuery variable.
links.append($("<a href='"+alink+"'></a> ").html(desc));
...however the does not output onto the page. I need this to separate the hrefs on output
I have also tried
links.append($("<a href='"+alink+"'></a>").html(desc));
links.append($(" "));
Many thanks!
$("<a href='"+alink+"'></a> ")
Yeah, that's actually only creating the <a> element, and discarding the nbsp. When you pass a string into the $() function that looks like(*) HTML, jQuery creates the stretch of markup between the first < in the string and the last >. If you've got any leading or trailing content outside those, it gets thrown away(**). You could fool jQuery by saying:
$("<a href='"+alink+"'></a> <!-- don't ignore me! -->")
This doesn't seem to be documented anywhere, makes no sense whatsoever, and might be considered a bug, but it has been jQuery's normal behaviour for some time so it's probably not going away.
When you pass an HTML string to the append function (and other manipulation methods) directly instead of via the $ function, this behaviour does not occur. So:
links.append("<a href='"+alink+"'></a> ");
actually does keep the space. But a better way forward is to stop throwing HTML strings about, so you don't have to worry about alink containing ', < or & characters either, and work in a more DOM style:
var link= $('<a/>');
link.attr('href', alink);
link.html(desc);
links.append(link);
links.append('\xA0');
Or, more concisely, using jQuery 1.4's props argument shortcut:
links.append($('<a/>', {href: alink, html: desc}));
links.append('\xA0');
assuming that desc is really something that should contain HTML markup; if not, use text instead.
(I used \xA0, the JavaScript string literal way to include a character U+00A0 NON-BREAKING SPACE as it is a whole two characters shorter than the HTML entity reference. Woohoo!)
(*: how does it tell that a string is HTML? Why, by checking to see if there's a < and > character in it, in that order, of course. Meaning it'll get fooled if you try to use a selector that has those characters in. Brilliant, jQuery, brilliant.(***))
(**: why? see line 125 of jQuery 1.4.2. It builds the HTML fragment from match[1]—the group from the first < to the last > in quickExpr—and not the original string or match[0].)
(***: I'm being sarcastic. The insane over-overloading of the $ function is one of jQuery's worst features.)
You better style with css, something like :
links.append($("<a class='link' href='"+alink+"'></a>").html(desc));
in css :
a.link {
padding-left : 5px ;
padding-right : 5px ;
}
you could try
 

Categories