forked from luis-almeida/unveil
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjquery.malaise.js
138 lines (117 loc) · 3.67 KB
/
jquery.malaise.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
134
135
136
137
138
/**
* jQuery malaise
* Lazy load images and backgrounds
* https://github.com/zaption/malaise
* Forked from https://github.com/luis-almeida/unveil
*
**/
;(function($) {
$.malaise = function(options) {
var desktopSource = 'data-src';
var mobileSource = 'data-src-mobile';
var retinaSource = 'data-src-retina';
var opts = options || {};
var settings = $.extend({
offset: 0,
path: '',
selector: '.malaise',
loadedClass: 'malaise-loaded',
breakpoint: '767px',
container: window,
throttle: 100
}, opts);
var retina = window.devicePixelRatio >= 1.5;
var offset = offset || 0;
var unLoaded = $(settings.selector);
var allElements = $(settings.selector);
var loaded;
var $container = $(settings.container);
var $window = $(window);
var windowHeight = $window.height();
var aboveBreakpoint = true;
if (window.matchMedia !== undefined) {
var transWidth = window.matchMedia('(min-width: ' + settings.breakpoint + ')');
var responsiveSources = function(mqw) {
aboveBreakpoint = mqw.matches ? true : false
unLoaded = allElements;
};
transWidth.addListener(responsiveSources);
responsiveSources(transWidth);
}
allElements.on('loadSourceAttribute', function() {
var source;
if (retina && this.hasAttribute(retinaSource)) source = retinaSource;
else if (!aboveBreakpoint && this.hasAttribute(mobileSource)) source = mobileSource;
else source = desktopSource;
var newSource = this.getAttribute(source);
if (newSource) {
if ($(this).is('img, iframe, video')) {
this.setAttribute('src', settings.path + newSource);
} else {
this.setAttribute('style', 'background-image: url(' + settings.path + newSource + ')');
}
if (!$(this).hasClass(settings.loadedClass)) {
$(this).addClass(settings.loadedClass);
if (typeof settings.callback === 'function') settings.callback.call(this);
}
}
});
var showImages = function() {
if (!unLoaded.length) return;
var windowTop = $window.scrollTop();
var windowBottom = windowTop + windowHeight;
var containerTop = $container.is($window) ? 0 : windowTop - $container.offset().top;
var onScreen = unLoaded.filter(function() {
var $element = $(this);
if ($element.is(':hidden')) return;
var elementTop = $element.offset().top + containerTop;
var elementBottom = elementTop + $element.height();
return elementBottom >= windowTop - settings.offset && elementTop <= windowBottom + settings.offset;
});
loaded = onScreen.trigger('loadSourceAttribute');
unLoaded = unLoaded.not(loaded);
}
var throttle = function(func) { // based on underscore's throttle
var context;
var result;
var timeout = null;
var previous = 0;
var later = function() {
previous = Date.now();
timeout = null;
result = func.apply(context);
if (!timeout) context = null;
};
return function() {
var now = Date.now();
if (!previous) previous = now;
var remaining = settings.throttle - (now - previous);
context = this;
if (remaining <= 0 || remaining > settings.throttle) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context);
if (!timeout) context = null;
} else if (!timeout) {
timeout = setTimeout(later, remaining);
}
return result;
};
};
var resize = function() {
windowHeight = $window.height();
showImages();
}
$container.on({
'resize.malaise': throttle(resize),
'scroll.malaise': throttle(showImages),
'wakeup.malaise': showImages,
'touchend.malaise': showImages
});
showImages();
return allElements;
};
})(window.jQuery);