in my project i have an xmlhttpresponse object with some node, and i need to print element of one (serps) in a div obj but formatted.
Node is like this:
now i have to create a div where store serps info like response.serps1.headline+""+response.serps1.url+""+response.serps2.headline+""+response.serps2.url ecc ecc and in my code i have tried like this:
//Data
var divSerp3 = createElement('div', 'divSerp3', 'divSerp3css');
if (typeof(response.serps) === 'undefined' || response.serps === null) {
tse3 = document.createTextNode("NO DATA");
} else {
tse3 = document.createTextNode(response.serps[1].headline+" <br>"+response.serps[1].url+"<br><br>"+response.serps[2].headline+" <br>"+response.serps[2].url+"<br><br>"+response.serps[3].headline+"<br>"+response.serps[3].url+"<br><br>"+response.serps[4].headline+"<br>"+response.serps[4].url+"<br><br>"+response.serps[5].headline+" <br>"+response.serps[5].url);
}
divSerp3.appendChild(tse3);
but the result is like:
How can i cycle my entire serps node and insert data in a formatted mode into my div??
Html won't be rendered correctly in a TextNode.. as the element's name says by itself, its content is basically textual.
I suggest you to append <br> separately and I would not use createTextNode().. I'd append as many childs as you need using the appropriate html elements (like spans, paragraphs, etc..) and filling their content with $.html('your content') function if you are using jQuery library or element.innerHtml if you are working with pure javascript.
Hope it helps ;)
Instead of creating a text node, create an element and use innerHTML.
var divSerp3 = createElement('div', 'divSerp3', 'divSerp3css');
if (typeof(response.serps) === 'undefined' || response.serps === null) {
tse3 = document.createTextNode("NO DATA");
} else {
tse3 = document.createElement('span');
tse3.innerHTML = response.serps[1].headline+" <br>"+response.serps[1].url+"<br><br>"+response.serps[2].headline+" <br>"+response.serps[2].url+"<br><br>"+response.serps[3].headline+"<br>"+response.serps[3].url+"<br><br>"+response.serps[4].headline+"<br>"+response.serps[4].url+"<br><br>"+response.serps[5].headline+" <br>"+response.serps[5].url);
}
divSerp3.appendChild(tse3);
You're creating a TextNode which will take all of your html and parse it as text. You want to document.createElement('br') and append those instead of doing +"<br><br>"
HTML won't render when inside a text node. See Is it possible to get the the createTextNode method to render html tags?
You could create <br> elements and append them.
Or you could use newlines instead of <br> and use CSS white-space: pre-wrap;
Related
I use a WYSIWYG editor in my page. I collect the HTML in a callback function. I would like now change the content with jQuery. For that I do a find() to select the text I want to replace. Then I want to replace it, but I'm stuck!
$('.save').click(function() {
var html = $('#edit').editor('get_html');
console.log(html)
var ma_societe_OLD = $(html).find('.ma_societe').attr('data');
var ma_societe = $(html).find('.ma_societe').text();
if (ma_societe === ma_societe_OLD) {
$(html).find('.ma_societe').text('dfdsfsdfds');
}
console.log(html);
});
As you can see, I want to replace the content of the span with my own text. But it's not working.
The issue is because you're making amendments to the jQuery object, but you never store those changes anywhere. You either create a new jQuery object containing the original, unchanged html, or return the html string directly.
Instead, create $(html) in a variable, make your changes to it, then work with it as needed. Something like this:
$('.save').click(function() {
var html = $('#edit').editor('get_html');
var $html = $(html);
var $maSociete = $html.find('.ma_societe')
if ($maSociete.text() === $maSociete.attr('data')) {
$maSociete.text('dfdsfsdfds');
}
var result = $html[0].outerHTML
console.log(result);
});
If I insert a comment node into a document fragment, can I convert it to HTML later? Example:
var fragment = document.createDocumentFragment();
var comment = document.createComment('<div>Testing</div>');
fragment.appendChild(comment);
// Convert comment into actual HTML?
What this would look like inside of a fragment:
<!--<div>Testing</div>-->
And how it should be when done (actual DOM):
<div>Testing</div>
Background:
There are many limitations for inserting HTML into a fragment. Fragments don't support innerHTML or insertAdjacentHTML etc. There are other methods for getting HTML into fragments, but they drop certain elements and leave only the inner text. For example, creating a fragment with the createRange API drops those types of nodes and I will be left with a fragment with just the text node "Data"
var fragment = document.createRange().createContextualFragment('<td>Data</td>');
The hope is that if I can convert a comment into actual DOM, that it will work as expected.
For the entire body you can use that snippet:
var body = document.getElementsByTagName('body')[0],
bodyHtml = body.innerHTML;
while (bodyHtml.indexOf("<!--") !== -1) { // will replace all the comments with empty string
bodyHtml = bodyHtml.replace("<!--", "").replace("-->", "");
}
body.innerHTML = bodyHtml;
Hello
<h1>hi</h1>
<!--<div>Testing</div>-->
<!--<div>Testing</div>-->
It sounds like your underlying problem is that you need to stuff HTML text into a DocumentFragment, so here is a helper function to do so for you.
var container = document.createElement('div')
function createFragmentWithHTML (html, doc) {
var result = (doc || document).createDocumentFragment()
container.innerHTML = html
while (container.firstChild) result.appendChild(container.firstChild)
return result
}
var fragment = createFragmentWithHTML('<div>Testing</div><p><strong>More text</strong></p>')
// do whatever you want with `fragment`
document.body.appendChild(fragment)
Something like this would do the trick
var element = document.getElementById("whatever"); // get the parent element
var comment = element.innerHTML; // get the thml
var html = comment.replace("<!--", "").replace("-->", ""); // remove the comment
element.innerHTML = html;
Text content of an HTML comment can be accessed via the nodeValue property of the Node interface or the data property of the CharacterData interface that the HTML Comment interface inherits from:
<!--<div>Example</div>-->
var code = comment.data; /* Now contains `<div>Example</div>` text */
var code = comment.nodeValue; // Same result.
Fwiw, I have a blog post about using HTML comment as data container.
You can get your comments with element.childNodes method, then use textContent method to get the content of comment, then change it into HTML Element with innerHTML method, then remove the comment node and replace it with Element Node.
parseComments('container');
function parseComments(getContainerId){
var container = document.getElementById(getContainerId);
var nodes = container.childNodes;
for(var i=0;i<nodes.length;i++){
if(nodes[i].nodeType===8){
var virtualCont = document.createElement('DIV');
var getContent = nodes[i].textContent;
virtualCont.innerHTML = getContent;
container.removeChild(nodes[i]);
if(nodes[i+1]){
container.insertBefore(virtualCont.children[0],nodes[i+1]);
} else {
container.appendChild(virtualCont.children[0]);
}
}
}
}
<div id="container">
<h1>some header A</h1>
<!--<p>some hidden content A</p>-->
<p>some content</p>
<!--<p>some hidden content B</p>-->
<p>another content</p>
<!--<h1>some hidden header B</h1>-->
<!--<p>another hidden content C</p>-->
</div>
I am trying to replace text on a webpage with links. When I try this it just replaces the text with the tag and not a link. For example this code will replace "river" with:
asdf
This is what I have so far:
function handleText(textNode)
{
var v = textNode.nodeValue;
v = v.replace(/\briver\b/g, 'asdf');
textNode.nodeValue = v;
}
If all you wanted to do was change the text to other plain text, then you could change the contents of the text nodes directly. However, you are wanting to add an <a> element. For each <a> element you want to add, you are effectively wanting to add a child element. Text nodes can not have children. Thus, to do this you have to actually replace the text node with a more complicated structure. In doing so, you will want to make as little impact on the DOM as possible, in order to not disturb other scripts which rely on the current structure of the DOM. The simplest way to make little impact is to replace the text node with a <span> which contains the new text nodes (the text will split around the new <a>) and any new <a> elements.
The code below should do what you desire. It replaces the textNode with a <span> containing the new text nodes and the created <a> elements. It only makes the replacement when one or more <a> elements need to be inserted.
function handleTextNode(textNode) {
if(textNode.nodeName !== '#text'
|| textNode.parentNode.nodeName === 'SCRIPT'
|| textNode.parentNode.nodeName === 'STYLE'
) {
//Don't do anything except on text nodes, which are not children
// of <script> or <style>.
return;
}
let origText = textNode.textContent;
let newHtml=origText.replace(/\briver\b/g,'asdf');
//Only change the DOM if we actually made a replacement in the text.
//Compare the strings, as it should be faster than a second RegExp operation and
// lets us use the RegExp in only one place for maintainability.
if( newHtml !== origText) {
let newSpan = document.createElement('span');
newSpan.innerHTML = newHtml;
textNode.parentNode.replaceChild(newSpan,textNode);
}
}
//Testing: Walk the DOM of the <body> handling all non-empty text nodes
function processDocument() {
//Create the TreeWalker
let treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT,{
acceptNode: function(node) {
if(node.textContent.length === 0) {
//Alternately, could filter out the <script> and <style> text nodes here.
return NodeFilter.FILTER_SKIP; //Skip empty text nodes
} //else
return NodeFilter.FILTER_ACCEPT;
}
}, false );
//Make a list of the text nodes prior to modifying the DOM. Once the DOM is
// modified the TreeWalker will become invalid (i.e. the TreeWalker will stop
// traversing the DOM after the first modification).
let nodeList=[];
while(treeWalker.nextNode()){
nodeList.push(treeWalker.currentNode);
}
//Iterate over all text nodes, calling handleTextNode on each node in the list.
nodeList.forEach(function(el){
handleTextNode(el);
});
}
document.getElementById('clickTo').addEventListener('click',processDocument,false);
<input type="button" id="clickTo" value="Click to process"/>
<div id="testDiv">This text should change to a link -->river<--.</div>
The TreeWalker code was taken from my answer here.
I have the following code,
$(document.getElementById('messages_message-wysiwyg-iframe').contentWindow.document).keydown(function() {
var iFrame = document.getElementById('messages_message-wysiwyg-iframe');
var iFrameBody;
if ( iFrame.contentDocument )
{ // FF
iFrameBody = iFrame.contentDocument.getElementsByTagName('body')[0];
}
else if ( iFrame.contentWindow )
{ // IE
iFrameBody = iFrame.contentWindow.document.getElementsByTagName('body')[0];
}
console.info(iFrameBody.innerHTML);
});
What I am trying to do if get the content of an iframe, but remove all the html tags that are not,
b, strong, i, a, u, img
However I do not want to remove any of the of the text, for example if the in the iframe there is the following,
<div class="box segment panel">
<a href="http://www.google.com>hello world</a>
click this link and go far.
<img src="http://placehold.it/100x100" alt="Placeholder"/>
</div>
What would be return would be the following,
hello world
click this link and go far.
</a>
<img src="http://placehold.it/100x100" alt="Placeholder" />
Is this even possible?
Here's my pure JS solution:
function sanitize(el) {
if (el.nodeType !== 1) return;
if (!/^(B|STRONG|I|A|U|IMG)$/.test(el.tagName)) {
var p = el.parentNode;
// move all children out of the element, recursing as we go
var c = el.firstChild;
while (c) {
var d = c.nextSibling; // remember the next element
p.insertBefore(c, el);
sanitize(c);
c = d; // look at the next sibling
}
// remove the element
p.removeChild(el);
}
}
demo at http://jsfiddle.net/alnitak/WvJAx/
It works by (recursively) moving the child nodes of restricted tags out of their parent, and then removing those tags once they're empty.
With a regex:
iFrameBody.innerHTML=iFrameBody.innerHTML.replace(/<[^(b|strong|i|a|u|img)]\b[^>]*>/gi,"").replace(/<\/[^(b|strong|i|a|u|img)]>/gi,"");
The first replace removes the start tags, the second removes the end tags.
Note that there are a couple traps when using regex to match html. But in this specific case it seems like a reasonable choice (cf. my comments on the other answers).
For the record, this is what I use to access an iframe's content document:
var doc=ifr.contentWindow||ifr.contentDocument;
if (doc.document) doc=doc.document;
var iFrame = document.getElementById('messages_message-wysiwyg-iframe');
var iFrameDoc = iFrame.contentDocument || iFrame.contentWindow.document;
$(iFrameDoc).keydown(function() {
var iFrameBody = $("body", iFrameDoc);
var cleared = iFrameBody.clone();
cleared.find("*:not(b,strong,i,a,u,img)").each(function() {
var $this = $(this);
$this.replaceWith($this.contents());
});
console.log(cleared.html());
});
Demo at jsfiddle.net
I think you're a little confused about how to describe what you're trying to do. When you talk about "text", you're referring to the innerHTML/text node inside of a tag. What you're really looking to do, I think, is grab all of the specific content and the structure of the content, aka the children elements of the iFrame.
You can use jQuery's .text() method to get the text content of each element individually and save that before removing the actual tag from the DOM, if you want to lets say, get the text content of a span but you don't want the span to be in the DOM anymore, or you want to place it somewhere else in your document.
var elemText = $('span#mySpan').text();
$('span#mySpan').remove();
For what it looks like you're trying to do based on your sample HTML, you may want to look into jQuery's detach method: http://api.jquery.com/detach/
This will allow you to store the returned children elements to be appended somewhere else later.
This is my jquery script that replace string to new string:
$("*").contents().each(function() {
if(this.nodeType == 3)
this.nodeValue = this.nodeValue.replace("1.(800).123.1234", "new");
});
working example : http://jsfiddle.net/webdesignerart/eKRGT/
but i want to add before and after to string html element like new
when i do this :
this.nodeValue = this.nodeValue.replace("1.(800).123.1234", "<b>new</b>");
The Result comes:
<b>new</b>
I want output this: new
i want to allow html tags during replacement.
is jquery .append work with this.
You are replacing the contents of a TextNode element which is always just text. To make the text bold, you will need to create another element, b which wraps around the TextNode. One approach is to use the wrap() from jQuery:
$("*").contents().each(function() {
var me = this;
if(this.nodeType == 3)
this.nodeValue = this.nodeValue.replace("1.(800).123.1234", function(a){
$(me).wrap('<b />');
return "new";
});
});
example: http://jsfiddle.net/niklasvh/eLkZp/
This should work:
$("*").contents().each(function() {
var me = this;
if(this.nodeType == 3
&& this.nodeValue.indexOf("1.(800).123.1234")>-1){
$(this).replaceWith(this.nodeValue.replace("1.(800).123.1234", "<b>new</b>"));
}
});
http://jsfiddle.net/eLkZp/20/
Basically replace the text node rather than just the text within it.
You should really consider if there's some way to narrow down that original filter though. Parsing your entire page is generally a bad idea.