再谈javascript 动态添加样式规则 W3C校检


Posted in Javascript onDecember 25, 2009

毫无疑问,基于表现与结构相分离的原则,直接导入一个新的样式表是最好的选择,但有些情况就行不通,如我们做一个能拖动的DIV,从设置样式的角度看,就是把它绝对定位,以防影响原来的文档流,然后一点点改变其top与left的值实现移动的效果。由于拖动是有时间概念的,一秒24帧,样式表不可能面面俱到都把它们写进去。因此动态生成样式规则与快速修改样式规则是非常有必要的,W3C为此做了大量的工作,在DOM2.0中,扩充了不少接口。

退一步说,表现与结构相分离也不止导入样式表这一条路。要知道,一共有三种样式类型,外部样式,内部样式,与内联样式。

* 外部样式,就是我们上面说的那个,写在一个独立的CSS文件中。
* 内部样式,就是独立写在一个style标签中,通常是放在head标签中,我最后提供的函数生成的样式就是内部样式。
* 内联样式,就是写在元素的style属性中的样式。

新添加的接口主要集中在外部样式中——之所以说接口,因为相应的实现是由浏览器方提供的,像IE6那样傲慢的家伙,从来无视它们的存在。

在W3C的模型中,type为"text/css"的link标签与style标签都是代表一个CSSStyleSheet对象,我们可以通过 document.styleSheets 获得当前页面中所有的CSSStyleSheet对象,不过这是一个集合,非单纯的数组。每一个CSSStyleSheet对象拥有如下属性,

* type:永远返回“text/css”字符串。
* disabled:和input的disabled的作用相同,默认是false。
* href:返回URL,如果是style标签为null。
* title:返回其title的值,title与普通元素的title无异,随你写什么。
* media:IE与火狐返回的东西并不一致,不太好说。media是用来规定它拥有的样式规则对什么设备有效,默认是所有。
* ownerRule:返回一个只读的CSSRule对象,如果样式表是用@import引入的话。
* cssRules: 返回一个只读的样式规则对象(CSSStyleRule object)的集合。

样式规则对象(CSSStyleRule object),是W3C为了对样式进行更细致的设定而搞出来的,如下面这个东西就是对应一个样式规则对象:

button[type] { 
padding:4px 10px 4px 7px; 
line-height:17px; 
}

样式规则对象拥有如下几个主要属性:type,cssText,parentStyleSheet,parentRule。

type有点类似节点的nodeType,对样式规则进行细分,它是用一个整数来表示其类型。具体情况如下

* 0: CSSRule.UNKNOWN_RULE
* 1: CSSRule.STYLE_RULE (定义一个CSSStyleRule对象)
* 2: CSSRule.CHARSET_RULE (定义一个CSSCharsetRule对象,用于设定当前样式表的字符集,默认与当前网页相同)
* 3: CSSRule.IMPORT_RULE (定义一个CSSImportRule对象,就是用@import引入其他的样式表)
* 4: CSSRule.MEDIA_RULE (定义一个CSSMediaRule对象,用于设定此样式是用于显示器,打印机还是投影机等等)
* 5: CSSRule.FONT_FACE_RULE (定义一个CSSFontFaceRule对象,CSS3的@font-face)
* 6: CSSRule.PAGE_RULE (定义一个CSSPageRule对象)

cssText不用多说,一个非常有用的属性,直接把字符串转换成样式规则,无视各浏览器样式属性的差异,如cssFloat 和styleFloat。

parentStyleSheet和parentRule都是针对@import来说的。不过,@import在IE下有问题,我基本不用它。

还有几个生不逢时的方法:

* nsertRule(rule,index): 添加一条样式规则。
* deleteRule(index): 移除一条样式规则。
* getPropertyValue(propertyName) 获取元素相应样式属性的值。如我们获得一个样式规则对象,可以利用CSSStyleRuleObject. getPropertyValue("color")获得其字体颜色的设置。与普通的el.style.color的方法相比,其效率相当高,因为 el.style.color获取的是内联样式,像IE那样的怪胎,如果你的元素没有设置style属性,根本无法得到准备的值,可能为空,可能是 inhert……可能还有兼容问题,而且这内联属性不一定是最终应用于元素的样式,IE只有调用不那么废物的 el.currentStyle[prop],其他浏览器就调用相当争气但有点麻烦的document. defaultView. getComputedStyle(el, "")[prop]。
* removeProperty(propertyName) 移除元素相应样式属性。
* setProperty(propertyName,value,priority)设定元素添加一个样式,还能指定优先级。

我们可以弄一个设定样式的函数出来:

var hyphenize =function(name){ 
return name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); 
} var camelize = function(name){ 
return name.replace(/\-(\w)/g, function(all, letter){ 
return letter.toUpperCase(); 
}); 
} 
var setStyle = function(el, styles) { 
for (var property in styles) { 
if(!styles.hasOwnProperty(property)) continue; 
if(el.style.setProperty) { 
//必须是连字符风格,el.style.setProperty('background-color','red',null); 
el.style.setProperty(hyphenize(property),styles[property],null); 
} else { 
//必须是驼峰风格,如el.style.paddingLeft = "2em" 
el.style[camelize(property)] = styles[property] 
} 
} 
return true; 
}

使用方法:
setStyle(div,{ 
'left':0, 
'top':0, 
'line-height':'2em', 
'padding-right':'4px' 
});

不过我非常不喜欢这方法,生成的是内联样式,它还得特殊处理float与opacity。在IE7的内联样式中,滤镜还有一个Bug,一定要让其得到hasLayout,要不滤镜就不会生效(我们可以通过el.currentStyle.hasLayout查看其状况)。因此,如其一个个设置,不如用cssText一网打尽。

最后附上我的加强版addSheet方法。它增添自动处理opacity的功能,也就是说我们只需要按标准设置cssText,它会自动生成相应的滤镜,这样一来至少让火狐等浏览器通过W3C的校检。

var addSheet = function(){ 
var doc,cssCode; 
if(arguments.length == 1){ 
doc = document; 
cssCode = arguments[0] 
}else if(arguments.length == 2){ 
doc = arguments[0]; 
cssCode = arguments[1]; 
}else{ 
alert("addSheet函数最多接受两个参数!"); 
} 
if(!+"\v1"){//新增功能,用户只需输入W3C的透明样式,它会自动转换成IE的透明滤镜 
var t = cssCode.match(/opacity:(\d?\.\d+);/); 
if(t!= null){ 
cssCode = cssCode.replace(t[0], "filter:alpha(opacity="+ parseFloat(t[1]) * 100+");"); 
} 
} 
cssCode = cssCode + "\n";//增加末尾的换行符,方便在firebug下的查看。 
var headElement = doc.getElementsByTagName("head")[0]; 
var styleElements = headElement.getElementsByTagName("style"); 
if(styleElements.length == 0){//如果不存在style元素则创建 
if(doc.createStyleSheet){ //ie 
doc.createStyleSheet(); 
}else{ 
var tempStyleElement = doc.createElement('style');//w3c 
tempStyleElement.setAttribute("type", "text/css"); 
headElement.appendChild(tempStyleElement); 
} 
} 
var styleElement = styleElements[0]; 
var media = styleElement.getAttribute("media"); 
if(media != null && !/screen/.test(media.toLowerCase()) ){ 
styleElement.setAttribute("media","screen"); 
} 
if(styleElement.styleSheet){ //ie 
styleElement.styleSheet.cssText += cssCode;//添加新的内部样式 
}else if(doc.getBoxObjectFor){ 
styleElement.innerHTML += cssCode;//火狐支持直接innerHTML添加样式表字串 
}else{ 
styleElement.appendChild(doc.createTextNode(cssCode)) 
} 
}
Javascript 相关文章推荐
深入理解JavaScript系列(2) 揭秘命名函数表达式
Jan 15 Javascript
jquery.artwl.thickbox.js  一个非常简单好用的jQuery弹出层插件
Mar 01 Javascript
详解jquery uploadify 上传文件
Nov 09 Javascript
你知道setTimeout是如何运行的吗?
Aug 16 Javascript
Vue.js每天必学之数据双向绑定
Sep 05 Javascript
bootstrap suggest搜索建议插件使用详解
Mar 25 Javascript
浅谈Vuex@2.3.0 中的 state 支持函数申明
Nov 22 Javascript
layui表格checkbox选择全选样式及功能的实例
Mar 07 Javascript
Angular入口组件(entry component)与声明式组件的区别详解
Apr 09 Javascript
Vue动态获取width的方法
Aug 22 Javascript
解决vue项目使用font-awesome,build后路径的问题
Sep 01 Javascript
JS+CSS实现动态时钟
Feb 19 Javascript
javascript 处理事件绑定的一些兼容写法
Dec 24 #Javascript
Javascript 键盘keyCode键码值表
Dec 24 #Javascript
JQuery与iframe交互实现代码
Dec 24 #Javascript
jquery 弹出登录窗口实现代码
Dec 24 #Javascript
Jquery 高亮显示文本中重要的关键字
Dec 24 #Javascript
JQuery 写的个性导航菜单
Dec 24 #Javascript
JavaScript中出现乱码的处理心得
Dec 24 #Javascript
You might like
Php中文件下载功能实现超详细流程分析
2012/06/13 PHP
一个php短网址的生成代码(仿微博短网址)
2014/05/07 PHP
linux下安装php的memcached客户端
2014/08/03 PHP
PHP获取服务器端信息的方法
2014/11/28 PHP
微信公众平台开发关注及取消关注事件的方法
2014/12/23 PHP
php使用递归计算文件夹大小
2014/12/24 PHP
PHP实现多级分类生成树的方法示例
2017/02/07 PHP
php 静态属性和静态方法区别详解
2017/04/09 PHP
PHP中OpenSSL加密问题整理
2017/12/14 PHP
PHP实现页面静态化深入讲解
2021/03/04 PHP
JavaScript 入门基础知识 想学习js的朋友可以参考下
2009/12/26 Javascript
php gethostbyname获取域名ip地址函数详解
2010/01/24 Javascript
jQuery EasyUI API 中文文档 - Dialog对话框
2011/11/15 Javascript
js获取指定日期前后的日期代码
2013/08/20 Javascript
js字符串转成JSON
2013/11/07 Javascript
JS文本获得焦点清除文本文字的示例代码
2014/01/13 Javascript
javascript动态向网页中添加表格实现代码
2014/02/19 Javascript
jquery操作checkbox示例分享
2014/07/21 Javascript
JQuery EasyUI 加载两次url的原因分析及解决方案
2014/08/18 Javascript
JS实现简单的选择题测评系统代码思路详解(demo)
2017/09/03 Javascript
vue用递归组件写树形控件的实例代码
2018/07/19 Javascript
基于Vue+ElementUI的省市区地址选择通用组件
2019/11/20 Javascript
VUE实现吸底按钮
2021/03/04 Vue.js
[43:47]DOTA2上海特级锦标赛主赛事日 - 4 败者组第四轮#2 MVP.Phx VS Fnatic第一局
2016/03/05 DOTA
介绍Python的Django框架中的静态资源管理器django-pipeline
2015/04/25 Python
Python 异常处理的实例详解
2017/09/11 Python
如何在python中判断变量的类型
2020/07/29 Python
纯CSS3打造动感漂亮时尚的扇形菜单
2014/03/18 HTML / CSS
Evisu官方网站:日本牛仔品牌,时尚街头设计风格
2016/12/30 全球购物
Lancer Skincare官方网站:抗衰老皮肤护理
2020/11/20 全球购物
房屋租赁合同补充协议
2014/10/11 职场文书
歌剧魅影观后感
2015/06/05 职场文书
2016廉洁从业学习心得体会
2016/01/19 职场文书
详解缓存穿透击穿雪崩解决方案
2021/05/28 Redis
详解Java实践之适配器模式
2021/06/18 Java/Android
Node.js实现爬取网站图片的示例代码
2022/04/04 NodeJs