jQuery interact with text outputted before doctype declation

Viewed 85

I have a PHP application that is outputting a PHP notice. This is text simply shot out into the browser before anything else, including the DOCTYPE declaration.

    <br />
    <b>Notice</b>:  Undefined property: bla bla blap</b> on line <b>16</b><br />
    <!DOCTYPE html>
...regular web page

Is there a way to interact with this text using jQuery? It shows in the browser as the very first thing. How do you select the stuff above <!DOCTYPE html> in jQuery?

1 Answers

You can access the elements using $('body').contents() because the browser interprets them as elements of the body. When the browser sees text before the doctype declaration, it shifts that text and the contents of the head into the body as it's way of trying to build a viable DOM even though the html was not valid.

Since the browser has reorganized the content, you cannot guess what the first element of the head was supposed to be. This script lets you set the element that was supposed to be the first element of the head. The script will then access the elements before the one you set and provides you with information regarding whether the element is a text node or DOM element.

You have to interact with the text nodes using vanilla js but you can use jQuery for the others.

// the script needs to know what should have been the first element in the head
const firstElementInHead = $( 'title' );
// remove all nodes prior to the intended content
$('body').contents().each( function() {
    if ( $(this).index() < firstElementInHead.index() ) {
        $(this).remove();
    }
});

<br />
<b>Notice</b>: Undefined property: bla bla blap on line <b>16</b><br />
<!doctype html>

<html lang="en">

<head>
  <title>The Broken Page</title>
  <meta charset="utf-8">


  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script type="text/javascript">
    // the script needs to know what should have been the first element in the head
    const firstElementInHead = $('title');
    // log the nodes that apear prior to the intended content
    $('body').contents().each(function() {
      if ($(this).index() < firstElementInHead.index()) {
        if (this.nodeType == Node.TEXT_NODE) {
          console.log('This is a text node. You can change it by setting this.nodeValue, remove it by calling this.remove(), or other vanilla JS operations.');
          console.log(this);
        } else {
          console.log('This is a DOM element. You can interact with it using jQuery the same way you interact with any normal DOM element.');
          console.log(this);
        }
      }
    });
  </script>
</head>

<body style="padding:0; margin:0;">
  <p style="padding:0; margin:0; background:red;">Test</p>
</body>

</html>

Related