再谈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 select下拉框操作的一些说明
Apr 02 Javascript
return false;和e.preventDefault();的区别
Jul 11 Javascript
js对象关系图 方便dom操作
Mar 18 Javascript
JS下拉缓冲菜单示例代码
Aug 30 Javascript
Js 获取、判断浏览器版本信息的简单方法
Aug 08 Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
Apr 27 Javascript
Angular 4.x 路由快速入门学习
May 03 Javascript
javascript显示动态时间的方法汇总
Jul 06 Javascript
详解JQuery基础动画操作
Apr 12 jQuery
Vue组件间通信 Vuex的用法解析
Aug 05 Javascript
javascript canvas封装动态时钟
Sep 30 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垃圾回收机制引用计数器概念分析
2013/06/24 PHP
ThinkPHP中RBAC类的四种用法分析
2014/11/24 PHP
Laravel框架源码解析之模型Model原理与用法解析
2020/05/14 PHP
tbody元素支持嵌套的注意方法
2007/03/24 Javascript
很酷的javascript loading效果代码
2008/06/18 Javascript
SWFObject Flash js调用类
2008/07/08 Javascript
js获取元素到文档区域document的(横向、纵向)坐标的两种方法
2013/05/17 Javascript
JS中数组Array的用法示例介绍
2014/02/20 Javascript
jQuery中使用data()方法读取HTML5自定义属性data-*实例
2014/04/11 Javascript
javascript数字时钟示例分享
2014/04/23 Javascript
JavaScript模板引擎用法实例
2015/07/10 Javascript
JS实现仿QQ效果的三级竖向菜单
2015/09/25 Javascript
Bootstrap Table表格一直加载(load)不了数据的快速解决方法
2016/09/17 Javascript
深入理解Vue-cli搭建项目后的目录结构探秘
2017/07/13 Javascript
nodejs动态创建二维码的方法
2017/08/12 NodeJs
vue自定义switch开关组件,实现样式可自行更改
2019/11/01 Javascript
vue 百度地图(vue-baidu-map)绘制方向箭头折线实例代码详解
2020/04/28 Javascript
小程序实现录音功能
2020/09/22 Javascript
OpenLayers加载缩放控件使用方法详解
2020/09/25 Javascript
对Python 网络设备巡检脚本的实例讲解
2018/04/22 Python
Python学习笔记之lambda表达式用法详解
2019/08/08 Python
python+selenium+Chrome options参数的使用
2020/03/18 Python
python怎么对数字进行过滤
2020/07/05 Python
Python调用系统命令os.system()和os.popen()的实现
2020/12/31 Python
利用CSS3实现动态的二级三级菜单效果实例源码
2017/01/04 HTML / CSS
简单掌握CSS3中resize属性的用法
2016/04/01 HTML / CSS
安全承诺书格式
2014/05/21 职场文书
关于九一八事变的演讲稿2014
2014/09/17 职场文书
合作协议书模板2014
2014/09/26 职场文书
离职报告范文
2014/11/04 职场文书
会计工作总结范文2014
2014/12/23 职场文书
高中诗歌鉴赏教学反思
2016/02/16 职场文书
go语言map与string的相互转换的实现
2021/04/07 Golang
React forwardRef的使用方法及注意点
2021/06/13 Javascript
你知道Java Spring的两种事务吗
2022/03/16 Java/Android
vue封装数字翻牌器
2022/04/20 Vue.js