2013-04-10 12 views
11

Tôi đang cố gắng sử dụng lệnh Angular JS để căn giữa nội dung của div.Làm thế nào để gọi một hàm trong một chỉ thị Góc sau khi các nút con đã được xử lý?

Đây là phiên bản đơn giản của mẫu:

<div id="mosaic" class="span12 clearfix" s-center-content> 
    <div ng-repeat="item in hits" id="{{item._id}}" > 
    </div> 
</div> 

Đây là chỉ thị:

module.directive('sCenterContent', function() { 
    var refresh = function(element){ 
     var aWidth= element.innerWidth(); 
     var cWidth= element.children()[0].offsetWidth; 
     var cHeight= element.children()[0].offsetHeight; 
     var perRow= Math.floor(aWidth/cWidth); 
     var margin=(aWidth-perRow*cWidth)/2; 
     if(perRow==0){ 
      perRow=1; 
     } 
     var top=0; 
     element.children().each(function(index, child){ 
      $(child).css('margin-left','0px'); 
      if((index % perRow)==0){ 
       $(child).css('margin-left',margin+'px'); 
      } 
     }); 
    }; 
    return { 
     link : function(scope, element, attrs) { 
      $(window).resize(function(event){ 
       refresh(element); 
      }); 
     } 
    }; 
}); 

Về cơ bản nó nổi một số divs bên trong và bổ sung thêm một lề để div đầu tiên trong mỗi hàng, để nội dung được căn giữa.

Tính năng này hoạt động tốt khi trình duyệt được thay đổi kích thước. Sự cố xảy ra khi tôi cố gắng làm mới sau khi khởi chạy.

Tôi đã thử với chức năng liên kết bài đăng như được thấy trong this question. Các liên kết trước và các chức năng liên kết bài viết được gọi theo thứ tự mong đợi nhưng không phải sau khi trẻ em của elemenet với chỉ thị s-center-content được hiển thị. Cuộc gọi để làm mới không thành công vì không tìm thấy trẻ em nào.

Làm cách nào để thực hiện cuộc gọi để làm mới đảm bảo trẻ em đã được xử lý?

Trả lời

1

Cuối cùng đã làm được!

tôi đã sử dụng livequery plugin và thêm dòng sau vào cuối của phương pháp liên kết:

$('*[s-center-content] > *').livequery(function(event){ 
    refresh(element); 
}); 

tôi chọn bất kỳ đứa trẻ cấp độ đầu tiên (hiện tại và tương lai) của nguyên tố này với các chỉ thị s-center-content và đính kèm một handler được gọi khi các phần tử được thêm vào DOM.

EDIT

Một lưu ý cuối cùng. Bố cục nội dung của tôi phụ thuộc chủ yếu vào hình ảnh bên trong với các thuộc tính được đánh giá động src. Vì vậy, để làm cho nó hoạt động, tôi đã phải thay đổi mã này:

$('*[s-center-content] img').livequery(function(event){ 
    $(this).load(function(){ 
     refresh(element);      
    }); 
}); 

Mã đầy đủ của chỉ thị đặt các div thả nổi bên trái được căn giữa như sau. Lưu ý rằng nó dựa vào việc thêm một lề đã tính vào div đầu tiên trong hàng.

module.directive('sCenterContent', function() { 
    var refresh = function(element){ 
     var aWidth= element.innerWidth(); 
     var cWidth= element.children()[0].offsetWidth; 
     var cHeight= element.children()[0].offsetHeight; 
     var perRow= Math.floor(aWidth/cWidth); 
     var margin=(aWidth-perRow*cWidth)/2; 
     if(perRow==0){ 
      perRow=1; 
     } 
     var top=0; 
     element.children().each(function(index, child){ 
      $(child).css('margin-left','0px'); 
      if((index % perRow)==0){ 
       $(child).css('margin-left',margin+'px'); 
      } 
     }); 
    }; 
    return { 
     link : function(scope, element, attrs) { 
      $(window).resize(function(event){ 
       refresh(element); 
      }); 
      $('*[s-center-content] img').livequery(function(event){ 
       $(this).load(function(){ 
        refresh(element);     
       }); 
      }); 
     } 
    }; 
}); 
+1

Thực hiện tốt, điều này rất tiện dụng! Tôi sẽ cố gắng tìm các chủ đề nhóm google và các vấn đề trong góc mà nói về vấn đề này và tôi sẽ tham khảo câu trả lời của bạn. –

+0

Cảm ơn vì nỗ lực của Roy. –

+4

Nếu bạn nhìn vào các plugin [code] (https://github.com/brandonaaron/livequery/blob/master/jquery.livequery.js), bạn sẽ thấy rằng nó cũng sử dụng 'setTimeout (fn, 20)' để phù hợp với các yếu tố mới. Vì vậy, một giải pháp bẩn của nó trong 'gói' thân thiện. – FelikZ

5

Đây là một vấn đề lặp đi lặp lại (Một nơi nào đó có một vấn đề liên quan với điều này, cũng như một sợi trong các diễn đàn google ..)

góc không có cách nào để biết khi dom xong, nó chỉ có thể biết khi các hàm mà nó gọi trở lại (và bất kỳ lời hứa nào được giải quyết). Nếu những chức năng đó không đồng bộ và không có gọi lại hoặc lời hứa, sẽ không có cách nào để được thông báo.

Cách tôi đã nhìn thấy nó được thực hiện (và cách tôi đã thực hiện nó) là với một setInterval kiểm tra định kỳ DOM để xem nếu nó ở trạng thái hoàn thành. Tôi ghét giải pháp này và sẽ biết ơn vì một giải pháp thay thế, nhưng nó hoàn thành công việc.

+0

Điều gì về việc xem phần tử gốc? tôi có được thông báo về việc bổ sung trẻ em không? Nếu vậy, đó có thể là cách. Tôi sẽ kiểm tra! –

7

Tôi nghĩ rằng sử dụng góc của $watch là một tốt hơn, giải pháp thanh lịch hơn:

link : function(scope, element, attrs) { 
      $(window).resize(function(event){ 
       refresh(element); 
      }); 

      var watchCount = 0, 
      unWatcher = $watch(
       function() { 
        return $('*[s-center-content] img').length !== 0; 
       }, 
       function() { 
        // ensure refresh isn't called the first time (before the count of elements is > 0) 
        if (++watchCount === 1) { 
         return; 
        } 

        refresh(element);     

        // stop watching the element now that refresh has been called 
        unWatcher(); 
       }, true); 
     } 

Về Ngừng theo dõi: AngularJS : Clear $watch

+1

Điều này rất thông minh - có thể mô tả một chút về câu trả lời sẽ làm cho nó dễ nhìn hơn. –

+0

Điều này khá thú vị. Có thể muốn chỉ xem trên $ (selector) .length Mặc dù không hoàn toàn chắc chắn nếu điều đó luôn hoạt động. – David

0

Tôi tin rằng điều này có thể được thực hiện với css. Các yếu tố mục tiêu có tập trung không phân biệt số lượng như thế này?

[] [] [] [] [] 

    [] [] [] 

Nếu vậy, điều này chắc chắn là có thể với css và có thể đạt được với ít nhiều phức tạp. Dưới đây là ví dụ:

http://codepen.io/thetallweeks/pen/kvAJb

Các vấn đề liên quan