日期:2014-05-16  浏览次数:20377 次

JavaScript动态添加样式,IE下通过
在.js文件对文档动态引入一些CSS样式。对于一些短小的CSS代码来说,这好办,我们可以调用其style方法,如

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

如果再长一点也无所谓:

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

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

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

function addSheetFile(path){
  var fileref=document.createElement("link")
  fileref.rel = "stylesheet";
  fileref.type = "text/css";
  fileref.href = path;
  fileref.media="screen";
  var headobj = document.getElementsByTagName('head')[0];
  headobj.appendChild(fileref);
}

这个函数在IE中有点累赘。我向来是支持哪个游览器就用哪个游览器的原生函数,直接使用二进制代码效率最高。

var oStylesheet = document.createStyleSheet ( sURL , iIndex );

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

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

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

      var iframe = document.createElement('iframe');//生成用于编辑的rich text editor
      var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
……

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

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <%# 强制IE8像IE7一样呈现网页 -%>
  <meta http-equiv=”X-UA-Compatible” content=”IE=EmulateIE7″ />
  <%#--默认所有的链接都在本窗口打开 -%>
  <base target="_self" />
  <title><%= h(yield(:title)) || controller.action_name  %></title>
  <%= stylesheet_link_tag "screen","button","style"  %>
  <link rel="stylesheet" href="/stylesheets/print.css" type="text/css" media="print">
  <!--[if lt IE 8]>
   <link rel="stylesheet" href="/stylesheets/ie.css" type="text/css" media="screen">
  <![endif]-->
  <%= javascript_tag "window._token = '#{form_authenticity_token}'" if ActionController::Base.allow_forgery_protection %>
  <%= javascript_include_tag :defaults  %>
   <style type="text/css" media="print"></style>
</head>

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

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

  var  styleElement = styleElements[0];
  var media = styleElement.getAttribute("media");
  if(media != null && !/screen/.test(media.toLowerCase()) ){
      styleElement.setAttribute("media", "screen");
  }

附上media的一些说明。

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

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

使用方法。