再谈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中的Document文档对象
Jan 16 Javascript
JS对img标签进行优化使用onerror显示默认图像
Apr 24 Javascript
node.js中的console用法总结
Dec 15 Javascript
jQuery焦点图轮播特效代码分享(3款)
Sep 05 Javascript
Jquery插件easyUi实现表单验证示例
Dec 15 Javascript
表单元素值获取方式js及java方式的简单实例
Oct 15 Javascript
基于angular实现三级联动的生日插件
May 12 Javascript
angularjs下拉框空白的解决办法
Jun 20 Javascript
layer子层给父层页面元素赋值,以达到向父层页面传值的效果实例
Sep 22 Javascript
解决vue-cli webpack打包后加载资源的路径问题
Sep 25 Javascript
vue实现自定义H5视频播放器的方法步骤
Jul 01 Javascript
JS如何在数组指定位置插入元素
Mar 10 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
利用Memcached在php下实现session机制 替换PHP的原生session支持
2010/08/21 PHP
编写php应用程序实现摘要式身份验证的方法详解
2013/06/08 PHP
探讨:如何通过stats命令分析Memcached的内部状态
2013/06/14 PHP
php中strtotime函数用法详解
2014/11/15 PHP
PHP简单选择排序算法实例
2015/01/26 PHP
PHP函数checkdnsrr用法详解(Windows平台用法)
2016/03/21 PHP
thinkphp3.2嵌入百度编辑器ueditor的实例代码
2017/07/13 PHP
解决laravel-admin 自己新建页面里 js 需要刷新一次的问题
2019/10/03 PHP
JavaScript中prototype为对象添加属性的误区介绍
2013/10/15 Javascript
JavaScript字符串对象toLowerCase方法入门实例(用于把字母转换为小写)
2014/10/17 Javascript
浅谈javascript 函数内部属性
2015/01/21 Javascript
JQuery基础语法小结
2015/02/27 Javascript
关于JavaScript的变量的数据类型的判断方法
2015/08/14 Javascript
jquery实现可自动收缩的TAB网页选项卡代码
2015/09/06 Javascript
jquery事件的ready()方法使用详解
2015/11/11 Javascript
JavaScript中递归实现的方法及其区别
2017/09/12 Javascript
浅谈vue中慎用style的scoped属性
2017/11/28 Javascript
vue-cli脚手架-bulid下的配置文件
2018/03/27 Javascript
浅谈手写node可读流之流动模式
2018/06/01 Javascript
解决vue 打包发布去#和页面空白的问题
2018/09/04 Javascript
浅谈在Vue.js中如何实现时间转换指令
2019/01/06 Javascript
原生js实现each方法实例代码详解
2019/05/27 Javascript
vue实现行列转换的一种方法
2019/08/06 Javascript
Vue.js仿Select下拉框效果
2020/02/18 Javascript
在Python中使用全局日志时需要注意的问题
2015/05/06 Python
python删除指定类型(或非指定)的文件实例详解
2015/07/06 Python
python按行读取文件,去掉每行的换行符\n的实例
2018/04/19 Python
浅析HTML5页面元素及属性
2021/01/20 HTML / CSS
审计专业自荐信范文
2014/04/21 职场文书
最常使用的求职信
2014/05/25 职场文书
承租经营合作者协议书
2014/10/01 职场文书
网络研修随笔感言
2015/11/18 职场文书
新店开业策划方案怎么书写?
2019/07/05 职场文书
pytorch 中autograd.grad()函数的用法说明
2021/05/12 Python
springboot临时文件存储目录配置方式
2021/07/01 Java/Android
openstack云计算keystone组件工作介绍
2022/04/20 Servers