2014-01-28 11 views
0

我們有一個指令,顯示一個彈出, 在模板被加載彈出,與捕獲所有點擊文檔中的指令。角:事件取消綁定在指令並不會自動解除綁定完全

這種情況發生時它廣播一個事件來關閉彈出窗口,並解除綁定事件的$document

這是捕獲文件的指令點擊。

aOS.directive('catchOutsideClick', 
    [ 
     '$document', 
     'eventsService', 
     function CatchOutsideClickDirective($document, eventsService) { 

      var CatchClick = function CatchClick(scope, element, attrs) { 

       // Check if there was clicked on parent or one of its children 
       function isDescendant(parent, child) { 
        var node = child.parentNode; 
        while (node !== null) { 
         if (node === parent) { 
          return true; 
         } 
         node = node.parentNode; 
        } 
        return false; 
       } 

       // Done clicking 
       var onOutsideClick = function onOutsideClick(event) { 
        var clickedItem = event.target; 
        if (!isDescendant(element[0], clickedItem) && element[0] !== clickedItem) { 
         eventsService.publish('clicked-outside-popup', element[0]); 
         $document.unbind('click', onOutsideClick); 
        } 
       }; 

       // Catch clicks! 
       $document.bind('click', onOutsideClick); 
      }; 

      return { 
       restrict: 'A', 
       scope: false, 
       link: CatchClick 
      }; 
     } 
    ] 
); 

這是加載彈出的HTML:

<div id="header" ng-controller="framework.header"> 
    <div data-ng-include="popupTemplate"></div> 
</div> 

爲簡單起見,讓狀態控制器framework.header 將切換$scope.popupTemplate對下面將呈現的HTML的路徑:

<div ng-controller="user.profle" catch-outside-click> 
    <!-- loads of content --> 
</div> 

的包括模板似乎完美地工作,但是這是我們現在看到的行爲:

  1. 您點擊按鈕來切換popupTemplate並將其加載到彈出的div中。
  2. 是很好的激發趕超外點擊指令,並綁定一個clickHandler事件對文檔
  3. 彈出裏面點擊什麼也不做(因爲這是在指令測試),但彈出外點擊很好地關閉因爲它廣播了在頭控制器中捕獲的事件。
  4. 單擊頁面中的任意位置不會再次觸發該指令,因此我們認爲它是正確解綁的。
  5. 除了點擊按鈕時再次打開彈出窗口。這似乎同時綁定了一個新的文檔點擊事件,但也立即觸發了clickhandler(這讓我覺得它觸發了第一個點擊處理程序)。

我不知道在這一刻如何測試是否觸發第一個或第二個點擊處理程序。

人有一個想法,我怎麼可以縮小下來,無論是我做的東西完全錯誤的,或者只是點我怎麼調試這個問題,看看哪些事件處理程序被觸發。

回答

0

我們能夠解決這個問題,現在做這個:

aOS.directive('catchOutsideClick', 
[ 
    '$document', 
    'eventsService', 
    function CatchOutsideClickDirective($document, eventsService) { 

     ... 

     setTimeout(function() { 
      $document.bind('click', onOutsideClick); 
     }, 0); 

     ... 

    } 
]); 

它看起來好像setTimeout的內部代碼(綁定到點擊)獲取下一個「週期」執行(雖然超時設置爲0),其中包含模板的點擊在catch-click指令初始化的相同(前一個)循環中處理。至少這是我在調查這個問題時得到的感覺。

如果任何人都可以證實這一點或有一個更合理的解釋(也許更符合邏輯的解決方案),我們仍然渴望學習:-)

+0

我覺得你不考慮事件冒泡考慮在內,如你綁定到點擊文檔INSIDE點擊處理器的後代元素?你只需要在按鈕點擊處理程序中調用event.stopPropagation() – schellmax