CSSASSCSSASS

三人行必有我师焉,择其善者而从之,其不善者而改之
三人行必有我师焉,择其善者而从之,其不善者而改之
三人行必有我师焉,择其善者而从之,其不善者而改之
三人行必有我师焉,择其善者而从之,其不善者而改之
三人行必有我师焉,择其善者而从之,其不善者而改之

  获取元素尺寸和位置的两个冷门方法 作者:ONEBOYS    发表时间: 2012年01月4号,星期三     阅读:140 次  

获取元素的尺寸,似乎offsetWidth/Height就可以了,还需要什么方法吗?
的确,一般情况下,获取元素尺寸,用offsetWidth/Height就搞定了,但如果这个元素是display:none的呢?
试验一下就知道,none元素的尺寸是0。

所以需要我们下面的这个方法来获取。

第二个,获取元素的位置。
或许你经常使用offsetLeft/Top来获取位置,不过offsetLeft/Top是相对 offsetParent的位置(在ie6,7下是相对直接父级的),并且在firefox下还有些小bug

下面这个方法提供获取元素相对于窗口(页面可视区)的距离。

这个方法是由ie提出的,不过在其他浏览器吸收之后,还加了width,height两个值。

重复一下,这个方法是相对于页面窗口的,至于相对于整个页面文档的距离,那只需加上scrollTop这些值就行了,不做赘述。

   

  mouseenter/mouseleave事件和delegate方法的实现 作者:ONEBOYS    发表时间: 2011年12月18号,星期天     阅读:308 次  

众所周知,事件onmouseover和onmouseout有一个极其不好的问题,就是在绑定元素内部的子元素上滑动会反复触发事件,及执行绑定的方法。

而ie在很早的时候有提供了另一对事件:mouseenter和mouseleaver。顾名思义,就是只有当mouse滑进滑出绑定元素的时候,才会触发。

但是,这本来只是ie的私有属性,虽然已属于DOM3 Event草案当中,其他浏览器的支持率并不是很高,目前看来,Opera11.10已提供支持,而Firefox到10.0会提供支持,Webkit的暂无消息。
所以,如果想要用,我们得自己动手。

先搞一个通用的事件绑定函数:

  1. var addEvent = function( target,type,fn ) {
  2.     if(target.addEventListener)
  3.     {
  4.         target.addEventListener(type,fn,false);
  5.     }
  6.     else if(target.attachEvent)
  7.     {
  8.         target.attachEvent("on" + type,fn);
  9.     }
  10. };
  11. var removeEvent = function(target,type,fn ) {
  12.     if(target.addEventListener)
  13.     {
  14.         target.removeEventListener(type,fn,false);
  15.     }
  16.     else if(target.attachEvent)
  17.     {
  18.         target.detachEvent("on" + type,fn);
  19.     }
  20. };

我们的mouseenter/leave是通过mouseover/out来实现的,只需屏蔽mouseover/out在元素内部触发时的事件传播即可。

为了解除绑定,我们设计了一个events._mouseFn来保存绑定的方法,在解除操作时读取对应的方法进行解绑。因为事件可以绑定多个方法,我们需要保存对应的方法,以便之后对应解除。
当然如果这里如果按面向对象的思路实现,就可以各自保存,而不需要保持在同一个events._mouseFn对象下。但每绑定一个事件,都需实例化一个对象,显得很多余,所以不采用面向对象的模式。

接下来是文章的第二部分,我们来实现下jquery中提供的delegate方法。
(delegate是live方法的扩展版。delegate是基于live的,live是基于bind的。在jquery1.7中又被封装进了on方法。1.7中的on方法是一个很辽阔的方法。其实封装的越厉害,效率就越差了,这也是为什么我们选择自己做简单封装的原因,而不是使用jquery已封装好的)。
这个方法可以将想要绑定在子级元素上的事件方法,委托绑定在其父级上,用事件传播机制来触发执行。
这么做的好处有:
1:如果子级有n个并列元素需要绑定,绑子级需要绑n次,而将其绑定在父级上则只需绑定一次,这是很高效的。
2:如果子级元素有动态增加的话,新增元素是没有绑定过任何事件方法的。而如果之前选择的是绑定其父级,就不会有这个问题。

这里的实现思路是这样的:如果触发事件的元素,是你想要绑定的元素的子级(当然他肯定已是委托实际绑定元素的子级),就执行绑定的事件方法,否则方法就不执行,看上去就像方法没绑定过一样。
同实现onmouseenter一样,我们也设计了一个events._deleFn来用于后面的解绑方法undelegate的实现。

在使用delegate时,我们同样遇到了mouseover/out的问题。
我们的解决方案是:不罗嗦,直接将mouseover/out处理成mouseenter/leave

最后,整理一下,封装一个支持mouseenter 和 mouseleave事件,delegate方法 及其他们的解除绑定的方法的 功能函数库。

  1. var events = {}
  2. events._deleFn = {}; //保存delegate所绑定的方法   
  3. events._mouseFn ={}; //保存“onmouseenter”和“onmouseleave”所绑定的方法
  4.  
  5. events._mouseHandle = function(fn){
  6.     /* 实现mouseenter/leave 的转换方法,符合条件时才会执行 */
  7.     var func = function(event){
  8.         var target = event.target;
  9.         var parent = event.relatedTarget; //在onmouseover/out操作中,相关的另一个节点
  10.         while( parent && parent != this ){ 
  11.             try{ parent = parent.parentNode; }
  12.             catch(e){break;}
  13.         }
  14.         /* 只有当相关节点的父级不会是绑定的节点时(即二者不是父子的包含关系),才调用fn,否则不做处理 */
  15.         ( parent != this ) && (fn.call(target,event));
  16.     };
  17.     return func;
  18. }
  19.  
  20. events._delegateHandle = function(obj,elm,fn){
  21.     /* 实现delegate 的转换方法,符合条件时才会执行 */
  22.     var func = function(event){
  23.         var event = event || window.event;
  24.         var target = event.srcElement || event.target;
  25.         var parent = target;
  26.  
  27.         function contain(item,list){
  28.             /* item对象是否就是list对象 */
  29.             if(list.length == undefined ) return (item === list);
  30.            
  31.             /* item对象是否是list对象数组中的一个 */
  32.             for(var i=0 ; i<list.length; i++){
  33.                 if(item === list[i]) return true;
  34.             }
  35.             return false;
  36.         }
  37.  
  38.         while(parent){
  39.             /* 如果触发的元素,属于绑定元素(elm)的子级。 */
  40.             if(contain(parent,elm)){
  41.                 if(event.type == 'mouseover' || event.type == 'mouseout'){
  42.                     /*
  43.                     * 将mouseover/out直接处理成mouseenter/leave: 事件相关元素不属于绑定元素的子级,才绑定方法
  44.                     */
  45.                     //事件相关元素。ie下使用toElement和fromElement,其他用relatedTarget。
  46.                     var related = event.relatedTarget || ((event.type == 'mouseout') ? event.toElement : event.fromElement);
  47.                     if(contain(target,elm) && contain(related,elm)) {
  48.                         /* 如果,触发元素和相关元素都属于绑定元素(elm)。执行方法 */
  49.                         fn.call(obj,event);
  50.                         return;
  51.                     }
  52.                     while( related && !contain(related,elm)){ 
  53.                           related = related.parentNode;
  54.                     }
  55.                     /* 事件相关元素,不属于绑定元素(elm)的子级,执行方法  */
  56.                     !contain(related,elm) && (fn.call(obj,event));
  57.                 }else{
  58.                     fn.call(obj,event);
  59.                 }
  60.                 return;
  61.             }
  62.             parent = parent.parentNode;   
  63.         }
  64.     };
  65.     return func;
  66. };
  67.  
  68. events.addEvent = function( obj,type,fn ) {
  69.     if(obj.addEventListener)
  70.     {   
  71.         if(obj.onmouseenter !== undefined){
  72.             //for opera11,firefox10。他们也支持“onmouseenter”和“onmouseleave”,可以直接绑定
  73.             obj.addEventListener(type,fn,false)
  74.             return ;
  75.         }
  76.         if(type=="mouseenter" || type=="mouseleave" ){ 
  77.             var eType = (type=="mouseenter") ? "mouseover" : "mouseout";
  78.             var fnNew = events._mouseHandle(fn);
  79.             obj.addEventListener(eType,fnNew,false);
  80.              /* 将方法存入events._mouseFn,以便以后remove */
  81.             if(!events._mouseFn[obj]) events._mouseFn[obj] = {};
  82.             if(!events._mouseFn[obj][eType]) events._mouseFn[obj][eType] = {};
  83.                 events._mouseFn[obj][eType][fn] = fnNew;
  84.         }else{
  85.             obj.addEventListener(type,fn,false);
  86.         }
  87.     }else if(obj.attachEvent)
  88.     {
  89.         // for ie
  90.         obj.attachEvent("on" + type,fn);
  91.     }
  92. };
  93.  
  94. events.removeEvent = function(obj,type,fn ) {
  95.     if(obj.addEventListener)
  96.     {   
  97.         if(obj.onmouseenter !== undefined){
  98.             obj.removeEventListener(type,fn,false)
  99.             return ;
  100.         }
  101.         if(type=="mouseenter" || type=="mouseleave" ){ 
  102.             var eType = (type=="mouseenter") ? "mouseover" : "mouseout";
  103.             if(!events._mouseFn[obj][eType][fn]) return;
  104.             obj.removeEventListener(eType,events._mouseFn[obj][eType][fn],false);
  105.             events._mouseFn[obj][eType][fn]={};
  106.         }else{
  107.             obj.removeEventListener(type,fn,false);
  108.         }
  109.     }
  110.     else if(obj.attachEvent)
  111.     {
  112.         obj.detachEvent("on" + type,fn);
  113.     }
  114. };
  115.  
  116. events.delegate = function(obj,elm,type,fn){
  117.     var fnNew = events._delegateHandle(obj,elm,fn);
  118.     events.addEvent(obj,type,fnNew);
  119.     /* 将绑定的方法存入events._deleFn,以便之后解绑操作 */
  120.     if(!events._deleFn[elm]) events._deleFn[elm] = {};
  121.     if(!events._deleFn[elm][type]) events._deleFn[elm][type] = {};
  122.     events._deleFn[elm][type][fn] = fnNew;
  123. };
  124.  
  125. events.undelegate = function(obj,elm,type,fn){
  126.     var fnNew = events._deleFn[elm][type][fn];
  127.     if(!fnNew) return;
  128.     events.removeEvent(obj,type,fnNew);
  129.     events._deleFn[elm][type][fn] = null;
  130. };
   

  瀑布流布局及扩展——格子块的智能堆砌 作者:ONEBOYS    发表时间: 2011年10月12号,星期三     阅读:1,909 次  

图片分享网站Pinterest(beta),在不久前获得了2700$的投资,估值已超2亿元(据说现该公司团队有8人)。该网站的一大特色就是每一张分享的图片被拟作“Pin”被钉在页面上面,每一Pin依尺寸智能排列,同时滚动页面时异步加载新Pin,极具效果。这种创新模式被在国内也被广泛copy,其中最有前途的当属Mark之,以”Mark”代”Pin”,也算有些想法。

以下是利用豆瓣API数据做的效果:完整效果
部分代码:

这种布局中虽然每个Pin的高度不尽相同,但是他们的宽度都是一样的。
那么假如,很邪恶的提出一个要求,宽度也不尽相同,只是说宽高都按比例成倍增加,那还怎么排列呢?
呵呵,如下:

现在这种布局已经不能叫瀑布流了,我们称之为格子块,格子块通过算法智能堆砌。

到最后,说点下睛也好,说添下足也好,我们再加一个拖动交换格子的效果。

   

  Typing… 作者:ONEBOYS    发表时间: 2011年07月28号,星期四     阅读:1,162 次  

最近一个多月都比较忙,没什么时间精力更新blog,现在终于闲下来了。
之前有个朋友发给我一个打字机的效果,蛮有感觉的,不过那是用VBscript写的…
而下面的这个demo里除了打字的效果,还结合了以前这个:我是谁里的效果。
至于里面的心形图案,是我一个一个取出坐标得到的,如果你对心形图案还有兴趣,还可以看看这篇文章笛卡尔情书的秘密

   

  烟花易冷,青春难留 作者:ONEBOYS    发表时间: 2011年06月26号,星期天     阅读:1,865 次  

繁华声,遁入空门,折煞了世人
梦偏冷,辗转一生,情债又几本
如你默认,生死枯等
枯等一圈,又一圈的年轮
浮屠塔,断了几层,断了谁的魂
痛直奔,一盏残灯,倾塌的山门
容我再等,历史转身
等酒香醇,等你弹一曲古筝

用周杰伦的一首《烟花易冷》,纪念我即刻逝去的青春。