Remove whitespace and line breaks between HTML elements using jQuery

Using jQuery, I'd like to remove the whitespace and line breaks between HTML tags.

var widgetHTML = '    <div id="widget">        <h2>Widget</h2><p>Hi.</p>        </div>';

Should be:

alert(widgetHTML); // <div id="widget"><h2>Widget</h2><p>Hi.</p></div>

I think the pattern I will need is:

>[\s]*<

Can this be accomplished without using regex?

Answers:

Answer

A recursive version:

jQuery.fn.htmlClean = function() {
    this.contents().filter(function() {
        if (this.nodeType != 3) {
            $(this).htmlClean();
            return false;
        }
        else {
            this.textContent = $.trim(this.textContent);
            return !/\S/.test(this.nodeValue);
        }
    }).remove();
    return this;
}
Answer

You can probably do this better after setting HTML into a DOM node. Once the browser has parsed everything and built a DOM tree out of our markup, you can do a DOM walk and for every text node that you find, either remove it completely if it has no non-whitespace characters, or trim whitespace off the start and end of it if it does.

Answer

I had to modify the accepted answer a bit because for some reason chrome didn't want to removeChild() on whitespace nodes. If this happens, you could replace the node with an empty text node like in this example helper function:

 var removeWhiteSpaceNodes = function ( parent ) {
    var nodes = parent.childNodes;
    for( var i =0, l = nodes.length; i < l; i++ ){
      if( nodes[i] && nodes[i].nodeType == 3 && !/\S/.test( nodes[i].nodeValue ) ){
        parent.replaceChild( document.createTextNode(''), nodes[i]  );
      }else if( nodes[i] ){
        removeWhiteSpaceNodes( nodes[i] );
      }
    }
  }

It takes a node from which you want to remove whitespace and recursively replaces all whitespace children with a truly empty textnode.

Answer

You could $.trim(widgetHTML); to get read of the surrounding whitespace.

Answer

I tried the technique that user76888 laid out and it worked nicely. I packaged it into a jQuery plugin for convenience, and thought the community might enjoy it, so here:

jQuery.fn.cleanWhitespace = function() {
    this.contents().filter(
        function() { return (this.nodeType == 3 && !/\S/.test(this.nodeValue)); })
        .remove();
    return this;
}

To use this, just include it in a script tag, then select a tag to clean with jQuery and call the function like so:

$('#widget').cleanWhitespace();
Answer

I think this will do it...

cleanWhitespace: function(element) {
 element = $(element);
 for (var i = 0; i < element.childNodes.length; i++) {
   var node = element.childNodes[i];
   if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
     Element.remove(node);
 }
}
Answer

This is what worked for me and the step by step discovery:

The output is from chrome console

First locato the parent node containing the nasty whitespace

$('.controls label[class="radio"]').parent();

[<div class=?"controls">?
<label class=?"radio">?…?</label>?
" "
"    "
<label class=?"radio">?…?</label>?
" "
"    "
</div>?]

You can see this is wrapped in an array from the [] brackets jQuery will always return an array like structure even when a single item has been found.

So to get to the HTMLElement we take the first item in the array at index 0

$('.controls label[class="radio"]').parent()[0];

<div class=?"controls">?
<label class=?"radio">?…?</label>?
" "
"    "
<label class=?"radio">?…?</label>?
" "
"    "
</div>?

Note how there are no more [] brackets. The reason we need to do this is because jQuery will ignore whitespace in the dom but HTMLElement won't, look what happens when we access the childNodes property

$('.controls label[class="radio"]').parent()[0].childNodes;

[<label class=?"radio">?…?</label>?, 
" ", 
"    ", 
<label class=?"radio">?…?</label>?, 
" ", 
"    "]

We have an array again, yes you spot the [] brackets but do you see another difference, look at all the commas, which we couldn't get with jQuery. Thank you HTMLElement but now we can go back to jQuery because I want to use each instead of a for loop, do you agree with me? So lets wrap the array in jQuery and see what happens:

$($('.controls label[class="radio"]').parent()[0].childNodes);

[<label class=?"radio">?…?</label>?, 
" ", 
"    ", 
<label class=?"radio">?…?</label>?, 
" ", 
"    "]

Perfect! we have exactly the same structure still but nnow inside a jQuery object so lets call each and print "this" to console to see what we have.

$($('.controls label[class="radio"]').parent()[0].childNodes).each(function () { 
   console.log('|'+$(this).html()+'|');
});

|<input id="gender_f" name="gender" type="radio" value="f">Female|
|undefined|
|undefined|
|<input id="gender_m" name="gender" type="radio" value="m" checked="">Male|
|undefined|
|undefined|

So we use jQuery to get the html of each element, standard stuff `$(this).html and because we can't see white space lets pad it with a pipe |, good plan but what do we have here? As you can see jQuery is not able to turn the whitespace to html and now we have undefined. But this is even better because where a space might be truthy undefined is definitely falsy =)

So lets get rid of the suckers with jQuery. All we need is $(this).html() || $(this).remove(); lets see:

$($('.controls label[class="radio"]').parent()[0].childNodes).each(function () { 
   $(this).html() || $(this).remove();
});

[<label class=?"radio">?…?</label>?, 
" ", 
"    ", 
<label class=?"radio">?…?</label>?, 
" ", 
"    "]

Oh dear.. but don't fear! Each still returns the previous structure not the one we've changed, lets look at what our initial query returns now.

$('.controls label[class="radio"]').parent();

[<div class=?"controls">?
<label class=?"radio">?…?</label>?
<label class=?"radio">?…?</label>?
</div>?]

And Wallah! All sexy and pretty =)

So there you have it, how to remove whitespace between elements/tags ala jQuery style.

nJoy!

Answer

Use

$($.parseHTML(widgetHTML, document, true)).filter("*"),

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.