2016-04-04 28 views
0

目的は、要素がページの上部に近づくと、クラスをnavアイテムに適用することです。AngularJS - 多くの用途の1つでディレクティブのみを実行する

TEMPLATE

<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(); 
      }); 

     } 
    }); 

、ディレクティブ属性を持つすべての要素に対してこのディレクティブ火災が、唯一の最後のinterationに登録します。だから私がsomeID1someID2someID3を持っていたならば、それはすべての要素に対して、しかし、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タグまたはルートdivタグのディレクティブを使用してください – dannielum

1

あなたのディレクティブは親のスコープを使用します。つまり、は、ディレクティブが初期化されるたびにscope.detectPosに上書きされます。そのため、最後の要素の1回だけ呼び出されるのは、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

私はあなたが言っていることを強調していません...私はコード例も添付しました。 –