1

I've run into a situation (a little out of my control) whereby debug text is getting inserted into my DOM when the HTML is being rendered. The text looks like the following:

, NameSpace.ClassName, Version=x.x.x.x, Culture=neutral, PublicKeyToken=null 

The text is just rendered inline, not in an element. If it were at least put inside a div or a span I could do something about it, but it's just part of the body wherever a module is loaded. So first I tried the following:

var goodText = $('body').html();
goodText = goodText.replace(/, Plugin.[a-zA-Z0-9]*, Version=\d\.\d\.\d\.\d, Culture=neutral, PublicKeyToken=null/g, '');
$('body').html(goodText);

While this takes the text out of the mix, it's replacing the entire body of the document and therefore jQuery's document ready is firing again. My other scripts start to cry like baby llamas in the Arctic and the page falls apart.

A typical chunk of the page looks like this, as output by a module:

<div class="row">
  , NameSpace.ClassName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
  <div> some stuff</div>
  <script> $(function(){ // some script }); </script>
</div>

So, even if I target .row, replace the text with the above regex/string.replace and set the HTML on the element, that jQuery block is getting executed again. Which plainly put is a big pile of hooky-doodle.

As a side, I am loading modules using RazorGenerator to build the DLLs and BoC's precompiled views in an Asp.Net MVC4 project.

I also tried using a class-level implementation of a custom ActionFilterAttribute but there is nothing in there I can trap/override where this text is actually being generated/rendered.

What are my options here? Can I scrub that text out in another way? Can I block the execution of that script block a second time? Do I have any other options in the ASP.NET request pipeline that would allow me to exercise that demon text?

MisterJames
  • 3,306
  • 1
  • 30
  • 48
  • 1
    You could look through the list of child nodes of the `` element, and get rid of the text nodes. – Pointy May 30 '12 at 14:27
  • 1
    Agreed, the way to go would be to select text nodes, filter to ones with said text, then modify/remove them. That is, if you can't get them removed on the server-side instead. – Kevin B May 30 '12 at 14:29
  • Shaded - it would, but I'm not in control of that, that's the 3rd party libraries doing that. I've contacted the authors to see what can be done, but their projects target MVC3, not MVC4. In a bit of a bind here server-side until I get that straightened out. Sometimes you need a bulldozer to do a shovel's work. – MisterJames May 30 '12 at 14:32

2 Answers2

2
$("body").contents().filter( function(){
    return this.nodeType === 3 && /Version=\d\.\d\.\d\.\d/.test(this.nodeValue);
}).remove();

Edit: since it appears the text might not be directly under body, we need to walk through the entire dom:

function walk( root ) {

    $( root ).contents().each( function() {

        if( this.nodeType === 1 && this.nodeName.toLowerCase() !== "iframe" ) {
            walk( this );
        }
        else if( this.nodeType === 3  && /Version=\d\.\d\.\d\.\d/.test(this.nodeValue)) {
            $(this).remove();
        }
    });
}

walk( "body" );
Esailija
  • 138,174
  • 23
  • 272
  • 326
  • That won't get direct children of the body, in case that's important. See http://stackoverflow.com/a/4399718/96100. – Tim Down May 30 '12 at 14:42
  • @TimDown it should be `.children()` that returns comments as well as text nodes. Do you mean it won't go any deeper? The OP said that the text is directly under body. – Esailija May 30 '12 at 14:43
  • Ah, I got it the wrong way round. So yes, it won't go deeper. I knew it was more complicated than just what you have. Sorry. – Tim Down May 30 '12 at 14:46
  • @TimDown yes I didn't bother walking the entire dom because of *The text is just rendered inline, not in an element. If it were at least put inside a div or a span I could do something about it, but it's just part of the body* Which I interpreted as: text nodes that are direct children of body. – Esailija May 30 '12 at 14:47
  • I think you're misreading that part of the question, based on the HTML snippet in the question. Looks like the offending text node could turn up in a `
    ` with class "row". I think the OP meant that the bad text nodes aren't in their own special container elements (i.e. elements containing just a bad text node and nothing else). I could be wrong though.
    – Tim Down May 30 '12 at 14:50
  • @TimDown ah I see, in that case I would need to walk the entire dom of course :P – Esailija May 30 '12 at 14:52
  • @Esailija Hey, perfect, thanks for this. I had just started working out something based on http://stackoverflow.com/a/4399718/266795 but this is simple and elegant. Cheers! – MisterJames May 30 '12 at 15:16
1

Here's a working jsfiddle based on @Pointy's suggestion. Adjust your regex as needed for your specific details.

//This is from http://stackoverflow.com/a/4399718/266795
var getTextNodesIn = function(el) {
    return $(el).find(":not(iframe)").andSelf().contents().filter(function() {
        return this.nodeType == 3;
    });
};

$(function () {
  getTextNodesIn("body").each(function (index, node) {
      if (/.*, NameSpace/.test(node.textContent)) {
         $(node).remove();              
      }
  });
});​
Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
  • Thanks for helping out...I ended up going with the 'walk' solution, but this was the path I was headed down as well. Cheers. – MisterJames May 30 '12 at 15:17