imgix-optimizer 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- }());