This repository has been archived by the owner on Dec 30, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 216
/
angular-masonry.js
133 lines (112 loc) · 3.67 KB
/
angular-masonry.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*!
* 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.scheduleMasonryOnce = function scheduleMasonryOnce() {
var args = arguments;
var found = schedule.filter(function (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 (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) {
// 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!
defaultLoaded(element);
// Keep track of added elements.
bricks[id] = true;
$element.masonry('appended', element, true);
self.scheduleMasonryOnce('layout');
}
}
element.imagesLoaded(_append);
};
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 = [];
};
}).directive('masonry', function () {
return {
restrict: 'AE',
controller: 'MasonryCtrl',
link: function postLink(scope, element, attrs, ctrl) {
var attrOptions = scope.$eval(attrs.options);
var options = angular.extend(attrOptions || {}, {
itemSelector: attrs.itemSelector || '.masonry-brick',
columnWidth: parseInt(attrs.columnWidth, 10)
});
element.masonry(options);
scope.$emit('masonry.created', element);
scope.$on('$destroy', ctrl.destroy);
}
};
}).directive('masonryBrick', function () {
return {
restrict: 'AC',
require: '^masonry',
scope: true,
link: function postLink(scope, element, attrs, ctrl) {
var id = scope.$id;
ctrl.appendBrick(element, id);
element.on('$destroy', function () {
ctrl.removeBrick(id, element);
});
}
};
});
}());