jQuery 与 doctype 声明之前输出的文本交互

Posted

技术标签:

【中文标题】jQuery 与 doctype 声明之前输出的文本交互【英文标题】:jQuery interact with text outputted before doctype declation 【发布时间】:2019-05-26 18:08:49 【问题描述】:

我有一个输出 php 通知的 PHP 应用程序。这是在其他任何内容(包括 DOCTYPE 声明)之前简单地射入浏览器的文本。

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

有没有办法使用 jQuery 与此文本进行交互?它在浏览器中显示为第一件事。 jQuery中&lt;!DOCTYPE html&gt;上面的东西怎么选择?

【问题讨论】:

修复导致消息的行肯定更有意义吗?如果您真的不想(或不能)这样做,您可以使用输出缓冲来防止在 HTML 开始之前输出消息。 请提供一个最小、完整且可验证的示例:***.com/help/mcve Nick - 我需要专门使用 jQuery 来修改 PHP 通知。我正在寻找一个通用的解决方案,所以没有办法修复特定的PHP错误,因为我不知道它是什么。 Twisty,这是一个完整的例子。我正在寻找如何在 DOM 之前选择从 PHP 输出的文本。具体来说,这正是 PHP 输出“通知”和“错误”的方式。一旦它在浏览器中呈现,有没有办法用 jQuery 选择这个文本。你如何选择 /span> 上面的东西 禁用错误输出。让人们看到各种错误不是很安全 【参考方案1】:

您可以使用$('body').contents() 访问这些元素,因为浏览器会将它们解释为正文的元素。当浏览器在 doctype 声明之前看到文本时,它会将文本和 head 的内容转移到 body 中,因为它试图构建一个可行的 DOM,即使 html 无效。

由于浏览器已经重新组织了内容,你无法猜测头部的第一个元素应该是什么。此脚本允许您设置应该是头部的第一个元素的元素。然后,该脚本将访问您设置的元素之前的元素,并为您提供有关该元素是文本节点还是 DOM 元素的信息。

您必须使用 vanilla js 与文本节点进行交互,但您可以使用 jQuery 进行其他操作。

// 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>

【讨论】:

这个脚本会删除你选择为firstElementInHead的所有内容,在这种情况下我使用$('title'),但你可能需要使用$('meta:first-of-type')或脚本或链接标签。 我的初始代码通过调用 .remove() 与之交互。你可以对这些节点做任何你想做的事,但其中一些不是 jquery 元素,它们是文本节点。 浏览器正在刮掉文档类型。我已经更新了脚本和答案,试图澄清为什么这很棘手,以及你可以做些什么来操纵这些元素。将此 html 加载到本地页面而不是沙盒 iframe sn-p 以真正查看浏览器中发生的情况。 干得好!谢谢你的解释。 好吧,说实话,我希望你能够修复 php 端的错误,并且你不需要使用任何这些东西!

以上是关于jQuery 与 doctype 声明之前输出的文本交互的主要内容,如果未能解决你的问题,请参考以下文章

DOCTYPE 与浏览器模式分析

DOCTYPE 与浏览器渲染模式分析

html5与html 4.01的区别 doctype几种分类及其不同

Doctype 严格模式与混杂模式-如何触发这两种模式,区分它们有何意义?

js或者jQuery怎么写判断时间是多久之前,

如何理解DocType? 什么是严格模式与混杂模式?如何触发这两种模式?