I am receiving HTML that is in various formats and I'm trying to standardize the code using jQuery. In some cases I receive it using breaks <br>
to separate lines. I need these to be <div>
(or <p>
) tags instead. For instance the following code:
a<br>b<br>c
needs to be converted into
<div>a</div><div>b</div><div>c</div>
This is a simple case as the contents in a
could be surrounded by all kinds of <font>
, <span>
and other formatting options, all of which need to be retained.
Here was my first attempt. It finds all the <br>
tags in the entire document then accesses the parent's contents to get all the HTML around the <br>
. If the contents length is 1 then <br>
is the only element in there (meaning a blank line) so skip on to the next one. Otherwise look at each element, surround it with <div>
(or <p>
) and remove the <br>
as it isn't needed any more. Variable wrapper
is either "<div />"
or "<p />"
depending on the browser.
$("br").each(function() {
// Find all the br tags' parent nodes
var elements = $(this).parent().contents();
if (elements.length > 1) {
// If there is one element than it is br so skip on.
elements.each(function() {
// Loop through each child element of the parent
var nodeName = this.nodeName.toLowerCase();
if (nodeName !== 'div' && nodeName !== 'p') {
// Make sure each child that is not <br> is wrapped. Remove <br> tags.
if (nodeName == 'br') {
$(this).remove();
} else {
$(this).wrap(wrapper);
}
}
});
}
});
This doesn't work, though, as it adds <div>
(or <p>
) tags around every sub-element so something like <font>a</font>bc<br>de<b>f</b>
ends up like
<div><font>a</font></div>
<div>bc</div>
<div>de</div>
<div><b>f</b></div>
when it really needs to be
<div><font>a</font>bc</div>
<div>de<b>f</b></div>
(I broke it up to be easier to read.)
If I was doing this in a text parser, I'd find the contents just like I did above for variable elements
, add a <div>
at the beginning and a </div>
at the end, then replace each <br>
with </div><div>
(except when it is already <div><br></div>
, at which point I'd skip it). I have no idea how to do this in jQuery/Javascript. though, especially regarding the replace <br>
with </div><div>
portion. (The first part is elements.wrap(wrapper)
.)
Any help on this approach or an alternative approach would be appreciated.
--- UPDATE ---
@Ian supplied must of the code that worked. I expanded on it just a little and thought I'd include it here. I have tested it in FF, Safari, Chrome and IE 9+.
$("br").each(function(idx, el) {
var $el = $(el),
$parent = $el.parent(),
$contents = $parent.contents(),
$cur, $set, i;
$set = $();
if ($contents.length > 1) {
for (i = 0; i < $contents.length; i++) {
$cur = $contents.eq(i);
if ($cur.is("br")) {
$set.wrapAll(wrapper);
$cur.remove();
$set = $();
} else {
$set = $set.add($cur);
}
}
$set.wrapAll(wrapper);
}
});