2016-04-04 21 views
0

目標是當元素接近頁面頂部時,它將類應用於導航項目。AngularJS - 指令只針對衆多用途之一發射

模板

<ul class="nav"> 
    <li> 
    <a href="#someID">Some ID</a> 
    </li> 
</ul> 
... 

<div id="someId" hightlight-relevant-items></div> 

DIRECTIVE

'use strict'; 

angular.module("common.directives") 
    .directive('highlightRelevantItems', function() { 
     return function (scope, element, attrs) { 

      scope.detectPos = function() { 
       var distanceScrolled = $(window).scrollTop(); 

       var topOfElement = element.offset().top; 
       var height = element.height(); 
       var link = '[href="#' + element.attr('id') + '"]'; 
       var delta = topOfElement - distanceScrolled; 
       var offScreen = delta+height 

       if (delta < 0 && offScreen > 0) { 
        $(link).addClass('active'); 
       } else if (delta >= 0) { 
        $(link).removeClass('active'); 
       } else if (offScreen <= 0) { 
        $(link).removeClass('active'); 
       } 
       console.log(element.attr('id') + ' ' + topOfElement); 

      } 

      $(window).bind('scroll', function() { 

       scope.detectPos(); 
      }); 

     } 
    }); 

眼下,這個指令火的所有指令屬性的元素,但只註冊到最後互爲作用。因此,如果我有someID1someID2,someID3,它將觸發所有元素,但只有數據爲someID3

如何讓它適用於所有使用該指令的元素?

回答

1

您需要爲指令的每個實例的隔離範圍。就像這樣:

angular.module("common.directives") 
 
    .directive('highlightRelevantItems', function() { 
 

 
     return { 
 
      scope: { 
 
      detectPos: '&' 
 
      }, 
 
      link: function(scope, element, attrs) { 
 

 
      scope.detectPos = function() { 
 
       var distanceScrolled = $(window).scrollTop(); 
 

 
       var topOfElement = element.offset().top; 
 
       var height = element.height(); 
 
       var link = '[href="#' + element.attr('id') + '"]'; 
 
       var delta = topOfElement - distanceScrolled; 
 
       var offScreen = delta + height 
 

 
       if (delta < 0 && offScreen > 0) { 
 
        $(link).addClass('active'); 
 
       } else if (delta >= 0) { 
 
        $(link).removeClass('active'); 
 
       } else if (offScreen <= 0) { 
 
        $(link).removeClass('active'); 
 
       } 
 
       console.log(element.attr('id') + ' ' + topOfElement); 
 

 
      } 
 

 
      $(window).bind('scroll', function() { 
 

 
       scope.detectPos(); 
 
      }); 
 

 
      } 
 
     } 
 
    });

+0

我曾看過這種方法,但無法弄清楚我的窗口滾動綁定的位置。非常感謝。 – Plummer

+0

爲此創建一個單獨的指令,並使用body標籤或root div標籤中的指令,因爲它應該只觸發一次 – dannielum

1

您的指示使用其父母的範圍。這意味着每次指令被初始化時,你都會覆蓋scope.detectPos。這就是爲什麼它只被調用一次,最後一個元素someID3

速戰速決將不結合detectPos行動範圍和剛剛宣佈它作爲一個功能:

angular 
    .module('common.directives') 
    .directive('highlightRelevantItems', function() { 
    return function(scope, element, attrs) { 

     var detectPos = function() { 
     var distanceScrolled = $(window).scrollTop(); 

     var topOfElement = element.offset().top; 
     var height = element.height(); 
     var link = '[href="#' + element.attr('id') + '"]'; 
     var delta = topOfElement - distanceScrolled; 
     var offScreen = delta + height 

     if (delta < 0 && offScreen > 0) { 
      $(link).addClass('active'); 
     } else if (delta >= 0) { 
      $(link).removeClass('active'); 
     } else if (offScreen <= 0) { 
      $(link).removeClass('active'); 
     } 

     console.log(element.attr('id') + ' ' + topOfElement); 
     } 

     $(window).bind('scroll', function() { 
     detectPos(); 
     }); 
    } 
    }); 
+0

我試着做'DIR =這一點;'但它回來了'ctrl'是不確定的。我的語法錯了嗎? – Plummer

+0

我不明白你在說什麼......我還附上了一個代碼示例。 –