2012-02-01 278 views
6

下面的代碼[jsfiddle] ...HTML中的自定義自閉合/不成對標籤?

var div = document.createElement("div"); 
div.innerHTML = "<foo>This is a <bar /> test. <br> Another test.</foo>"; 
alert(div.innerHTML); 

...顯示了這種分析的結構:

<foo>This is a <bar> test. <br> Another test.</bar></foo> 

即瀏覽器知道<br>沒有結束標籤,但由於<bar>是一個未知的標籤到瀏覽器,它假定它需要一個結束標記。

我知道/>(solidus)語法在HTML5中被忽略,在HTML4中無效,但無論如何想教某個瀏覽器<bar>不需要結尾標記,我可以忽略它。 這可能嗎?

是的,我試圖(暫時)濫用自定義標記的HTML代碼,我有我的具體原因做到這一點。畢竟,瀏覽器應該忽略未知標籤,並將它們視爲無格式的內嵌標籤,所以我不應該破壞任何東西,只要我能確保標籤名稱不會在真正的HTML標準中使用。

+1

您可以自由落後,但請添加註釋以解釋原因... – 2012-02-01 15:59:28

回答

5

你不得不使用Object.defineProperty上HTMLElement.prototype覆蓋innerHTML的setter和用自己的innerHTML的實現,把要作爲void元素吸氣劑。關於默認情況下如何實現innerHTML和HTML解析器,請看here

請注意,雖然Firefox在繼承時需要在HTMLElement.prototype上定義一些內容,例如它會過濾掉HTMLDivElement。事情應該在Opera中正常工作。

換句話說,什麼元素是無效的取決於HTML解析器。解析器遵循this list,而innerHTML大多使用相同的規則。所以,換句話說,除非你想在JS中創建你自己的innerHTML實現,否則你可能應該忘記這一點。

儘管您可以使用live DOM viewer來向其他人顯示某些標記是如何解析的。那麼你可能會注意到相同的結束標籤會隱式關閉打開的元素。

我有一些過時的innerHTML getter(不是setter雖然)代碼here,它使用一個void元素列表。這可能會給你一些想法。但是,編寫一個setter實現可能會更困難。另一方面,如果使用createElement()和appendChild()等代替innerHTML,則不必擔心此問題,並且本地innerHTML獲取器將使用結束標記輸出未知元素。

不過請注意,你可以把這種未知的元素爲XML和使用的XMLSerializer()和的DOMParser()做的事情:

var x = document.createElement("test"); 
var serializer = new XMLSerializer(); 
alert(serializer.serializeToString(x)); 
var parser = new DOMParser(); 
var doc = parser.parseFromString("<test/>", "application/xml"); 
var div = document.createElement("div"); 
div.appendChild(document.importNode(doc.documentElement, true)); 
alert(serializer.serializeToString(div)); 

這不正是你想要的,但有些事你可以玩。 (測試在Opera而不是Firefox中看到與xmlns屬性的區別,另外請注意,Chrome並不像Opera和Firefox那樣)

+0

感謝所有有用的參考。我使用innerHTML有兩個原因:第一,因爲它是一個相當快且容忍的解析器。其次,因爲我的目標不是依賴innerHTML,而是允許使用現有的DOM子樹。這意味着瀏覽器本身必須接受新的無效標籤,如果可能的話。 ---作爲一個方面說明,我想知道如何將HTML **標準添加到新的** void **標記中,因爲它們顯然會混淆所有的HTML5-解析器...... – 2012-02-01 13:45:03

+0

@UdoG增加了一個一點你可以玩的東西。 – Shadow2531 2012-02-01 16:41:22