IE6,IE7下设置透明度Opacity的Bug

今天在写一个跨浏览器的setOpacity设置HTML元素的透明度函数的时候,函数代码如下:

var setOpacity = function(elem, l){
     if (elem.filters) {
           elem.style.filter ="alpha(opacity="+l+")";
     } else {
           elem.style.opacity = l / 100;
     }
}

//Example:
onload=function(){
     setOpacity(document.getElementById("div"),20);
}

发现在IE6,IE7下总是没有效果,郁闷了一些时间,后来经过测试,无意中设置了元素的width和height样式,IE6,IE7出来效果了。惊奇了一下,之后又测试了只声明width或者只声明height的情况下,也有效果。现在发现问题了,可能是IE6、7下的Bug,也或者Microsoft有意这样设置。
问题找到了也就好对症下药了,可以按照这样的思路来解决这个问题:第一是根据需要在css里声明width或者height;第二是在Javascript里动态获取HTML元素潜在的width或者height,重新给它的width或者height赋值,这样就相当于“显示”声明了它的width或者height。下面是获取HTML元素潜在width和height的两个方法:

var Style = {
	//获取HTML元素最终样式的辅助函数
	getFinalStyle: function(elem, css){
		if (window.getComputedStyle) { //W3C
			return window.getComputedStyle(elem, null)[css];
		} else if (elem.currentStyle) {  //IE
			return elem.currentStyle[css];
		} else {
			return elem.style[css];
		}
	},
	height: function(elem){
		//首先检查HTML元素是否隐藏,因为display='none'的元素是获取不到高度和宽度的
		if (this.getFinalStyle(elem, "display") !== "none") {
			return elem.offsetHeight || elem.clientHeight;
		} else {
			//获取隐藏掉的函数的高度,先让它显示,获取到高度之后再隐藏,下同
			elem.style.display = "block";
			var h = elem.offsetHeight || elem.clientHeight;
			elem.style.display = "none";
			return h;
		}
	},
	width: function(elem){
		if (this.getFinalStyle(elem, "display") !== "none") {
			return elem.offsetWidth || elem.clientWidth;
		} else {
			elem.style.display = "block";
			var w = elem.offsetWidth || elem.clientWidth;
			elem.style.display = "none";
			return w;
		}
	}
}

通过上面Style对象的height和width就可以获取任何HTML元素的height和width。这样就可以在IE下在给元素设置透明度之前,获得它的width和height并赋值给它的style.height或者style.width:

var setOpacity = function(elem, l){
      if (elem.filters) {
            //在IE下给elem的height重新赋值
	elem.style.height=Style.height(elem,"height")+"px";
             elem.style.filter ="alpha(opacity="+l+")";
      } else {
             elem.style.opacity = l / 100;
      }
}

利用上面修改过后的方法,在IE6,IE7下运行正常了,问题得到了解决。不过值得说明的是,这个问题在IE8版本中似乎得到了修正,没有显示声明width或者height也都可以设置透明度,这是件好事。

IE的那些@cc_on

最近在编写一个获取DOM元素在文档中的X/Y坐标的时候,遇到了一个ie6,ie7下多出2个像素的问题,临时想到了ie的那套@cc_on特定判断语法,网上狂搜关于这方面的代码,搜出来一大把。现在将它们总结整理如下:

@_jscript_version是IE的版本号,/*@cc_on …… @*/就是IE专属的一个判断执行块,@_x86和@_x32 表示OS的位数。

 /*@cc_on
     @if (@_jscript_version < 5.7) {
         //code for IE6 and lower
     } @else {
        //code for IE7 and upper
     }
    @end
@*/

////////////////////////////////////////////

/*@cc_on
    @if (@_jscript_version > 5.7)
         document.write("You are using IE8+");

    @elif (@_jscript_version == 5.7 && window.XMLHttpRequest)
         document.write("You are using IE7");

    if (@_jscript_version==5.6 ||(@_jscript_version==5.7 && navigator.userAgent.toLowerCase().indexOf("msie 6.") != -1))
         document.write("You are using IE6");

    @elif (@_jscript_version == 5.5)
    document.write("You are using IE5.5");

    @else
    document.write("You are using IE5 or older");
    @end
@*/

//////////////////////////////////////////////////////////

/*@cc_on
   @if (@_jscript_version >= 5)
      document.write("IE Browser that supports JScript 5+");
   @elif (@_jscript_version >= 4)
      document.write("IE Browser that supports JScript 4+");
   @else
      document.write("Very old IE Browser");
   @end
@*/

通过上面的@cc_on,你可以针对目前IE的各版本来编写js脚本,但是还是那句话:可以不用的就别用吧,它也确实是有些丑陋。:)