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.
Related
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;
I am new to javascript but understand jQuery. I am trying to use this code to convert www. and http in p tags to working links.
Here is the code I am using, the problem is that I do not fully understand how the code works, could anybody please explain?
<script>
var re = /(http:\/\/[^ ]+)/g;
function createLinks(els) {
$(els).contents().each(function () {
if (this.nodeType === 1 && this.nodeName !== 'script') {
createLinks(this);
} else if (this.nodeType === 3 && this.data.match(re)) {
var markup = this.data.replace(re, '$1');
$(this).replaceWith(markup);
}
});
}
createLinks(document.body);
</script>
First, you set regular expression template for matching text which starts from "http://"
Second, you create recursive function which traverse whole html document.
nodeType == 1 means that current element is html tag (i.e. a, p, div etc)
nodeType == 2 means that element is Attribute
nodeType == 3 means that element is text node
So when you found html tag, you're searching inside it,
when you found text node, you are checking via regular expression, if this text starts from "http://", if so you change and replce this text to yourmatchedurl
in the end you call your function to start from body as a root
ok, here goes...
//create a regular expression to format the link
var re = /(http:\/\/[^ ]+)/g;
//this is the create links function which gets called below, "els" is the elements passed to the function (document.body)
function createLinks(els) {
//for each of the elements in the body
$(els).contents().each(function () {
//check if its an element type but not a script
if (this.nodeType === 1 && this.nodeName !== 'script') {
//call the create links function and send in this object
createLinks(this);
//if its not an element but is a text node and the format matches the regular expression
} else if (this.nodeType === 3 && this.data.match(re)) {
//create the markup
var markup = this.data.replace(re, '$1');
//finally, replace this link with the marked up link
$(this).replaceWith(markup);
}
});
}
//call the create links function
createLinks(document.body);
I hope the commented code helps you understand.
I am using ligatures.js to replace text within my site with the ligature of some character combinations. For instance, the 'fi' in 'five'.
Here is my example: http://jsfiddle.net/vinmassaro/GquVy/
When you run it, you can select the output text and see that the 'fi' in 'five' has become one character as intended. If you copy the link address and paste it, you will see that the href portion has been replaced as well:
/news/here-is-a-url-with-%EF%AC%81ve-ligature
This is unintended and breaks the link. How can I make the replacement on JUST the text of the link but not the href portion? I've tried using .text() and .not() with no luck. Thanks in advance.
I think you can solve it using the appropiate jQuery selectors
$('h3 a, h3:not(:has(a))')
.ligature('ffi', 'ffi')
.ligature('ffl', 'ffl')
.ligature('ff', 'ff')
.ligature('fi', 'fi')
.ligature('fl', 'fl');
See http://jsfiddle.net/GquVy/7/
You are applying the function to the whole heading's innerHTML, which includes the anchor's href attribute. This should work for your fiddle example:
$('h1 a, h2 a, h3 a, h4 a').ligature( //...
However, it will only work on links inside the headings, and I'm not sure that's what you're looking for. If you want something that works for any contents inside a certain element (with any level of tag nesting), then you'll need a recursive approach. Here is an idea, which is basically plain JavaScript since jQuery does not provide a way to target DOM text nodes:
$.fn.ligature = function(str, lig) {
return this.each(function() {
recursiveLigatures(this, lig);
});
function recursiveLigatures(el, lig) {
if(el.childNodes.length) {
for(var i=0, len=el.childNodes.length; i<len; i++) {
if(el.childNodes[i].childNodes.length > 0) {
recursiveLigatures(el.childNodes[i], lig);
} else {
el.childNodes[i].nodeValue = htmlDecode(el.childNodes[i].nodeValue.replace(new RegExp(str, 'g'), lig));
}
}
} else {
el.nodeValue = htmlDecode(el.nodeValue.replace(new RegExp(str, 'g'), lig));
}
}
// http://stackoverflow.com/a/1912522/825789
function htmlDecode(input){
var e = document.createElement('div');
e.innerHTML = input;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
};
// call this from the document.ready handler
$(function(){
$('h3').ligature('ffi', 'ffi')
.ligature('ffl', 'ffl')
.ligature('ff', 'ff')
.ligature('fi', 'fi')
.ligature('fl', 'fl');
});
That should work on contents like this:
<h3>
mixed ffi content
<span>this is another tag ffi <span>(and this is nested ffi</span></span>
Here is a ffi ligature
</h3>
http://jsfiddle.net/JjLZR/
I am trying to find // (slashes) in the document and wrap it with a span.
I've tried
var slashes = "//";
/slashes+/
So output should be:
Hello There! I Am <span class="slashes">//</span> An Alien
With jQuery .replace() and :contains but nothing happens, and I am new to reguler expressions to do this correctly. How would I do this?
Edit: What have I tried:
Solution for this question didn't work:
function slashes($el) {
$el.contents().each(function () {
dlbSlash = "//";
if (this.nodeType == 3) { // Text only
$(this).replaceWith($(this).text()
.replace(/(dlbSlash)/gi, '<span class="slashes">$1</span>'));
} else { // Child element
slashes($(this));
}
});
}
slashes($("body"));
You need to escape the slashes in your regex. Try
var mystring = "adjfadfafdas//dsagdsg//dsafda"
mystring.replace(/\/\//g,'<span class="slashes">\/\/</span>');
Should output
"adjfadfafdas<span class="slashes">//</span>dsagdsg<span class="slashes">//</span>dsafda"
If you want to replace the slashes in h2 and p tags, you can loop through them like so:
$('h2, p').each(function(i, elem) {
$(elem).text(
$(elem).text().replace(/\/\//g,'<span class="slashes">\/\/</span>'));
});
This will blow away any additional html tags you may have had in your p and h2 tags, though.
This is one more way of doing this
//Find html inside element with id content
var html = $('#content').html();
//Replace // with <span style='color:red'>//</span>
html = html.replace(/\/{2}/g,"<span style='color:red'>$&</span>");
//Return updated html back to DOM
$('#content').html(html);
and here is the demo
I think you were looking in the right place. The only thing to fix is your regular expression:
.replace(/\/\//g, '<span class="slashes">$1</span>'));
Focusing on text nodes (type 3) is important, instead of doing a global replace of the body innerHTML that might break your page.
If you want to apply such replacement for single // only, go with
mystring = mystring.replace(/(\/{2})/g, "<span class=\"slashes\">$1</span>");
However if you want to apply that for 2 or more slashes, then use
mystring = mystring.replace(/(\/{2,})/g, "<span class=\"slashes\">$1</span>");
But if you want to apply it for any even quantity of slashes (e.g. //, ////, etc.) then you need to use
mystring = mystring.replace(/((?:\/{2})+)/g, "<span class=\"slashes\">$1</span>");
Test the code here.
How to select a part of string?
My code (or example):
<div>some text</div>
$(function(){
$('div').each(function(){
$(this).text($(this).html().replace(/text/, '<span style="color: none">$1<\/span>'));
});
});
I tried this method, but in this case is selected all context too:
$(function(){
$('div:contains("text")').css('color','red');
});
I try to get like this:
<div><span style="color: red">text</span></div>
$('div').each(function () {
$(this).html(function (i, v) {
return v.replace(/foo/g, '<span style="color: red">$&<\/span>');
});
});
What are you actually trying to do? What you're doing at the moment is taking the HTML of each matching DIV, wrapping a span around the word "text" if it appears (literally the word "text") and then setting that as the text of the element (and so you'll see the HTML markup on the page).
If you really want to do something with the actual word "text", you probably meant to use html rather than text in your first function call:
$('div').each(function(){
$(this).html($(this).html().replace(/text/, '<span style="color: none">$1<\/span>'));
// ^-- here
}
But if you're trying to wrap a span around the text of the div, you can use wrap to do that:
$('div').wrap('<span style="color: none"/>');
Like this: http://jsbin.com/ucopo3 (in that example, I've used "color: blue" rather than "color: none", but you get the idea).
$(function(){
$('div:contains("text")').each(function() {
$(this).html($(this).html().replace(/(text)/g, '<span style="color:red;">\$1</span>'));
});
});
I've updated your fiddle: http://jsfiddle.net/nMzTw/15/
The general practice of interacting with the DOM as strings of HTML using innerHTML has many serious drawbacks:
Event handlers are removed or replaced
Opens the possibility of script inject attacks
Doesn't work in XHTML
It also encourages lazy thinking. In this particular instance, you're matching against the string "text" within the HTML with the assumption that any occurrence of the string must be within a text node. This is patently not a valid assumption: the string could appear in a title or alt attribute, for example.
Use DOM methods instead. This will get round all the problems. The following will use only DOM methods to surround every match for regex in every text node that is a descendant of a <div> element:
$(function() {
var regex = /text/;
function getTextNodes(node) {
if (node.nodeType == 3) {
return [node];
} else {
var textNodes = [];
for (var n = node.firstChild; n; n = n.nextSibling) {
textNodes = textNodes.concat(getTextNodes(n));
}
return textNodes;
}
}
$('div').each(function() {
$.each(getTextNodes(this), function() {
var textNode = this, parent = this.parentNode;
var result, span, matchedTextNode, matchLength;
while ( textNode && (result = regex.exec(textNode.data)) ) {
matchedTextNode = textNode.splitText(result.index);
matchLength = result[0].length;
textNode = (matchedTextNode.length > matchLength) ?
matchedTextNode.splitText(matchLength) : null;
span = document.createElement("span");
span.style.color = "red";
span.appendChild(matchedTextNode);
parent.insertBefore(span, textNode);
}
});
});
});