14

Internet Explorer のみが element プロパティを持っているようです: canHaveHtml( MSDNDottoro )。タグ名のリストで正規表現を使用する以外に、他のブラウザでエミュレートするものを見つけることができないようです。Chrome、Firefoxなどでこれを判断する方法はありますか?

たとえば、innerHTMLプロパティを確認する方法はありますか?これは 100% 同等ですか?

4

4 に答える 4

5

それについての仕様はないと思います:

http://www.w3.org/TR/domcore/#concept-node-append

たとえば、Firefox、Chrome、および Safari では、次のように要素にノードを実際に追加でき<input>ます。

var input = document.createElement("input");
var div = document.createElement("div");

div.textContent = 'hello';

console.log(input.outerHTML, input.childNodes.length);

input.appendChild(div);

console.log(input.outerHTML, input.childNodes.length);

それらはレンダリングされていません。ただしinput、どちらの場合もノードの子と見なされます。Firefox の場合はouterHTML変更されず、childNodes長さのみが 1 と報告され、Chrome と Safari の場合はouterHTMLから に変更さ<input><input></input>ます。Firefox では、Safari や Chrome とは反対に、innerHTML実際には子の HTML を返します。たとえレンダリングされず、outerHTML.

更新: @Bergi が @MårtenWikström の回答で指摘したように、私が作成した以前のようなアプローチは、textarea、またはのようなコンテンツを持つことができるがtitle、HTML コンテンツを持たない要素では実際にはうまく機能しません。したがって、より良いcanHaveHTMLものは次のようになります。

// Improving the `canHaveHTML` using `canHaveChildren`,
// using the approach shown by Mårten Wikström
function canHaveChildren(node) {
  // Uses the native implementation, if any.
  // I can't test on IE, so maybe it could be worthy to never use
  // the native implementation to have a consistent and controlled
  // behaviors across browsers. In case, just remove those two lines
  if (node && node.canHaveChildren)
    return node.canHaveChildren();

  // Returns false if it's not an element type node; or if it has a end tag.
  // Use the `ownerDocument` of the `node` given in order to create
  // the node in the same document NS / type, rather than the current one,
  // useful if we works across different windows / documents.
  return node.nodeType === 1 && node.ownerDocument
      .createElement(node.tagName).outerHTML.indexOf("></") > 0;
}

function canHaveHTML(node) {
  // See comment in `canHaveChildren` about native impl.
  if (node && node.canHaveHTML)
    return node.canHaveHTML();

  // We don't bother to create a new node in memory if it
  // can't have children at all
  if (!canHaveChildren(node))
    return false;

  // Can have children, then we'll check if it can have
  // HTML children.
  node = node.ownerDocument.createElement(node.tagName);

  node.innerHTML = "<b></b>";

  // if `node` can have HTML children, then the `nodeType`
  // of the node just inserted with `innerHTML` has to be `1`
  // (otherwise will be likely `3`, a textnode).
  return node.firstChild.nodeType === 1;  
}

Firefox、Chrome、Safari でテスト済み。これは、すべてのノードとすべてのシナリオをカバーする必要があります。

于 2013-04-21T11:11:10.537 に答える
3

タグ名のリストで正規表現を使用する以外に、他のブラウザでエミュレートするものを見つけることができないようです。

エレガントでも賢くもないように見えるかもしれませんが、ホワイトリスト (またはブラックリスト) を作成するのが最も簡単で、最速で、最も信頼できる方法です。正規表現は必要ありません。連想配列などの単純な構造を使用して作成できます。

// blacklist approach

var noChildren = {
    input: true,
    meta: true,
    br: true,
    link: true,
    img: true

    // other properties here
};

function canHaveChildren(tagName) {
    tagName = tagName.toLowerCase();
    alert(noChildren[tagName] === undefined);
}

canHaveChildren("BR");
canHaveChildren("div");

デモ: http://jsfiddle.net/FTbWa/
再利用可能な関数: Github Gist

このパラダイムには優先順位がないわけではありません。多くのスクリプト ライブラリや HTML パーサー/サニタイザーで使用されています。たとえば、jQuery のソースを見ると、多くの要素固有のテストと、要素名と属性名の配列に気付くでしょう。

于 2013-04-21T11:28:07.450 に答える
0

ここで、要素に innerHTML プロパティがない場合は、値または src または type プロパティが必要であると想定しています。他の方法は考えられません。以下のコードでは処理できない特定のケースを処理するために、特定の TagName チェックを追加できます。

function CheckInnerHTMLSupport(oElement)
{
    var oDiv = document.createElement(oElement.tagName);
    if('canHaveHTML' in oDiv)
    {
        return oDiv.canHaveHTML;
    }
    var bSupportsInnerHTML = oDiv.type === undefined && oDiv.value === undefined && oDiv.src === undefined;
    return bSupportsInnerHTML;
}
于 2013-04-21T10:46:38.060 に答える