Replace specific text without affecting styling - javascript

Need to replace colons wherever they're found in specific elements with id's. This works but for some reason also replaces the styling attached to the elements:
$(document).ready(function(){
$("#element").each(function () { //for element
var s=$(this).text(); //get text
$(this).text(s.replace(/:/g, ' ')); //set text to the replaced version
});
});
I tried attaching a class to the element but it made no difference. How do I just remove the colons without affecting anything else?
Demo

I think you want to use the .html() method: http://api.jquery.com/html/
because according to this: http://api.jquery.com/text/
it calls the DOM method .createTextNode(), which replaces special characters with their HTML entity equivalents (such as < for <)
$(document).ready(function(){
$("#element").each(function () { //for element
var s=$(this).html(); //get text
$(this).html(s.replace(/:/g, ' ')); //set text to the replaced version
});
});

What is the HTML code in #element ?
If replacing the text in #element changes the style, it means that #element also contains some HTML tags (and the style is actually applied on those tags).
Try this:
$(document).ready(function() {
$("#element").each(function () {
(function trim_colons(el) {
for (var i = 0; i < el.childNodes.length; ++i) {
var c = el.childNodes[i];
if (c.nodeType == 1) trim_colons(c);
else if (c.nodeType == 3) c.nodeValue = c.nodeValue.replace(/:/g, ' ');
}
})(this);
});
});
This will correctly remove : characters, without changing the style.

Certainly you did'nt meant to have text in input types replaced ha!
For html elements other than input elements to fetch innerhtml you should use
var s=$(this).html();

Related

JQuery | change a part of a string with links

I have the following code:
<div class="TopMenu">
<h3>Create an Account</h3>
<h3>yup</h3>
<h3>lol</h3>
yo
<ul>
<li sytle="display:">
start or
finish
</li>
</ul>
and I'm using:
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).text();
$(this).text(text.replace('or', 'triple'));
});
It works fine, but suddenly the links aren't active,
how do I fix it?
Thank you very much in advance.
Here's what your jQuery basically translates to when it's being run:
text = this.textContent;
// text = "\n\t\tstart or\n\t\t finish\n\t\t\n";
text = text.replace('or','triple');
// text = "\n\t\tstart triple\n\t\t finish\n\t\t\n";
this.textContent = text;
// essentially, remove everything from `this` and put a single text node there
Okay, that's not a great explanation XD The point is, setting textContent (or, in jQuery, calling .text()), replaces the element's contents with that text.
What you want to do is just affect the text nodes. I'm not aware of how to do this in jQuery, but here's some Vanilla JS:
function recurse(node) {
var nodes = node.childNodes, l = nodes.length, i;
for( i=0; i<l; i++) {
if( nodes[i].nodeType == 1) recurse(node);
else if( nodes[i].nodeType == 3) {
nodes[i].nodeValue = nodes[i].nodeValue.replace(/\bor\b/g,'triple');
}
}
}
recurse(document.querySelector(".TopMenu"));
Note the regex-based replacement will prevent "boring" from becoming "btripleing". Use Vanilla JS and its magic powers or I shall buttbuttinate you!
Change .text() to .html()
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).html();
$(this).html(text.replace('or', 'triple'));
});
See Fiddle
Since or is a text node, you can use .contents() along with .replaceWith() instead:
$('.TopMenu li:contains("or")').each(function () {
var text = $(this).text();
$(this).contents().filter(function () {
return this.nodeType === 3 && $.trim(this.nodeValue).length;
}).replaceWith(' triple ');
});
Fiddle Demo
You need to us .html() instead of .text(),
Like this:
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).html();
$(this).html(text('or', 'triple'));
});
Here is a live example: http://jsfiddle.net/7Mamj/
jsFiddle Demo
You are placing the anchors into text by doing that. You should iterate the matched elements' childNodes and only use replace on their textContent to avoid modifying any html tags or attributes.
$('.TopMenu li:contains("or")').each(function() {
for(var i = 0; i < this.childNodes.length; i++){
if(this.childNodes[i].nodeName != "#text") continue;
this.childNodes[i].textContent = this.childNodes[i].textContent.replace(' or ', ' triple ');
}
});
It is a bit more complicated task. You need to replace text in text nodes (nodeType === 3), which can be done with contents() and each iteration:
$('.TopMenu li:contains("or")').contents().each(function() {
if (this.nodeType === 3) {
this.nodeValue = this.nodeValue.replace('or', 'triple');
}
});
All other approaches will either rewrite the markup in the <li> element (removing all attached events), or just remove the inner elements.
As discussed in the comments below, fool-proof solution will be to use replacement with regular expression, i.e. this.nodeValue.replace(/\bor\b/g, 'triple'), which will match all or as standalone words and not as parts of words.
DEMO: http://jsfiddle.net/48E6M/

How to add onto a HTML attachment like href=""

So I ran up onto a problem, how would I add text into the HTML attachment href. So, and example:
...
How would I change it too:
...
But, what if I had mutiple of these with different href's:
...
...
...
How would I change them all?
href is called an attribute, and you can use .attr() to change it
If you want to add same prefix to all of them then
jQuery(function () {
$('a').attr('href', function (i, href) {
return 'http://google.com' + href;
});
})
Demo: Fiddle
First find all the elements you wish to change and put them into an array (below, I'm just using all anchor tags, but you could do getElementsByClassName and give them all some class as to not affect every anchor tag on the page), then loop through them and append the code.
(function () {
var anchors = document.getElementsByTagName("a");
for (var x = 0; x < anchors.length; x++) {
anchors[x].href = "http://google.com" + anchors[x].href;
}
})();
If you're appending the same string to the start of all anchor tags' HREF attribute within a particular DIV or other container (say it has ID myDiv), that's relatively easy:
$('#myDiv a').each(function(){
$(this).attr('href', 'http://google.com' + $(this).attr('href'));
});

Equivalent of PHP preg_match, substr in javaScript

i'm makeing a tinyMce plugin that change word/letter space between highlighted text. My fn() looks like this:
function wordsLettersSpace(words, letters) {
var inst = tinyMCE.activeEditor;
var currSelection = $.trim(inst.selection.getSel());
if(currSelection != ""){
var content = "";
content = inst.selection.getContent({
format: 'html'
});
contentReplace = '<span style="word-spacing: '+words+'px; letter-spacing: '+letters+'px;">' + inst.selection.getContent({
format: 'html'
}) + '</span>';
inst.selection.setContent(content.replace(content, contentReplace));
window.alert(content);
}else{
Hyphenator.hyphenate(inst.getBody(), language);
}
tinyMceUpdate();
}
Now i need to find closest tag before select start position (if exist) and get style values of "word-spacing" and "letter-spacing". Also i need to get rid of any inside of selection, but only tags not the text, knowing that span tags can have different styles so simple str.replace won't work.
I know that there is a built-in plugin for that, but i need to do it outside of tinyMce iframe, and customize it.
Any sugestions?
JS regexes are available and do exactly what you want with preg_match.
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Regular_Expressions
Substring in javascript is str.substr(start, length)

How To Append <a></a> Tags To Specific Words In An Element With jQuery

The tricky part is not selecting the elements here, but just selecting the text within. The only true jQuery that will give you back text contents is .contents(). So I'm getting the contents of every element not he page, and I want to pick out a word, such as "hashtag". Then append to it.
What am I doing wrong here:
<html>
<p>
The word hashtag is in this sentence.
</p>
</html>
jQuery:
$(function() {
$('*')
.contents()
.filter(function(){
return this.nodeType === 3;
})
.filter(function(){
return this.nodeValue.indexOf('hashtag') != -1;
})
.each(function(){
alert("It works!")
});
});
$('*') grabs every element
.contents() grabs the contents of every element
.filter(function(){ return this.noteType === 3; refines it down to the text contents of elements. (#3 node type is text)
return this.nodeValue.indexOf('hashtag') should grab the word "hashtag". Not sure if this is working.
!= -1; should prevent it from grabbing every single element in the HTML. Not sure about that one.
Why doesn't it work? I know I have anything appending tags yet, but can I select the word "hashtag" thanks!
If you want to do this for the whole page you can work on the HTML of the body element:
$(function() {
var regExp = new RegExp("\\b(" + "hashtag" + ")\\b", "gm");
var html = $('body').html();
$('body').html(html.replace(regExp, "<a href='#'>$1</a>"));
});
Keep in mind that this may be slow if your page is large. Also, all elements will be rewritten and thus loose their event handlers etc.
If you don't want this or want to restrict the replacement to certain elements, you can select and iterate over them:
$(function() {
var regExp = new RegExp("\\b(" + "hashtag" + ")\\b", "gm");
$('div, p, span').each(function() { // use your selector of choice here
var html = $(this).html();
$(this).html(html.replace(regExp, "<a href='#'>$1</a>"));
});
});
JS :
function replaceText() {
$("*").each(function() {
if($(this).children().length==0) {
$(this).html($(this).text().replace('hashtag', '<span style="color: red;">hashtag</span>'));
}
});
}
$(document).ready(replaceText);
$("html").ajaxStop(replaceText);
HTML :
<html>
<p>
The word hashtag is in this sentence.
</p>
</html>
Fiddle : http://jsfiddle.net/zCxsY/
Source : jQuery - Find and replace text, after body was loaded
This is done with span but will work with obviously
The clean variant would be this:
$(function() {
var searchTerm = 'hashtag';
$('body *').contents()
.filter(function () {
return this.nodeType == 3
&& this.nodeValue.indexOf(searchTerm) > -1;
})
.replaceWith(function () {
var i, l, $dummy = $("<span>"),
parts = this.nodeValue.split(searchTerm);
for (i=0, l=parts.length; i<l; i++) {
$dummy.append(document.createTextNode(parts[i]));
if (i < l - 1) {
$dummy.append( $("<a>", {href: "", text: searchTerm}) );
}
}
return $dummy.contents();
})
});
It splits the value of the text node at searchTerm and re-joins the parts as a sequence of either new text nodes or <a> elements. The nodes created this way replace the respective text node.
This way all text values keep their original meaning, which cannot be guaranteed when you call replace() on them and feed them to .html() (think of text that contains HTML special characters).
See jsFiddle: http://jsfiddle.net/Tomalak/rGcxw/
I don't know jQuery very much but I think you can't just say .indexOf('hashtag'), you have to iterate through the text itself. Let's say with substring. Probably there's an jQuery function that will do this for you, but that might be your problem for finding 'hashtag'.

Creating links for elements with a particular class with jQuery

How can I wrap every element belonging to a particular class with a link that is built from the text inside the div? What I mean is that I would like to turn:
<foo class="my-class>sometext</foo>
into
<a href="path/sometext" ><foo class="my-class>sometext</foo></a>
Url encoding characters would also be nice, but can be ignored for now if necessary.
EDIT: Just to clarify, the path depends on the text within the element
Use jQuery.wrap() for the simple case:
$(".my-class").wrap("<a href='path/sometext'></a>");
To process text inside:
$(".my-class").each(function() {
var txt = $(this).text();
var link = $("<a></a>").attr("href", "path/" + txt);
$(this).wrap(link[0]);
});
$(".my-class").each(function(){
var thisText = $(this).text();
$(this).wrap("<a></a>").attr("href","path/"+thisText);
});
you can wrap them inside anchor element like this:
$(document).ready(function(){
$(".my-class").each(function(){
var hr="path/"+$(this).text();
$(this).wrap("<a href='"+hr+"'></a>");
});
});
if you are opening links in same page itself then easier way than modifying dom to wrap elements inside anchor is to define css for the elements so that they look like links then handle click event:
$(".my-class").click(function(){
window.location.href="path/"+$(this).text();
});
$("foo.my-class").each(function(){
var foo = $(this);
foo.wrap("<a href='path/" + foo.Text() +"'>");
});
This ought to do it:
$('foo.my-class').each(function() {
var element = $(this);
var text = element.html(); // or .text() or .val()
element.wrap('');
});

Categories