• 精确获取样式属性(第2部分)(转)


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

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

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

    01.if(style.search(/background|color/) != -1) {
    02.  var color = {
    03.    aqua: '#0ff',
    04.    black: '#000',
    05.    blue: '#00f',
    06.    gray: '#808080',
    07.    purple: '#800080',
    08.    fuchsia: '#f0f',
    09.    green: '#008000',
    10.    lime: '#0f0',
    11.    maroon: '#800000',
    12.    navy: '#000080',
    13.    olive: '#808000',
    14.    orange:'#ffa500',
    15.    red: '#f00',
    16.    silver: '#c0c0c0',
    17.    teal: '#008080',
    18.    transparent:'rgba(0,0,0,0)',
    19.    white: '#fff',
    20.    yellow: '#ff0'
    21.  }
    22.  if(!!color[value]){
    23.    value = color[value]
    24.  }
    25.  if(value == "inherit"){
    26.    return getStyle(el.parentNode,style);
    27.  }
    28.  if(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(value)){
    29.    return rgb2hex(value)
    30.  }else if(/^#/.test(value)){
    31.    value = value.replace('#', '');
    32.    return "#" +  (value.length == 3 ? value.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : value);
    33.  }
    34.  return value;
    35.}

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

    001.(function(){
    002.  var isQuirk = (document.documentMode) ? (document.documentMode==5) ? true : false : ((document.compatMode=="CSS1Compat") ? false : true);
    003.  var isElement = function(el) {
    004.    return !!(el && el.nodeType == 1);
    005.  }
    006.  var propCache = [];
    007.  var propFloat = !+"\v1" ? 'styleFloat' : 'cssFloat';
    008.  var camelize = function(attr){
    009.    return attr.replace(/\-(\w)/g, function(all, letter){
    010.      return letter.toUpperCase();
    011.    });
    012.  }
    013.  var memorize = function(prop) { //意思为:check out form cache
    014.    return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : camelize(prop));
    015.  }
    016.  var getIEOpacity = function(el){
    017.    var filter;
    018.    if(!!window.XDomainRequest){
    019.      filter = el.style.filter.match(/progid:DXImageTransform.Microsoft.Alpha\(.?opacity=(.*).?\)/i);
    020.    }else{
    021.      filter = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
    022.    }
    023.    if(filter){
    024.      var value = parseFloat(filter[1]);
    025.      if (!isNaN(value)) {
    026.        return value ? value / 100 : 0;
    027.      }
    028.    }
    029.    return 1;
    030.  }
    031.  var convertPixelValue = function(el, value){
    032.    var style = el.style,left = style.left,rsLeft = el.runtimeStyle.left;
    033.    el.runtimeStyle.left = el.currentStyle.left;
    034.    style.left = value || 0;
    035.    var px = style.pixelLeft;
    036.    style.left = left;//还原数据
    037.    el.runtimeStyle.left = rsLeft;//还原数据
    038.    return px + "px"
    039.  }
    040.  var rgb2hex = function(rgb) {
    041.    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    042.    return "#"+tohex(rgb[1])+tohex(rgb[2])+tohex(rgb[3])
    043.  }
    044.  var tohex = function(x) {
    045.    var hexDigits = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
    046.    return isNaN(x) ? '00' : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
    047.  }
    048.  var getStyle = function (el, style){
    049.    var value;
    050.    if(!+"\v1"){
    051.      //特殊处理IE的opacity
    052.      if(style == "opacity"){
    053.        return getIEOpacity(el)
    054.      }
    055.      value = el.currentStyle[memorize(style)];
    056.      //特殊处理IE的height与width
    057.      if (/^(height|width)$/.test(style)){
    058.        var values = (style == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
    059.        if(isQuirk){
    060.          return el[camelize("offset-"+style)] + "px"
    061.        }else{
    062.          var client = parseFloat(el[camelize("client-"+style)]),
    063.          paddingA = parseFloat(getStyle(el, "padding-"+ values[0])),
    064.          paddingB = parseFloat(getStyle(el, "padding-"+ values[1]));
    065.          return (client - paddingA - paddingB)+"px";
    066.        }
    067.      }
    068.    }else{
    069.      if(style == "float"){
    070.        style = propFloat;
    071.      }
    072.      value = document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
    073.    }
    074.    //下面部分全部用来转换上面得出的非精确值
    075.    if(!/^\d+px$/.test(value)){
    076.      //转换可度量的值
    077.      if(/(em|pt|mm|cm|pc|in|ex|rem|vw|vh|vm|ch|gr)$/.test(value)){
    078.        return convertPixelValue(el,value);
    079.      }
    080.      //转换百分比,不包括字体
    081.      if(/%$/.test(value) && style != "font-size"){
    082.        return parseFloat(getStyle(el.parentNode,"width")) * parseFloat(value) /100 + "px"
    083.      }
    084.      //转换border的thin medium thick
    085.      if(/^(border).+(width)$/.test(style)){
    086.        var s = style.replace("width","style"),
    087.        b  = {
    088.          thin:["1px","2px"],
    089.          medium:["3px","4px"],
    090.          thick:["5px","6px"]
    091.        };
    092.        if(value == "medium" && getStyle(el,s) == "none"){
    093.          return "0px";
    094.        }
    095.        return !!window.XDomainRequest ? b[value][0] : b[value][1];
    096.      }
    097.      //转换margin的auto
    098.      if(/^(margin).+/.test(style) && value == "auto"){
    099.        var father = el.parentNode;
    100.        if(/MSIE 6/.test(navigator.userAgent) && getStyle(father,"text-align") == "center"){
    101.          var fatherWidth = parseFloat(getStyle(father,"width")),
    102.          _temp = getStyle(father,"position");
    103.          father.runtimeStyle.postion = "relative";
    104.          var offsetWidth = el.offsetWidth;
    105.          father.runtimeStyle.postion = _temp;
    106.          return (fatherWidth - offsetWidth)/2 + "px";
    107.        }
    108.        return "0px";
    109.      }
    110.      //转换top|left|right|bottom的auto
    111.      if(/(top|left|right|bottom)/.test(style) && value == "auto"){
    112.        return el.getBoundingClientRect()[style];
    113.      }
    114.      //转换颜色
    115.      if(style.search(/background|color/) != -1) {
    116.        var color = {
    117.          aqua: '#0ff',
    118.          black: '#000',
    119.          blue: '#00f',
    120.          gray: '#808080',
    121.          purple: '#800080',
    122.          fuchsia: '#f0f',
    123.          green: '#008000',
    124.          lime: '#0f0',
    125.          maroon: '#800000',
    126.          navy: '#000080',
    127.          olive: '#808000',
    128.          orange:'#ffa500',
    129.          red: '#f00',
    130.          silver: '#c0c0c0',
    131.          teal: '#008080',
    132.          transparent:'rgba(0,0,0,0)',
    133.          white: '#fff',
    134.          yellow: '#ff0'
    135.        }
    136.        if(!!color[value]){
    137.          value = color[value]
    138.        }
    139.        if(value == "inherit"){
    140.          return getStyle(el.parentNode,style);
    141.        }
    142.        if(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(value)){
    143.          return rgb2hex(value)
    144.        }else if(/^#/.test(value)){
    145.          value = value.replace('#', '');
    146.          return "#" +  (value.length == 3 ? value.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : value);
    147.        }
    148.        return value;
    149.      }
    150.    }
    151.    return value;//如 0px
    152.  }
    153.  var css = function(){
    154.    var a = arguments;
    155.    if(a.length == 1){
    156.      return getStyle(this,a[0])
    157.    }
    158.  }
    159.  var _ = function(el){
    160.    var el = isElement(el)? el :document.getElementById(el);
    161.    var gene = !el.constructor ? el : el.constructor.prototype;
    162.    gene.css = css;
    163.    gene.width = function(){ 
    164.      return getStyle(this,"width");
    165.    };
    166.    gene.height = function(){ 
    167.      return getStyle(this,"height");
    168.    };
    169.    return el
    170.  }
    171.  if(!window._){ //为了避免与JQuery的$发生冲突,我用_作为类库唯一的全局变量
    172.    window['_'] =_;
    173.  }
    174.  _.q = isQuirk;
    175.})()

    用法如下:

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

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

    01.function text(){
    02.  var body = document.body,html = document.documentElement;
    03.  _("w1").innerHTML = _(body).width();
    04.  _("w2").innerHTML = _(html).width();
    05.  _("h1").innerHTML = _(body).height();
    06.  _("h2").innerHTML = _(html).height();
    07.  _("ml1").innerHTML = _(body).css("margin-left");
    08.  _("ml2").innerHTML = _(html).css("margin-left");
    09.  _("mr1").innerHTML = _(body).css("margin-right");
    10.  _("mr2").innerHTML = _(html).css("margin-right");
    11.  _("mt1").innerHTML = _(body).css("margin-top");
    12.  _("mt2").innerHTML = _(html).css("margin-top");
    13.  _("mb1").innerHTML = _(body).css("margin-bottom");
    14.  _("mb2").innerHTML = _(html).css("margin-bottom");
    15.  _("pl1").innerHTML = _(body).css("padding-left");
    16.  _("pl2").innerHTML = _(html).css("padding-left");
    17.  _("pr1").innerHTML = _(body).css("padding-right");
    18.  _("pr2").innerHTML = _(html).css("padding-right");
    19.  _("bl1").innerHTML = _(body).css("border-left-width");
    20.  _("bl2").innerHTML = _(html).css("border-left-width");
    21.  _("br1").innerHTML = _(body).css("border-right-width");
    22.  _("br2").innerHTML = _(html).css("border-right-width");
    23.  _("qqq").innerHTML = !_.q ? "标准模式" : "怪癖模式";
    24.  _("t1").innerHTML = _(body).css("top");
    25.  _("t2").innerHTML = _(html).css("top");
    26.  _("l1").innerHTML = _(body).css("left");
    27.  _("l2").innerHTML = _(html).css("left");
    28.  _("ot1").innerHTML = body.offsetTop;
    29.  _("ot2").innerHTML = html.offsetTop;
    30.  _("ol1").innerHTML = body.offsetLeft;
    31.  _("ol2").innerHTML = html.offsetLeft;
    32.  _("ct1").innerHTML = body.clientTop;
    33.  _("ct2").innerHTML = html.clientTop;
    34.  _("cl1").innerHTML = body.clientLeft;
    35.  _("cl2").innerHTML = html.clientLeft;
    36.  _("cw1").innerHTML = body.clientWidth;
    37.  _("cw2").innerHTML = html.clientWidth;
    38.  _("ow1").innerHTML = body.offsetWidth;
    39.  _("ow2").innerHTML = html.offsetWidth;
    40.  _("sw1").innerHTML = body.scrollWidth;
    41.  _("sw2").innerHTML = html.scrollWidth;
    42.}

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

    1.<style type="text/css">
    2.  html{
    3.    border: 0;
    4.  }
    5.</style>

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

    再看怪癖模式,

    测试属性 document.body document.documentElement
    width 1024px 1024px
    height 604px 604px
    margin-left 0px undefined
    margin-right 0px undefined
    margin-top 0px undefined
    margin-bottom 0px undefined
    padding-left 0px 0px
    padding-right 0px 0px
    border-left-width 4px 0px
    border-right-width 4px 0px
    渲染模式 怪癖模式
    top 0 0
    left 0 0
    offsetTop 0 0
    offsetLeft 0 0
    clientTop 2 0
    clientLeft 2 0
    offsetWidth 1024 1024
    clientWidth 1003 0
    scrollWidth 1003 1024

    火狐等没有所谓的怪癖模式,直接看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(真拗口,难怪网景会失败),但滚动条的位置不是说变就变。
    来源:http://www.cnblogs.com/rubylouvre/archive/2009/09/08/1562212.html

  • 相关阅读:
    ArcEngine 9.3 学习笔记(十一):地图输出(Printer类,PageLayoutControl控件打印出图,栅格格式文件输出,矢量格式文件输出)
    SpringBoot动态修改Logger的日志级别
    SpringBoot整合SpringDataJpa + QueryDsl以及使用案例
    HPA 自动水平伸缩(基于CPU)
    k8s dashboard:v2.0.5
    PHP debug_backtrace的胡思乱想 豆浆油条
    PHP命名空间(Namespace)初探 豆浆油条
    sphinx全文检索之PHP使用教程 豆浆油条
    sphinx中文分词搜索coreseek windows下安装与基本使用简介 豆浆油条
    PHP闭包(Closure)初探 豆浆油条
  • 原文地址:https://www.cnblogs.com/luluping/p/1567557.html
Copyright © 2020-2023  润新知