imgix-optimizer 0.0.3 → 0.0.4

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