escape characters not working with innerHTML - javascript

I have a string containing HTML escape characters (for <and >) that I am trying to render inside a div using innerHTML. the escaped characters are not supposed to be rendered like normal html, but rather as text. However, they still do, so is there a work around for this?
NOTE: the objective is to display a few (meaning not all) tags as normal text.
Here is an example implementation:
var string = "<div>yolo</div>";
string = string.replace(/</g, '<'); //replaces all '<' with its escape character
string = string.replace(/>/g, '>'); //replaces all '>' with its escape character
string = string.replace(/(=|%|\/|\*|-|,|;|\+|<|>)/g, "<span class=\"sc\">$1</span>");
//the last line adds special formatting
//to certain characters using CSS (not shown)
//and a span tag with class, "sc".
//this is the reason that I cannot just simply
//use innertext instead of innerhtml
document.body.innerHTML = string;
P.S. please give an answer in pure JavaScript. I do not care if you add a jQuery solution, I just need a pure javascript one.

It doesn't work properly because you're replacing the ;s with <spans>. Try replacing the whole < first to prevent your span-replacer from breaking the entities.
e.g.
var string = "<div>yolo</div>";
string = string.replace(/</g, '<'); //replaces all '<' with its escape character
string = string.replace(/>/g, '>'); //replaces all '>' with its escape character
string = string.replace(/(<|>|=|%|\/|\*|-|,|;|\+|<|>)/g, "<span class=\"sc\">$1</span>");
//the last line adds special formatting
//to certain characters using CSS (not shown)
//and a span tag with class, "sc".
//this is the reason that I cannot just simply
//use innertext instead of innerhtml
document.body.innerHTML = string;
.sc {
color: red;
font-weight: bold;
}

If you use jQuery, you may want to deal with text() instead of innerHTML().

Related

JavaScript Regex to Extract Text from Style HTML Tags

I am trying JavaScript RegEx to extract all text between CSS HTML tags:
var rawHtml = "<style type='text/css'> div { color: red; } </style>";
//var rawHtml = "<style type=\"text/css\"> div { color: red; } </style>";
//var rawHtml = "<style> div { color: red; } </style>";
var cssString = rawHtml.match(/<style[^>]*>(.+?)<\/style>/gi);
console.log(cssString);
The style tag may have attributes as well as single or double quotes. How to successfully extract for all use cases? My Regex is not picking it up.
Just use DOMParser instead:
const rawHTML = "<style type='text/css'> div { color: red; } </style>";
const doc = new DOMParser().parseFromString(rawHTML, "text/html");
const matches = [...doc.querySelectorAll('style')]
.map(style => style.textContent);
console.log(matches);
I think the main problem in your code is that you've set cssString to the full match rather than to the part matched in parentheses. You need something like:
var innerHTML = cssString ? cssString[1] : "";
The important part here is that the parenthetical match from your regex - (.+?) - is stored in backreference 1, i.e. in cssString[1], not in cssString.
However, I'd also make a small change to make your regex more robust:
/<style[^>]*>([^<]+)<\/style>/i
Here we're matching "anything that is not a <" in the parenthetical backreference. Since the code inside the style tags could go over more than one line, .* or .+ is not a great way to match "everything", since in JavaScript, the dot doesn't match line breaks. You can use negated character classes instead. To match absolutely anything, use [\s\S]* (anything none or as many times as possible) or [\s\S]+ (anything at least once and as many times as possible). However, here you want to make sure the match stops at the next <. I eliminated the question mark, because you don't need to make the search lazy if the regex can't jump past the next <.
EDIT: I've just realized you're using the global flag, which changes things a bit. Above answer assumes a single match, without the /g flag. Will add some info about global matching shortly.
So, to iterate over all <style> elements in a document that may have several, with your regex, you need to do something like this:
var styleMatchRegExp = /<style[^>]*>([^<]+)<\/style>/ig;
var match = styleMatchRegExp.exec(rawHtml);
var cssStringArray = [];
while (match != null) {
cssStringArray.push(match[1]);
match = styleMatchRegExp.exec(rawHtml);
}
You'll end up with an array (cssStringArray) containing the css in each of the <style>...</style> groups in your document.

Getting :before content and printing special characters from content

I would like to get the content from my :before tag. I know some will say it's not a real (pseudo) element but there is a way in JS but can some one help me do it in JQ because I have multiple tags and I want to iterate with $.each...
Here is how I got the content in JS
window.getComputedStyle(document.querySelector('i'), ':before').getPropertyValue('content')
How can I do this in JQ?
Here is what I tried:
$.each($('div'),function(){
$(this).find('i:before').css('content');
});
Print a special char?
When I get the content I would like to print it, the problem is it's a special character and I would like to get a real code.
My content has a code like this: \e002. So I would like to print it like that not .
Iterate $.each($('div i') instead of $.each($('div'), so you can avoid using find() within the iterator.
You can then use your window.getComputedStyle() code on this:
window.getComputedStyle(this, ':before').getPropertyValue('content')
You'll then be left with a Unicode string, which brings us to the second part of your question.
You can use charCodeAt() to view this string character by character, which gives the following for \e002:
34
57346
34
The 34s represent double-quotes, which you can ignore.
57346 is the decimal equivalent of hexadecimal e002. You can use toString(16) to convert it to hex.
All that's left is to prepend the \ in front.
So our code becomes:
$.each($('div i'),function() {
var s = window.getComputedStyle(this, ':before').getPropertyValue('content'),
char = '\\' + s.charCodeAt(1).toString(16);
console.log(char); // \e002
});
Snippet:
$.each($('div i'),function() {
var s = window.getComputedStyle(this, ':before').getPropertyValue('content'),
char = '\\' + s.charCodeAt(1).toString(16);
console.log(char); // \e002
});
i:before {
content: '\e002';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<i>Our italic node</i>
</div>

How to replace string with the main string with javascript

Trying to do something like making html codes usable in my forum. I want to make text hidden when wrapped with the [hidden] string and after clicking on a button the original text between the [hidden] and [/hidden] tags should be shown. I try using
var res = str.replace("[hidden]$1[/hidden]", "$1");
You need to escape the brackets, [], otherwise they will be interpreted as a character set.
var string = '[hidden]test[/hidden]';
string = string.replace(/\[hidden\](.*?)\[\/hidden\]/g, '$1');
// "test"

Removing non-break-spaces in JavaScript

I am having trouble removing spaces from a string. First I am converting the div to text(); to remove the tags (which works) and then I'm trying to remove the "&nbsp" part of the string, but it won't work. Any Idea what I'm doing wrong.
newStr = $('#myDiv').text();
newStr = newStr.replace(/ /g, '');
$('#myText').val(newStr);
<html>
<div id = "myDiv"><p>remove space</p></div>
<input type = "text" id = "myText" />
</html>
When you use the text function, you're not getting HTML, but text: the entities have been changed to spaces.
So simply replace spaces:
var str = " a     b   ", // bunch of NBSPs
newStr = str.replace(/\s/g,'');
console.log(newStr)
If you want to replace only the spaces coming from do the replacement before the conversion to text:
newStr = $($('#myDiv').html().replace(/ /g,'')).text();
.text()/textContent do not contain HTML entities (such as ), these are returned as literal characters. Here's a regular expression using the non-breaking space Unicode escape sequence:
var newStr = $('#myDiv').text().replace(/\u00A0/g, '');
$('#myText').val(newStr);
Demo
It is also possible to use a literal non-breaking space character instead of the escape sequence in the Regex, however I find the escape sequence more clear in this case. Nothing that a comment wouldn't solve, though.
It is also possible to use .html()/innerHTML to retrieve the HTML containing HTML entities, as in #Dystroy's answer.
Below is my original answer, where I've misinterpreted OP's use case. I'll leave it here in case anyone needs to remove from DOM elements' text content
[...] However, be aware that re-setting the .html()/innerHTML of an element means trashing out all of the listeners and data associated with it.
So here's a recursive solution that only alters the text content of text nodes, without reparsing HTML nor any side effects.
function removeNbsp($el) {
$el.contents().each(function() {
if (this.nodeType === 3) {
this.nodeValue = this.nodeValue.replace(/\u00A0/g, '');
} else {
removeNbsp( $(this) );
}
});
}
removeNbsp( $('#myDiv') );
Demo

JavaScript string replace() not working when replacing variable

I'm trying to create a JavaScript script for highlighting certain text on a page. Right now I'm having issues trying to replace text (from the body html) with other text. I want to replace all instances of each item in the array highlights with some other text.
The code that I'm using is:
var responseText = server.responseText;
var highlights = responseText.split("\n");
var text = document.body.innerHTML;
for (i in highlights) {
if (highlights[i].length > 1) {
var exp = new RegExp(highlights[i], "g");
console.log(exp);
console.log(highlights[i]);
text = text.replace(exp, "XXXXXXXXXXX");
}
}
document.body.innerHTML = text;
Currently, I am getting the correct value printouts for highlights[i] and I think I am for the regular expression exp; if highlights[i] is 'Remember', then the printout I'm getting for exp is '/Remember/g' (without the quotation marks) -- but it's not replacing the word 'Remember' on the page. 'And if I replace highlights[i] in the new RegExp() with simply the string "Remember" it works correctly. Any ideas on what's wrong?
EDIT:
I solved the problem! When creating the RegExp() I passed in highlights[i].trim() instead of just highlights[i] to get rid of whitespace at the beginning/end and it appears to be working now.
There is some problem with your multiline server.responseText .
I replaced the input with spaces instead of newlines, and all the replacements work fine :
http://jsfiddle.net/XTdgJ/1/

Categories

Resources