JS函数:动态添加CSS样式表

作者:网络 来源:佚名 更新时间:2009-09-02 08:04:14 点击:

先给出函数。

01.var addsheet = function(){
02.  var doc,csscode;
03.  if(arguments.length == 1){
04.    doc = document;
05.    csscode = arguments[0]
06.  }else if(arguments.length == 2){
07.    doc = arguments[0];
08.    csscode = arguments[1];
09.  }else{
10.    alert("addsheet函数最多接受两个参数!");
11.  }
12.  if(!+"\v1"){//增加自动转换透明度功能,用户只需输入w3c的透明样式,它会自动转换成ie的透明滤镜
13.    var t = csscode.match(/opacity:(\d?\.\d+);/);
14.    if(t!= null){
15.      csscode = csscode.replace(t[0], "filter:alpha(opacity="+ parsefloat(t[1]) * 100+")")
16.    }
17.  }
18.  csscode = csscode + "\n";//增加末尾的换行符,方便在firebug下的查看。
19.  var headelement = doc.getelementsbytagname("head")[0];
20.  var styleelements = headelement.getelementsbytagname("style");
21.  if(styleelements.length == 0){//如果不存在style元素则创建
22.    if(doc.createstylesheet){    //ie
23.      doc.createstylesheet();
24.    }else{
25.      var tempstyleelement = doc.createelement('style');//w3c
26.      tempstyleelement.setattribute("type", "text/css");
27.      headelement.appendchild(tempstyleelement);
28.    }
29.  }
30.  var  styleelement = styleelements[0];
31.  var media = styleelement.getattribute("media");
32.  if(media != null && !/screen/.test(media.tolowercase()) ){
33.    styleelement.setattribute("media","screen");
34.  }
35.  if(styleelement.stylesheet){    //ie
36.    styleelement.stylesheet.csstext += csscode;
37.  }else if(doc.getboxobjectfor){
38.    styleelement.innerhtml += csscode;//火狐支持直接innerhtml添加样式表字串
39.  }else{
40.    styleelement.appendchild(doc.createtextnode(csscode))
41.  }
42.}

有时我们需要在.js文件对文档动态引入一些css样式。对于一些短小的css代码来说,这好办,我们可以调用其style方法,如

1.var ddd = document.getelementbyid("ddd");
2.ddd.style.border = "1px solid red";

如果再长一点也无所谓:

1.var ddd = document.getelementbyid("ddd");
2.ddd.style.csstext = "border:1px solid red;color:#000;background:#444;float:left";

本人而言,我是喜欢后者。因为前者有严重的兼容问题。如float这个样式,在ie是stylefloat,在火狐等w3c标准游览器是cssfloat。而csstext则是通吃。

如果很长,我们可以动态导入一css文件。如

01.function addsheetfile(path){
02.    var fileref=document.createelement("link")
03.    fileref.rel = "stylesheet";
04.    fileref.type = "text/css";
05.    fileref.href = path;
06.    fileref.media="screen";
07.    var headobj = document.getelementsbytagname('head')[0];
08.    headobj.appendchild(fileref);
09.}
这个函数在ie中有点累赘。我向来是支持哪个游览器就用哪个游览器的原生函数,直接使用二进制代码效率最高。
1.var ostylesheet = document.createstylesheet ( surl , iindex );

createstylesheet带的两个参数都是可选的。

但如果我们的样式是某个页面独有的,而且只有管理员才能使用到,而且那部分页面是动态生成的,我们需要一开始就引入它吗?需要特意弄个文件来装载它吗?最好的方法让这些样式与动态脚本捆绑在一起。我这个函数就为此而开发的。

坦白说,它最开始是为富文本编辑器而开发的。大家都知道,富文本输入框最流行的做法是把要输入的内容放到iframe中,这就涉及到两种document,一个主页面的document,另一个是iframe的document。 iframe的document又涉及到兼容问题。我们可以:

1.        var iframe = document.createelement('iframe');//生成用于编辑的rich text editor
2.        var iframedocument = iframe.contentdocument || iframe.contentwindow.document;
3.……

嘛,扯远了。总而言之,函数最开始的判定就是为这两种document而准备。如果没有涉及到iframe,我们只传入一个参数就行了。最后一个参数永远是css字符串。

然后是动态生成stylesheet元素,把css字符串加入到此元素的问题。当然如果有现阶段的,当然就用现成的。dom元素越多对游览器的负担就越大。我们想到document.stylesheets方法。它返回一个集合,包含style元素与link元素,还涉及一兼容问题,如:

01.<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en"
02."http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
03.<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
04.  <head>
05.    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
06.    <%# 强制ie8像ie7一样呈现网页 -%>
07.    <meta http-equiv=”x-ua-compatible” content=”ie=emulateie7′ />
08.    <%#--默认所有的链接都在本窗口打开 -%>
09.    <base target="_self" />
10.    <title><%= h(yield(:title)) || controller.action_name  %></title>
11.    <%= stylesheet_link_tag "screen","button","style"  %>
12.    <link rel="stylesheet" href="/stylesheets/print.css" type="text/css" media="print">
13.    <!--[if lt ie 8]>
14.     <link rel="stylesheet" href="/stylesheets/ie.css" type="text/css" media="screen">
15.    <![endif]-->
16.    <%= javascript_tag "window._token = '#{form_authenticity_token}'" if actioncontroller::base.allow_forgery_protection %>
17.    <%= javascript_include_tag :defaults  %>
18.     <style type="text/css" media="print"></style>
19.  </head>

上面用alert(document.stylesheets.length);测试一下,ie返回6,w3c游览器返回5。因此,否决了它。而且我们只用到style元素,不使用外联。第二部分的判定就针对head中的style元素而言,没有就创建一个。然后我们把css字符串加在第一个style元素就行了。

接着我们要加把保险锁,因为当media="print"时,只在页面打印时,定义的效果才有效。为了防止第一个style元素的media值不是screen,我们得改一改。

1.var  styleelement = styleelements[0];
2.var media = styleelement.getattribute("media");
3.if(media != null && !/screen/.test(media.tolowercase()) ){
4.    styleelement.setattribute("media", "screen");
5.}

附上media的一些说明。

  • screen (缺省值),提交到计算机屏幕;
  • print, 输出到打印机;
  • projection,提交到投影机;
  • aural,扬声器;
  • braille,提交到凸字触觉感知设备;
  • tty,电传打字机 (使用固定的字体);
  • tv,电视机;
  • all,所有输出设备。

最后是如此添加的问题。分ie,火狐与其他游览器三种。判定游览器也用各自的私有属性或方法。如stylesheet是ie独用的,getboxobjectfor是火狐独用的(当然你也可以使用(/firefox/.test(navigator.useragent.tolowercase())),通常dom操作是最耗时的,能用私有就用私有!

使用方法。

 

01.addsheet("\
02.  .rte_iframe{width:600px;height:300px;}\
03.  .rte_toolbar{width:600px;}\
04.  .color_result{width:216px;}\
05.  .color_view{width:110px;height:25px;}\
06.  .color_code{text-align:center;font-weight:700;color:blue;font-size:16px;}\
07.  div.table{width:176px;position:absolute;padding:1px;}\
08.  div.table td{font-size:12px;color:red;text-align:center;}\
09." );*/

对比一下51js的客服果果脚本,更短小,但是它会可能会创建多个style元素,还有一些效率的问题……毕竟我这个最初是为开发富文本编辑而开发的,功能不强大不行啊!

01./*
02.动态添加样式表的规则
03.*/
04.icss={add:function(css){
05.    var d=document,$=d.createelement('style');
06.    $.setattribute("type","text/css");
07.    $.stylesheet&&($.stylesheet.csstext=css)||
08.        $.appendchild(d.createtextnode(css));
09.    d.getelementsbytagname('head')[0].appendchild($);
10.}};
11.icss.add("\
12.    .dhooolistbox,.dhooolistbox li{margin:0;padding:0;list-style-type:none;font-size:12px;cursor:default}\
13.    .dhooolistbox{border:1px solid #aaa;width:180px;background:#eee;height:200px;overflow:auto;float:left}\
14.    .dhooolistbox li{margin:5px;line-height:24px;background:url(images/smilies/time.gif) no-repeat 0 60%;padding-left:25px;color:#555;}\
15.    .dhooolistbox li.selected{background-color:#ffcc33}\
16.");

最后追加几个相关的方法:

01.var getclass = function(ele) {
02.    return ele.classname.replace(/\s+/,' ').split(' ');
03.};
04.var hasclass = function(ele,cls) {
05.    return ele.classname.match(new regexp('(\\s|^)'+cls+'(\\s|$)'));
06.}
07.var addclass = function(ele,cls) {
08.    if (!this.hasclass(ele,cls)) ele.classname += " "+cls;
09.}
10.var removeclass = function(ele,cls) {
11.    if (hasclass(ele,cls)) {
12.        var reg = new regexp('(\\s|^)'+cls+'(\\s|$)');
13.        ele.classname=ele.classname.replace(reg,' ');
14.    }
15.}