2017-03-01 7 views
3

私は、ブラウザが無効な、あるいは壊れたHTMLから初期構築中にDOMを "救助"しようとしますが、初期の構築後に有効なHTML規則を守っているようには見えません。例として最初のページロードの後に​​ブラウザがDOMを「レスキュー」するようトリガーされる手段はありますか?

button { 
 
    display: block; 
 
} 
 

 
img, 
 
td > img { 
 
    border: 3px solid limegreen; 
 
} 
 

 
tr>img { 
 
    border-color: red; 
 
} 
 

 
table { 
 
    table-layout: fixed; 
 
    border-collapse: collapse; 
 
} 
 

 
td { 
 
    padding: 1em; 
 
    text-align: center; 
 
    vertical-align: middle; 
 
    border: 1px solid #000; 
 
}
<table> 
 
    <tr> 
 
    <td>cell 1</td> 
 
    <!-- this was deliberately inserted into a bad 
 
      place (I already know it's wrong) --> 
 
    <img src="https://i.stack.imgur.com/92t7rs.png" /> 
 
    <td>cell 2</td> 
 
    <td><img src="https://i.stack.imgur.com/92t7rs.png" /></td> 
 
    </tr> 
 
</table>

JS Fiddle demo

私の現在のブラウザでは、Chrome 56、Opera 43、Edge 38、Firefox Developer Edition 53、Internet Explorer 11の場合、<img>は次のように表示されます。<table>は無効です。 <table><img>要素のみ<th>または<td>要素の子になります

この予想通りであり、私は比較的最近まで想定していたものを、意図的に、から私たちを防止し、一貫性のある行動だろうかそうでなければ、悪用するJavaScriptを使用して無効なDOMを作成します。

無効なDOMを作成するJavaScriptの明白な意思を示すために、<img>がページロード時に<table>から削除されています(前述のとおり、期待どおり)。 <button>をクリックすると、選択された<td>要素の次の兄弟として<img>要素を挿入するものの:

// 
 
// 
 
let image = document.createElement('img'); 
 
image.src = 'https://i.stack.imgur.com/92t7rs.png' 
 
document.querySelector('button').addEventListener('click', function() { 
 
    let cell = document.querySelector('td:first-child'); 
 
    cell.parentNode.insertBefore(image.cloneNode(), cell.nextSibling); 
 
});
button { 
 
    display: block; 
 
} 
 

 
img, 
 
td > img { 
 
    border: 3px solid limegreen; 
 
} 
 

 
tr > img { 
 
    border-color: red; 
 
} 
 

 
table { 
 
    table-layout: fixed; 
 
    border-collapse: collapse; 
 
} 
 

 
td { 
 
    padding: 1em; 
 
    text-align: center; 
 
    vertical-align: middle; 
 
    border: 1px solid #000; 
 
}
<button>add image inside a &lt;tr&gt; element (<strong>bad!</strong>)</button> 
 
<table> 
 
    <tr> 
 
    <td>cell 1</td> 
 
    <img src="https://i.stack.imgur.com/92t7rs.png" /> 
 
    <td>cell 2</td> 
 
    <td><img src="https://i.stack.imgur.com/92t7rs.png" /></td> 
 
    </tr> 
 
</table>

JS Fiddle demo

再び(上記のように)すべての私の現在のブラウザで、<button>をクリックするには、次のようになります:

述べたように<img>がの直接の子孫であるとして、上記、確かに無効なHTMLです<tr>tr > imgのCSSルールで選択して赤い枠線を適用します。

So:非破壊的な(バインドされたイベントハンドラを破壊しない)手段は、ページロード時に実装されている「レスキュー」の手段をブラウザに繰り返し実行させることを意味します。適切に「有効な」場所に移動しますか?

終了時には、–のソリューションをご希望の方は、–をJavaScriptライブラリではなくネイティブDOM APIに掲載することができます。ぜひ、のネイティブDOM APIソリューションだけを使って、ライブラリがどれくらい簡単かを示す回答を投稿してください。また

は、さらに添加剤として、私はこのようなアプローチ–に対応するためにあまりにも多くのエッジケースが存在することになるようだエミュレートネイティブDOMの「救出」–したいが、単にことを誘発しません "レスキュー'。

+0

かわいい赤の境界線がこれらの私たちのための代替として提供されているが、私はここに(、最初の、のためのテキストと、第二、任意のフリーハンド赤い丸の欠如の壁に私の謝罪を拡張[meta]からの訪問)。 –

+3

ページの読み込み中にエラーリカバリが発生するのは、マークアップを解析するときにのみ発生するからです。DOM操作にはマークアップは一切含まれていません。なぜなら、*要素*は操作されていてテキスト表現ではないからです。だから、私は想像していた、このエラー回復をトリガするためには、シリアライズされたフォーム(マークアップ)で要素ツリーを再解析する必要があります。 – BoltClock

+0

好奇心をそそり、ここでユースケースを持っているのですか、それとも一般知識を求めているだけですか? –

答えて

1

innerHTMLの種類を無効にすると、ページの読み込みが模倣されます。 innerHTMLをリセットすると、特定の要素にロードするときと同じ作業をブラウザに強制します。

ここでは、関数fixで、要素のinnerHTMLを取り戻して戻しました。ブラウザは、読み込み時に修正されるエラーを自動的に修正します。

// 
 
// 
 
let image = document.createElement('img'); 
 
image.src = 'https://i.stack.imgur.com/92t7rs.png' 
 
document.querySelector('button').addEventListener('click', function() { 
 
    let cell = document.querySelector('td:first-child'); 
 
    cell.parentNode.insertBefore(image.cloneNode(), cell.nextSibling); 
 
}); 
 

 
function fix(selector) { 
 
    var elem = document.querySelector(selector); 
 
    elem.innerHTML = elem.innerHTML; 
 
}
button { 
 
    display: block; 
 
} 
 

 
img, 
 
td > img { 
 
    border: 3px solid limegreen; 
 
} 
 

 
tr > img { 
 
    border-color: red; 
 
} 
 

 
table { 
 
    table-layout: fixed; 
 
    border-collapse: collapse; 
 
} 
 

 
td { 
 
    padding: 1em; 
 
    text-align: center; 
 
    vertical-align: middle; 
 
    border: 1px solid #000; 
 
}
<button>add image inside a &lt;tr&gt; element (<strong>bad!</strong>)</button> 
 
<button onclick="fix('table')">Fix it Felix!</button> 
 
<table> 
 
    <tr> 
 
    <td>cell 1</td> 
 
    <img src="https://i.stack.imgur.com/92t7rs.png" /> 
 
    <td>cell 2</td> 
 
    <td><img src="https://i.stack.imgur.com/92t7rs.png" /></td> 
 
    </tr> 
 
</table>

+0

私はそのアプローチについても考えていませんでした。しかし、このメソッドで見ることができる1つの問題は、要素の「innerHTML」をリセットすると、それらの既存要素にバインドされたイベントハンドラがすべて破棄されることです。私は「非破壊的」アプローチを探していることを明確にするために質問を更新しました。 –

+1

これは 'innerHTML'の欠点です。 –

+0

確かに、最終結果を(ほとんどの)達成する唯一の手段かもしれません。 –

関連する問題