Find Characters and wrap with HTML - javascript

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.

Related

Why an unexpected <br> being inserted by replace() function?

I'm seeing some very unexpected behavior with the replace() javascript function that I'm using. Essentially, if the user inputs [Hi there] into a text form, I want to replace the brackets [ and ] with tags that will add margin to the text for e.g. [Hi there] to <div>Hi there</div>. In addition to the desired tags, a <br> tag is also added after the closing div.
Here is my code:
javascript
$('.servicebody').each(function() {
var string = $(this).html();
$(this).html(string.replace(/\[/g, '<div class="marginme">')); // to replace opening square bracket
});
$('.servicebody').each(function() {
var string = $(this).html();
$(this).html(string.replace(/\]/g, '</div>')); // to replace closing square bracket
});
css
.marginme {
margin: 10px auto;
}
Any thoughts on why a <br> tag is being inserted by this replace() function?
I think it's because you insert the HTML below you close the tags. Try the following code, instead:
$('.servicebody').each(function() {
var string = $(this).html();
$(this).html(string.replace(/\[/g , '<div class="bulletflex"><div class="bullet"></div><div class="bullet2">').replace(/\]/g, '</div></div>'));
});
Here is my answer:
I would recommend you to use one single function instead of two. Using two functions, as you did in your sample code, only makes unnecessarily calculations.
As best practice I would reccomend you to store this into a variable. Otherwise this could lead to unexpected behavior.
Avoid multiple calls of the jquery functions: make $(lorem).ipsum();$(lorem).xyz() to var $lorem = $(lorem);$lorem.ipsum();$lorem.xyz();
Here is my version of your code:
$('.servicebody').each(function() {
var self = this;
var $self = $(self);
var html = $self.html();
html = html.replace(/\[/g, '<div class="marginme">');
html = html.replace(/\]/g, '</div>');
$self.html(html);
});
i think you might try another syntax
$('.servicebody').empty().add($('</div></div>'));

How to replace only the text of this element with jQuery?

I'm trying to make a kind of simple search engine, where
the user enters a string and if it's equal to the text inside
an element, that portion of text must be highlighted some way.
This is the html:
<input type="text">
<input type="button" value="Change text"><br>
Click here to get more info!
this is the css:
.smallcaps{
color:red;
}
and this is the jquery function that makes the search and replace:
$("input[type='button']").click(function(){
var textValue = $("input[type=text]").val();
$("a").html(function(_, html) {
return html.replace(new RegExp(textValue,"ig"), '<span class="smallcaps">'+textValue+'</span>');
});
});
This is an example of how it looks like:
Everything works fine, until the search string is equals to the name of a node element, so for example if the search string is a, the html will be broken.
How can I avoid the replace of the html itself?. I just want to work over the text.
This is the codepen:
http://codepen.io/anon/pen/mefkb
Thanks in advance!
I assume that you want to only highlight the last search and not store the ones from before.
With this assumption, you can store the old value if it is the first call and use the stored value in the calls afterwards:
$("input[type='button']").click(function(){
// Escape the html of the input to be able to search for < or >
var textValue = $('<div/>').text($("input[type=text]").val()).html();
if(textValue === '') return;
$("a").html(function(_, html) {
var old = $(this).data('content');
if(!old) {
old = html;
$(this).data('content', old);
}
var replacer = function(match) {
return match.replace(new RegExp(textValue, "ig"), '<span class="smallcaps">'+textValue+'</span>');
};
if(/[<>]/.test(old)) {
return old.replace(/^[^<>]*</gi, replacer).replace(/>[^<>]*</gi, replacer).replace(/>[^<>]*$/gi, replacer);
}
return replacer(old);
});
});
Also i fixed two bugs I found when testing:
if you search for an empty string, everything is broken.
If you search for html characters like < or > nothing is found as in the text they are converted to < or >.
One thing is not solved, as it is not possible to easily implement it without destroying the subelement structure: It is not possible to search in different subelements, as you have to remove the tags, search then and insert the tags at the right position afterwards.
Working fiddle: http://codepen.io/anon/pen/KlxEB
Updated Demo
A workaround would be to restore <a> to original text, instead of complicating the regex.
Your problem is a form the <span> tag is getting replaced.
var init = $("a").text(); //save initial value
$("input[type='button']").click(function(){
$('a').text(init); //replace with initial value
var textValue = $("input[type=text]").val();
$("a").html(function(_, html) {
return html.replace(new RegExp(textValue,"ig"), '<span class="smallcaps">'+textValue+'</span>');
});
});

Apply ligature with jquery to link text only, not link href

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/

Replace text with HTML element

How can I replace a specific text with HTML objects?
example:
var text = "some text to replace here.... text text text";
var element = $('<img src="image">').event().something...
function ReplaceWithObject(textSource, textToReplace, objectToReplace);
So I want to get this:
"some text to replace < img src...etc >.... text text text"
And I would like manipulate the object element without call again $() method.
UPDATE:
I solved.
thanx #kasdega, i made a new script based in your script, because in your script i can't modify the "element" after replace.
This is the script:
$(document).ready(function() {
var text = "some text to replace here.... text text text";
var element = $('<img />');
text = text.split('here');
$('.result').append(text[0],element,text[1]);
$(element).attr('src','http://bit.ly/mtUXZZ');
$(element).width(100);
});
I didnt know that append method accept multiples elements.
That is the idea, only need to automate for multiple replacements
thanx to all, and here the jsfiddle
do a split on the text you want to replace then use the array indexes 0 and 1...something like:
function ReplaceWithObject(textSource, textToReplace, objectToReplace) {
var strings = textSource.split(textToReplace);
if(strings.length >= 2) {
return strings[0] + objectToReplace.outerHTML() + strings[1];
}
return "";
}
UPDATE: I found another SO post Get selected element's outer HTML that pointed me to a tiny jquery plugin that helps here.
I believe this jsfiddle has what you want. outerHTML is the tiny jquery plugin I included in the JSFiddle.
You can also use replace which will reduce some code: http://jsfiddle.net/kasdega/MxRma/1/
function ReplaceWithObject(textSource, textToReplace, objectToReplace) {
return textSource.replace(textToReplace, objectToReplace.outerHTML());
}
function textToObj (text,obj,$src){
var className = "placeholder-"+text;
$src.html($src.html().replace(text,"<div class='"+className+"'></div>"));
$("."+className).replace(obj);
}
you can use $(selector).outerHtml to get the html string of an element
You can replace the html directly: http://jsfiddle.net/rkw79/qNFKF/
$(selector).html(function(i,o) {
return o.replace('old_html','new_html');
})

Jquery String Replace Can't add html element before and after

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.

Categories

Resources