Find + replace content of an element without losing events - javascript

I have a function that reads the content of an element, replaces a word with a link and then rewrites the content back into the element. Obviously this means that all events that were previously set are lost.
Does anyone know of a function/method that could find and replace the content of an element without losing the events?
Edit: Without using a library
Here is my current code that does not destroy the events but turns <, for example, into <, so I can not append HTML. This is the closest I have got:
element.appendChild(document.createTextNode(content));
My original code worked but got rid of the events:
element.innerHTML += content;

By using jQuery you could do it with the text() method
var str = $('#element-id').text();
str = yourReplaceFunction(str);
$('#element-id').text(str);
Edit:
Another option would the innerHTML property. It's not very elegant but works nevertheless.
var strElem = document.getElementById('element-id');
var str = strElem.innerHTML;
str = yourReplaceFunction(str);
strElem.innerHTML = str;
Edit2:
Yet another option would be to wrap the text you want to replace inside of a separate tag, for example <span>.
<div id="container">
<a id="link-with-events">Link</a>
<span id="replaceable">The Text Gets Replaced</span>
<a id="more-links-with-events">Another Link</a>
</div>
Then you'd simply access and replace the contents of the span tag, leaving the surrounding elements untouched.

Assuming the tag contains just text (and not additional tags):
element.firstChild.nodeValue=content;
See https://jsfiddle.net/Abeeee/ubj6hte4/

Related

HTML DOM manipulation : properly replace tag by heading tag

I want to replace some tag-inside-a-paragraph-tag by a heading-tag-enclosed-by-a-paragraph tag. This would result in proper W3C coding, but it seems that jQuery is not able to manipulate the DOM in the right way!? I tried several ways of (jQuery) coding, but i can't get it to work ..
Original code:
<p>some text <span>replace me</span> some more text</p>
Desired code:
<p>some text</p><h2>my heading</h2><p>some more text</p>
Resulting code by jQuery replaceWith():
<p>some text<p></p><h2>my heading</h2><p></p>some more text</p>
Demo: http://jsfiddle.net/foleox/J43rN/4/
In this demo, look at "make H2 custom" : i expect this to work (it's a logical replace statement), but it results in adding two empty p-tags .. The other 2 functions ("make code" and "make H2 pure") are for reference.
Officially the W3C definition states that any heading tag should not be inside a paragraph tag - you can check this by doing a W3C validation. So, why does jQuery add empty paragraph tags? Does anybody know a way to achieve this? Am i mistaken somehow?
You can achieve this with this code. However it's pretty ugly:
$('.replaceMe').each(function() {
var $parent = $(this).parent(),
$h2 = $(this).before('$sep$').wrap('<h2>').parent().insertAfter($parent);
var split = $parent.html().split('$sep$');
$parent.before('<p>' + split[0] + '</p>');
$h2.after('<p>' + split[1] + '</p>');
$parent.remove();
});
http://jsfiddle.net/J43rN/5/
If you read the jQuery docs, you will find:
When the parameter has a single tag (with optional closing tag or
quick-closing) — $("<img />") or $("<img>"), $("<a></a>") or $("<a>")
— jQuery creates the element using the native JavaScript
createElement() function.
So that is exactly what it is doing. And as I said in my comment, you can't change a parent node from a child node, you're altering the DOM here, not HTML code. So you'll need to either use replaceWith on the parent node and replace everything or use something like remove and append to split it up in multiple elements which you append after each other.
Try this:
var temp = "<p>some text <span>replace me</span> some more text</p>";
temp.replace(/(\<span\>replace me\<\/span\>)/gi, '</p><h2>my heading</h2><p>');
This will do a case insensitive replace for multiple occurences as well.
Read more about capturing groups here
Original credit to this question!
Please try this I have updated the http://jsfiddle.net/J43rN/6/ example by the below java script function please check I hope it will work for you
function fnMakeCode() {
$('#myP #replaceMe').html("<code id='replaceMe'>My Code</code>");
}
function fnMakeH2pure() {
$('#myP #replaceMe').html("<h2 id='replaceMe'>My H2 pure</h2>");
}
function fnMakeH2custom() {
$('#replaceMe').html("<p></p>").html("<h2>My H2 custom</h2>");
}

How can I Strip all regular html tags except <a></a>, <img>(attributes inside) and <br> with javascript?

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);

Replace html placeholder text with html element using javascript

I have a scenario where i have in my page a placeholder text that I will replace after the page is fully loaded.
My problem is that the text i need to replace is a plugin of the recaptcha image, for example:
I have the text loading... which will be replaced by:
<recaptcha:recaptchacontrol ID='recaptcha' runat='server' PublicKey='kfldsjfh4378qyf43h4eidfhew' PrivateKey='sdflkdsfy908s6dfdsfkj' Theme='clean' />
I couldn't find a way to do so, any help will be appreciated.
found the answer in chat:
as the <recaptcha:...> tags are parsed by some server side plugin, they were not rendered after writing them in client side JS. so replacing works fine, but plugin didn't...
you can do any string operations (like search and replace) on document.body.innerHtml:
document.body.innerHtml = document.body.innerHtml.replace(/Loading\.\.\./g,
"<recaptcha...>");
Wrap your "Loading..." text in a <span> with a unique id, such as
<span id="removeme">Loading...</span>
Then, if you don't want to do much DOM-fu with that complex, namespaced tag, you can do the following:
var removeme = document.getElementById('removeme');
removeme.innerHTML = "<recaptcha:recaptchacontrol ...";
var recaptchaThing = removeme.firstChild;
removeme.removeChild(recaptchaThing);
var parent = removeme.parentNode;
parent.insertBefore(recaptchaThing, removeme);
parent.removeChild(removeme);
This will replace the <span> with the <recaptcha:recaptchacontrol> element, after letting the browser figure out how to build the DOM for that bizarre element. If it turns out <recaptcha:recaptchacontrol> can't be placed inside of a <span> element, make it a <div style="display:inline"> instead.

string search in body.html() not working

Hi here is my total work to search a string in HTML and highlight it if it is found in document:
The problem is here
var SearchItems = text.split(/\r\n|\r|\n/);
var replaced = body.html();
for(var i=0;i<SearchItems.length;i++)
{
var tempRep= '<span class="highlight" style="background-color: yellow">';
tempRep = tempRep + SearchItems[i];
tempRep = tempRep + '</span>';
replaced = replaced.replace(SearchItems[i],tempRep); // It is trying to match along with html tags...
// As the <b> tags will not be there in search text, it is not matching...
}
$("body").html(replaced);
The HTML I'm using is as follows;
<div>
The clipboardData object is reserved for editing actions performed through the Edit menu, shortcut menus, and shortcut keys. It transfers information using the system clipboard, and retains it until data from the next editing operation replace s it. This form of data transfer is particularly suited to multiple pastes of the same data.
<br><br>
This object is available in script as of <b>Microsoft Internet Explorer 5.</b>
</div>
<div class='b'></div>
If I search for a page which is pure or without any html tags it will match. However, if I have any tags in HTML this will not work.. Because I am taking body html() text as the target text. It is exactly trying to match along with html tags..
In fiddle second paragraph will not match.
First of all, to ignore the HTML tags of the element to look within, use the .text() method.
Secondly, in your fiddle, it wasn't working because you weren't calling the SearchQueue function on load.
Try this amended fiddle

javascript innerHTML adding instead of replacing

quick question, i know we can change the content of a
<div id="whatEverId">hello one<div> by using:
document.getElementById("whatEverId").innerHTML="hello two";
now, is there a way I can ADD stuff to the div instead of replacing it???
so i can get
<div id="whatEverId">hello one hello two<div>
(using something similar of course)
<div id="whatever">hello one</div>
<script>
document.getElementById("whatever").innerHTML += " hello two";
</script>
Notice that using element.innerHTML += 'content' would empty inputs and textareas to their default, blank state, unclick checkboxes, as well as removing any events attached to those elements (such as onclick, on hover etc.) because the whole innerHTML would be reinterpreted by the browser, which means .innerHTML is emptied and filled again from scratch with the combined content.
If you need to keep the state, you'd need to create a new element (a <span> for instance) and append it to the current element, as in:
let newElement = 'span'
newElement.innerHTML = 'new text'
document.getElementById('oldElement').appendChild(newElement)
document.getElementById("whatEverId").innerHTML = document.getElementById("whatEverId").innerHTML + "hello two" + document.getElementById("whatEverId").innerHTM ;
What jcomeau_ictx suggested is an inefficient way of editing the innerHTML.
Check Ben cherry's PPT http://www.bcherry.net/talks/js-better-faster
The correct way will be detaching the element and making changes to it and then appending it back to the parent node.
Use https://gist.github.com/cowboy/938767 Native javascript from this gist to
detach element.
If you are appending, you can just change your = to a +=
document.getElementById("whatEverId").innerHTML += 'hello two';
If prefixing
document.getElementById("whatEverId").innerHTML = 'hello two' + document.getElementById("whatEverId").innerHTML;
Although I would highly recommend using jQuery or MooTools javascript libraries/frameworks to do this sort of thing. If you're adding tags not just text nodes, then you should use the DOM createElement or one of the aforementioned libraries/frameworks.
You can do it by appending div string like this..
document.getElementById('div_id').innerHTML += 'Hello Two';

Categories