imgix-optimizer 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/dist/imgix-optimizer-0.0.5.min.js +1 -0
- data/dist/imgix-optimizer.js +22 -1
- data/package.json +1 -1
- data/src/imgix_bg_image.js +19 -1
- data/vendor/assets/javascripts/imgix-optimizer.js +695 -0
- metadata +4 -3
- data/dist/imgix-optimizer-0.0.3.min.js +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f8ebafc45462fd9534d73b40fd5d700688a15c94852d57e63f5e47e633d26f2
|
4
|
+
data.tar.gz: 95d929ae1beda1f74fc82cedd1f414c90a069ab8ece1d90a67159782393d9ec7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c42f618d3b5aef875911b05b2e76b942110fcaa06af2a870d2d3443bc8bf131eb7b2d21d520f4cdcdfae5be04e053eae4424951dbcf545e74220b2e9b404edd
|
7
|
+
data.tar.gz: d4d88a4384f3030009e6f5e9564cc5788e4fd712be36a305dcc87062ad7816d16765456b939cc052884f635b3d6250985fe28b502d88a410e9dfcf679ad982d4
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
!function(){"use strict";var t=function(e,i){if(!(e instanceof i))throw new TypeError("Cannot call a class as a function")},e=function(){function l(e,i){for(var t=0;t<i.length;t++){var l=i[t];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(e,l.key,l)}}return function(e,i,t){return i&&l(e.prototype,i),t&&l(e,t),e}}(),l=function(){function i(e){t(this,i),this.timeToFade=500,this.dpr=window.devicePixelRatio||1,this.el=$(e),"none"!=this.el.css("background-image")&&(this.initEl(),this.initOptimization(),this.initEventListeners())}return e(i,[{key:"initOptimization",value:function(){var e=this;$("<img>").on("load",function(){return e.renderTmpPlaceholderEl()}).attr("src",this.placeholderImgUrl)}},{key:"initEl",value:function(){this.setPlaceholderImgUrl(),this.setContainerTmpCss(),this.setElTmpCss()}},{key:"setPlaceholderImgUrl",value:function(){this.placeholderImgUrl=this.el.css("background-image").replace("url(","").replace(")","").replace(/\"/gi,"").replace(/\'/gi,"").split(", ")[0]}},{key:"setContainerTmpCss",value:function(){this.parentStyles={display:this.el.parent().css("display"),position:this.el.parent().css("position")},this.el.parent().css({display:"block",position:"relative"})}},{key:"setElTmpCss",value:function(){"absolute"!=this.el.css("position")&&this.el.css("position","relative")}},{key:"renderTmpPlaceholderEl",value:function(){this.initTmpPlaceholderEl(),this.setTmpPlaceholderElCss(),this.addTmpPlaceholderElToDom(),this.renderFullSizeImg()}},{key:"initTmpPlaceholderEl",value:function(){this.tmpPlaceholderEl=this.el.clone(),this.tmpPlaceholderEl.html("")}},{key:"setTmpPlaceholderElCss",value:function(){this.tmpPlaceholderEl.addClass("imgix-optimizing"),this.tmpPlaceholderEl.css({position:"absolute",top:this.el.position().top,left:this.el.position().left,width:this.el.outerWidth(),height:this.el.outerHeight(),backgroundColor:"transparent"})}},{key:"addTmpPlaceholderElToDom",value:function(){this.tmpPlaceholderEl.insertBefore(this.el)}},{key:"renderFullSizeImg",value:function(){this.removeElBgImg(),this.initTmpFullSizeEl(),this.setTmpFullSizeElImg(),this.addTmpFullSizeElToDom(),this.initTransition()}},{key:"removeElBgImg",value:function(){this.elBgColor=this.el.css("background-color"),this.el.css("background-color","transparent"),this.el.css("background-image","")}},{key:"initTmpFullSizeEl",value:function(){this.tmpFullSizeEl=this.tmpPlaceholderEl.clone()}},{key:"setFullSizeImgUrl",value:function(){var e=this.placeholderImgUrl.split("?"),i=e[e.length-1].split("&"),t={};for(var l in i.map(function(e){return t[e.split("=")[0]]=e.split("=")[1]}),this.el.outerWidth()>=this.el.outerHeight()?(t.w=this.el.outerWidth()*this.dpr,delete t.h):(t.h=this.el.outerHeight()*this.dpr,delete t.w),i=[],t)i.push(l+"="+t[l]);return this.fullSizeImgUrl=e[0]+"?"+i.join("&")}},{key:"setTmpFullSizeElImg",value:function(){this.setFullSizeImgUrl(),this.tmpFullSizeEl.css("background-image",'url("'+this.fullSizeImgUrl+'")')}},{key:"addTmpFullSizeElToDom",value:function(){this.tmpFullSizeEl.insertBefore(this.tmpPlaceholderEl)}},{key:"initTransition",value:function(){$("<img>").on("load",$.proxy(this.transitionImg,this)).attr("src",this.fullSizeImgUrl)}},{key:"transitionImg",value:function(){var e=this;this.fadeOutTmpPlaceholderEl(),setTimeout(function(){e.updateElImg(),e.replaceElTmpCss(),e.replaceContainerTmpCss(),e.removeTmpEls()},this.timeToFade)}},{key:"fadeOutTmpPlaceholderEl",value:function(){this.tmpPlaceholderEl.fadeTo(this.timeToFade,0)}},{key:"updateElImg",value:function(){this.setFullSizeImgUrl(),this.el.css("background-image","url('"+this.fullSizeImgUrl+"')")}},{key:"replaceElTmpCss",value:function(){this.el.css("background-color",this.elBgColor)}},{key:"replaceContainerTmpCss",value:function(){this.el.parent().css({display:this.parentStyles.display,position:this.parentStyles.position})}},{key:"removeTmpEls",value:function(){this.tmpPlaceholderEl.remove(),this.tmpFullSizeEl.remove(),this.tmpPlaceholderEl=void 0,this.tmpFullSizeEl=void 0}},{key:"initEventListeners",value:function(){var i=this;this.initResizeEnd(),$(window).on("resizeEnd",function(e){return i.updateElImg()})}},{key:"initResizeEnd",value:function(){$(window).resize(function(){this.resizeTo&&clearTimeout(this.resizeTo),this.resizeTo=setTimeout(function(){$(this).trigger("resizeEnd")},500)})}}]),i}(),s=function(){function i(e){t(this,i),this.timeToFade=500,this.placeholderImg=$(e),this.initPlaceholder(),this.initOptimization()}return e(i,[{key:"initOptimization",value:function(){$("<img>").on("load",$.proxy(this.renderFullSizeImg,this)).attr("src",this.placeholderImg.attr("src"))}},{key:"initPlaceholder",value:function(){this.setPlaceholderCss()}},{key:"setPlaceholderCss",value:function(){"absolute"!=this.placeholderImg.css("position")&&this.placeholderImg.css("position","relative")}},{key:"renderFullSizeImg",value:function(){this.initFullSizeImg(),this.setFullSizeImgTempCss(),this.setFullSizeImgSrc(),this.addFullSizeImgToDom(),this.initTransition()}},{key:"initFullSizeImg",value:function(){this.fullSizeImg=this.placeholderImg.clone()}},{key:"setFullSizeImgTempCss",value:function(){this.fullSizeImg.css({position:"absolute",top:this.placeholderImg.position().top,left:this.placeholderImg.position().left,width:this.placeholderImg.width(),height:this.placeholderImg.height()})}},{key:"setFullSizeImgSrc",value:function(){var e=this.placeholderImg.attr("src").replace(/(\?|\&)(w=)(\d+)/i,"$1$2"+this.placeholderImg.width()).replace(/(\?|\&)(h=)(\d+)/i,"$1$2"+this.placeholderImg.height());this.fullSizeImg.attr("ix-src",e),this.fullSizeImg.addClass("img-responsive imgix-optimizing"),this.fullSizeImg.removeAttr("data-optimize-img")}},{key:"addFullSizeImgToDom",value:function(){this.fullSizeImg.insertBefore(this.placeholderImg)}},{key:"initTransition",value:function(){var e=this;this.fullSizeImg.on("load",function(){return e.transitionImg()}),imgix.init()}},{key:"transitionImg",value:function(){var e=this;if(!this.placeholderImg)return!0;this.fadeOutPlaceholder(),setTimeout(function(){e.removeFullSizeImgProperties(),e.removeImg()},this.timeToFade)}},{key:"fadeOutPlaceholder",value:function(){this.placeholderImg.fadeTo(this.timeToFade,0)}},{key:"removeFullSizeImgProperties",value:function(){this.fullSizeImg.removeAttr("style"),this.fullSizeImg.removeClass("imgix-optimizing")}},{key:"removeImg",value:function(){this.placeholderImg&&(this.placeholderImg.remove(),this.placeholderImg=void 0)}}]),i}(),i=function(){function i(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};t(this,i),this.initOptions(e),this.optimizeImages(),this.optimizeBgImages()}return e(i,[{key:"initOptions",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.options=e;var i={parent:"body"};for(var t in i)i.hasOwnProperty(t)&&!this.options[t]&&(this.options[t]=i[t])}},{key:"optimizeImages",value:function(){$(this.options.parent+" img[data-optimize-img]").each(function(e,i){new s(i)})}},{key:"optimizeBgImages",value:function(){return $(this.options.parent+" [data-optimize-bg-img]").each(function(e,i){new l(i)}),!0}}]),i}();window.Imgix=window.Imgix||{},Imgix.ImgixBgImage=l,Imgix.ImgixImage=s,Imgix.Optimizer=i}();
|
data/dist/imgix-optimizer.js
CHANGED
@@ -98,7 +98,14 @@
|
|
98
98
|
}, {
|
99
99
|
key: 'setContainerTmpCss',
|
100
100
|
value: function setContainerTmpCss() {
|
101
|
-
this.
|
101
|
+
this.parentStyles = {
|
102
|
+
display: this.el.parent().css('display'),
|
103
|
+
position: this.el.parent().css('position')
|
104
|
+
};
|
105
|
+
this.el.parent().css({
|
106
|
+
display: 'block',
|
107
|
+
position: 'relative'
|
108
|
+
});
|
102
109
|
}
|
103
110
|
|
104
111
|
/**
|
@@ -308,6 +315,7 @@
|
|
308
315
|
setTimeout(function () {
|
309
316
|
_this2.updateElImg();
|
310
317
|
_this2.replaceElTmpCss();
|
318
|
+
_this2.replaceContainerTmpCss();
|
311
319
|
_this2.removeTmpEls();
|
312
320
|
}, this.timeToFade);
|
313
321
|
}
|
@@ -349,6 +357,19 @@
|
|
349
357
|
this.el.css('background-color', this.elBgColor);
|
350
358
|
}
|
351
359
|
|
360
|
+
/**
|
361
|
+
* Reset the container's adjusted CSS properties.
|
362
|
+
*/
|
363
|
+
|
364
|
+
}, {
|
365
|
+
key: 'replaceContainerTmpCss',
|
366
|
+
value: function replaceContainerTmpCss() {
|
367
|
+
this.el.parent().css({
|
368
|
+
display: this.parentStyles.display,
|
369
|
+
position: this.parentStyles.position
|
370
|
+
});
|
371
|
+
}
|
372
|
+
|
352
373
|
/**
|
353
374
|
* Remove both temporary elements from the DOM.
|
354
375
|
*/
|
data/package.json
CHANGED
data/src/imgix_bg_image.js
CHANGED
@@ -58,7 +58,14 @@ export default class ImgixBgImage {
|
|
58
58
|
* correct location.
|
59
59
|
*/
|
60
60
|
setContainerTmpCss() {
|
61
|
-
this.
|
61
|
+
this.parentStyles = {
|
62
|
+
display: this.el.parent().css('display'),
|
63
|
+
position: this.el.parent().css('position')
|
64
|
+
}
|
65
|
+
this.el.parent().css({
|
66
|
+
display: 'block',
|
67
|
+
position: 'relative'
|
68
|
+
});
|
62
69
|
}
|
63
70
|
|
64
71
|
/**
|
@@ -225,6 +232,7 @@ export default class ImgixBgImage {
|
|
225
232
|
setTimeout(() => {
|
226
233
|
this.updateElImg();
|
227
234
|
this.replaceElTmpCss();
|
235
|
+
this.replaceContainerTmpCss();
|
228
236
|
this.removeTmpEls();
|
229
237
|
}, this.timeToFade);
|
230
238
|
}
|
@@ -257,6 +265,16 @@ export default class ImgixBgImage {
|
|
257
265
|
this.el.css('background-color', this.elBgColor);
|
258
266
|
}
|
259
267
|
|
268
|
+
/**
|
269
|
+
* Reset the container's adjusted CSS properties.
|
270
|
+
*/
|
271
|
+
replaceContainerTmpCss() {
|
272
|
+
this.el.parent().css({
|
273
|
+
display: this.parentStyles.display,
|
274
|
+
position: this.parentStyles.position
|
275
|
+
});
|
276
|
+
}
|
277
|
+
|
260
278
|
/**
|
261
279
|
* Remove both temporary elements from the DOM.
|
262
280
|
*/
|
@@ -0,0 +1,695 @@
|
|
1
|
+
(function () {
|
2
|
+
'use strict';
|
3
|
+
|
4
|
+
var classCallCheck = function (instance, Constructor) {
|
5
|
+
if (!(instance instanceof Constructor)) {
|
6
|
+
throw new TypeError("Cannot call a class as a function");
|
7
|
+
}
|
8
|
+
};
|
9
|
+
|
10
|
+
var createClass = function () {
|
11
|
+
function defineProperties(target, props) {
|
12
|
+
for (var i = 0; i < props.length; i++) {
|
13
|
+
var descriptor = props[i];
|
14
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
15
|
+
descriptor.configurable = true;
|
16
|
+
if ("value" in descriptor) descriptor.writable = true;
|
17
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
return function (Constructor, protoProps, staticProps) {
|
22
|
+
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
23
|
+
if (staticProps) defineProperties(Constructor, staticProps);
|
24
|
+
return Constructor;
|
25
|
+
};
|
26
|
+
}();
|
27
|
+
|
28
|
+
var ImgixBgImage = function () {
|
29
|
+
function ImgixBgImage(el) {
|
30
|
+
classCallCheck(this, ImgixBgImage);
|
31
|
+
|
32
|
+
// Length of time to complete fade-in transition.
|
33
|
+
this.timeToFade = 500;
|
34
|
+
// Device pixel ratio assumes 1 if not set.
|
35
|
+
this.dpr = window['devicePixelRatio'] || 1;
|
36
|
+
// The primary element (i.e. the one with the background image).
|
37
|
+
this.el = $(el);
|
38
|
+
// Background image CSS property must be present.
|
39
|
+
if (this.el.css('background-image') == 'none') {
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
// Prepare the element and its container for optimization.
|
43
|
+
this.initEl();
|
44
|
+
// Kick off the optimization process.
|
45
|
+
this.initOptimization();
|
46
|
+
// Listen for window resize events.
|
47
|
+
this.initEventListeners();
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Load an image in memory (not within the DOM) with the same source as the
|
52
|
+
* placeholder image. Once that has completed, we know we're safe to begin
|
53
|
+
* processing.
|
54
|
+
*/
|
55
|
+
|
56
|
+
|
57
|
+
createClass(ImgixBgImage, [{
|
58
|
+
key: 'initOptimization',
|
59
|
+
value: function initOptimization() {
|
60
|
+
var _this = this;
|
61
|
+
|
62
|
+
$('<img>').on('load', function () {
|
63
|
+
return _this.renderTmpPlaceholderEl();
|
64
|
+
}).attr('src', this.placeholderImgUrl);
|
65
|
+
}
|
66
|
+
|
67
|
+
// ---------------------------------------- | Main Element
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Prepare the main element and its container for optimization.
|
71
|
+
*/
|
72
|
+
|
73
|
+
}, {
|
74
|
+
key: 'initEl',
|
75
|
+
value: function initEl() {
|
76
|
+
this.setPlaceholderImgUrl();
|
77
|
+
this.setContainerTmpCss();
|
78
|
+
this.setElTmpCss();
|
79
|
+
}
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Set reference to original image URL, which is expected to be a small
|
83
|
+
* placeholder.
|
84
|
+
*/
|
85
|
+
|
86
|
+
}, {
|
87
|
+
key: 'setPlaceholderImgUrl',
|
88
|
+
value: function setPlaceholderImgUrl() {
|
89
|
+
this.placeholderImgUrl = this.el.css('background-image').replace('url(', '').replace(')', '').replace(/\"/gi, "").replace(/\'/gi, "").split(', ')[0];
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* The parent of our jumbotron container should be relatively positioned
|
94
|
+
* (temporarily) so that we can absolutely position the temp image in the
|
95
|
+
* correct location.
|
96
|
+
*/
|
97
|
+
|
98
|
+
}, {
|
99
|
+
key: 'setContainerTmpCss',
|
100
|
+
value: function setContainerTmpCss() {
|
101
|
+
this.parentStyles = {
|
102
|
+
display: this.el.parent().css('display'),
|
103
|
+
position: this.el.parent().css('position')
|
104
|
+
};
|
105
|
+
this.el.parent().css({
|
106
|
+
display: 'block',
|
107
|
+
position: 'relative'
|
108
|
+
});
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* The main element must have a position set for it to be rendered on top of
|
113
|
+
* the temporary full-size image. We assume that if the element is not
|
114
|
+
* explicitly positioned absolutely, then it can safely be positioned
|
115
|
+
* relatively.
|
116
|
+
*/
|
117
|
+
|
118
|
+
}, {
|
119
|
+
key: 'setElTmpCss',
|
120
|
+
value: function setElTmpCss() {
|
121
|
+
if (this.el.css('position') != 'absolute') {
|
122
|
+
this.el.css('position', 'relative');
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
// ---------------------------------------- | Placeholder Image (Temp)
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Render a clone of the element with the background image directly behind
|
130
|
+
* itself.
|
131
|
+
*/
|
132
|
+
|
133
|
+
}, {
|
134
|
+
key: 'renderTmpPlaceholderEl',
|
135
|
+
value: function renderTmpPlaceholderEl() {
|
136
|
+
this.initTmpPlaceholderEl();
|
137
|
+
this.setTmpPlaceholderElCss();
|
138
|
+
this.addTmpPlaceholderElToDom();
|
139
|
+
this.renderFullSizeImg();
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Create a clone of the element with the background image. Remove content
|
144
|
+
* from the clone -- often elements with a background image contain content.
|
145
|
+
*/
|
146
|
+
|
147
|
+
}, {
|
148
|
+
key: 'initTmpPlaceholderEl',
|
149
|
+
value: function initTmpPlaceholderEl() {
|
150
|
+
this.tmpPlaceholderEl = this.el.clone();
|
151
|
+
this.tmpPlaceholderEl.html('');
|
152
|
+
}
|
153
|
+
|
154
|
+
/**
|
155
|
+
* Position the clone directly behind the main element
|
156
|
+
*/
|
157
|
+
|
158
|
+
}, {
|
159
|
+
key: 'setTmpPlaceholderElCss',
|
160
|
+
value: function setTmpPlaceholderElCss() {
|
161
|
+
this.tmpPlaceholderEl.addClass('imgix-optimizing');
|
162
|
+
this.tmpPlaceholderEl.css({
|
163
|
+
position: 'absolute',
|
164
|
+
top: this.el.position().top,
|
165
|
+
left: this.el.position().left,
|
166
|
+
width: this.el.outerWidth(),
|
167
|
+
height: this.el.outerHeight(),
|
168
|
+
backgroundColor: 'transparent'
|
169
|
+
});
|
170
|
+
}
|
171
|
+
|
172
|
+
/**
|
173
|
+
* Add temporary element to the DOM, directly before the main element
|
174
|
+
* containing the background image.
|
175
|
+
*/
|
176
|
+
|
177
|
+
}, {
|
178
|
+
key: 'addTmpPlaceholderElToDom',
|
179
|
+
value: function addTmpPlaceholderElToDom() {
|
180
|
+
this.tmpPlaceholderEl.insertBefore(this.el);
|
181
|
+
}
|
182
|
+
|
183
|
+
// ---------------------------------------- | Full-Size Image (Temp)
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Create another clone, this time of the temporary placeholder image. This
|
187
|
+
* new element sits behind the other two and is responsible for loading the
|
188
|
+
* full-size image.
|
189
|
+
*/
|
190
|
+
|
191
|
+
}, {
|
192
|
+
key: 'renderFullSizeImg',
|
193
|
+
value: function renderFullSizeImg() {
|
194
|
+
this.removeElBgImg();
|
195
|
+
this.initTmpFullSizeEl();
|
196
|
+
this.setTmpFullSizeElImg();
|
197
|
+
this.addTmpFullSizeElToDom();
|
198
|
+
this.initTransition();
|
199
|
+
}
|
200
|
+
|
201
|
+
/**
|
202
|
+
* Remove the background color and image from the main element. The user won't
|
203
|
+
* notice this transition because the temp duplicate image is already set and
|
204
|
+
* is sitting behind the primary element.
|
205
|
+
*
|
206
|
+
* This also stores a reference to the original background color so we can put
|
207
|
+
* it back when the transition is complete.
|
208
|
+
*/
|
209
|
+
|
210
|
+
}, {
|
211
|
+
key: 'removeElBgImg',
|
212
|
+
value: function removeElBgImg() {
|
213
|
+
this.elBgColor = this.el.css('background-color');
|
214
|
+
this.el.css('background-color', 'transparent');
|
215
|
+
this.el.css('background-image', '');
|
216
|
+
}
|
217
|
+
|
218
|
+
/**
|
219
|
+
* The temporary full-size element is a clone of the temporary placeholder
|
220
|
+
* image element.
|
221
|
+
*/
|
222
|
+
|
223
|
+
}, {
|
224
|
+
key: 'initTmpFullSizeEl',
|
225
|
+
value: function initTmpFullSizeEl() {
|
226
|
+
this.tmpFullSizeEl = this.tmpPlaceholderEl.clone();
|
227
|
+
}
|
228
|
+
|
229
|
+
/**
|
230
|
+
* Sets a reference to the full-size image URL based on the current dimensions
|
231
|
+
* of the main element.
|
232
|
+
*/
|
233
|
+
|
234
|
+
}, {
|
235
|
+
key: 'setFullSizeImgUrl',
|
236
|
+
value: function setFullSizeImgUrl() {
|
237
|
+
// Work with the placeholdler image URL, which has been pulled from the
|
238
|
+
// background-image css property of the main elements.
|
239
|
+
var url = this.placeholderImgUrl.split('?');
|
240
|
+
// q is an array of querystring parameters as ["k=v", "k=v", ...].
|
241
|
+
var q = url[url.length - 1].split('&');
|
242
|
+
// Mapping q converts the array to an object of querystring parameters as
|
243
|
+
// { k: v, k: v, ... }.
|
244
|
+
var args = {};
|
245
|
+
q.map(function (x) {
|
246
|
+
return args[x.split('=')[0]] = x.split('=')[1];
|
247
|
+
});
|
248
|
+
// If the image's container is wider than it is tall, we only set width and
|
249
|
+
// unset height, and vice versa.
|
250
|
+
if (this.el.outerWidth() >= this.el.outerHeight()) {
|
251
|
+
args['w'] = this.el.outerWidth() * this.dpr;
|
252
|
+
delete args['h'];
|
253
|
+
} else {
|
254
|
+
args['h'] = this.el.outerHeight() * this.dpr;
|
255
|
+
delete args['w'];
|
256
|
+
}
|
257
|
+
// Redefine q and go the other direction -- take the args object and convert
|
258
|
+
// it back to an array of querystring parameters, as ["k=v", "k=v", ...].
|
259
|
+
q = [];
|
260
|
+
for (var k in args) {
|
261
|
+
q.push(k + '=' + args[k]);
|
262
|
+
}
|
263
|
+
// Store the result and return.
|
264
|
+
return this.fullSizeImgUrl = url[0] + '?' + q.join('&');
|
265
|
+
}
|
266
|
+
|
267
|
+
/**
|
268
|
+
* Change the URL of this temporary element's background image to be the
|
269
|
+
* full-size image.
|
270
|
+
*/
|
271
|
+
|
272
|
+
}, {
|
273
|
+
key: 'setTmpFullSizeElImg',
|
274
|
+
value: function setTmpFullSizeElImg() {
|
275
|
+
this.setFullSizeImgUrl();
|
276
|
+
this.tmpFullSizeEl.css('background-image', 'url("' + this.fullSizeImgUrl + '")');
|
277
|
+
}
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Add the temporary full-size element direct before the temporary placeholder
|
281
|
+
* element.
|
282
|
+
*/
|
283
|
+
|
284
|
+
}, {
|
285
|
+
key: 'addTmpFullSizeElToDom',
|
286
|
+
value: function addTmpFullSizeElToDom() {
|
287
|
+
this.tmpFullSizeEl.insertBefore(this.tmpPlaceholderEl);
|
288
|
+
}
|
289
|
+
|
290
|
+
// ---------------------------------------- | Transition
|
291
|
+
|
292
|
+
/**
|
293
|
+
* Load full-size image in memory. When it has loaded we can confidentally
|
294
|
+
* fade out the placeholder, knowing the full-size image will be in its place.
|
295
|
+
*/
|
296
|
+
|
297
|
+
}, {
|
298
|
+
key: 'initTransition',
|
299
|
+
value: function initTransition() {
|
300
|
+
$('<img>').on('load', $.proxy(this.transitionImg, this)).attr('src', this.fullSizeImgUrl);
|
301
|
+
}
|
302
|
+
|
303
|
+
/**
|
304
|
+
* Fade out the temporary placeholder, set the background-image on the main
|
305
|
+
* element to the full-size URL, then remove the temporary elements behind the
|
306
|
+
* main element
|
307
|
+
*/
|
308
|
+
|
309
|
+
}, {
|
310
|
+
key: 'transitionImg',
|
311
|
+
value: function transitionImg() {
|
312
|
+
var _this2 = this;
|
313
|
+
|
314
|
+
this.fadeOutTmpPlaceholderEl();
|
315
|
+
setTimeout(function () {
|
316
|
+
_this2.updateElImg();
|
317
|
+
_this2.replaceElTmpCss();
|
318
|
+
_this2.replaceContainerTmpCss();
|
319
|
+
_this2.removeTmpEls();
|
320
|
+
}, this.timeToFade);
|
321
|
+
}
|
322
|
+
|
323
|
+
/**
|
324
|
+
* Fade out the placeholder element. This was the temporary clone of the main
|
325
|
+
* element that has a placeholder background image.
|
326
|
+
*
|
327
|
+
* Rememeber the main element's background image was unset and its color set
|
328
|
+
* to transparent. That is why fading out this temporary image will work
|
329
|
+
* properly.
|
330
|
+
*/
|
331
|
+
|
332
|
+
}, {
|
333
|
+
key: 'fadeOutTmpPlaceholderEl',
|
334
|
+
value: function fadeOutTmpPlaceholderEl() {
|
335
|
+
this.tmpPlaceholderEl.fadeTo(this.timeToFade, 0);
|
336
|
+
}
|
337
|
+
|
338
|
+
/**
|
339
|
+
* Reset the image URL (this helps if the size of the element has changed),
|
340
|
+
* then set the background image to the new source.
|
341
|
+
*/
|
342
|
+
|
343
|
+
}, {
|
344
|
+
key: 'updateElImg',
|
345
|
+
value: function updateElImg() {
|
346
|
+
this.setFullSizeImgUrl();
|
347
|
+
this.el.css('background-image', 'url(\'' + this.fullSizeImgUrl + '\')');
|
348
|
+
}
|
349
|
+
|
350
|
+
/**
|
351
|
+
* Set the background color back to what it was before the transition.
|
352
|
+
*/
|
353
|
+
|
354
|
+
}, {
|
355
|
+
key: 'replaceElTmpCss',
|
356
|
+
value: function replaceElTmpCss() {
|
357
|
+
this.el.css('background-color', this.elBgColor);
|
358
|
+
}
|
359
|
+
|
360
|
+
/**
|
361
|
+
* Reset the container's adjusted CSS properties.
|
362
|
+
*/
|
363
|
+
|
364
|
+
}, {
|
365
|
+
key: 'replaceContainerTmpCss',
|
366
|
+
value: function replaceContainerTmpCss() {
|
367
|
+
this.el.parent().css({
|
368
|
+
display: this.parentStyles.display,
|
369
|
+
position: this.parentStyles.position
|
370
|
+
});
|
371
|
+
}
|
372
|
+
|
373
|
+
/**
|
374
|
+
* Remove both temporary elements from the DOM.
|
375
|
+
*/
|
376
|
+
|
377
|
+
}, {
|
378
|
+
key: 'removeTmpEls',
|
379
|
+
value: function removeTmpEls() {
|
380
|
+
this.tmpPlaceholderEl.remove();
|
381
|
+
this.tmpFullSizeEl.remove();
|
382
|
+
this.tmpPlaceholderEl = undefined;
|
383
|
+
this.tmpFullSizeEl = undefined;
|
384
|
+
}
|
385
|
+
|
386
|
+
// ---------------------------------------- | Event Listeners
|
387
|
+
|
388
|
+
/**
|
389
|
+
* Listener for window resize events and update the image when the event ends.
|
390
|
+
*/
|
391
|
+
|
392
|
+
}, {
|
393
|
+
key: 'initEventListeners',
|
394
|
+
value: function initEventListeners() {
|
395
|
+
var _this3 = this;
|
396
|
+
|
397
|
+
this.initResizeEnd();
|
398
|
+
$(window).on('resizeEnd', function (event) {
|
399
|
+
return _this3.updateElImg();
|
400
|
+
});
|
401
|
+
}
|
402
|
+
|
403
|
+
/**
|
404
|
+
* Trigger "resizeEnd" event on the window object after resizing has ceased
|
405
|
+
* for at least 0.5 seconds.
|
406
|
+
*/
|
407
|
+
|
408
|
+
}, {
|
409
|
+
key: 'initResizeEnd',
|
410
|
+
value: function initResizeEnd() {
|
411
|
+
$(window).resize(function () {
|
412
|
+
if (this.resizeTo) {
|
413
|
+
clearTimeout(this.resizeTo);
|
414
|
+
}
|
415
|
+
this.resizeTo = setTimeout(function () {
|
416
|
+
$(this).trigger('resizeEnd');
|
417
|
+
}, 500);
|
418
|
+
});
|
419
|
+
}
|
420
|
+
}]);
|
421
|
+
return ImgixBgImage;
|
422
|
+
}();
|
423
|
+
|
424
|
+
var ImgixImage = function () {
|
425
|
+
function ImgixImage(img) {
|
426
|
+
classCallCheck(this, ImgixImage);
|
427
|
+
|
428
|
+
// Length of crossfade transition.
|
429
|
+
this.timeToFade = 500;
|
430
|
+
// The main image (pixelated placeholder).
|
431
|
+
this.placeholderImg = $(img);
|
432
|
+
// Configure the main placeholder image.
|
433
|
+
this.initPlaceholder();
|
434
|
+
// Kick off the optimization process.
|
435
|
+
this.initOptimization();
|
436
|
+
}
|
437
|
+
|
438
|
+
/**
|
439
|
+
* Load an image in memory (not within the DOM) with the same source as the
|
440
|
+
* placeholder image. Once that has completed, we know we're safe to begin
|
441
|
+
* processing.
|
442
|
+
*/
|
443
|
+
|
444
|
+
|
445
|
+
createClass(ImgixImage, [{
|
446
|
+
key: 'initOptimization',
|
447
|
+
value: function initOptimization() {
|
448
|
+
$('<img>').on('load', $.proxy(this.renderFullSizeImg, this)).attr('src', this.placeholderImg.attr('src'));
|
449
|
+
}
|
450
|
+
|
451
|
+
// ---------------------------------------- | Placeholder Image
|
452
|
+
|
453
|
+
/**
|
454
|
+
* Make necessary CSS adjustments to main placeholder image.
|
455
|
+
*/
|
456
|
+
|
457
|
+
}, {
|
458
|
+
key: 'initPlaceholder',
|
459
|
+
value: function initPlaceholder() {
|
460
|
+
this.setPlaceholderCss();
|
461
|
+
}
|
462
|
+
|
463
|
+
/**
|
464
|
+
* The main image must have a position set for it to remain in front of the
|
465
|
+
* full-size image. We assume that if the element is not explicitly positioned
|
466
|
+
* absolutely, then it can safely be positioned relatively.
|
467
|
+
*/
|
468
|
+
|
469
|
+
}, {
|
470
|
+
key: 'setPlaceholderCss',
|
471
|
+
value: function setPlaceholderCss() {
|
472
|
+
if (this.placeholderImg.css('position') != 'absolute') {
|
473
|
+
this.placeholderImg.css('position', 'relative');
|
474
|
+
}
|
475
|
+
}
|
476
|
+
|
477
|
+
// ---------------------------------------- | Full-Size Image
|
478
|
+
|
479
|
+
/**
|
480
|
+
* Render the full-size image behind the placeholder image.
|
481
|
+
*/
|
482
|
+
|
483
|
+
}, {
|
484
|
+
key: 'renderFullSizeImg',
|
485
|
+
value: function renderFullSizeImg() {
|
486
|
+
this.initFullSizeImg();
|
487
|
+
this.setFullSizeImgTempCss();
|
488
|
+
this.setFullSizeImgSrc();
|
489
|
+
this.addFullSizeImgToDom();
|
490
|
+
this.initTransition();
|
491
|
+
}
|
492
|
+
|
493
|
+
/**
|
494
|
+
* The full-size image is a clone of the placeholder image. This enables us to
|
495
|
+
* easily replace it without losing any necessary styles or attributes.
|
496
|
+
*/
|
497
|
+
|
498
|
+
}, {
|
499
|
+
key: 'initFullSizeImg',
|
500
|
+
value: function initFullSizeImg() {
|
501
|
+
this.fullSizeImg = this.placeholderImg.clone();
|
502
|
+
}
|
503
|
+
|
504
|
+
/**
|
505
|
+
* Give the full-size image a temporary set of CSS rules so that it can sit
|
506
|
+
* directly behind the placeholder image while loading.
|
507
|
+
*/
|
508
|
+
|
509
|
+
}, {
|
510
|
+
key: 'setFullSizeImgTempCss',
|
511
|
+
value: function setFullSizeImgTempCss() {
|
512
|
+
this.fullSizeImg.css({
|
513
|
+
position: 'absolute',
|
514
|
+
top: this.placeholderImg.position().top,
|
515
|
+
left: this.placeholderImg.position().left,
|
516
|
+
width: this.placeholderImg.width(),
|
517
|
+
height: this.placeholderImg.height()
|
518
|
+
});
|
519
|
+
}
|
520
|
+
|
521
|
+
/**
|
522
|
+
* Prep the full-size image with the attributes necessary to become its full
|
523
|
+
* size. Right now it is still just a replica of the placeholder, sitting
|
524
|
+
* right behind the placeholder.
|
525
|
+
*
|
526
|
+
* We set the src directly even though we're using imgix.js because older
|
527
|
+
* browsers don't support the srcset attribute which is what imgix.js relies
|
528
|
+
* upon.
|
529
|
+
*/
|
530
|
+
|
531
|
+
}, {
|
532
|
+
key: 'setFullSizeImgSrc',
|
533
|
+
value: function setFullSizeImgSrc() {
|
534
|
+
var newSrc = this.placeholderImg.attr('src').replace(/(\?|\&)(w=)(\d+)/i, '$1$2' + this.placeholderImg.width()).replace(/(\?|\&)(h=)(\d+)/i, '$1$2' + this.placeholderImg.height());
|
535
|
+
this.fullSizeImg.attr('ix-src', newSrc);
|
536
|
+
// TODO: Make this a configurable option or document it as a more semantic temporary class
|
537
|
+
this.fullSizeImg.addClass('img-responsive imgix-optimizing');
|
538
|
+
// TODO: This should respect the option from the Optimizer class for the select
|
539
|
+
this.fullSizeImg.removeAttr('data-optimize-img');
|
540
|
+
}
|
541
|
+
|
542
|
+
/**
|
543
|
+
* Render the full-size image in the DOM.
|
544
|
+
*/
|
545
|
+
|
546
|
+
}, {
|
547
|
+
key: 'addFullSizeImgToDom',
|
548
|
+
value: function addFullSizeImgToDom() {
|
549
|
+
this.fullSizeImg.insertBefore(this.placeholderImg);
|
550
|
+
}
|
551
|
+
|
552
|
+
// ---------------------------------------- | Image Transition
|
553
|
+
|
554
|
+
/**
|
555
|
+
* Once the full-size image is loaded, begin the transition. This is the
|
556
|
+
* critical piece of this process. Imgix.js uses the ix-src attribute to build
|
557
|
+
* out the srcset attribute. Then, based on the sizes attribute, the browser
|
558
|
+
* determines which source to render. Therefore we can't preload in memory
|
559
|
+
* because we need imgix to do its thing directly in the DOM.
|
560
|
+
*/
|
561
|
+
|
562
|
+
}, {
|
563
|
+
key: 'initTransition',
|
564
|
+
value: function initTransition() {
|
565
|
+
var _this = this;
|
566
|
+
|
567
|
+
this.fullSizeImg.on('load', function () {
|
568
|
+
return _this.transitionImg();
|
569
|
+
});
|
570
|
+
imgix.init();
|
571
|
+
}
|
572
|
+
|
573
|
+
/**
|
574
|
+
* Fade out the placeholder image, effectively showing the image behind it.
|
575
|
+
*
|
576
|
+
* Once the fade out transition has completed, remove any temporary properties
|
577
|
+
* from the full-size image (so it gets back to being a clone of the
|
578
|
+
* placeholder, with the full-size src).
|
579
|
+
*
|
580
|
+
* Finally, remove the placeholder image from the DOM since we don't need it
|
581
|
+
* any more.
|
582
|
+
*/
|
583
|
+
|
584
|
+
}, {
|
585
|
+
key: 'transitionImg',
|
586
|
+
value: function transitionImg() {
|
587
|
+
var _this2 = this;
|
588
|
+
|
589
|
+
if (!this.placeholderImg) return true;
|
590
|
+
this.fadeOutPlaceholder();
|
591
|
+
setTimeout(function () {
|
592
|
+
_this2.removeFullSizeImgProperties();
|
593
|
+
_this2.removeImg();
|
594
|
+
}, this.timeToFade);
|
595
|
+
}
|
596
|
+
|
597
|
+
/**
|
598
|
+
* Fade out the placeholder image.
|
599
|
+
*/
|
600
|
+
|
601
|
+
}, {
|
602
|
+
key: 'fadeOutPlaceholder',
|
603
|
+
value: function fadeOutPlaceholder() {
|
604
|
+
this.placeholderImg.fadeTo(this.timeToFade, 0);
|
605
|
+
}
|
606
|
+
|
607
|
+
/**
|
608
|
+
* Remove temporary styles and class from the full-size image, which
|
609
|
+
* effectively means it has replaced the placeholder image.
|
610
|
+
*/
|
611
|
+
|
612
|
+
}, {
|
613
|
+
key: 'removeFullSizeImgProperties',
|
614
|
+
value: function removeFullSizeImgProperties() {
|
615
|
+
this.fullSizeImg.removeAttr('style');
|
616
|
+
// TODO: Update this with how the class is handled above.
|
617
|
+
this.fullSizeImg.removeClass('imgix-optimizing');
|
618
|
+
}
|
619
|
+
|
620
|
+
/**
|
621
|
+
* Remove the placeholder image from the DOM since we no longer need it.
|
622
|
+
*/
|
623
|
+
|
624
|
+
}, {
|
625
|
+
key: 'removeImg',
|
626
|
+
value: function removeImg() {
|
627
|
+
if (!this.placeholderImg) {
|
628
|
+
return;
|
629
|
+
}
|
630
|
+
this.placeholderImg.remove();
|
631
|
+
this.placeholderImg = undefined;
|
632
|
+
}
|
633
|
+
}]);
|
634
|
+
return ImgixImage;
|
635
|
+
}();
|
636
|
+
|
637
|
+
var Optimizer = function () {
|
638
|
+
function Optimizer() {
|
639
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
640
|
+
classCallCheck(this, Optimizer);
|
641
|
+
|
642
|
+
this.initOptions(options);
|
643
|
+
this.optimizeImages();
|
644
|
+
this.optimizeBgImages();
|
645
|
+
}
|
646
|
+
|
647
|
+
// ---------------------------------------- | Options
|
648
|
+
|
649
|
+
createClass(Optimizer, [{
|
650
|
+
key: 'initOptions',
|
651
|
+
value: function initOptions() {
|
652
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
653
|
+
|
654
|
+
this.options = options;
|
655
|
+
var defaultOptions = {
|
656
|
+
parent: 'body'
|
657
|
+
};
|
658
|
+
for (var key in defaultOptions) {
|
659
|
+
if (defaultOptions.hasOwnProperty(key) && !this.options[key]) {
|
660
|
+
this.options[key] = defaultOptions[key];
|
661
|
+
}
|
662
|
+
}
|
663
|
+
}
|
664
|
+
|
665
|
+
// ---------------------------------------- | Inline Images
|
666
|
+
|
667
|
+
}, {
|
668
|
+
key: 'optimizeImages',
|
669
|
+
value: function optimizeImages() {
|
670
|
+
$(this.options.parent + ' img[data-optimize-img]').each(function (idx, img) {
|
671
|
+
new ImgixImage(img);
|
672
|
+
});
|
673
|
+
}
|
674
|
+
|
675
|
+
// ---------------------------------------- | Background Images
|
676
|
+
|
677
|
+
}, {
|
678
|
+
key: 'optimizeBgImages',
|
679
|
+
value: function optimizeBgImages() {
|
680
|
+
$(this.options.parent + ' [data-optimize-bg-img]').each(function (idx, img) {
|
681
|
+
new ImgixBgImage(img);
|
682
|
+
});
|
683
|
+
return true;
|
684
|
+
}
|
685
|
+
}]);
|
686
|
+
return Optimizer;
|
687
|
+
}();
|
688
|
+
|
689
|
+
window['Imgix'] = window['Imgix'] || {};
|
690
|
+
|
691
|
+
Imgix.ImgixBgImage = ImgixBgImage;
|
692
|
+
Imgix.ImgixImage = ImgixImage;
|
693
|
+
Imgix.Optimizer = Optimizer;
|
694
|
+
|
695
|
+
}());
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imgix-optimizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean C Davis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -37,7 +37,7 @@ files:
|
|
37
37
|
- LICENSE
|
38
38
|
- README.md
|
39
39
|
- Rakefile
|
40
|
-
- dist/imgix-optimizer-0.0.
|
40
|
+
- dist/imgix-optimizer-0.0.5.min.js
|
41
41
|
- dist/imgix-optimizer.js
|
42
42
|
- dist/index.html
|
43
43
|
- dist/main.css
|
@@ -56,6 +56,7 @@ files:
|
|
56
56
|
- src/optimizer.js
|
57
57
|
- test/test.js
|
58
58
|
- vendor/assets/javascripts/.keep
|
59
|
+
- vendor/assets/javascripts/imgix-optimizer.js
|
59
60
|
homepage: https://www.ample.co/
|
60
61
|
licenses:
|
61
62
|
- MIT
|
@@ -1 +0,0 @@
|
|
1
|
-
!function(){"use strict";var t=function(e,i){if(!(e instanceof i))throw new TypeError("Cannot call a class as a function")},e=function(){function l(e,i){for(var t=0;t<i.length;t++){var l=i[t];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(e,l.key,l)}}return function(e,i,t){return i&&l(e.prototype,i),t&&l(e,t),e}}(),l=function(){function i(e){t(this,i),this.timeToFade=500,this.dpr=window.devicePixelRatio||1,this.el=$(e),"none"!=this.el.css("background-image")&&(this.initEl(),this.initOptimization(),this.initEventListeners())}return e(i,[{key:"initOptimization",value:function(){var e=this;$("<img>").on("load",function(){return e.renderTmpPlaceholderEl()}).attr("src",this.placeholderImgUrl)}},{key:"initEl",value:function(){this.setPlaceholderImgUrl(),this.setContainerTmpCss(),this.setElTmpCss()}},{key:"setPlaceholderImgUrl",value:function(){this.placeholderImgUrl=this.el.css("background-image").replace("url(","").replace(")","").replace(/\"/gi,"").replace(/\'/gi,"").split(", ")[0]}},{key:"setContainerTmpCss",value:function(){this.el.parent().css("position","relative")}},{key:"setElTmpCss",value:function(){"absolute"!=this.el.css("position")&&this.el.css("position","relative")}},{key:"renderTmpPlaceholderEl",value:function(){this.initTmpPlaceholderEl(),this.setTmpPlaceholderElCss(),this.addTmpPlaceholderElToDom(),this.renderFullSizeImg()}},{key:"initTmpPlaceholderEl",value:function(){this.tmpPlaceholderEl=this.el.clone(),this.tmpPlaceholderEl.html("")}},{key:"setTmpPlaceholderElCss",value:function(){this.tmpPlaceholderEl.addClass("imgix-optimizing"),this.tmpPlaceholderEl.css({position:"absolute",top:this.el.position().top,left:this.el.position().left,width:this.el.outerWidth(),height:this.el.outerHeight(),backgroundColor:"transparent"})}},{key:"addTmpPlaceholderElToDom",value:function(){this.tmpPlaceholderEl.insertBefore(this.el)}},{key:"renderFullSizeImg",value:function(){this.removeElBgImg(),this.initTmpFullSizeEl(),this.setTmpFullSizeElImg(),this.addTmpFullSizeElToDom(),this.initTransition()}},{key:"removeElBgImg",value:function(){this.elBgColor=this.el.css("background-color"),this.el.css("background-color","transparent"),this.el.css("background-image","")}},{key:"initTmpFullSizeEl",value:function(){this.tmpFullSizeEl=this.tmpPlaceholderEl.clone()}},{key:"setFullSizeImgUrl",value:function(){var e=this.placeholderImgUrl.split("?"),i=e[e.length-1].split("&"),t={};for(var l in i.map(function(e){return t[e.split("=")[0]]=e.split("=")[1]}),this.el.outerWidth()>=this.el.outerHeight()?(t.w=this.el.outerWidth()*this.dpr,delete t.h):(t.h=this.el.outerHeight()*this.dpr,delete t.w),i=[],t)i.push(l+"="+t[l]);return this.fullSizeImgUrl=e[0]+"?"+i.join("&")}},{key:"setTmpFullSizeElImg",value:function(){this.setFullSizeImgUrl(),this.tmpFullSizeEl.css("background-image",'url("'+this.fullSizeImgUrl+'")')}},{key:"addTmpFullSizeElToDom",value:function(){this.tmpFullSizeEl.insertBefore(this.tmpPlaceholderEl)}},{key:"initTransition",value:function(){$("<img>").on("load",$.proxy(this.transitionImg,this)).attr("src",this.fullSizeImgUrl)}},{key:"transitionImg",value:function(){var e=this;this.fadeOutTmpPlaceholderEl(),setTimeout(function(){e.updateElImg(),e.replaceElTmpCss(),e.removeTmpEls()},this.timeToFade)}},{key:"fadeOutTmpPlaceholderEl",value:function(){this.tmpPlaceholderEl.fadeTo(this.timeToFade,0)}},{key:"updateElImg",value:function(){this.setFullSizeImgUrl(),this.el.css("background-image","url('"+this.fullSizeImgUrl+"')")}},{key:"replaceElTmpCss",value:function(){this.el.css("background-color",this.elBgColor)}},{key:"removeTmpEls",value:function(){this.tmpPlaceholderEl.remove(),this.tmpFullSizeEl.remove(),this.tmpPlaceholderEl=void 0,this.tmpFullSizeEl=void 0}},{key:"initEventListeners",value:function(){var i=this;this.initResizeEnd(),$(window).on("resizeEnd",function(e){return i.updateElImg()})}},{key:"initResizeEnd",value:function(){$(window).resize(function(){this.resizeTo&&clearTimeout(this.resizeTo),this.resizeTo=setTimeout(function(){$(this).trigger("resizeEnd")},500)})}}]),i}(),s=function(){function i(e){t(this,i),this.timeToFade=500,this.placeholderImg=$(e),this.initPlaceholder(),this.initOptimization()}return e(i,[{key:"initOptimization",value:function(){$("<img>").on("load",$.proxy(this.renderFullSizeImg,this)).attr("src",this.placeholderImg.attr("src"))}},{key:"initPlaceholder",value:function(){this.setPlaceholderCss()}},{key:"setPlaceholderCss",value:function(){"absolute"!=this.placeholderImg.css("position")&&this.placeholderImg.css("position","relative")}},{key:"renderFullSizeImg",value:function(){this.initFullSizeImg(),this.setFullSizeImgTempCss(),this.setFullSizeImgSrc(),this.addFullSizeImgToDom(),this.initTransition()}},{key:"initFullSizeImg",value:function(){this.fullSizeImg=this.placeholderImg.clone()}},{key:"setFullSizeImgTempCss",value:function(){this.fullSizeImg.css({position:"absolute",top:this.placeholderImg.position().top,left:this.placeholderImg.position().left,width:this.placeholderImg.width(),height:this.placeholderImg.height()})}},{key:"setFullSizeImgSrc",value:function(){var e=this.placeholderImg.attr("src").replace(/(\?|\&)(w=)(\d+)/i,"$1$2"+this.placeholderImg.width()).replace(/(\?|\&)(h=)(\d+)/i,"$1$2"+this.placeholderImg.height());this.fullSizeImg.attr("ix-src",e),this.fullSizeImg.addClass("img-responsive imgix-optimizing"),this.fullSizeImg.removeAttr("data-optimize-img")}},{key:"addFullSizeImgToDom",value:function(){this.fullSizeImg.insertBefore(this.placeholderImg)}},{key:"initTransition",value:function(){var e=this;this.fullSizeImg.on("load",function(){return e.transitionImg()}),imgix.init()}},{key:"transitionImg",value:function(){var e=this;if(!this.placeholderImg)return!0;this.fadeOutPlaceholder(),setTimeout(function(){e.removeFullSizeImgProperties(),e.removeImg()},this.timeToFade)}},{key:"fadeOutPlaceholder",value:function(){this.placeholderImg.fadeTo(this.timeToFade,0)}},{key:"removeFullSizeImgProperties",value:function(){this.fullSizeImg.removeAttr("style"),this.fullSizeImg.removeClass("imgix-optimizing")}},{key:"removeImg",value:function(){this.placeholderImg&&(this.placeholderImg.remove(),this.placeholderImg=void 0)}}]),i}(),i=function(){function i(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};t(this,i),this.initOptions(e),this.optimizeImages(),this.optimizeBgImages()}return e(i,[{key:"initOptions",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.options=e;var i={parent:"body"};for(var t in i)i.hasOwnProperty(t)&&!this.options[t]&&(this.options[t]=i[t])}},{key:"optimizeImages",value:function(){$(this.options.parent+" img[data-optimize-img]").each(function(e,i){new s(i)})}},{key:"optimizeBgImages",value:function(){return $(this.options.parent+" [data-optimize-bg-img]").each(function(e,i){new l(i)}),!0}}]),i}();window.Imgix=window.Imgix||{},Imgix.ImgixBgImage=l,Imgix.ImgixImage=s,Imgix.Optimizer=i}();
|