How can I replace text on a page using jQuery without replacing tags and text within tags such as: <a>,<input>,<button>,<textarea>,<input>,<select>.
For example, here is the HTML code
<html>
<head>
<title>Testing</title>
</head>
<body>
Hello, this is a test replacing {REPLACE_ME} with <b>{REPLACED}</b>.
<br/><br/>
I want {REPLACE_ME} and {REPLACE_ME} to be <b>{REPLACED}</b>, however I don't want this {REPLACE_ME} to become {REPLACED}.
Same with <textarea>{REPLACE_ME}</textarea>, it shouldn't change.
<br/><br/>
</body>
I have this jQuery to replace the text
var replaced = $("body").html().replace(/{REPLACE_ME}/gi,'<b>{REPLACED}</b>');
$("body").html(replaced);
Here it is on JSFiddle
http://jsfiddle.net/E8ZPY/
$('body, body *:not(a,button,textarea,option)').contents().filter(function() {
return this.nodeType === 3;
}).each(function() {
var escaped = $('<div></div>').text($(this).text()).html();
$(this).replaceWith(escaped.replace(/\{REPLACE_ME\}/gi,'<b>{REPLACED}</b>'));
});
JSFiddle
(I didn't need to include input, and I used option instead of select, since option is the one with text nodes for children.)
first add jquery file
apply "\" in regex pattern for special character
var replaced = $("body").html().replace(/\{REPLACE_ME\}/gi,'<b>{REPLACED}</b>');
// see here^^^__________^^^^
$("body").html(replaced);
see updated fiddle
var replaced = $("body").html().replace(/[^>]{REPLACE_ME}[^<]*/gi, '<b>{REPLACED}</b>');
$("body").html(replaced);
Related
I have a text variable in Javascript. Its name is text. It contains a whole HTML document. I've tried to find a jQuery selector that matches a contained div with id "mainContent":
var innerText = text.find('div[id=mainContent]');
Unfortunately, this does not work. The JavaScript somehow breaks at this point.
I've also tried it with:
var innerText = $(text).find('div[id=mainContent]');
But this also does break the JavaScript flow.
Does anybody have an idea?
If text is string then you should parse them first, you can do so using jQuery.parseHTML().
Demo:
var text = `<div><div id="mainContent">Test Container</div></div>`;
text = $.parseHTML(text);
console.log($(text).find('div#mainContent'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This should be a pretty easy thing to do, but it's not returning anything.
The function love() should kick off, getting a simple number prompt, and spitting out a list of a few items that uses that starting number.
the alert box correctly displays what I expect, but I want it to display on the screen.
(this is but a small section of what I'm after, but it's the kernel of it). No text is displaying in the IE, FF, or Chrome...
<script type="text/javascript">
function love()
{
var ncxElement="";
var idNumber = prompt("Enter beginning number","");
var myText=document.getElementById("here");
for (var i=1;i<5;i++)
{
ncxElement+=("<navPoint class=\"other\" id=\"page_"+idNumber+"\">\n");
idNumber++;
}
alert(ncxElement);
myText.innerHTML=ncxElement;
}
</script>
</head>
<body onload="love()">
<p id="here">Begin!</p>
</body>
If you want to display HTML on your page (without it being parsed), use .textContent instead of .innerHTML and wrap it in a <pre> (to preserve the line breaks).
Demo:
Change:
myText.innerHTML=ncxElement;
To:
myText.textContent=ncxElement;
Change:
<p id="here">Begin!</p>
To:
<pre id="here">Begin!</pre>
navPoints are not valid html elements, so the browser doesn't know what to do with them. They are being added to the DOM, just not displayed unless you add styling to do so.
If you replace them with paragraph tags, it works fine. See the example here.
<script type="text/javascript">
function love()
{
var ncxElement="";
var idNumber = prompt("Enter beginning number","");
var myText=document.getElementById("here");
for (var i=1;i<5;i++)
{
ncxElement+=("<p class=\"other\" id=\"page_"+idNumber+"\">"+idNumber+ "</p>");
idNumber++;
}
alert(ncxElement);
myText.innerHTML=ncxElement;
}
</script>
</head>
<body onload="love()">
<p id="here">Begin!</p>
</body>
Your function just wraps elements inside another. There is no text inside or outside these elements to dipslay.
Try inserting some random text before closing tags to see the result.
Btw, the elements are successfully placed in the p tag.
When a user create a message there is a multibox and this multibox is connected to a design panel which lets users change fonts, color, size etc.. When the message is submited the message will be displayed with html tags if the user have changed color, size etc on the font.
Note: I need the design panel, I know its possible to remove it but this is not the case :)
It's a Sharepoint standard, The only solution I have is to use javascript to strip these tags when it displayed. The user should only be able to insert links, images and add linebreaks.
Which means that all html tags should be stripped except <a></a>, <img> and <br> tags.
Its also important that the attributes inside the the <img> tag that wont be removed. It could be isplayed like this:
<img src="/image/Penguins.jpg" alt="Penguins.jpg" style="margin:5px;width:331px;">
How can I accomplish this with javascript?
I used to use this following codebehind C# code which worked perfectly but it would strip all html tags except <br> tag only.
public string Strip(string text)
{
return Regex.Replace(text, #"<(?!br[\x20/>])[^<>]+>", string.Empty);
}
Any kind of help is appreciated alot
Does this do what you want? http://jsfiddle.net/smerny/r7vhd/
$("body").find("*").not("a,img,br").each(function() {
$(this).replaceWith(this.innerHTML);
});
Basically select everything except a, img, br and replace them with their content.
Smerny's answer is working well except that the HTML structure is like:
var s = '<div><div>Link<span> Span</span><li></li></div></div>';
var $s = $(s);
$s.find("*").not("a,img,br").each(function() {
$(this).replaceWith(this.innerHTML);
});
console.log($s.html());
The live code is here: http://jsfiddle.net/btvuut55/1/
This happens when there are more than two wrapper outside (two divs in the example above).
Because jQuery reaches the most outside div first, and its innerHTML, which contains span has been retained.
This answer $('#container').find('*:not(br,a,img)').contents().unwrap() fails to deal with tags with empty content.
A working solution is simple: loop from the most inner element towards outside:
var $elements = $s.find("*").not("a,img,br");
for (var i = $elements.length - 1; i >= 0; i--) {
var e = $elements[i];
$(e).replaceWith(e.innerHTML);
}
The working copy is: http://jsfiddle.net/btvuut55/3/
with jQuery you can find all the elements you don't want - then use unwrap to strip the tags
$('#container').find('*:not(br,a,img)').contents().unwrap()
FIDDLE
I think it would be better to extract to good tags. It is easy to match a few tags than to remove the rest of the element and all html possibilities. Try something like this, I tested it and it works fine:
// the following regex matches the good tags with attrinutes an inner content
var ptt = new RegExp("<(?:img|a|br){1}.*/?>(?:(?:.|\n)*</(?:img|a|br){1}>)?", "g");
var input = "<this string would contain the html input to clean>";
var result = "";
var match = ptt.exec(input);
while (match) {
result += match;
match = ptt.exec(input);
}
// result will contain the clean HTML with only the good tags
console.log(result);
<html>
<head>
<title>Test</title>
</head>
<body>
hello
<script>
var str=document.body.innerHTML;
document.body.innerHTML=str.replace(/hello/g, "hi");</script>
</body>
</html>
In this code hello.html and hello will change hi.html and hi. I don't want to replace href="". How to write regular expression for that ?
The following regex replace wil do what you want:
<script>
var str=document.body.innerHTML;
document.body.innerHTML=str.replace(/(>[^<]*)hello/g, "\1hi");
</script>
But I think it is still fragile, and any solution with regex replaces in .innerHTML will be... Remember that regexes are always a hacky solution when trying to solve problems which involve html/xml parsing.
What do you need this for? Am I guessing correctly when I say that you want to replace all the text content of the document?
In that case, I would suggest getting a list of all content nodes from the DOM (see this question’s accepted answer for two ways to do this, one with jQuery and one without).
Using that, you could then apply your function to update each text node's contents:
var textNodes = getTextNodesIn(el);
for (var i = 0; i < textNodes.length; i += 1) {
textNodes[i].innerHTML = textNodes[i].innerHTML.replace(/hello/g, "hi");
}
This would leave all the HTML attributes unaffected. If you want to adjust those as well (excepting, of course, any href attribute), you could expand the getTextNodes function to include attributes (excepting href attributes) in the returned list of nodes.
I am using CEWP (webpart) and putting this code in there. But this code is not going inside <head> tag. I need to insert this code in <head> tag,
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$("*").each(function () { if ($(this).children().length == 0) { $(this).text($(this).text().replace('Respuesta','Responder')); } });
</script>
How can I do this? How this code will work in CEWP webpart?
Firstly, you can put the code in the <head> if you set it to run at document ready time.
However, it's still not going to work. You're iterating over all tags. Including <html>, which will be the first one selected by $('*').
So you read all the text inside the <html> element (ie. the entire document text), do a string replace on it, then write it back to the html text(). Replacing all the previous text and element content of the <html> element with a single simple text string. And thereby destroying every other element on the page. Oops.
What you want to do is find every text node and do a separate string replace on it:
$(document).ready(function() {
$('*').each(function() {
for (var i= this.childNodes.length; i-->0;) {
var child= this.childNodes[i];
if (child.nodeType===3) // TEXT_NODE
child.data= child.data.replace(/Respuesta/g, 'Responder');
}
});
});
(Note there are still a bunch of possible edge cases here with form fields and other elements where changing the text inside them might not do what you expect.)