zoukankan      html  css  js  c++  java
  • 动态添加样式表规则

    先给出函数。

      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))
        }
      }
    

    有时我们需要在.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操作是最耗时的,能用私有就用私有!

    使用方法。

    addSheet("\
      .RTE_iframe{600px;height:300px;}\
      .RTE_toolbar{600px;}\
      .color_result{216px;}\
      .color_view{110px;height:25px;}\
      .color_code{text-align:center;font-weight:700;color:blue;font-size:16px;}\
      div.table{176px;position:absolute;padding:1px;}\
      div.table td{font-size:12px;color:red;text-align:center;}\
    " );*/
    

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

    /*
    动态添加样式表的规则
    */
    iCSS={add:function(css){
    	var D=document,$=D.createElement('style');
    	$.setAttribute("type","text/css");
    	$.styleSheet&&($.styleSheet.cssText=css)||
    		$.appendChild(D.createTextNode(css));
    	D.getElementsByTagName('head')[0].appendChild($);
    }};
    iCSS.add("\
    	.dhoooListBox,.dhoooListBox li{margin:0;padding:0;list-style-type:none;font-size:12px;cursor:default}\
    	.dhoooListBox{border:1px solid #aaa;180px;background:#eee;height:200px;overflow:auto;float:left}\
    	.dhoooListBox li{margin:5px;line-height:24px;background:url(images/smilies/time.gif) no-repeat 0 60%;padding-left:25px;color:#555;}\
    	.dhoooListBox li.selected{background-color:#FFCC33}\
    ");
    

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

    var getClass = function(ele) {
        return ele.className.replace(/\s+/,' ').split(' ');
    };
    var hasClass = function(ele,cls) {
        return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
    }
    //更快的版本
    var hasClass =function(ele,cls){
          return -1 < (" "+ele.className+" ").indexOf(" "+cls+" ");
    }
    var addClass = function(ele,cls) {
        if (!this.hasClass(ele,cls)) ele.className += " "+cls;
    }
    var removeClass = function(ele,cls) {
        if (hasClass(ele,cls)) {
            var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
            ele.className=ele.className.replace(reg,' ');
        }
    }
    
  • 相关阅读:
    一次关于聚合根的激烈讨论
    基于 abp vNext 和 .NET Core 开发博客项目
    PYTHON 学习笔记1 PYTHON 入门 搭建环境与基本类型
    DOCKER 学习笔记9 Kubernetes (K8s) 弹性伸缩容器 下
    DOCKER 学习笔记8 Docker Swarm 集群搭建
    DOCKER 学习笔记7 Docker Machine 建立虚拟机实战,以及错误总结
    DOCKER 学习笔记6 WINDOWS版尝鲜
    DOCKER 学习笔记5 Springboot+nginx+mysql 容器编排
    DOCKER 学习笔记4 认识DockerCompose 多容器编排
    DOCKER 学习笔记3 使用Docker部署SpringBoot
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1523104.html
Copyright © 2011-2022 走看看