Using javascript, I need to parse the HTML of a page and replace all occurrences of ABC with ABC that occur within a content block such as <p>ABC Company lorem ipsum</p> would be changed to <p><span class="abc">ABC</span> Company lorem ipsum</p> but mailto:joe#abccompany.com would stay the same.
So pretty much replace ABC anywhere that is preceded by a space or quote, but obviously I would like to make it a little more generic. Perhaps the expression would say when it is not preceded/followed by [a-zA-z].
What I have so far:
<script type="text/javascript">
$(document).ready(function() {
$('body').find('div').each(function(i, v) {
h = $(v).html();
if (h.indexOf('abc') > 0) {
h = h.replace('abc', '<span class="abc">abc</span>');
$(v).html(h);
}
});
});
</script>
I suggest going about it a different way that preserves data and events on the elements and doesn't interfere with attributes on said elements.
$("body div").find("*").addBack().contents().filter(function(){
return this.nodeType === 3;
}).each(function() {
$(this).parent().html(this.nodeValue.replace(/abc/g, '<span class="abc">abc</span>'));
})
http://jsfiddle.net/hrEyC/1/
Note, requires jQuery 1.9+ due to use of .addBack(), for older versions replace with .andSelf()
This is not a very efficient thing to do (loop through all div tags in the DOM and apply a regex to each one) but since I don't know what constraints you have or what situation you are using this code in, I'll just assume there's a good reason you're doing this client-side in this way.
Anyway, this regex seems to match your requirements (albeit not very well defined requirements):
h = h.replace(/([^A-Z])(ABC)([^A-Z])/gi, '$1<span style="color: red">$2</span>$3');
Fiddle here: http://jsfiddle.net/czJFG/
Related
I want to remove following tags
1. <div>
2. </div>
3. <p>
4. </p>
5. <span>
6. </span>
var str = '<div><p><span>Hello World</span></p></div>';
I can do
str = str.replace('<div>', '');
str = str.replace('<p>', '');
and so on.
But using regular expressions etc can we accomplish the same in 1 step.
Do not use regexes for this: RegEx match open tags except XHTML self-contained tags
Parse the HTML and retrieve what you need. This is a basic one, that retrieves the text from the nodes you supplied. You can extend this further to seed your needs.
var container = document.createElement("div"); //load div in memory
container.insertAdjacentHTML("afterbegin", str); //append the nodes into the container div.
str = container.getElementsByTagName("span")[0].textContent || container.getElementsByTagName;("span")[0].innerText;
You can even do container.textContent || container.innerText; to get all text and no nodes from the string container HTML elements. (innerText is there to support older browsers, IE).
Try this pattern:
/<\/?([a-z])+\>/g
Heres an example
RegExr v2.0 is a very handy tool for testing regular expression. In order to see the result, click on the "substitution" tab on the bottom of the page.
Hope this is what you were looking for.
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>");
}
I have the following HTML code:
<p> hello every body, to day is a sunny day</p>
I have use wrap() method to wrap element with <em> tag like the following:
<p> hello every body, to day is <em>a sunny day<em></p>
When I finished my test, I use $("em").contents().unwrap() to unwrap all <em> tag:
I make a loop for all elements in my page
So I found that
-----hello every body, to day is a----
and
-----a sunny day-----
are 2 seperated text nodes,
How can I use wrap() and unwrap(), so my text won't be splited like that?
I'm afraid, you cannot use .wrap() and .unwrap() to do what I think you intend to do. .unwrap() calls replaceWith() in jQuery code which eventually calls .replaceChild(). The replaceChild() method in JS, replaces one DOM child node, with another. The use of .contents() is creating a text node.
This updates the render tree in the browser, which in turn updates the markup you see in a developer tool. The nodes in a render tree are placed on their own lines for the markup... not to be confused with what actually ends up being displayed: since \n is a whitespace character, the text nodes will show in one line on the screen.
If you need the actual text (innerHTML) to not be broken up as textNodes you will have to resort to somewhat drastic, measures:
$(document).ready(function () {
var _childContent = $('em').contents()[0].data,
_childIndex = $('p')[0].innerHTML.indexOf('<em>'),
_parentText;
$('em').remove();
_parentText = $('p')[0].innerHTML;
$('p')[0].innerHTML = _parentText.substr(0, _childIndex) +
_childContent +
_parentText.substr(_childIndex + 1, _parentText.length);
});
Due to having to take such measures, I would agree with grmmph's comment about if it is an issue of styling, then take the addClass() approach.
However, if what you want is to have all the text between the <p> and </p> tags appear on one line instead of being treated as textNodes, then the above works (at least in IE 10 when viewed in the developer tool).
This question goes back a while, so my answer may only be of use to people in the future facing similar problems to the OP (as I was myself).
A neat way to re-combine the unwrapped text nodes is by resetting the innerHtml of the span's parent element using $.html()
HTML
<p>Lorem ipsum <span>dolor sit</span> amet.</p>
JS
function reset () {
var parent = $('span').parent();
$('span').contents().unwrap();
parent.html(function(i, html) {
return html;
});
}
This has been asked so long ago, but because an answer hasn't been marked yet, I'll post an answer. I'm not sure if you wanted those text nodes split or not, but both ways can be done like this (run snippets to see it work):
The vanilla Javascript way (found here):
function unwrapElement () {
var el = document.querySelector('em')
var parent = el.parentNode
while (el.firstChild) parent.insertBefore(el.firstChild, el)
parent.removeChild(el)
}
<p>Hello every body, to day is <em>a sunny day<em></p>
<button onclick="unwrapElement()">Do unwrap</button>
The JQuery way (similar to #StevieP's way):
function unwrapElement() {
$('em').contents().unwrap()
$('em').parent().html((i, html) => html) // if you remove this, then the text will be split
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Hello every body, to day is <em>a sunny day<em></p>
<button onclick="unwrapElement()">Do unwrap</button>
I Just wanted to know, is there any way though which we can display only First Word from h2 Heading.
For Example:
In the source code it should look like this
<h2> Stackoverflow is an Ideal Place</h2>
However, on live website it should look like this
Stackoverflow
Basically, we want to display the FIRST WORD from the whole heading. However, Search engine should read the complete title.
Try this way
$(document).ready(function(){
var ac = $("#ac").text().split(' ');
$("#ac").text(ac[0])
})
You cannot do this with just CSS. You have pseudo-element selector for first letter, first line, but not first word.
You can set a width so that only the first word is visible (and use overflow:hidden of course), but that's not foolproof for all font families and sizes.
Finally you can do it with plain JavaScript or jQuery.
Plain JS:
var el = document.getElementById("ac");
el.innerHTML = el.innerHTML.split(/\s/)[0];
jQuery:
$("#ac").html(function(i, h) { return h.split(/\s/)[0];});
This will do what you want it to...
<h2 id="ac">Stackoverflow is an Ideal Place</h2>
$('#ac').html( function(i, h) {
var words = h.split(/\s/);
return ' <h2>' + words[0] + '</h2>';
});
I have the HTML from a page in a variable as just plain text. Now I need to remove some parts of the text. This is a part of the HTML that I need to change:
<div class="post"><a name="6188729"></a>
<div class="igmline small" style="height: 20px; padding-top: 1px;">
<span class="postheader_left">
RuneRifle
op 24.08.2012 om 21:41 uur
</span>
<span class="postheader_right">
Citaat Bewerken
</span>
<div style="clear:both;"></div>
</div>
<div class="text">Testforum</div>
<!-- Begin Thank -->
<!-- Thank End -->
</div>
These replaces work:
pageData = pageData.replace(/href=\".*?\"/g, "href=\"#\"");
pageData = pageData.replace(/target=\".*?\"/g, "");
But this replace does not work at all:
pageData = pageData.replace(
/<span class=\"postheader_right\">(.*?)<\/span>/g, "");
I need to remove every span with the class postheader_right and everything in it, but it just doesn't work. My knowledge of regex isn't that great so I'd appreciate if you would tell me how you came to your answer and a small explanation of how it works.
The dot doesn't match newlines. Use [\s\S] instead of the dot as it will match all whitespace characters or non-whitespace characters (i.e., anything).
As Mike Samuel says regular expressions are not really the best way to go given the complexity allowed in HTML (e.g., if say there is a line break after <a), especially if you have to look for attributes which may occur in different orders, but that's the way you can do it to match the case in your example HTML.
I need to remove every span with the class postheader_right and everything in it, but it just doesn't work.
Don't use regular expressions to find the spans. Using regular expressions to parse HTML: why not?
var allSpans = document.getElementsByClassName('span');
for (var i = allSpans.length; --i >= 0;) {
var span = allSpans[i];
if (/\bpostheader_right\b/.test(span.className)) {
span.parentNode.removeChild(span);
}
}
should do it.
If you only need to work on newer browsers then getElementsByClassName makes it even easier:
Find all div elements that have a class of 'test'
var tests = Array.filter( document.getElementsByClassName('test'), function(elem){
return elem.nodeName == 'DIV';
});