再谈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 相关文章推荐
如何让页面加载完成后执行js
Jun 26 Javascript
jQuery实现点击文本框弹出热门标签的提示效果
Nov 17 Javascript
常见浏览器多长时间会提示“脚本运行时间过长”总结
Apr 29 Javascript
可编辑下拉框的2种实现方式
Jun 13 Javascript
基于jquery实现鼠标左右拖动滑块滑动附源码下载
Dec 23 Javascript
基于javascript简单实现对身份证校验
Jan 25 Javascript
JavaScript触发onScroll事件的函数节流详解
Dec 14 Javascript
Vue.js bootstrap前端实现分页和排序
Mar 10 Javascript
js获取指定时间的前几秒
Apr 05 Javascript
分享十三个最佳JavaScript数据网格库
Apr 07 Javascript
js判断用户是输入的地址请求的路径(实例讲解)
Jul 18 Javascript
jQuery Ajax 实现分页 kkpager插件实例代码
Aug 10 jQuery
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
Win9x/ME下Apache+PHP安装配置
2006/10/09 PHP
?繁体转换的class
2006/10/09 PHP
使用新浪微博API的OAuth认证发布微博实例
2015/03/27 PHP
记Laravel调用Gin接口调用formData上传文件的实现方法
2019/12/12 PHP
图片轮换效果实现代码(点击按钮停止执行)
2013/04/12 Javascript
js正文内容高亮效果的实现方法
2013/06/30 Javascript
详解JS 比较两个Json对象的值是否相等的实例
2013/11/20 Javascript
JS获取月的最后一天与JS得到一个月份最大天数的实例代码
2013/12/16 Javascript
将中国标准时间转换成标准格式的代码
2014/03/20 Javascript
js+jquery常用知识点汇总
2015/03/03 Javascript
JS通过ajax动态读取xml文件内容的方法
2015/03/24 Javascript
jQuery图片渐变特效的简单实现
2016/06/25 Javascript
javascript事件的绑定基础实例讲解(34)
2017/02/14 Javascript
详解vue-cli脚手架build目录中的dev-server.js配置文件
2017/11/24 Javascript
vue项目环境变量配置的实现方法
2018/10/12 Javascript
js微信分享接口调用详解
2019/07/23 Javascript
JavaScript面向对象程序设计中对象的定义和继承详解
2019/07/29 Javascript
javascript实现函数柯里化与反柯里化过程解析
2019/10/08 Javascript
vue 接口请求地址前缀本地开发和线上开发设置方式
2020/08/13 Javascript
python之pandas用法大全
2018/03/13 Python
python设置环境变量的原因和方法
2019/06/24 Python
PYTHON如何读取和写入EXCEL里面的数据
2019/10/28 Python
tensorflow获取预训练模型某层参数并赋值到当前网络指定层方式
2020/01/24 Python
Python ATM功能实现代码实例
2020/03/19 Python
英国家居用品和床上用品零售商:P&B Home
2020/01/16 全球购物
荷兰家电销售网站:Welhof
2020/12/08 全球购物
J2EE系统只能是基于web
2015/09/08 面试题
计算机专业自荐信
2013/10/14 职场文书
数学教学随笔感言
2014/02/17 职场文书
幼儿园的门卫岗位职责
2014/04/10 职场文书
领导干部保密承诺书
2014/08/30 职场文书
酒店管理失职检讨书
2014/09/16 职场文书
部门经理助理岗位职责
2015/04/13 职场文书
2015年妇产科工作总结
2015/05/18 职场文书
redis sentinel监控高可用集群实现的配置步骤
2022/04/01 Redis
tomcat默认最大连接数及相关调整方法
2022/05/06 Servers