首页 > 开发 > CSS > 正文

再谈动态添加样式规则

2024-07-11 08:22:26
字体:
来源:转载
供稿:网友

以前我就是一篇博文 就给出一个好用的函数,它在我几篇博文中被广泛运用的。最近看了不少东西,于是便有了这篇博文,以梳理我学到的新东西。

毫无疑问,基于表现与结构相分离的原则,直接导入一个新的样式表是最好的选择,但有些情况就行不通,如我们做一个能拖动的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 capitalize = function(prop){ 
  return prop.replace(//b[a-z]/g, function(match){ 
    return match.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))

  }

}

原文:http://www.cnblogs.com/rubylouvre/archive/2009/08/30/1556869.html

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表