2014-05-14 20 views
5

Tôi có các div mở rộng và hợp đồng khi được nhấp vào. Thư viện Masonry đã làm việc rất tốt để khởi tạo trang. Vấn đề tôi đang gặp phải là với việc định vị tuyệt đối tại chỗ từ Masonry và chỉ thị bên dưới, khi các div mở rộng chúng chồng lên nhau với các div bên dưới. Tôi cần phải có các div dưới div mở rộng di chuyển xuống để đối phó với việc mở rộng.AngularJS Masonry cho chiều cao thay đổi động

nguồn của tôi là: http://masonry.desandro.com/

https://github.com/passy/angular-masonry/blob/master/src/angular-masonry.js

/*! 
* angular-masonry <%= pkg.version %> 
* Pascal Hartig, weluse GmbH, http://weluse.de/ 
* License: MIT 
*/ 
(function() { 
    'use strict'; 

angular.module('wu.masonry', []) 
.controller('MasonryCtrl', function controller($scope, $element, $timeout) { 
    var bricks = {}; 
    var schedule = []; 
    var destroyed = false; 
    var self = this; 
    var timeout = null; 

    this.preserveOrder = false; 
    this.loadImages = true; 

    this.scheduleMasonryOnce = function scheduleMasonryOnce() { 
    var args = arguments; 
    var found = schedule.filter(function filterFn(item) { 
     return item[0] === args[0]; 
    }).length > 0; 

    if (!found) { 
     this.scheduleMasonry.apply(null, arguments); 
    } 
    }; 

    // Make sure it's only executed once within a reasonable time-frame in 
    // case multiple elements are removed or added at once. 
    this.scheduleMasonry = function scheduleMasonry() { 
    if (timeout) { 
     $timeout.cancel(timeout); 
    } 

    schedule.push([].slice.call(arguments)); 

    timeout = $timeout(function runMasonry() { 
     if (destroyed) { 
     return; 
     } 
     schedule.forEach(function scheduleForEach(args) { 
     $element.masonry.apply($element, args); 
     }); 
     schedule = []; 
    }, 30); 
    }; 

    function defaultLoaded($element) { 
    $element.addClass('loaded'); 
    } 

    this.appendBrick = function appendBrick(element, id) { 
    if (destroyed) { 
     return; 
    } 

    function _append() { 
     if (Object.keys(bricks).length === 0) { 
     $element.masonry('resize'); 
     } 
     if (bricks[id] === undefined) { 
     // Keep track of added elements. 
     bricks[id] = true; 
     defaultLoaded(element); 
     $element.masonry('appended', element, true); 
     } 
    } 

    function _layout() { 
     // I wanted to make this dynamic but ran into huuuge memory leaks 
     // that I couldn't fix. If you know how to dynamically add a 
     // callback so one could say <masonry loaded="callback($element)"> 
     // please submit a pull request! 
     self.scheduleMasonryOnce('layout'); 
    } 

    if (!self.loadImages){ 
     _append(); 
     _layout(); 
    } else if (self.preserveOrder) { 
     _append(); 
     element.imagesLoaded(_layout); 
    } else { 
     element.imagesLoaded(function imagesLoaded() { 
     _append(); 
     _layout(); 
     }); 
    } 
    }; 

    this.removeBrick = function removeBrick(id, element) { 
    if (destroyed) { 
     return; 
    } 

    delete bricks[id]; 
    $element.masonry('remove', element); 
    this.scheduleMasonryOnce('layout'); 
    }; 

    this.destroy = function destroy() { 
    destroyed = true; 

    if ($element.data('masonry')) { 
     // Gently uninitialize if still present 
     $element.masonry('destroy'); 
    } 
    $scope.$emit('masonry.destroyed'); 

    bricks = []; 
    }; 

    this.reload = function reload() { 
    $element.masonry(); 
    $scope.$emit('masonry.reloaded'); 
    }; 


}).directive('masonry', function masonryDirective() { 
    return { 
    restrict: 'AE', 
    controller: 'MasonryCtrl', 
    link: { 
     pre: function preLink(scope, element, attrs, ctrl) { 
     var attrOptions = scope.$eval(attrs.masonry || attrs.masonryOptions); 
     var options = angular.extend({ 
      itemSelector: attrs.itemSelector || '.masonry-brick', 
      columnWidth: parseInt(attrs.columnWidth, 10) || attrs.columnWidth 
     }, attrOptions || {}); 
     element.masonry(options); 
     var loadImages = scope.$eval(attrs.loadImages); 
     ctrl.loadImages = loadImages !== false; 
     var preserveOrder = scope.$eval(attrs.preserveOrder); 
     ctrl.preserveOrder = (preserveOrder !== false && attrs.preserveOrder !== undefined); 

     scope.$emit('masonry.created', element); 
     scope.$on('$destroy', ctrl.destroy); 
     } 
    } 
    }; 
}).directive('masonryBrick', function masonryBrickDirective() { 
    return { 
    restrict: 'AC', 
    require: '^masonry', 
    scope: true, 
    link: { 
     pre: function preLink(scope, element, attrs, ctrl) { 
     var id = scope.$id, index; 

     ctrl.appendBrick(element, id); 
     element.on('$destroy', function() { 
      ctrl.removeBrick(id, element); 
     }); 

     scope.$on('masonry.reload', function() { 
      ctrl.scheduleMasonryOnce('reloadItems'); 
      ctrl.scheduleMasonryOnce('layout'); 
     }); 

     scope.$watch('$index', function() { 
      if (index !== undefined && index !== scope.$index) { 
      ctrl.scheduleMasonryOnce('reloadItems'); 
      ctrl.scheduleMasonryOnce('layout'); 
      } 
      index = scope.$index; 
     }); 
     } 
    } 
    }; 
}); 
}()); 
+0

Giải pháp tôi tin là chạy lại nề sau một trong những sự kiện này nhưng tôi không thể tìm ra cách thực hiện điều đó từ bên trong bộ điều khiển góc mà tôi đang sử dụng. Tôi đã thêm tiền thưởng cho câu hỏi này. – Guy

+1

Hãy làm một kẻ nói chuyện đơn giản chứng minh vấn đề –

+0

Hoặc bạn chỉ có thể viết một chỉ thị đơn giản hơn: http://plnkr.co/edit/UyRS0clrCwDpSrYgBsXS?p=preview – SoluableNonagon

Trả lời

1

Giống như với nhiều thư viện phi kiễu góc, dường như câu trả lời nằm trong gói thư viện trong một chỉ thị góc.

tôi đã không thử nó ra nhưng có vẻ như là những gì this person did

+1

Có, OP bao gồm liên kết đó là một trong 2 thư viện mà anh ta đang sử dụng. Vấn đề mà chúng tôi đang cố gắng giải quyết là làm thế nào để bạn gọi hàm masonry một lần nữa từ bên trong bộ điều khiển của bạn để cho nó biết "làm mới" bởi vì bạn đã thay đổi kích thước của các thành phần trên trang. – Guy

0

Bạn có thể sử dụng của góc $ phát ra, $ phát sóng, và $ vào chức năng.

Bên masonry chỉ thị liên kết chức năng của bạn:

scope.$on('$resizeMasonry', ctrl.scheduleMasonryOnce('layout'));

Bên trong chức năng liên kết masonryBrick chỉ thị của bạn hoặc bất kỳ phần tử con khác:

scope.$emit('$resizeMasonry');

Sử dụng $ phát ra để gửi một sự kiện lên phạm vi cây và $ phát sóng để gửi một sự kiện xuống cây phạm vi.

+0

Cảm ơn Travis. Hãy tưởng tượng bạn đã bao gồm cả khối xây và khối xây trong một dự án và trong bộ điều khiển của bạn trên một trang mà bạn đã thêm một phần tử thông qua một sự kiện nhấp chuột. Phần tử này giờ chồng chéo phần tử khác. Làm thế nào bây giờ bạn sẽ gọi "làm mới/tải lại" từ bên trong bộ điều khiển của trang? – Guy

+0

@Guy, điều đó sẽ phụ thuộc vào phạm vi của bộ điều khiển có liên quan đến 'MasonryCtrl'. Nếu đó là phạm vi con bạn sẽ muốn $ phát ra một phạm vi gốc. Nếu đó là phạm vi phụ huynh, hãy sử dụng chương trình phát sóng $. Như một phương sách cuối cùng '$ rootScope. $ Broadcast' sẽ chảy xuống tất cả các phạm vi. – Travis

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