I am trying to build a custom HTML/Javascript command using the following Javascript (for now, "dialogText" contains the name of a vegetable, but it may later contain HTML tags too):
str = str + "<span onClick=showDialog('"+dialogText+"')>";
When dialogText is only one word long (i.e. "Basil"), this works correctly, giving the following result:
<span onclick="showDialog('Basil')">
But when dialogText includes more than one word (i.e. "Beet root"), this fails. The result is syntactically invalid and generates a Javascript error:
<span onclick="showDialog('Beet" root')="">
Why does this happen (where did the equals sign come from?)?
And how can I change the code so that it works?
You aren't looking at the HTML you are generating, you are converting that HTML to a DOM and then serializing it back to HTML.
Since you have a " as data in the attribute value, but haven't represented it as a character reference ("), and the value is limited with " - the " ends the attribute.
You then start a new attribute.
Since the next attribute doesn't have a value, it gets assigned an empty string when the browser attempts to error correct.
In general, avoid mashing strings together to generate HTML for conversion to a DOM. Use DOM methods directly instead.
var span = document.createElement('span');
span.addEventListener('click', function (event) {
showDialog(dialogText);
});
Related
I am working on an autocomplete used inside a textarea. I know there is some autocompletes already created, but anyway.
It works well, but if when I'm typing something and I select one or many characters and delete it, a appears at the end of my string (or where I was inside it). I tried to replace it while retrieving my html with replaceAll, but it doesn't work (There is not this special char when I use an indexOf). The problem is he doesn't find any result because of this char. Let's see an exemple :
This is my array (a little bit cut but we don't really care)
let array = [{
name: "test",
value: "I'm a test value"
},
{
name: "valueorange",
value: "I'm just an orange"
},
// This is how I get the contents of my span (I tried both innerHTML and innerText, same results).
// Same while using .text() or .html() with jquery
let value = jqElement.find("#searching-span")[0].innerHTML.substring(1).toLowerCase();
value = value.replaceAll(" ", " ");
value = value.replaceAll("", "");
I can replace every without any problems. Finally I check with a loop if there is some value with indexOf on each value, and if it returns anything I push it and get it in a new array. But when I have I have no results.
Any idea how I can resolve it ?
I tried to be clear, I hope my english wasn't so bad, sorry if I made many mistakes !
Character entities and HTML escaped characters like and appearing in HTML source code are converted by the HTML parser into unicode characters like \u00a0 and \ufeff before being inserted into the DOM.
If replacing them in JavaScript, use their unicode characters, not HTML escape sequences, to match them in DOM strings. For example:
p.textContent = p.textContent.replaceAll("\ufeff", '*'); // zwj
p.textContent = p.textContent.replaceAll("\xa0", '-'); // nbsp
<p id="p"> </p>
Note that zero width joiners are uses a lot in emoji character sequences and arbitrarily removing may break emoji character decoding (although decoding badly formed emoji strings is almost a prerequisite for handling emojis in the wild).
Second note: I am not suggesting this as a means of circumventing badly decoding characters that have been encoded using a Unicode Transform Format. Making sure decoding is performed correctly is always a better option.
I have a html page in which I need to pass a String variable to javascript function. This works until String does not have a special charecter.
<html>
<head>
<script>
function test(v){
alert(v);
}
</script>
</head>
<body>
<input type="button" value="Test Button" onClick="test('BlahBlah')"/>
</body>
</html>
As soon as I change onClick like below, it stops working.
onClick="test('Blah'Blah')"
Any solution for this problem. Please take a note parameter which is being passed to JavaScript function is dynamic.Source of Parameter is backend and I cannot change that peice of code. Second thing even if put escape it still does not work. My problem is I have to retian the special charecter for some processing at backend
There are two layers to this:
The content of onClick attributes, like all attributes, is HTML text. That means that any character that's special in HTML (like <) must be replaced with an HTML entity (e.g., <). Additionally, if you use double quotes around the attribute value, any double quotes within the value must be replaced with entities ("); if you used single quotes around the attribute, you'd need to replace ' with '.
Your attribute contains a JavaScript string literal. That means that any characters that are special inside JavaScript string literals must be escaped according to the JavaScript rules. Since you've used single quotes to delimit the JavaScript string, for instance, you have to escape any single quotes in the string with a backslash.
I'm assuming that HTML is generated server-side. If so, the work above must be done server-side, when building the HTML of the page. You haven't said what server-side tech you're using, so it's hard to point you at solutions that your server-side tech/environment might provide.
In the simple case of your
onClick="test('Blah'Blah')"
...you just need to add the backslash within the JavaScript string
onClick="test('Blah\'Blah')"
...but that's just that one specific case.
The dramatically simpler option is to not put JavaScript code in attribute values. Instead, use modern techniques (addEventListener, attachEvent) to hook up JavaScript code.
But if you must use an onClick attribute, avoid having text in it (or deal with the complexities above); have it call a function defined in a script element that then has the text, as you then have only the one layer (#2 above) to deal with.
Source of Parameter is backend and I cannot change that peice of code.
That backend is broken and needs fixing.
If:
the backend is only producing invalid JavaScript code (not invalid HTML)
and the code consists of a single function call
and the code is always a single function call
and the function call always has a single string literal argument
and that argument is always delimited with single quotes
and the single quotes within the string are never correctly escaped
...we might be able to salvage it client-side. But my guess is that the backend will also produce invalid HTML, for instance when the text has a " in it. (We can't do anything about that, because the attribute value will be chopped off at that point.)
But let's keep a good thought: Given the ridiculous list of caveats above, this might do it:
var elm = document.getElementById("the-div");
var code = elm.getAttribute("onclick");
var m = code.match(/^([^(]+)\('(.*)'\)$/);
if (m) {
code = m[1] + "('" + m[2].replace(/'/g, "\\'") + "')";
}
elm.setAttribute("onclick", code);
Live Example:
function foo(str) {
alert(str);
}
var elm = document.getElementById("the-div");
var code = elm.getAttribute("onclick");
var m = code.match(/^([^(]+)\('(.*)'\)$/);
if (m) {
code = m[1] + "('" + m[2].replace(/'/g, "\\'") + "')";
}
elm.setAttribute("onclick", code);
<div id="the-div" onclick="foo('blah'blah')">Click me</div>
Well this is an very common problem you wanted to add single quotes inside single quotes to do this you have to escape that Sigle quotes to do that you have to put an forward slash.
onClick="test('Blah\'Blah')"
I’m transforming dumb quotes into smart quotes in a contenteditable but the problem is that it also replaces them inside HTML elements like:
<a href=“something” title=“something”
thus making them invalid. I want to only do it for user’s text. Here’s the catch. I have to keep the original formatting elements, so I can’t do something like:
clean($('#something_container').text());
This would remove all HTML elements (formatting) when returned. Here’s the code that I have:
content = clean($('#post_content').html());
$('#post_content').html(content);
// replaces ", ', --, <div> with <p>
function clean(html) {
html = html.replace(/'\b/g, "\u2018") // opening singles
.replace(/\b'/g, "\u2019") // closing singles
.replace(/"\b/g, "\u201c") // opening doubles
.replace(/\b"/g, "\u201d") // closing doubles
.replace(/--/g, "\u2014") // em-dashes
.replace(/<div>/g, "<p>") //<div> to <p>
.replace(/<\/div>/g, "</p>"); //</div> to </p>
return html;
};
What would be the best (most efficient) way to replace dumb quotes only in user’s text and skip the HTML tags like <img src="" />? Thanks!
Here’s a possible approach (don’t know about efficiency, but if you only handle strings typed in by users by hand, they probably won’t be very long, so it shouldn’t matter):
split your string into non-overlapping chunks: HTML tags vs. the rest
“educate quotes” only in the non-tags, leaving the tags alone
put the string back together
If the HTML you’re dealing with is well-formed (in particular, if there’s no "<" floating around), the splitting into chunks is easy:
var html = '<p style="color:red">some "quotes" in here</p>'
var chunks = html.match(/(<.+?>|[^<]+)/g)
// returns Array: ['<p style="color:red">', 'some "quotes" in here', '</p>']
Then, given your clean() function that handles the replacements, you can say:
cleaned = chunks.map(function(chunk){
return /</.test(chunk) ? chunk : clean(chunk)
}).join('');
to apply your replacements anywhere except between < and >.
I was inspecting this site in firebug. Inside the third <script/> tag in the head section of the page , I found an object variable declared in the following way ( truncated here however by me) :
var EM={
"ajaxurl":"http:\/\/ipsos.com.au\/wp-admin\/admin-ajax.php",
"bookingajaxurl":"http:\/\/ipsos.com.au\/wp-admin\/admin-ajax.php",
"locationajaxurl":"http:\/\/ipsos.com.au\/wp-admin\/admin-ajax.php?action=locations_search",
"firstDay":"1","locale":"en"};
The utility of the variable is unknown to me. What struck me is the 3 urls presented there. Why are the backward slashes present there? Couldn't it be something like :
"ajaxurl" : "http://ipsos.com.au/wp-admin/admin-ajax.php"
?
In a script element there are various character sequences (depending on the version of HTML) that will terminate the element. </script> will always do this.
<\/script> will not.
Escaping / characters will not change the meaning of the JS, but will prevent any such HTML from ending the script.
The \/\/ is to avoid the below scenario:
when the url looks something similar to "ajaxurl" : "http://google.com/search?q=</script>"
Try copy paste the url in browsers address bar. This is handled correctly. Otherwise, You might end up getting script errors and page might not work as you've expected.
imagine DOM manipulators replacing the value as it is in the src attribute of the script tag and then the javascript engine reporting multiple errors because that particular script referenced might not get loaded due to incorrectly defined src value
Hope this helps.
Life would be hectic without these lil things
It is used to escape the characters..
The backslash () can be used to insert apostrophes, new lines, quotes, and other special characters into a string.
var str = " Hello "World" !! ";
alert(str)
This won't work..
You have to escape them first
var str = " Hello \"World\" !! ";
alert(str) ; \\ This works
In terms of Javascript / and <\/ are identical inside a string. As far as HTML is concerned </ starts an end tag but <\/ does not.
I have a custom attribute that is being filled from a database. This attribute can contain an embedded single quote like this,
MYATT='Tony\'s Test'
At some pont in my code I use jquery to copy this attribute to a field like this,
$('#MY_DESC').val($(recdata).attr('MYATT'));
MY_DESC is a text field in a dialog box. When I display the dialog box all I see in the field is
Tony\
What I need to see is,
Tony's Test
How can I fix this so I can see the entire string?
Try:
MYATT='Tony's Test'
I didn't bother verifying this with the HTML spec, but the wikipedia entry says:
The ability to "escape" characters in this way allows for the characters < and & (when written as < and &, respectively) to be interpreted as character data, rather than markup. For example, a literal < normally indicates the start of a tag, and & normally indicates the start of a character entity reference or numeric character reference; writing it as & or & or & allows & to be included in the content of elements or the values of attributes. The double-quote character ("), when used to quote an attribute value, must also be escaped as " or " or " when it appears within the attribute value itself. The single-quote character ('), when used to quote an attribute value, must also be escaped as ' or ' (should NOT be escaped as ' except in XHTML documents) when it appears within the attribute value itself. However, since document authors often overlook the need to escape these characters, browsers tend to be very forgiving, treating them as markup only when subsequent text appears to confirm that intent.
In case you won't use double-quotes, put your custom attribute into them :)
If not, I suggest escape the value.
Before setting the value of your text field, you might try running a regular expression against the string to remove all backslashes from the string.
If you do this:
alert($(recdata).attr('MYATT'));
You will see the same result of "Tony\" meaning that the value isn't being properly consumed by the browser. The escaped \' value isn't working in this case.
Do you have the means to edit these values as they are being produced? Can you parse them to include escape values before being rendered?