document.enableStyleSheetsForSet() 的兼容

可能有不少同學已經瞭解 alternate stylesheet ,不過實際上author樣式表可以被設定爲三類:

1. persistent style sheet:總是應用的樣式表
2. preferred style sheet:默認應用的樣式表
3. alternate style sheet:其他可選的樣式表

我們平時通常寫的樣式表都是第一類,即persistent style sheet。
第二類樣式表就是有title屬性的樣式表,比如:

<link rel="stylesheet" [color=red]title="人文主義"[/color] href="...">

第三類則是這樣:

<link rel="[color=red]alternate[/color] stylesheet" [color=red]title="古典"[/color] href="...">
<link rel="[color=red]alternate[/color] stylesheet" [color=red]title="Geek風"[/color] href="...">

一些瀏覽器(FF和Opera)可以通過菜單切換到alternate stylesheet。Safari可能也有,Chrome默認沒有,但是可安裝extension。

注意,切換是依據title屬性互斥的,相同title的樣式表稱爲一個樣式表集(style sheet set)。比如切換到“古典”之後,原先perferred的“人文主義”就被disable了。但是persistent style sheet仍然是起作用的。

問題是如何通過腳本來切換樣式表集?CSSOM規範引入了一個新的API來達成這個目的:

[Supplemental] interface Document {
readonly attribute StyleSheetList styleSheets;
...
void [color=red]enableStyleSheetsForSet[/color](DOMString? name);
};

所以簡單的:
document.enableStyleSheetsForSet('Geek風')
就可以切換到“Geek風”樣式表集。

FF4已經支持該方法,不過較早的版本以及使用WebKit引擎的Safari、Chrome等怎麼辦呢?

一種想法是遍歷document.styleSheets然後根據title來設定disabled值,因爲標準所規定的行爲就是如此。代碼如下:


// 以下代碼在當前WebKit下不能work!
document.enableStyleSheetsForSet = function(name) {
if (name != null) for (var i = 0, n = this.styleSheets.length; i < n; i++) {
var sheet = this.styleSheets[i]
if (sheet.title) sheet.disabled = !(sheet.title == name)
}
}


不幸的是,上述看似合理的代碼在WebKit下不能work,因爲WebKit的document.styleSheets集合里根本不包括所有alternate style sheet。

那麼我們是否能自行取樣式集合呢?比如通過 document.querySelectorAll("style, link[rel~='stylesheet']") 。實際也是不行的,因爲WebKit根本就忽略了那些alternate樣式表,即使你直接設置那些樣式表的 disabled = false ,也不能啓用樣式表(實際上它們的disabled值原本就是false)。

難道除了抱怨WebKit在這個方面不合標準之外,我們就沒轍了嗎?


在放棄之前,我們應該把spec翻出來再好好讀讀。

直接上代碼:

if (!document.enableStyleSheetsForSet) document.enableStyleSheetsForSet = function(name) {
if (name != null) {
var meta = document.querySelector('meta[http-equiv="default-style"]')
if (!meta) {
meta = document.createElement('meta')
meta.httpEquiv = 'default-style'
document.head.appendChild(meta)
}
meta.content = name
}
}


非常簡單的實現,一切皆源自於default-style這個被人遺忘的特性。以上代碼在Chrome 10下測試通過。


PS. 在上述代碼裏,你可能注意到了“document.head”,這也是HTML5新增的屬性,但是那些更早的瀏覽器並沒有這個屬性。類似的問題還有querySelector方法。這些就作爲瀏覽器兼容性的練習題留給讀者了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章