imgix-optimizer 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.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}();
@@ -1,695 +0,0 @@
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
- }());