-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathangular-lazy-loader.js
91 lines (75 loc) · 2.84 KB
/
angular-lazy-loader.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
;(function() {
"use strict"
var app = angular.module('angular-lazy-loader', [])
.directive('angularLazyLoad', ['$window', '$timeout', '$rootScope', function($window, $timeout, $rootScope) {
return {
restrict: 'EA',
//child scope instead of isolate scope because need to listen for ng-include load events from other scopes
scope: true,
link: function(scope, element, attrs) {
var elements = [],
threshold = Number(attrs.threshold) || 0;
//gets all img(s), iframe(s) with the 'data-src' attribute and changes it to 'src'
function getElements() {
//fetch all image elements inside the current element
//fetch all iframe elements inside the current element
// fetch all divs inside the current element
elements = Array.prototype.slice.call(element[0].querySelectorAll('img[data-src], iframe[data-src], div[data-src]'));
//if images and videos were found call loadMedia
if(elements.length > 0 ) {
loadMedia();
}
}
//checks if element passed in the argument is inside the viewport. Returns a boolean value.
function inViewPort(media) {
var coordinates = media.getBoundingClientRect();
return (
coordinates.bottom + threshold >= 0 &&
coordinates.left >= 0 &&
coordinates.top - threshold <= (window.innerHeight || document.documentElement.clientHeight) &&
coordinates.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
//replaces 'data-src' with 'src' for the elements found.
function loadMedia() {
elements = elements.reduce(function ( arr, item ) {
var src = item.getAttribute("data-src");
if (!inViewPort ( item)) {
arr.push(item);
return arr;
}
switch(item.tagName) {
case "IMG":
case "IFRAME":
item.src = src;
break;
case "DIV":
item.style.backgroundImage = "url("+src+")";
break;
default:
arr.push(item);
}
return arr;
}, []);
};
getElements();
function reloadElements () {
$timeout(getElements, 0);
}
function reloadMedia ( ) {
$timeout(loadMedia, 0);
}
//listens for partials loading events using ng-include
scope.$on('$includeContentLoaded', reloadElements);
//listens for selective loading, that is, if the developer using this directive wants to load the elements programmatically he can emit a selectiveLoad event
$rootScope.$on('selectiveLoad', reloadElements);
//calls loadMedia for each window scroll event
angular.element($window).bind('scroll', reloadMedia);
//calls loadMedia for each window scroll event
angular.element($window).bind('resize', reloadMedia);
//calls loadMedia for each element scroll event
angular.element(element).bind('scroll', reloadMedia);
}
}
}])
})();