zoukankan      html  css  js  c++  java
  • 精确获取样式属性(第2部分)

    继续上一部分,我们要看一下颜色。火狐好像不管三七二十一都会转变为rgb格式,不过我们通常比较习惯的是hex格式。这就用到以下两函数。

        var rgb2hex = function(rgb) {
          rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
          return "#"+tohex(rgb[1])+tohex(rgb[2])+tohex(rgb[3])
        }
    
        var tohex = function(x) {
          var hexDigits = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
          return isNaN(x) ? '00' : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
        }
    

    我们用正则表达式在检测其是否为rgb格式,是就用rgb2hex来转换它。但如果是red,green等值呢,火狐就一反常态,转换为hex格式,但IE依然如故。我们没有办法,自己做一个哈希,把常用的颜色都弄进去,然后一一匹对便是。

            if(style.search(/background|color/) != -1) {
              var color = {
                aqua: '#0ff',
                black: '#000',
                blue: '#00f',
                gray: '#808080',
                purple: '#800080',
                fuchsia: '#f0f',
                green: '#008000',
                lime: '#0f0',
                maroon: '#800000',
                navy: '#000080',
                olive: '#808000',
                orange:'#ffa500',
                red: '#f00',
                silver: '#c0c0c0',
                teal: '#008080',
                transparent:'rgba(0,0,0,0)',
                white: '#fff',
                yellow: '#ff0'
              }
              if(!!color[value]){
                value = color[value]
              }
              if(value == "inherit"){
                return getStyle(el.parentNode,style);
              }
              if(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(value)){
                return rgb2hex(value)
              }else if(/^#/.test(value)){
                value = value.replace('#', '');
                return "#" +  (value.length == 3 ? value.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : value);
              }
              return value;
            }
    

    基本上是对于CSS的精确取值就是这样,显然它还存在许多不足之处,但对于布局用的和常用的样式都实现了。还提供了一个判断页面渲染模式的常数q,为了方便,方法名与JQuery同名(只能取值,不能赋值,以后有空慢慢与我的addSheet函数整合到一起)。

      (function(){
        var isQuirk = (document.documentMode) ? (document.documentMode==5) ? true : false : ((document.compatMode=="CSS1Compat") ? false : true);
        var isElement = function(el) {
          return !!(el && el.nodeType == 1);
        }
        var propCache = [];
        var propFloat = !+"\v1" ? 'styleFloat' : 'cssFloat';
        var camelize = function(attr){
          return attr.replace(/\-(\w)/g, function(all, letter){
            return letter.toUpperCase();
          });
        }
        var memorize = function(prop) { //意思为:check out form cache
          return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : camelize(prop));
        }
        var getIEOpacity = function(el){
          var filter;
          if(!!window.XDomainRequest){
            filter = el.currentStyle.filter.match(/progid:DXImageTransform.Microsoft.Alpha\(.?opacity=(.*).?\)/i);
          }else{
            filter = el.currentStyle.filter.match(/alpha\(opacity=(.*)\)/i);
          }
          if(filter){
            var value = parseFloat(filter[1]);
            if (!isNaN(value)) {
              return value ? value / 100 : 0;
            }
          }
          return 1;
        }
        var convertPixelValue = function(el, value){
          var style = el.style,left = style.left,rsLeft = el.runtimeStyle.left;
          el.runtimeStyle.left = el.currentStyle.left;
          style.left = value || 0;
          var px = style.pixelLeft;
          style.left = left;//还原数据
          el.runtimeStyle.left = rsLeft;//还原数据
          return px + "px"
        }
    
        var rgb2hex = function(rgb) {
          rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
          return "#"+tohex(rgb[1])+tohex(rgb[2])+tohex(rgb[3])
        }
    
        var tohex = function(x) {
          var hexDigits = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
          return isNaN(x) ? '00' : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
        }
        var getStyle = function (el, style){
          var value;
          if(!+"\v1"){
            //特殊处理IE的opacity
            if(style == "opacity"){
              return getIEOpacity(el)
            }
            value = el.currentStyle[memorize(style)];
            //特殊处理IE的height与width
            if (/^(height|width)$/.test(style)){
              var values = (style == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
              if(isQuirk){
                return el[camelize("offset-"+style)] + "px"
              }else{
                var client = parseFloat(el[camelize("client-"+style)]),
                paddingA = parseFloat(getStyle(el, "padding-"+ values[0])),
                paddingB = parseFloat(getStyle(el, "padding-"+ values[1]));
                return (client - paddingA - paddingB)+"px";
              }
            }
          }else{
            if(style == "float"){
              style = propFloat;
            }
            value = document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
          }
          //下面部分全部用来转换上面得出的非精确值
          if(!/^\d+px$/.test(value)){
            //转换可度量的值
            if(/(em|pt|mm|cm|pc|in|ex|rem|vw|vh|vm|ch|gr)$/.test(value)){
              return convertPixelValue(el,value);
            }
            //转换百分比,不包括字体
            if(/%$/.test(value) && style != "font-size"){
              return parseFloat(getStyle(el.parentNode,"width")) * parseFloat(value) /100 + "px"
            }
            //转换border的thin medium thick
            if(/^(border).+(width)$/.test(style)){
              var s = style.replace("width","style"),
              b  = {
                thin:["1px","2px"],
                medium:["3px","4px"],
                thick:["5px","6px"]
              };
              if(value == "medium" && getStyle(el,s) == "none"){
                return "0px";
              }
              return !!window.XDomainRequest ? b[value][0] : b[value][1];
            }
            //转换margin的auto
            if(/^(margin).+/.test(style) && value == "auto"){
              var father = el.parentNode;
              if(/MSIE 6/.test(navigator.userAgent) && getStyle(father,"text-align") == "center"){
                var fatherWidth = parseFloat(getStyle(father,"width")),
                _temp = getStyle(father,"position");
                father.runtimeStyle.postion = "relative";
                var offsetWidth = el.offsetWidth;
                father.runtimeStyle.postion = _temp;
                return (fatherWidth - offsetWidth)/2 + "px";
              }
              return "0px";
            }
            //转换top|left|right|bottom的auto
            if(/(top|left|right|bottom)/.test(style) && value == "auto"){
              return el.getBoundingClientRect()[style];
            }
            //转换颜色
            if(style.search(/background|color/) != -1) {
              var color = {
                aqua: '#0ff',
                black: '#000',
                blue: '#00f',
                gray: '#808080',
                purple: '#800080',
                fuchsia: '#f0f',
                green: '#008000',
                lime: '#0f0',
                maroon: '#800000',
                navy: '#000080',
                olive: '#808000',
                orange:'#ffa500',
                red: '#f00',
                silver: '#c0c0c0',
                teal: '#008080',
                transparent:'rgba(0,0,0,0)',
                white: '#fff',
                yellow: '#ff0'
              }
              if(!!color[value]){
                value = color[value]
              }
              if(value == "inherit"){
                return getStyle(el.parentNode,style);
              }
              if(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(value)){
                return rgb2hex(value)
              }else if(/^#/.test(value)){
                value = value.replace('#', '');
                return "#" +  (value.length == 3 ? value.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : value);
              }
              return value;
            }
          }
          return value;//如 0px
        }
    
        var css = function(){
          var a = arguments;
          if(a.length == 1){
            return getStyle(this,a[0])
          }
        }
        var _ = function(el){
          var el = isElement(el)? el :document.getElementById(el);
          var gene = !el.constructor ? el : el.constructor.prototype;
          gene.css = css;
          gene.width = function(){ 
            return getStyle(this,"width");
          };
          gene.height = function(){ 
            return getStyle(this,"height");
          };
          return el
        }
        if(!window._){ //为了避免与JQuery的$发生冲突,我用_作为类库唯一的全局变量
          window['_'] =_;
        }
        _.q = isQuirk;
      })()
    

    用法如下:

      window.onload = function(){
        alert(_("ccc").css("background-color"))
        alert(_("aaa").css("width"))
        alert(_(document.body).width())
      };
    

    我们可以用这个东西研究一下document.body与document.documentElement。

      function text(){
        var body = document.body,html = document.documentElement;
        _("w1").innerHTML = _(body).width();
        _("w2").innerHTML = _(html).width();
        _("h1").innerHTML = _(body).height();
        _("h2").innerHTML = _(html).height();
        _("ml1").innerHTML = _(body).css("margin-left");
        _("ml2").innerHTML = _(html).css("margin-left");
        _("mr1").innerHTML = _(body).css("margin-right");
        _("mr2").innerHTML = _(html).css("margin-right");
        _("mt1").innerHTML = _(body).css("margin-top");
        _("mt2").innerHTML = _(html).css("margin-top");
        _("mb1").innerHTML = _(body).css("margin-bottom");
        _("mb2").innerHTML = _(html).css("margin-bottom");
        _("pl1").innerHTML = _(body).css("padding-left");
        _("pl2").innerHTML = _(html).css("padding-left");
        _("pr1").innerHTML = _(body).css("padding-right");
        _("pr2").innerHTML = _(html).css("padding-right");
        _("bl1").innerHTML = _(body).css("border-left-width");
        _("bl2").innerHTML = _(html).css("border-left-width");
        _("br1").innerHTML = _(body).css("border-right-width");
        _("br2").innerHTML = _(html).css("border-right-width");
        _("qqq").innerHTML = !_.q ? "标准模式" : "怪癖模式";
        _("t1").innerHTML = _(body).css("top");
        _("t2").innerHTML = _(html).css("top");
        _("l1").innerHTML = _(body).css("left");
        _("l2").innerHTML = _(html).css("left");
        _("ot1").innerHTML = body.offsetTop;
        _("ot2").innerHTML = html.offsetTop;
        _("ol1").innerHTML = body.offsetLeft;
        _("ol2").innerHTML = html.offsetLeft;
        _("ct1").innerHTML = body.clientTop;
        _("ct2").innerHTML = html.clientTop;
        _("cl1").innerHTML = body.clientLeft;
        _("cl2").innerHTML = html.clientLeft;
        _("cw1").innerHTML = body.clientWidth;
        _("cw2").innerHTML = html.clientWidth;
        _("ow1").innerHTML = body.offsetWidth;
        _("ow2").innerHTML = html.offsetWidth;
        _("sw1").innerHTML = body.scrollWidth;
        _("sw2").innerHTML = html.scrollWidth;
      }
    

    在标准模式下,火狐等浏览器中我们看到offsetWidth等值最大为1007,因为火狐的offsetWidth不大于clientWidth,而clientWidth是不包含滚动条(滚动条的宽都固定为17px)。在IE中,offsetWidth是比clientWidth多了两个border,由此发现问题,1024-1003-17=4,4应该是两个auto生成,而这个auto应该为border的值,这两个border在IE中是固定死,不能通过以下手段修改。

    <style type="text/css">
      html{
        border: 0;
      }
    </style>
    

    换言之,在标准模式下,IE的html是存在不可修改的宽为2px的border。也换言之,我的程序是有个BUG,没有正确显示出html的border为2px,囧。

    再看怪癖模式,

    测试属性document.bodydocument.documentElement
    width
    height
    margin-left
    margin-right
    margin-top
    margin-bottom
    padding-left
    padding-right
    border-left-width
    border-right-width
    渲染模式
    top
    left
    offsetTop
    offsetLeft
    clientTop
    clientLeft
    offsetWidth
    clientWidth
    scrollWidth

    火狐等没有所谓的怪癖模式,直接看IE的。发现那神秘的2px又出现,这时出现在document.body的clientTop,clientLeft中。那么怪癖模式下的document.body的clientTop,clientLeft又相当于CSS的什么概念呢?我们来看微软给出的一幅老图,那时IE5独步天下,没有所谓标准模式与怪癖模式之分,因此这幅图的东西都是按怪癖模式表示的。

    不难看出,clientLeft相当于borderLeft,clientTop相当于borderTop。至于上面的border-left-width与border-right-width,就不要看了,是错误,因为我当初就没有考虑这两个元素在标准模式与怪癖模式下的问题。既然document.body的边框区就达1024px了,那么html元素的脸往哪里搁呢?!对不起,在微软早期的设想,body元素才是代表文档(一个强有力的证据是,在怪癖模式下,网页的滚动条是位于body元素中)。模准模式连同火狐那帮失败者宣扬的各种没有市场份额的“标准”,都是在微软极不情愿下支持的。你看,documentElement这样累赘傻气的名字像是微软起的吗?!如果是微软,它应该就叫html,和document.boy那样简洁。搞到在标准模式下,我们取scrollLeft,要用document.documentElement.scrollLeft,因为这时body不存在滚动条;在怪癖模式下,要用document.body,虽然微软以打补丁的方法添加上document.documentElement(真拗口,难怪网景会失败),但滚动条的位置不是说变就变。

  • 相关阅读:
    struts2 ajax传值
    s:iterator遍历
    JavaScript闭包
    组合继承与寄生组合式继承
    JSP EL表达式详细介绍
    js判断字符串是否包含中文或英文
    jQuery 中 jQuery(function(){})与(function(){})(jQuery) 的区别
    HTML5--新增结构元素(2)
    HTML5--新增全局属性(1)
    nodejs的安装配置(nvm-windows)
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1562212.html
Copyright © 2011-2022 走看看