document.enableStyleSheetsForSet() 的兼容

标签: document enablestylesheetsforset | 发表时间:2011-06-17 16:27 | 作者:(author unknown) never-online
出处:http://hax.iteye.com
可能有不少同学已经了解 alternate stylesheet ,不过实际上author样式表可以被设定为三类:

1. persistent style sheet:总是应用的样式表
2. preferred style sheet:默认应用的样式表
3. alternate style sheet:其他可选的样式表

我们平时通常写的样式表都是第一类,即persistent style sheet。
第二类样式表就是有title属性的样式表,比如:

<link rel="stylesheet" title="人文主义" href="...">

第三类则是这样:

<link rel="alternate stylesheet" title="古典" href="...">
<link rel="alternate stylesheet" title="Geek风" 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 enableStyleSheetsForSet(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方法。这些就作为浏览器兼容性的练习题留给读者了。






已有 0 人发表留言,猛击->>这里<<-参与讨论


ITeye推荐



相关 [document enablestylesheetsforset] 推荐:

PDF转全格式文档工具Ailt PDF to All Document Converter

- QQ - 软矿
A想将PDF转换成JPG格式,B想将PDF转换成Word文档,C想将PDF转换成PPT文档,D想将PDF转换成HTML文档……现在Ailt PDF to All Document Converter一次性满足所有人的要求,如名,PDF转全格式文档. Ailt PDF to All Document Converter有多牛X呢.