K_Reverter的网页开发记录

要么不做,要么就当作艺术品来做!

导航

Google Maps API 2.0解析(3-GEvent事件功能支持)

 
//以a为参数,运行b和c函数,如果a是一个html控件而且包含子控件,则以子控件为参数也运行该函数
  function RunFunction(a,b,c)
  {
   
if(b)
   {
    b.call(
null,a)
   }
   
for(var d=a.firstChild;d;d=d.nextSibling)
   {
    
if(d.nodeType==1)
    {
     arguments.callee.call(
this,d,b,c)
    }
   }
   
if(c)
   {
    c.call(
null,a)
   }
  }
  
//设置html控件的属性
  function setElementAttribute(a,b,c)
  {
   a.setAttribute(b,c)
  };
  
var GEvent_newcopyright="newcopyright";
  
var GEvent_click="click";
  
var GEvent_contextmenu="contextmenu";
  
var GEvent_dblclick="dblclick";
  
var GEvent_error="error";
  
var GEvent_load="load";
  
var GEvent_mousedown="mousedown";
  
var GEvent_mousemove="mousemove";
  
var GEvent_mouseout="mouseout";
  
var GEvent_mouseup="mouseup";
  
var GEvent_unload="unload";
  
var GEvent_remove="remove";
  
var GEvent_mouseover="mouseover";
  
var GEvent_closeclick="closeclick";
  
var GEvent_addmaptype="addmaptype";
  
var GEvent_addoverlay="addoverlay";
  
var GEvent_clearoverlays="clearoverlays";
  
var GEvent_infowindowclose="infowindowclose";
  
var GEvent_infowindowopen="infowindowopen";
  
var GEvent_maptypechanged="maptypechanged";
  
var GEvent_moveend="moveend";
  
var GEvent_movestart="movestart";
  
var GEvent_removemaptype="removemaptype";
  
var GEvent_removeoverlay="removeoverlay";
  
var GEvent_resize="resize";
  
var GEvent_zoom="zoom";
  
var GEvent_zoomend="zoomend";
  
var GEvent_dragstart="dragstart";
  
var GEvent_drag="drag";
  
var GEvent_dragend="dragend";
  
var GEvent_move="move";
  
var GEvent_clearlisteners="clearlisteners";
  
var AllEvents=[];
  
//添加一个事件,参数分别为:对象、事件名称、运行句柄
  function addListener(a,b,c)
  {
   
var d=new GEventListener(a,b,c,0);
   AllEvents.push(d);
   
return d
  }
  
//删除一个事件
  function removeListener(a)
  {
   a.remove();
   RemoveFromArray(AllEvents,a)
  }
  
//删除a对象的所有b事件
  function clearListeners(a,b)
  {
   trigger(a,GEvent_clearlisteners,b);
//先触发clearlisteners事件
   RunMethodForAll(CopyEventArray(a),function()
   {
    
if(this.isEvent(b))
    {
     
this.remove();
     RemoveFromArray(AllEvents,
this)
    }
   })
  }
  
//删除对象a的所有事件
  function clearInstanceListeners(a)
  {
   trigger(a,GEvent_clearlisteners);
   RunMethodForAll(CopyEventArray(a),
function()
   {
    
this.remove();
    RemoveFromArray(AllEvents,
this)
   })
  }
  
//删除系统之中的所有事件
  function RemoveAllEvents()
  {
   
var a=[];
   
var b="__tag__";
   
for(var c=0;c<AllEvents.length;++c)
   {
    
var d=AllEvents[c];
    
var e=d.getSrcObject();//获得事件源
    if(!e[b])
    {
     e[b]
=true;
     trigger(e,GEvent_clearlisteners);
//删除源上的所有事件
     a.push(e)
    }
    d.remove()
   }
   
for(var c=0;c<a.length;++c)//这一段代码比较古怪,不过我觉得很可能是为了防止对象循环引用造成内存不能释放的原因
   {
    
var e=a[c];
    
if(e[b])
    {
     
try
     {
      
delete e[b]
     }
     
catch(f)
     {
      e[b]
=false
     }
    }
   }
   AllEvents.length
=0
  }
  
//复制事件数组
  function CopyEventArray(a)
  {
   
var b=[];
   
if(a["__e_"])
   {
    CopyArray(b,a[
"__e_"])
   }
   
return b
  }
  
//返回a的事件监视器列表数组
  function getEventArray(a,b)
  {
   
var c=a["__e_"];
   
if(!c)
   {
    
if(b)
    {
     c
=(a["__e_"]=[])
    }
    
else
    {
     c
=[]
    }
   }
   
return c
  }
  
//触发对象a的b事件
  function trigger(a,b,c,d)
  {
   
var e=[];
   
//将arguments之后的参数作为运行参数
   CopyArray(e,arguments,2);
   RunMethodForAll(getEventArray(a),
function()
   {
    
if(this.isEvent(b))
    {
     
try
     {
      
this.apply(a,e)
     }
     
catch(f)
     {
     }
    }
   })
  }
  
//实际上这个就是以前的那个AddBuiltInListener
  function addDomListener(a,b,c)
  {
   
var d;
   
if(browser.type==2&&b==GEvent_dblclick)
   {
    a[
"on"+b]=c;
    d
=new GEventListener(a,b,c,3)
   }
   
else if(a.addEventListener)
   {
    a.addEventListener(b,c,
false);
    d
=new GEventListener(a,b,c,1)
   }
   
else if(a.attachEvent)
   {
    
var e=callback(a,c);
    a.attachEvent(
"on"+b,e);
    d
=new GEventListener(a,b,e,2)
   }
   
else
   {
    a[
"on"+b]=c;
    d
=new GEventListener(a,b,c,3)
   }
   
if(a!=window||b!=GEvent_unload)
   {
    AllEvents.push(d)
   }
   
return d
  }
  
//将c的d方法绑定到a(HTML控件)的b事件
  function bindDom(a,b,c,d)
  {
   
var e=.createAdapter(c,d);
   
return addDomListener(a,b,e)
  }
  
//针对点击,在IE之中特别处理
  function bindClick(a,b,c)
  {
   bindDom(a,GEvent_click,b,c);
   
if(browser.type==1)
   {
//在IE之中绑定点击的同时绑定双击
    bindDom(a,GEvent_dblclick,b,c)
   }
  }
  
//将c的d方法绑定到a(非HTML控件)的b事件
  function bind(a,b,c,d)
  {
   
return addListener(a,b,callback(c,d))
  }
  
//这个可能是要实现事件冒泡的功能,要知道,在Google原有的事件系统之中,只有浏览器集成的事件可以冒泡,而Google扩展的事件不支持的,
  //这个方法,将c对象的b事件绑定到a对象的b事件,这样就能实现当点击一个GMark的时候,地图也能捕获到点击事件的“冒泡”功能
  //这个方法的使用我还没有看,因此还不知道这个方法会实现哪些功能
  function bindEventToEvent(a,b,c)
  {
   
return addListener(a,b,function()
   {
    
var d=[c,b];
    CopyArray(d,arguments);
    trigger.apply(
this,d)
   })
  }
  
//返回一个事件适配器,因为IE之中事件发生时并不将Event对象作为参数传递,因此,必须用该适配器来读取window.event的值
  function .createAdapter(a,b)
  {
   
return function(c)
   {
    
if(!c)
    {
     c
=window.event
    }
    
if(c&&!c.target)
    {
     c.target
=c.srcElement
    }
    b.call(a,c,
this)
   }
  }
  
//取得对a的b方法的回调函数
  function callback(a,b)
  {
   
return function()
   {
    
return b.apply(a,arguments)
   }
  }
  
//取得对a的b方法的回调函数,并将第二个参数之后的参数作为调用参数
  function callbackArgs(a,b,c,d)
  {
   
var e=[];
   CopyArray(e,arguments,
2);
   
return function()
   {
    
return b.apply(a,e)
   }
  }
  
//这是一个listener的对象
  function GEventListener(a,b,c,d)
  {
   
var e=this;
   e.object
=a;
   e.event
=b;
   e.handle
=c;
   e.type
=d;//listener的类型
   getEventArray(a,true).push(e)
  }
  
//移除该listener
  GEventListener.prototype.remove=function()
  {
   
var a=this;
   
switch(a.type)
   {
    
case 1:
     a.object.removeEventListener(a.event,a.handle,
false);
     
break;
    
case 2:
     a.Z.detachEvent(
"on"+a.event,a.handle);
     
break;
    
case 3:
     a.object[
"on"+a.event]=null;
     
break;
   }
   RemoveFromArray(getEventArray(a.object),a)
  };
  
//判断是否a事件的绑定
  GEventListener.prototype.isEvent=function(a)
  {
   
return this.event==a
  };
  
//运行该listener的句柄
  GEventListener.prototype.apply=function(a,b)
  {
   
return this.handle.apply(a,b)
  };
  
//获得该listener的对象
  GEventListener.prototype.getSrcObject=function()
  {
   
return this.object
  };
  
//静态函数,事件发生时,获得该事件的对象,如果srcElement是文字,则为其父对象
  function GetEventElement(a)
  {
   
var b=a.srcElement||a.target;
   
if(b&&b.nodeType==3)
   {
    b
=b.parentNode
   }
   
return b
  }
  
//清除a和其包含的控件的所有事件
  function clearNode(a)
  {
   RunFunction(a,clearInstanceListeners)
  };

 事件处理函数大体上和以前差不多,主要是针对"closure"问题,产生的代码泄漏问题而进行了一些优化,并且将GEventListener分离了出来。

posted on 2006-05-08 20:40  K_Reverter  阅读(1781)  评论(7编辑  收藏  举报