forked from aFarkas/lazysizes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathls.parent-fit.js
124 lines (103 loc) · 3.33 KB
/
ls.parent-fit.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
(function(window, document){
'use strict';
if(!window.addEventListener){return;}
var oldReadCallback;
var regDescriptors = /\s+(\d+)(w|h)\s+(\d+)(w|h)/;
var regPicture = /^picture$/i;
var parentFit = {
getFit: function(element){
var obj = {
fit: element.getAttribute('data-parent-fit')
};
if(obj.fit){
obj.parent = element.parentNode;
if(obj.parent && regPicture.test(obj.parent.nodeName || '')){
obj.parent = obj.parent.parentNode;
}
} else {
obj.fit = (getComputedStyle(element) || {getPropertyValue: function(){}}).getPropertyValue("object-fit");
}
return obj;
},
getImageRatio: function(element){
var i, srcset, media;
var dims = {};
var parent = element.parentNode;
var elements = parent && regPicture.test(parent.nodeName || '') ?
parent.querySelectorAll('source, img') :
[element]
;
for(i = 0; i < elements.length; i++){
element = elements[i];
srcset = element.getAttribute(lazySizesConfig.srcsetAttr) || element.getAttribute('srcset') || element.getAttribute('data-pfsrcset') || element.getAttribute('data-risrcset') || '';
media = element.getAttribute('media');
media = lazySizesConfig.customMedia[element.getAttribute('data-media') || media] || media;
if(srcset && (!media || (window.matchMedia && matchMedia(media) || {}).matches )){
if(srcset.match(regDescriptors)){
if(RegExp.$2 == 'w'){
dims.w = RegExp.$1;
dims.h = RegExp.$3;
} else {
dims.w = RegExp.$3;
dims.h = RegExp.$1;
}
}
break;
}
}
return dims.w / dims.h;
},
calculateSize: function(element, width){
if(element._parentfitWidthCache){
return element._parentfitWidthCache;
}
var displayRatio, height, imageRatio, retWidth;
var fitObj = this.getFit(element);
var fit = fitObj.fit;
var fitElem = fitObj.parent;
if(fit != 'width' && ((fit != 'contain' && fit != 'cover') || !(imageRatio = this.getImageRatio(element)))){return width;}
if(fitElem){
width = fitElem.offsetWidth;
} else {
fitElem = element;
}
retWidth = width;
if(fit == 'width'){
retWidth = width;
} else {
height = fitElem.offsetHeight;
if(height > 40 && (displayRatio = width / height) && ((fit == 'cover' && displayRatio < imageRatio) || (fit == 'contain' && displayRatio > imageRatio))){
retWidth = width * (imageRatio / displayRatio);
}
}
return retWidth;
}
};
var extend = function(){
if(window.lazySizes){
if(!lazySizes.parentFit){
lazySizes.parentFit = parentFit;
}
window.removeEventListener('lazybeforeunveil', extend, true);
}
};
window.lazySizesConfig = window.lazySizesConfig || {};
oldReadCallback = window.lazySizesConfig.rC;
window.lazySizesConfig.rC = function(elem, width){
if(oldReadCallback){
width = oldReadCallback.apply(this, arguments) || width;
}
elem._parentfitWidthCache = parentFit.calculateSize(elem, width) || width;
return elem._parentfitWidthCache;
};
window.addEventListener('lazybeforeunveil', extend, true);
document.addEventListener('lazybeforesizes', function(e){
if(e.defaultPrevented){return;}
var element = e.target;
e.detail.width = parentFit.calculateSize(element, e.detail.width);
if(element._parentfitWidthCache){
delete element._parentfitWidthCache;
}
});
setTimeout(extend);
})(window, document);