简体   繁体   English

我可以使用innerHTML将所有可能的HTML元素附加到哪个HTML元素?

[英]To what HTML element can I append all possible HTML elements using innerHTML?

I have to pass HTML around in as a string (as I'm using postmessage for communication). 我必须将HTML作为字符串传递(因为我正在使用postmessage进行通信)。 To apply modifications to the html, I'm doing: 要将修改应用于html,我正在做:

function foo(my_string) {
  var temp, element_list;

  temp = document.createElement("div")
  temp.innerHTML = my_string;
  element_list = temp.querySelectorAll(".foo");
  ...

My problem is that my_string can be anything and in case I'm passing a string with table rows and cells like this: 我的问题是my_string可以是任何东西,以防我传递带有表行和像这样的单元格的字符串:

  '<tr>' +
    '<td>' +
      '<a href="#gadget._key=project_module%2F1&amp;gadget.view=view">' +
        'My Test Project 2014/12/16 14:24:48.930904 GMT' +
      '</a>' +
    '</td>' +
    '...' +
  '</tr>'

appending this to a <div> removes the table rows and cells and I'm left with links only. 将其附加到<div>会删除表中的行和单元格,而我只剩下链接。 Something like this: 像这样:

      '<a href="#gadget._key=project_module%2F1&amp;gadget.view=view">' +
        'My Test Project 2014/12/16 14:24:48.930904 GMT' +
      '</a>' +

Question: 题:
Is there a generic element, which accepts any type of child elements and does not modify whatever it's passed via innerHTML? 是否有一个通用元素,该元素可以接受任何类型的子元素,并且不会修改通过innerHTML传递的任何内容?

Thanks! 谢谢!

Edit : 编辑
The method is used to translate html snippets. 该方法用于翻译html代码段。 When I'm updating a table, it will only pass the generated table rows vs receiving the whole table on the initial page rendering. 当我更新表时,它将只传递生成的表行,而不是在初始页面呈现时接收整个表。

There isn't such an element. 没有这样的元素。 <tr> is a very good example of this. <tr>是一个很好的例子。 According to W3C standards, the "Permitted parent elements" for <tr> are "A <table> , <thead> , <tbody> or <tfoot> element." 根据W3C标准, <tr>的“允许的父元素”是“ A <table><thead><tbody><tfoot>元素。

If you must have these strings coming in as they are, your best bet is to perform some sort of detection as to the type of element(s) you are inserting, and wrap them in the appropriate HTML if required. 如果必须按原样输入这些字符串,则最好的选择是对要插入的元素类型进行某种检测,并在需要时将它们包装在适当的HTML中。

For example: ( View as a CodePen ) 例如:( 以CodePen的形式查看

HTML HTML

<div id="container"></div>

JavaScript JavaScript的

var anyone = "<div>In a Div</div>";
var tableOnly = "<tr><td>In a..</td></tr>" +
    "<tr><td>...table</td></tr>";

$(function () {
  var $container = $("#container");
  appendContent(anyone);
  appendContent(tableOnly);

  function appendContent(html) {
    var $html = $(html),
        $parent = $(),
        lastParent = "";
    $html.each(function () {
      var parent = parentTag(this.tagName);

      if(parent !== lastParent)
      {
        $container.append($parent);
        $parent = $(parent);
      }
      $parent.append(this);
      lastParent = parent;
    });

    $container.append($parent);
  }

  function parentTag(tagName) {
    switch (tagName.toLowerCase()) {
      case "tr":
        return "<table></table>";
      default:
        return "<div></div>";
    }
  }

});

Edit: Note that the technique used here to detect the tags used in your HTML can have problems if your HTML contains content that cannot be part of the same parent. 编辑:请注意,如果HTML包含的内容不能属于同一父级,则此处用于检测HTML中使用的标签的技术可能会出现问题。 For example, the following code would fail: 例如,以下代码将失败:

appendContent("<tr><td>Also in a table</td></tr><div>Also in a div</div>");

This is because of how jQuery internally builds its selectors. 这是因为jQuery如何在内部构建其选择器。 Since you can't have a div tag as a sibling to a tr , effectively the div element gets dropped. 由于您不能将div标签作为tr的兄弟,因此div元素将被有效删除。 Here's a CodePen demonstrating this , but from the sound of things, this wouldn't be an issue for the OP's needs. 这是一个CodePen演示的 ,但是从实际情况来看,这对于OP的需求而言不是问题。 If it is, you could use some alternative method of detecting the tags such as Regular Expressions. 如果是这样,则可以使用其他检测标记的方法,例如正则表达式。

If you append the mal-formatted HTML data (as you've noticed) with missing tags you're at the Browser DOM parser mercy removing every single one till a conformable HTML is returned. 如果您使用缺少的标签附加格式错误的HTML数据(如您所注意到的),那么您将受到浏览器DOM分析器的怜悯,将每一个都删除,直到返回符合标准的HTML。

If your main concern ( project-wise ) is just about table HTML content than you could treat the string as an XML data structure and get the needed wrapping tag and act accordingly: 如果您的主要关注点( 项目方面 )仅涉及表HTML内容 ,则可以将字符串视为XML数据结构并获取所需的包装标签并采取相应的措施:

jsBin demo jsBin演示

function sanitizeHTML( string ) {

  // Treat friendly a HTMLString as XML structure:
  var par = new DOMParser();
  var doc = par.parseFromString(string, 'text/xml');
  var chd = doc.firstChild;
  var tag = chd.nodeName.toUpperCase(); // Get the tag
  var ele;

  function wrapWith(parent, childEl){ // Wrap a node into a parent
    var p = document.createElement(parent);
    p.appendChild(childEl);
    return p;                         // And return that parent element.
  }

  if(/^(THEAD|TBODY|TR)$/.test(tag)){ // If THEAD or TBODY or TR
    ele = wrapWith("table", chd);     // just wrap in TABLE.
  }else if(/^(TD|TH)$/.test(tag)){    // Else if TD or TH
    ele = wrapWith("tr", chd);        // wrap first in TR
    ele = wrapWith("table", ele);     // and than in TABLE.
  }else{
    // All fine. Do we need something here?
  }

  return ele || chd; // Returns a HTMLElement
}

// This will return the final HTMLElement:
// var myEl = sanitizeHTML( str ); 

// Let's see in console:
console.log( sanitizeHTML( str ).outerHTML ); 

For simplicity sake the above code will consider strings with only one children. 为了简单起见,以上代码将考虑仅包含一个子代的字符串。
To extend it - loop all the children of the doc object. 要扩展它-循环doc对象的所有子对象。

See this jsfiddle: http://jsfiddle.net/Grezzo/x1qxjx5y/ 看到这个jsfiddle: http : //jsfiddle.net/Grezzo/x1qxjx5y/

With <tr> s in <table> s they are ok. <table>使用<tr>可以。

It's because you are putting a <tr> in a <div> which isn't valid. 这是因为您将<tr>放在<div>中是无效的。

Putting unsanitized content in the page like this is a real security risk 像这样在页面中放置未经消毒的内容是真正的安全风险

Update: I updated the jsfiddle to include two <div> s that were not modified by javascript and you can see that the <tr> s are stripped if they are not in a <table> parent: http://jsfiddle.net/Grezzo/x1qxjx5y/1/ 更新:我更新了jsfiddle,使其包含两个未被javascript修改的<div> ,并且您可以看到,如果<tr>不在<table>父级中,则它们会被剥离: http : //jsfiddle.net/ Grezzo / x1qxjx5y / 1 /

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM