阿当的博客











{三月 28, 2009}   ie6 png透明
#img{width:200px;height:200px;background:url(123.png);_background-image:none;_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=’123.png ‘, sizingMethod=’crop’);}


{三月 24, 2009}   window.open的小问题

window.open方法,通常会被浏览器拦截,但如果是用户行为驱动的,就不会被拦截了。

==================================

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>阿当制作</title>
</head>

<body>
<input type="button" id="btn" value="弹出" />
<script type="text/javascript">
function win(){
   window.open("http://www.sina.com.cn");
}
var btn = document.getElementById("btn");
btn.onclick = win;
win();
setTimeout(win,2000);
</script>
</body>
</html>

========================================

注意,ie下不但会被拦截,还会报错,事实上,ie下, setTimeout(win,2000); 这一句都没有运行。



{三月 24, 2009}   改变dom样式的方法[续]
   前两天才刚刚想到可不可以用改变<style>标签innerHTML的方式改变dom的样式,昨天看YUI文档的时候,发现新增了StyleSheet Utility组件,其功能就是支持通过更改<style>标签的innerHTML来改变dom样式。

   还没去看源码,不过,大概猜得到源码里做了些什么动作。就像我在《改变dom样式的方法》一文中说的一样,<style>标签在FF下是可以读写的,但ie下却需要通过特殊的方法实现,StyleSheet Utility组件一定会透明地对其进行封装。总之,YUI现在提供了对<style>标签innerHTML更改的组件了,那么,现在改变dom样式的方法,有三种方式可以自由选择了。

   YUI的确是不错,前两天刚想到的问题,马上就在YUI最新的组件里找到了答案,继续支持。



{三月 21, 2009}   读《javascript设计模式》后感
《javascript设计模式》的作者一个是美国雅虎的前端开发工程师,另一个是google的前端开发工程师,两人都十分熟悉YUI,所以这本书里随处可以看到YUI的影子,比如单一模式中的全局变量,直接对应的是YUI的YAHOO对象,然后extend方法,on方法,等等,在YUI源码中全都找得到相应的代码,呵呵,这对于包括我在内的一直使用YUI进行开发的工程师们来说,是非常有亲和力的。

书里讲的比较有趣的地方,并不在于第二部分的设计模式的讲解,而在第一部分对js的比较深入又有些生僻的地方的讲解,比如说js的继承。书中提到js有三种继承方式,其实第三种掺元类继承不应该算做继承,可以理解为面向对象中一种常用的方法——组合的衍生。第一种继承类式继承和第二种原型继承是真正的继承。对于类式继承,我比较熟悉,而对于原型继承,就真如作者据说,很少有人知晓了。感觉很新颖,不过,并不觉得实用,从团队合作的代码可读性方面,自己代码的一个维护难度方面考虑,还是用类式继承比较稳妥,原型继承算是了解一下,扩充一下知识点吧。

类式继承中,书里也提到了几个很有趣的地方,比如静态常量,私有变量,特权方法等等,充分利用了闭包的特性,让人耳目一新。非常有价值!

书中还提到了接口的问题,任何一个面向对象语言中,接口都是个非常重要的东西,特别在复杂应用中,团队合作中,接口的地位无可替代!可是对于js这种基于原型的非正统面向对象语言,原生js是不提供接口这个类型的。一种方法是通过规范的文档,约定好接口的相关事宜,大家统一遵守,另一种就是书中介绍的模拟接口的方式。这个方法也非常有意思,不一定在我们的应用中有这样的需求,不过,可以把这个做为一个解决方案的知识点记下来,以后有需要的时候,可以考虑使用。

对于书中的第二部分,也就是设计模式的讲解,书中提到的模式不太多,比如说状态模式,策略模式等等都没有讲到。其实帮助不是太大,设计模式本身也是超脱于具体语言的一种东西,所以这个后半部分有或没有,帮助不算太大,学习设计模式的话,可以看别的书籍也一样。让我有些意外的是,书中设计模式的名称好像不太正确。我看过的其它的设计模式的书,名称和相应的模式规则比较统一,估且认为那些书中相关模式的名称是对的吧,那么《j式》中的设计模式的名称就不太对了,比如说,书中提到的观察者模式,其实应该是命令模式,门面模式应该是组合模式,而组合模式应该是观察者模式。



{三月 21, 2009}   [原创] tab选项卡
写tab选项卡,主要可以分两种思路,一种是通过约定html结构,绑定class,然后通过一个js就实现页面内所有的tab。另一种是需要不约定html结构,只通过传id来给tab类来实现。我觉得后一种方式更灵活,虽然缺点是需要为每个tab去实例化一次类,好在问题不算大。用原生js写了个通用的tab类,如下:

========================
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>阿当制作</title>
</head>
<style type="text/css">
    .hidden{display:none;}
    .select{color:red;}
    .select2{color:green;}
</style>
<body>
<div><a href="#" id="t1" class="select">tab1</a> <a href="#" id="t2">tab2</a> <a href="#" id="t3">tab3</a></div>
<div>
    <div id="c1">111111111</div>
    <div id="c2" class="hidden">222222222</div>
    <div id="c3" class="hidden">333333333</div>
</div>
<br />
<br />
<br />
<br />
<br />
<div><a href="#" id="t4" class="select2">tab4</a> <a href="#" id="t5">tab5</a></div>
<div>
    <div id="c4">444444444444</div>
    <div id="c5" class="hidden">5555555555555</div>
</div>
<br />
<br />
<br />
<br />
<br />
<div><a href="#" id="t6" class="select">tab6</a> <a href="#" id="t7">tab7</a> <a href="#" id="t8">tab8</a></div>
<div>
    <div id="c6">6666666666</div>
    <div id="c7" class="hidden">777777777777</div>
    <div id="c8" class="hidden">8888888888888</div>
</div>
<br />
<br />
<br />
<br />
<br />
<div><a href="#" id="t9" class="select2">tab9</a> <a href="#" id="t10">tab10</a></div>
<div>
    <div id="c9">999999999999999</div>
    <div id="c10" class="hidden">101010101010101010</div>
</div>
<script type="text/javascript">
function Tab(itemList,config){
    if(config){
        var activeClass = config.activeClass || "selected";
        var act = config.act || "mouseover";
    } else {
        var activeClass = "selected";
        var act = "mouseover";
    }
    this.index = 0;
    this.labelList = [];
    this.contentList = [];
    this.count = itemList.length;
    var scope = this;
    var handler = function(){
        scope.activeHandle(this,scope,activeClass);
    }
    for(var i=0,n=this.count;i<n;i++){
        var label = this.$(itemList[i].label);
        var content = this.$(itemList[i].content);
        label.index = content.index = i;
        this.labelList.push(label);  
        this.contentList.push(content);
        if(act == "mouseover"){  
            label.onmouseover = handler;
        } else if(act == "click") {  
            label.onclick = handler;;
        }
    }
    if(config.auto){
        var oTime = config.time || 3000;
        setInterval(function(){
            scope.index++;
            if(scope.index >= scope.count){
                scope.index = 0;
            }
            scope.showContent(scope.index,activeClass);
        },oTime);
    }
}
Tab.prototype = {
    $ : function(id){
        return document.getElementById(id);
    },
    activeHandle:function(target,scope,activeClass){
        var index = target.index;
        var str = activeClass;
        scope.index = index;
        scope.showContent.call(scope,index,str);
    },
    showContent:function(index,str){
        for(var i=0,n=this.labelList.length;i<n;i++){
            if(this.labelList[i].className.indexOf(str)!=-1){  
                this.labelList[i].className = this.labelList[i].className.split(str).join("");
                this.contentList[i].style.display = "none";
            }
        }
        this.labelList[index].className = this.labelList[index].className + " " + str;
        this.contentList[index].style.display = "block";
    }  
}

new Tab([{label:"t1",content:"c1"},{label:"t2",content:"c2"},{label:"t3",content:"c3"}],{activeClass:"select"});
new Tab([{label:"t4",content:"c4"},{label:"t5",content:"c5"}],{activeClass:"select2",act:"click"});
new Tab([{label:"t6",content:"c6"},{label:"t7",content:"c7"},{label:"t8",content:"c8"}],{activeClass:"select",auto:true});
new Tab([{label:"t9",content:"c9"},{label:"t10",content:"c10"}],{activeClass:"select2",act:"click",auto:true,time:8000});
</script>
</body>
</html>

================================
功能说明:

Tab类,有两个构造参数,第一个参数是数组类型,里面是{labe:"",content:""}的json对象,label对应的是tab的标签,content是tab相应的内容,第二个参数是配置对象,是可选的,有四个参数,第一个是activeClass,用于设置当前激活tab的标签的class名,第二个是act,用于说明tab的触发条件,可以是"click",或者"mouseover",默认是mouseover,第三个是auto,设置是否自动切换,可选,默认是false,如果设置为true还可以设置第四个参数time,用于设置自动切换的间隔时间,可选,单位为微秒,默认为3000。



{三月 21, 2009}   [转载 js] YUI解决mouseout事件冒泡的办法

原文出处:http://design.alibaba-inc.com/?q=node/727

========================================

YAHOO.util.Dom.isAncestor —— 给元素寻根问祖

小马 的头像

语法:

YAHOO.util.Dom.isAncestor(haystack, needle)
YAHOO.util.Dom.inDocument(el)

YUI的源码里使用 haystack(草堆) 和 needle(针) 作为参数名,体现了YUI开发人员的幽默感。look for a needle in a haystack 正是大海捞针的意思。

isAncestor() 方法用来判断 haystack 元素是否是 needle 元素的父节点。它在鼠标参与的一些交互中非常有用。

我们都知道 mouseovermouseout 事件,它们不方便之处在于,当鼠标在容器上滑动时,可能多次触发 mouseovermouseout 事件,这增加了我们编码的复杂度。

IE支持mouseentermouseleave 事件,它们只在鼠标移到或移出容器时才触发。但其他浏览器并不支持这两个事件。但是,使用 inAncestor() 方法可以帮助我们模拟实现。看下面的例子:

//HTML 结构
<div id="demo-container">
    <ul id="demo-ul">
        <li id="child_1"><span><span><b><b>child 1</b></b></span></span></li>
        <li id="child_2"><span><span><b><b>child 2</b></b></span></span></li>
        <li id="child_3"><span><span><b><b>child 3</b></b></span></span></li>
    </ul>
</div>

<div id="msg"></div>

//JS
$E.onDOMReady(function() {
 var container = $('demo-container');
 var msgbox =  $('msg'); 

 //模拟 mouseenter 事件
 var mouseEnterHandler = function(ev) {
  //relatedTarget 在mouseover事件中指向鼠标从该处移过来的元素
  var rt = $E.getRelatedTarget(ev);
  //如果rt 不是container本身,同时也不是container的子元素,那么就是 Enter 的情况
  if (rt !== container && !$D.isAncestor(container, rt)) {
   msgbox.innerHTML += 'Entering ...';
  }
  msgbox.innerHTML += 'Mouse Over ...';
 }

 //模拟 mouseleave 事件
 var mouseLeaveHandler = function(ev) {
  msgbox.innerHTML += 'Mouse Out ...';
  //relatedTarget 在mouseout事件中指向鼠标移动到的元素
  var rt = $E.getRelatedTarget(ev);
  //如果rt 不是container本身,同时也不是container的子元素,那么就是 Leave 的情况
  if (rt !== container && !$D.isAncestor(container, rt)) {
   msgbox.innerHTML += 'Leaving ...';
  }
 } 

 $E.on(container, 'mouseover', mouseEnterHandler);
 $E.on(container, 'mouseout', mouseLeaveHandler);

});

打开范例文件

TBra 中的TB.widget.SimplePopup 组件正是采用了上例中的实现。

isAncestor() 方法还衍生 inDocument() 方法,该方法用来判断一个元素是否存在于DOM树中,其实它就是简单的调用 isAncestor() 方法,看它的源码:

/**
 * Determines whether an HTMLElement is present in the current document.
 * @method inDocument
 * @param {String | HTMLElement} el The element to search for
 * @return {Boolean} Whether or not the element is present in the current document
 */
inDocument: function(el) {
 return this.isAncestor(document.documentElement, el);
},


{三月 06, 2009}   改变dom样式的方法

改变dom样式有两种做法,一种是通过domNode.style.xxx = "",给domNode加上内置样式,这种方式如果需要的样式比较多,就只好一个个增加,比较麻烦,还有一种方式比较聪明,通过在css里预设好几种不同样式的类,然后需要更改某domNode的样式时,可以修改domNode的className,这是比较聪明的一种做法。

但是如果是某种类型的domNodes全都要改某种样式,这两种做法都需要遍历元素,对每一个进行操作一次,今天空想冒出个想法,能不能动态创建一个<style>节点,然后通过.innerHTML,给这个<style>节点填充css内容呢?

var newNode = document.creatElement("style");

document.body.appendChild(newNode);

newNode.innerHTML = "body{background:#000}";

按这个设想写了代码,结果在FF下执行正常,IE下没有出现我想要的效果。于是调试了半天,把.innerHTML换成.firstChild.nodeValue依然不行。最终发现,一直到document.body.appendChild(newNode);这一步都可以顺利执行,但是到了赋值这一步就不行了。于是换了种方法,直接在body里写上一个<style type="text/css" id =’test’></style>标签,然后用document.getElementById("test").innerHTML = "body{background:#000;}"来写,不动态创建节点了,结果还是在IE下不行。于是想偷偷骗浏览器一下试试,不直接把<style>结点赋值,改成

<div id = "test"></div>

document.getElementById("test").innerHTML = "<style type=’text/css’>body{background:#000}</style>";

还是不行,哭 T_T

最终结论,FF下<style>结点是可读写的,而IE下<style>结点是只读的。

================================================================

后记:

     今天找到一篇文章,讲的东西和我这篇文章讲的相似,但那篇文章里提到了ie下修改<style>标签的方法,有点生僻。转载过来。原文地址:http://hi.baidu.com/chenlinwei/blog/item/4a287f0a664c521995ca6b41.html

========================================

关于STYLE标签在FF,IE下的不同操作

有时候要动态的在页面中调整样式,需要用到对<style id="styleHandle"> .main a{text-decoration:none;}</style>标签的操作,这个在firefox下比较好办,
以jquery举例,只要$("#styleHandle").html("内容") 就可以了
但是在IE中,这样是不可以的。
IE对Style的处理很严格,不像其他普通的标签。
这里是IE对style标签操作的代码
    var obj = document.styleSheets[document.styleSheets.length-1]; 获得style的引用
                var rules = obj.rules || obj.cssRules;
                var selectorText;
                var styleObj = {};
                for(var i=0;o=rules[i];i++){
                    selectorText = o.selectorText; 这个selectorText 就是 <style>里面的每个样式的名称
                   
                   
                    styleObj[selectorText] = o.style;    每个样式具体的样式map        
                   
                }

操作到这里,比如我们现在要修改 开头所指的那个<style>中 .main a 的样式,将text-decoration设为underline
设置如下:
styleObj [".main A"].textDecoration = "underline";

注意这里的A要大写,不管你在style里面写的是大写还是小写,IE都会将a转换为大写。

完整测试代码:
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style type="text/css">
<!–
* {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 12px;
}
.height {
height:200px;
}
.width {
width:200px;
}
.color{
background-color:#CCCCCC;
}

.object_text{background-color:#CCCCCC;text-decoration:none; color:#377AD9; border-bottom: 1px none #377AD9;}

.object_text a:hover{background-color:#CCCCCC;text-decoration:none; color:#377AD9; border-bottom: 1px none #377AD9;}

–>
</style>
</head>

<body>
<hr />
Color:<br />
<input type="radio" name="radio" id="radio" value="#ff0000" onclick="c(this)" />#ff0000
<input type="radio" name="radio" id="radio2" value="#ff00ff" onclick="c(this)" />#ff00ff
<input type="radio" name="radio" id="radio3" value="#cc6600" onclick="c(this)" />#cc6600
<input type="radio" name="radio" id="radio4" value="#000000" onclick="c(this)" />#000000
<hr />
Width:
<input type="text" name="textfield" id="textfield" oninput="w(this)" onpropertychange="w(this)" />
Height:
<input type="text" name="textfield2" id="textfield2" oninput="h(this)" onpropertychange="h(this)" />
<table border="1">
<tr>
    <td class="height width color"></td>
    <td class="height width color"></td>
    <td class="height width color"></td>
    <td class="height width color"></td>
    <td class="height width color"></td>
</tr>
</table>
</body>
</html>
<script language="javascript" type="text/javascript">
var o;
var obj = document.styleSheets[0];
var rules = obj.rules || obj.cssRules;

var styleObj = {};
var selectorText,readonly,style,cssText;
for(var i=0;o=rules[i];i++){
selectorText = o.selectorText;
//readonly = new String(o.readOnly); IE
//cssText = o.cssText; FF
style = o.style;
alert(selectorText);
document.write(selectorText.fontcolor("#ff0000"),"<br />");
styleObj[selectorText] = style;
}

function c(obj){
if(obj.checked)
styleObj[".color"].backgroundColor = obj.value;
}

function h(obj){
try{
styleObj[".height"].height = parseInt(obj.value) + "px";
}catch(e){}
}

function w(obj){
try{
alert(styleObj[".object_text A"].color);
styleObj[".width"].width = parseInt(obj.value) + "px";
}catch(e){
     alert(e);
}
}
</script>




about

打造高品质的前端代码

pages
categories
archive
et cetera