有才華的人,別忘記給滋潤你的那塊土壤施肥

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            28 隨筆 :: 5 文章 :: 147 評論 :: 0 Trackbacks

             事件(上)

          JavaScript事件列表
          事件 解說
          一般事件 onclick 鼠標(biāo)點(diǎn)擊時(shí)觸發(fā)此事件
          ondblclick 鼠標(biāo)雙擊時(shí)觸發(fā)此事件
          onmousedown 按下鼠標(biāo)時(shí)觸發(fā)此事件
          onmouseup 鼠標(biāo)按下后松開鼠標(biāo)時(shí)觸發(fā)此事件
          onmouseover 當(dāng)鼠標(biāo)移動(dòng)到某對象范圍的上方時(shí)觸發(fā)此事件
          onmousemove 鼠標(biāo)移動(dòng)時(shí)觸發(fā)此事件
          onmouseout 當(dāng)鼠標(biāo)離開某對象范圍時(shí)觸發(fā)此事件
          onkeypress 當(dāng)鍵盤上的某個(gè)鍵被按下并且釋放時(shí)觸發(fā)此事件.
          onkeydown 當(dāng)鍵盤上某個(gè)按鍵被按下時(shí)觸發(fā)此事件
          onkeyup 當(dāng)鍵盤上某個(gè)按鍵被按放開時(shí)觸發(fā)此事件
          頁面相關(guān)事件 onabort 圖片在下載時(shí)被用戶中斷
          onbeforeunload 當(dāng)前頁面的內(nèi)容將要被改變時(shí)觸發(fā)此事件
          onerror 出現(xiàn)錯(cuò)誤時(shí)觸發(fā)此事件
          onload 頁面內(nèi)容完成時(shí)觸發(fā)此事件
          onmove 瀏覽器的窗口被移動(dòng)時(shí)觸發(fā)此事件
          onresize 當(dāng)瀏覽器的窗口大小被改變時(shí)觸發(fā)此事件
          onscroll 瀏覽器的滾動(dòng)條位置發(fā)生變化時(shí)觸發(fā)此事件
          onstop 瀏覽器的停止按鈕被按下時(shí)觸發(fā)此事件或者正在下載的文件被中斷
          oncontextmenu 當(dāng)彈出右鍵上下文菜單時(shí)發(fā)生
          onunload 當(dāng)前頁面將被改變時(shí)觸發(fā)此事件
          表單相關(guān)事件 onblur 當(dāng)前元素失去焦點(diǎn)時(shí)觸發(fā)此事件
          onchange 當(dāng)前元素失去焦點(diǎn)并且元素的內(nèi)容發(fā)生改變而觸發(fā)此事件
          onfocus 當(dāng)某個(gè)元素獲得焦點(diǎn)時(shí)觸發(fā)此事件
          onreset 當(dāng)表單中RESET的屬性被激發(fā)時(shí)觸發(fā)此事件
          onsubmit 一個(gè)表單被遞交時(shí)觸發(fā)此事件

          了解上面的事件如此簡單,那么事件還有什么可講的呢?

          問題一:每個(gè)事件只能注冊一個(gè)函數(shù)

              var oDiv = document.getElementById("oDiv");
              oDiv.onclick 
          = fn1;
              oDiv.onclick 
          =fn2;
              
          function fn1() {alert("我被覆蓋了!")}
              
          function fn2() {alert("只有我被執(zhí)行到!")}

          解決方案一:
              obj.onclick = function () {
                  fn1();
                  fn2();
                  fn3();
              }
          ;

          缺陷一:需要將所有函數(shù)一次添加進(jìn)去,不能在運(yùn)行時(shí)添加

          缺陷二:在事件處理函數(shù)中this將指向window,而不是obj

          解決方案二:


              function addEvent(fn,evtype,obj) {
                  
          //obj是要添加事件的HTML元素對象
                  //evtype是事件名字,不包含on前綴,因?yàn)槊總€(gè)都有on,所以寫個(gè)on是多余的
                  //fn是事件處理函數(shù)
                  var oldFn;
                  
          if (obj["on"+evtype] instanceof Function) {
                      oldFn 
          = obj["on"+evtype];//當(dāng)添加函數(shù)時(shí),如果已注冊過了,則將其保存起來
                  }

                  obj[
          "on"+evtype]=function () {
                          
          if (oldFn) {
                              oldFn.call(
          this);
                          }

                          fn.call(
          this);//使用call方法,使事件處理函數(shù)中的this仍指向obj
                  }
          ;
              }

          這樣已經(jīng)解決了問題,但如何刪除事件呢?如果直接將對象的onevtype這類的屬性賦值為null將會刪除所有的事件處理函數(shù)!

          解決方案二的修改版:先將事件存儲起來,存儲在對象的__EventHandles屬性里面

              eventHandlesCounter=1;//計(jì)數(shù)器,將統(tǒng)計(jì)所有添加進(jìn)去的函數(shù)的個(gè)數(shù),0位預(yù)留作其它用
              function addEvent(fn,evtype,obj) {
                  
          if (!fn.__EventID) {//__EventID是給函數(shù)加的一個(gè)標(biāo)識,見下面給函數(shù)添加標(biāo)識的部分
                      fn.__EventID=eventHandlesCounter++;
                      
          //使用一個(gè)自動(dòng)增長的計(jì)數(shù)器作為函數(shù)的標(biāo)識以保證不會重復(fù)
                  }

                  
          if (!obj.__EventHandles) {
                      obj.__EventHandles
          =[];//當(dāng)不存在,也就是第一次執(zhí)行時(shí),創(chuàng)建一個(gè),并且是數(shù)組
                  }

                  
          if (!obj.__EventHandles[evtype]) {//將所有事件處理函數(shù)按事件類型分類存放
                      obj.__EventHandles[evtype]={};//當(dāng)不存在時(shí)也創(chuàng)建一個(gè)散列表<BR>                      &nbsp;if (obj["on"+evtype] instanceof Function) {
                          //查看是否已經(jīng)注冊過其它函數(shù)
                          //如果已經(jīng)注冊過,則將以前的事件處理函數(shù)添加到下標(biāo)為0的預(yù)留的位置
                          obj.__EventHandles[evtype][0]=obj["on"+evtype];
                          obj[
          "on"+evtype]=handleEvents;//使用handleEvents集中處理所有的函數(shù)
                      }

                  }

                  obj.__EventHandles[evtype][fn.__EventID]
          =fn;
                  
          //如果函數(shù)是第一次注冊為事件處理函數(shù),那么它將被添加到表中,函數(shù)的標(biāo)識作為下標(biāo)
                  //如果函數(shù)已經(jīng)注冊過相同對象的相同事件了,那么將覆蓋原來的而不會被添加兩次
                  function handleEvents() {
                      
          var fns = obj.__EventHandles[evtype];
                      
          for (var i in fns) {
                          fns[i].call(
          this);
                      }

                  }

              }

          使用上面的函數(shù)已經(jīng)可以在一個(gè)對象添加多個(gè)事件處理函數(shù),在函數(shù)內(nèi)部this關(guān)鍵字也指向了相應(yīng)的對象,并且這些函數(shù)都被作了標(biāo)識,那么移除某個(gè)事件處理函數(shù)就是輕而易舉的了!
          //使用傳統(tǒng)方法:obj.onevtype = null;但這樣會移除所有的事件處理函數(shù)
              function delEvent(fn,evtype,obj) {
                  
          if (!obj.__EventHandles || !obj.__EventHandles[evtype] || !fn.__EventID) {
                      
          return false;
                  }

                  
          if (obj.__EventHandles[evtype][fn.__EventID] == fn) {
                      
          delete obj.__EventHandles[evtype][fn.__EventID];
                  }

              }

          事件(下)

          事件對象——Event

          事件對象是用來記錄一些事件發(fā)生時(shí)的相關(guān)信息的對象。事件對象只有事件發(fā)生時(shí)才會產(chǎn)生,并且只能是事件處理函數(shù)內(nèi)部訪問,在所有事件處理函數(shù)運(yùn)行結(jié)束后,事件對象就被銷毀!

          訪問事件對象:W3C DOM方法與IE專用方法

          //W3C DOM把事件對象作為事件處理函數(shù)的第一個(gè)參數(shù)傳入進(jìn)去
              document.onclick = function (evt) {//這樣,事件對象只能在對應(yīng)的事件處理函數(shù)內(nèi)部可以訪問到
                  alert(evt);
              }
          ;
              
          //IE將事件對象作為window對象的一個(gè)屬性(相當(dāng)于全局變量)
              //貌似全局對象,但是只有是事件發(fā)生時(shí)才能夠訪問
              alert(window.event);//null
              window.onload = function () {
                  alert(window.event);
              }
          ;

          事件對象的屬性及方法

          鼠標(biāo)相關(guān)
          屬性名 值類型 讀/寫 描述
          button Integer R

          對于特定的鼠標(biāo)事件,表示按下的鼠標(biāo)按鈕,該屬性僅可以在mouseup與mousedown事件中訪問。W3C 規(guī)定:0表示按下了左鍵,1表示按下了中鍵,2表示按下了右鍵,相當(dāng)于對于鼠標(biāo)鍵從左到右進(jìn)行的編號,而編號從0開始; 而IE有另外一套規(guī)定:0表示沒有任何鍵按下,1表示左鍵,2表示右鍵,4表示中鍵,而其它按鍵的組合則只要將鍵碼相加即可,如:同時(shí)按下左右鍵時(shí)button值為3

          clientX Integer R 事件發(fā)生時(shí),鼠標(biāo)在客戶端區(qū)域的X坐標(biāo),客戶端區(qū)域是指頁面可視區(qū)域
          clientY Integer R 事件發(fā)生時(shí),鼠標(biāo)在客戶端區(qū)域的Y坐標(biāo)
          screenX Integer R(IE) R/W(W3C) 相對于屏幕的鼠標(biāo)X坐標(biāo)
          screenY Integer R(IE) R/W(W3C) 相對于屏幕的鼠標(biāo)Y坐標(biāo)
          x(僅IE) Integer R 鼠標(biāo)相對于引起事件的元素的父元素的X坐標(biāo)
          y(僅IE) Integer R 鼠標(biāo)相對于引起事件的元素的父元素的Y坐標(biāo)
          offsetX(僅IE) layerX(僅W3C) Integer R 鼠標(biāo)相對于引起事件的對象的X坐標(biāo)
          offsetY(僅IE) layerY(僅W3C) Integer R 鼠標(biāo)相對于引起事件的對象的Y坐標(biāo)
          pageX(僅W3C) Integer R 鼠標(biāo)相對于頁面的X坐標(biāo)
          pageY(僅W3C) Integer R 鼠標(biāo)相對于頁面的Y坐標(biāo)
          鍵盤相關(guān)
          屬性名 值類型 讀/寫 描述
          altKey Boolean R true表示按下了ALT鍵;false表示沒有按下
          ctrlKey Boolean R true表示按下了CTROL,false表示沒有
          shiftKey Boolean R true表示按下了shift,false表示沒有
          keyCode Integer R/W(IE) R(W3C) 對于keypress事件,表示按下按鈕的Unicode字符;對于keydown/keyup事件 ,表示按下按鈕的數(shù)字代號
          charCode(僅W3C) Integer R 在keypress事件中所按鍵的字符Unicode編碼,如果不是字符鍵,則該屬性為0,并且,當(dāng)CapsLock打開與關(guān)閉時(shí)charCode的值也對應(yīng)著大小寫字母
          其它
          屬性名 值類型 讀/寫 描述
          srcElement(IE) target(W3C) Element R 引起事件的元素
          fromElement(僅IE) Element R 某些鼠標(biāo)事件中(mouseover與mouseout),鼠標(biāo)所離開的元素
          toElement(僅IE) Element R 某些鼠標(biāo)事件中(mouseover與mouseout),鼠標(biāo)所進(jìn)入的元素
          relatedTarget(僅W3C) Element R 某些鼠標(biāo)事件中(mouseover與mouseout),返回與事件的目標(biāo)節(jié)點(diǎn)相關(guān)的節(jié)點(diǎn)。
          repeat(僅IE) Boolean R 如果不斷觸發(fā)keydown事件,則為true,否則為false
          returnValue(僅IE) Boolean R/W 將其設(shè)為false表示以取消事件的默認(rèn)動(dòng)作
          preventDefault(僅W3C) Function R 執(zhí)行方法以取消事件的默認(rèn)動(dòng)作
          type String R 事件的名稱,不帶on前綴
          cancelable(僅W3C ) Boolean R 當(dāng)為true表示事件的默認(rèn)動(dòng)作可以被取消(用preventDefault方法取消)
          cancelBubble(僅IE) Boolean R/W 將其設(shè)置為true將取消事件冒泡
          stopPropagation(僅W3C) Function R 執(zhí)行方法取消事件冒泡
          bubbles(僅W3C) Boolean R 返回true表示事件是冒泡類型
          eventPhase(僅W3C) Integer R 返回事件傳播的當(dāng)前階段。它的值是下面的三個(gè)常量之一,它們分別表示捕獲階段、在目標(biāo)對象上時(shí)和起泡階段:
          常量
          Event.CAPTURING_PHASE(捕獲階段) 1
          Event.AT_TARGET(在目標(biāo)對象上) 2
          Event.BUBBLING_PHASE(冒泡階段) 3
          timeStamp (僅W3C) Long R 返回一個(gè)時(shí)間戳。指示發(fā)生事件的日期和時(shí)間(從 epoch 開始的毫秒數(shù))。epoch 是一個(gè)事件參考點(diǎn)。在這里,它是客戶機(jī)啟動(dòng)的時(shí)間。并非所有系統(tǒng)都提供該信息,因此,timeStamp 屬性并非對所有系統(tǒng)/事件都是可用的。


          取得事件對象及取得事件目標(biāo)對象

          document.onclick =function (evt) {
                  evt 
          = evt || window.event;//在IE中evt會是undefined
                  //而支持W3C DOM事件的瀏覽器中事件對象將會作為事件處理函數(shù)的第一個(gè)參數(shù)
                  var targetElement = evt.target || evt.srcElement;
                  
          //IE中事件對象沒有target屬性
              }
          ;

          阻止事件發(fā)生時(shí)瀏覽器的默認(rèn)行為

              document.onclick = function (evt) {
                  evt 
          = evt || window.event;
                  
          var target = evt.target || evt.srcElement;
                  
          if (!target) {
                      
          return;
                  }

                  
          if (target.tagName=="A" && target.href) {
                      
          //使用傳統(tǒng)的方法取消事件默認(rèn)行為必須使用return false
                      //但使用了return ,函數(shù)便終止了運(yùn)行,可以使用事件對象來取消
                      if (window.event) {//IE
                          window.event.returnValue = false;
                      }
           else {
                          evt.preventDefault();
                      }

                      window.open(target.href,
          "newWindow");
                      
          //這樣讓所有的鏈接在新窗口打開
                  }

              }
          ;
              

          事件傳播——冒泡與捕獲

          DOM事件標(biāo)準(zhǔn)定義了兩種事件流,這兩種事件流有著顯著的不同并且可能對你的應(yīng)用有著相當(dāng)大的影響。這兩種事件流分別是捕獲和冒泡。和許多Web技術(shù)一樣,在它們成為標(biāo)準(zhǔn)之前,Netscape和微軟各自不同地實(shí)現(xiàn)了它們。Netscape選擇實(shí)現(xiàn)了捕獲事件流,微軟則實(shí)現(xiàn)了冒泡事件流。幸運(yùn)的是,W3C決定組合使用這兩種方法,并且大多數(shù)新瀏覽器都遵循這兩種事件流方式。

          默認(rèn)情況下,事件使用冒泡事件流,不使用捕獲事件流。然而,在Firefox和Safari里,你可以顯式的指定使用捕獲事件流,方法是在注冊事件時(shí)傳入useCapture參數(shù),將這個(gè)參數(shù)設(shè)為true。

          冒泡事件流

          當(dāng)事件在某一DOM元素被觸發(fā)時(shí),例如用戶在客戶名字節(jié)點(diǎn)上點(diǎn)擊鼠標(biāo),事件將跟隨著該節(jié)點(diǎn)繼承自的各個(gè)父節(jié)點(diǎn)冒泡穿過整個(gè)的DOM節(jié)點(diǎn)層次,直到它遇到依附有該事件類型處理器的節(jié)點(diǎn),此時(shí),該事件是onclick事件。在冒泡過程中的任何時(shí)候都可以終止事件的冒泡,在遵從W3C標(biāo)準(zhǔn)的瀏覽器里可以通過調(diào)用事件對象上的stopPropagation()方法,在Internet Explorer里可以通過設(shè)置事件對象的cancelBubble屬性為true。如果不停止事件的傳播,事件將一直通過DOM冒泡直至到達(dá)文檔根。

          捕獲事件流

          事件的處理將從DOM層次的根開始,而不是從觸發(fā)事件的目標(biāo)元素開始,事件被從目標(biāo)元素的所有祖先元素依次往下傳遞。在這個(gè)過程中,事件會被從文檔根到事件目標(biāo)元素之間各個(gè)繼承派生的元素所捕獲,如果事件監(jiān)聽器在被注冊時(shí)設(shè)置了useCapture屬性為true,那么它們可以被分派給這期間的任何元素以對事件做出處理;否則,事件會被接著傳遞給派生元素路徑上的下一元素,直至目標(biāo)元素。事件到達(dá)目標(biāo)元素后,它會接著通過DOM節(jié)點(diǎn)再進(jìn)行冒泡。

          現(xiàn)代事件綁定方法

          針對如上節(jié)課所討論的,使用傳統(tǒng)事件綁定有許多缺陷,比如不能在一個(gè)對象的相同事件上注冊多個(gè)事件處理函數(shù)。而瀏覽器和W3C也并非沒有考慮到這一點(diǎn),因此在現(xiàn)代瀏覽器中,它們有自己的方法綁定事件。

          W3C DOM

          • obj.addEventListener(evtype,fn,useCapture)——W3C提供的添加事件處理函數(shù)的方法。obj是要添加事件的對象,evtype是事件類型,不帶on前綴,fn是事件處理函數(shù),如果useCapture是true,則事件處理函數(shù)在捕獲階段被執(zhí)行,否則在冒泡階段執(zhí)行
          • obj.removeEventListener(evtype,fn,useCapture)——W3C提供的刪除事件處理函數(shù)的方法

          微軟IE方法

          • obj.attachEvent(evtype,fn)——IE提供的添加事件處理函數(shù)的方法。obj是要添加事件的對象,evtype是事件類型,帶on前綴,fn是事件處理函數(shù),IE不支持事件捕獲
          • obj.detachEvent(evtype,fn,)——IE提供的刪除事件處理函數(shù)的方法,evtype包含on前綴

          整合兩者的方法


              function addEvent(obj,evtype,fn,useCapture) {
                  
          if (obj.addEventListener) {
                      obj.addEventListener(evtype,fn,useCapture);
                  }
           else {
                      obj.attachEvent(
          "on"+evtype,fn);//IE不支持事件捕獲
                  }
           else {
                      obj[
          "on"+evtype]=fn;//事實(shí)上這種情況不會存在
                  }

              }

              
          function delEvent(obj,evtype,fn,useCapture) {
                  
          if (obj.removeEventListener) {
                      obj.removeEventListener(evtype,fn,useCapture);
                  }
           else {
                      obj.detachEvent(
          "on"+evtype,fn);
                  }
           else {
                      obj[
          "on"+evtype]=null;
                  }

              }

          其它兼容性問題:IE不支持事件捕獲?很抱歉,這個(gè)沒有辦法解決!但I(xiàn)E的attach方法有個(gè)問題,就是使用attachEvent時(shí)在事件處理函數(shù)內(nèi)部,this指向了window,而不是obj!當(dāng)然,這個(gè)是有解決方案的!
          function addEvent(obj,evtype,fn,useCapture) {
                  
          if (obj.addEventListener) {
                      obj.addEventListener(evtype,fn,useCapture);
                  }
           else {
                      obj.attachEvent(
          "on"+evtype,function () {
                          fn.call(obj);
                      }
          );
                  }
           else {
                      obj[
          "on"+evtype]=fn;//事實(shí)上這種情況不會存在
                  }

              }

          但I(xiàn)E的attachEvent方法有另外一個(gè)問題,同一個(gè)函數(shù)可以被注冊到同一個(gè)對象同一個(gè)事件上多次,解決方法:拋棄IE的 attachEvent方法吧!IE下的attachEvent方法不支持捕獲,和傳統(tǒng)事件注冊沒多大區(qū)別(除了能綁定多個(gè)事件處理函數(shù)),并且IE的 attachEvent方法存在內(nèi)存泄漏問題!

          addEvent,delEvent現(xiàn)代版

              function addEvent(obj,evtype,fn,useCapture) {
                  
          if (obj.addEventListener) {//優(yōu)先考慮W3C事件注冊方案
                      obj.addEventListener(evtype,fn,!!useCapture);
                  }
           else {//當(dāng)不支持addEventListener時(shí)(IE),由于IE同時(shí)也不支持捕獲,所以不如使用傳統(tǒng)事件綁定
                      if (!fn.__EventID) {fn.__EventID = addEvent.__EventHandlesCounter++;}
                      
          //為每個(gè)事件處理函數(shù)分配一個(gè)唯一的ID
                      
                      
          if (!obj.__EventHandles) {obj.__EventHandles={};}
                      
          //__EventHandles屬性用來保存所有事件處理函數(shù)的引用
                      
                      
          //按事件類型分類
                      if (!obj.__EventHandles[evtype]) {//第一次注冊某事件時(shí)
                          obj.__EventHandles[evtype]={};
                          
          if (obj["on"+evtype]) {//以前曾用傳統(tǒng)方式注冊過事件處理函數(shù)
                              (obj.__EventHandles[evtype][0]=obj["on"+evtype]).__EventID=0;//添加到預(yù)留的0位
                              //并且給原來的事件處理函數(shù)增加一個(gè)ID
                          }

                          obj[
          "on"+evtype]=addEvent.execEventHandles;
                          
          //當(dāng)事件發(fā)生時(shí),execEventHandles遍歷表obj.__EventHandles[evtype]并執(zhí)行其中的函數(shù)
                      }

                  }

              }

              addEvent.__EventHandlesCounter
          =1;//計(jì)數(shù)器,0位預(yù)留它用
              addEvent.execEventHandles = function (evt) {//遍歷所有的事件處理函數(shù)并執(zhí)行
                  if (!this.__EventHandles) {return true;}
                  evt 
          = evt || window.event;
                  
          var fns = this.__EventHandles[evt.type];
                  
          for (var i in fns) {
                          fns[i].call(
          this);
                  }

              }
          ;
              
          function delEvent(obj,evtype,fn,useCapture) {
                  
          if (obj.removeEventListener) {//先使用W3C的方法移除事件處理函數(shù)
                      obj.removeEventListener(evtype,fn,!!useCapture);
                  }
           else {
                      
          if (obj.__EventHandles) {
                          
          var fns = obj.__EventHandles[evtype];
                          
          if (fns) {delete fns[fn.__EventID];}
                      }

                  }

              }

              

          標(biāo)準(zhǔn)化事件對象

          IE的事件對象與W3C DOM的事件對象有許多不一樣的地方,解決的最好的方法就是調(diào)整IE的事件對象,以使它盡可能的與標(biāo)準(zhǔn)相似!下表列出了IE事件對象中一些和W3C DOM名稱或值不一樣但含義相同的屬性

          IE與W3C DOM事件對象的不同
          W3C DOM IE
          button——按鍵編碼為:0-左鍵,1-中鍵,2-右鍵 button——按鍵編碼為:1-左鍵,2-右鍵,4-中鍵
          charCode 沒有對應(yīng)屬性,但可以用keyCode來代替
          preventDefault 沒有對應(yīng)方法,但可以將event對象的returnValue設(shè)為false來模擬
          target srcElement
          relatedTarget fromElement與toElement
          stopPropagation 沒有對應(yīng)方法,但可以通過將event對象的cancelBubble屬性設(shè)為true來模擬

           

          總結(jié)出fixEvent函數(shù)

              function fixEvent(evt) {
                  
          if (!evt.target) {
                      evt.target 
          = evt.srcElement;
                      evt.preventDefault 
          = fixEvent.preventDefault;
                      evt.stopPropagation 
          = fixEvent.stopPropagation;
                      
          if (evt.type == "mouseover"{
                          evt.relatedTarget 
          = evt.fromElement;
                      }
           else if (evt.type =="mouseout"{
                          evt.relatedTarget 
          = evt.toElement;
                      }

                      evt.charCode 
          =  (evt.type=="keypress")?evt.keyCode:0;
                      evt.eventPhase 
          = 2;//IE僅工作在冒泡階段
                      evt.timeStamp = (new Date()).getTime();//僅將其設(shè)為當(dāng)前時(shí)間
                  }

                  
          return evt;
              }

              fixEvent.preventDefault 
          =function () {
                  
          this.returnValue = false;//這里的this指向了某個(gè)事件對象,而不是fixEvent
              }
          ;
              fixEvent.stopPropagation 
          =function () {
                  
          this.cancelBubble = true;
              }
          ;

          fixEvent函數(shù)不是單獨(dú)執(zhí)行的,它必須有一個(gè)事件對象參數(shù),而且只有事件發(fā)生時(shí)它才被執(zhí)行!最好的方法是把它整合到addEvent函數(shù)的execEventHandles里面
              addEvent.execEventHandles = function (evt) {//遍歷所有的事件處理函數(shù)并執(zhí)行
                  if (!this.__EventHandles) {return true;}
                  evt 
          = fixEvent(evt || window.event);//在這里對其進(jìn)行標(biāo)準(zhǔn)化操作
                  var fns = this.__EventHandles[evt.type];
                  
          for (var i in fns) {
                          fns[i].call(
          this,evt);//并且將其作為事件處理函數(shù)的第一個(gè)參數(shù)
                          //這樣在事件處理函數(shù)內(nèi)部就可以使用統(tǒng)一的方法訪問事件對象了
                  }

              }
          ;

          Load事件

          使用JavaScript操縱DOM,必須等待DOM加載完畢才可以執(zhí)行代碼,但window.onload有個(gè)壞處,它非要等到頁面中的所有圖片及視頻加載完畢才會觸發(fā)load事件。結(jié)果就是一些本來應(yīng)該在打開時(shí)隱藏起來的元素,由于網(wǎng)絡(luò)延遲,在頁面打開時(shí)仍然會出現(xiàn),然后又會突然消失,讓用戶覺得莫名其妙。

           

          大師們想出來的方法:

              function addLoadEvent(fn) {
                  
          var init = function() {
                      
          if (arguments.callee.done) return;
                      arguments.callee.done 
          = true;
                      fn.apply(document,arguments);
                  }
          ;
                  
          //注冊DOMContentLoaded事件,如果支持的話
                  if (document.addEventListener) {
                      document.addEventListener(
          "DOMContentLoaded", init, false);
                  }

                  
          //但對于Safari,我們需要使用setInterval方法不斷檢測document.readyState
                  //當(dāng)為loaded或complete的時(shí)候表明DOM已經(jīng)加載完畢
                  if (/WebKit/i.test(navigator.userAgent)) {
                      
          var _timer = setInterval(function() {
                          
          if (/loaded|complete/.test(document.readyState)) {
                              clearInterval(_timer);
                              init();
                          }

                      }
          ,10);
                  }

                  
          //對于IE則使用條件注釋,并使用script標(biāo)簽的defer屬性
                   //IE中可以給script標(biāo)簽添加一個(gè)defer(延遲)屬性,這樣,標(biāo)簽中的腳本只有當(dāng)DOM加載完畢后才執(zhí)行
                   /*@cc_on @*/
                   
          /*@if (@_win32)
                   document.write("<script id=\"__ie_onload\" defer=\"defer\" src=\"javascript:void(0)\"><\/script>");
                   var script = document.getElementById("__ie_onload");
                   script.onreadystatechange = function() {
                       if (this.readyState == "complete") {
                           init();
                       }
                   };
                   /*@end @
          */

                   
          return true;
               }

          from :http://www.javaeye.com/topic/517899
          posted on 2009-11-20 10:23 kissjava 閱讀(1341) 評論(0)  編輯  收藏 所屬分類: js&css

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 延边| 武邑县| 和林格尔县| 宾阳县| 漯河市| 来宾市| 崇阳县| 青冈县| 昌邑市| 临猗县| 兴和县| 红原县| 高平市| 宜川县| 河池市| 吴桥县| 叙永县| 北票市| 安岳县| 固安县| 义马市| 黑水县| 永年县| 漳平市| 赫章县| 石嘴山市| 九江市| 上林县| 吐鲁番市| 威宁| 旅游| 隆林| 皮山县| 日土县| 个旧市| 新蔡县| 本溪市| 仲巴县| 龙游县| 抚松县| 西昌市|