imgix-optimizer 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/dist/imgix-optimizer-0.0.7.min.js +1 -0
- data/dist/imgix-optimizer.js +56 -40
- data/dist/inline-test.html +50 -0
- data/dist/main.css +0 -1
- data/package.json +1 -1
- data/src/image.js +42 -29
- data/vendor/assets/javascripts/imgix-optimizer.js +1583 -0
- metadata +5 -3
- data/dist/imgix-optimizer-0.0.6.min.js +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 003e3c834f09df27d2057b68bc0c63dd599503d513b8e18944596ca7d700e033
|
4
|
+
data.tar.gz: 56d0c88dc28b460a13c362bdcc773f125f1aad805ca9e2301e90adc6560377dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df9b55aaad2f6c893ce732d78d2bead5370c713469ea61d494e29797a819174783318e1b473c60f28b5a419ee8fcaf01791171b9b020ea51c87b34a1f2fcdcdf
|
7
|
+
data.tar.gz: 4c920564345f22588833ad4eaf2c75714397b59e5c19f004f5567e726fced26d8a4fe6413d87163a0f2583bd8e7d6db86f022d2ee31362bfb2515beae7d57c83
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
!function(){"use strict";var i=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},t=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}(),n=function(){function e(t){i(this,e),this.timeToFade=500,this.processingAttr="data-imgix-img-processed",this.placeholderImg=$(t),0<this.placeholderImg.height()?this.init():this.placeholderImg.on("load",$.proxy(this.init,this))}return t(e,[{key:"init",value:function(){this.initPlaceholder(),this.initOptimization()}},{key:"initOptimization",value:function(){$("<img>").on("load",$.proxy(this.listenForIntersection,this)).attr("src",this.placeholderImg.attr("src"))}},{key:"listenForIntersection",value:function(){new IntersectionObserver($.proxy(this.onIntersection,this)).observe(this.placeholderImg[0])}},{key:"onIntersection",value:function(t,e){var i=$(t[0].target);t[0].isIntersecting&&!$(i).attr(this.processingAttr)&&(i.attr(this.processingAttr,!0),this.renderFullSizeImg())}},{key:"initPlaceholder",value:function(){this.wrapPlaceholder(),this.setPlaceholderCss()}},{key:"wrapPlaceholder",value:function(){this.tmpWrapper=$("<div>").css({position:"relative",height:this.placeholderImg[0].getBoundingClientRect().height,width:this.placeholderImg[0].getBoundingClientRect().width,margin:this.placeholderImg.css("margin")}),this.placeholderImg.wrap(this.tmpWrapper)}},{key:"setPlaceholderCss",value:function(){"absolute"!=this.placeholderImg.css("position")&&this.placeholderImg.css("position","relative"),this.placeholderImg.css({margin:0})}},{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:"100%",height:"100%"})}},{key:"getPlaceholderImgRect",value:function(){return{width:this.placeholderImg[0].getBoundingClientRect().width,height:this.placeholderImg[0].getBoundingClientRect().height}}},{key:"setFullSizeImgSrc",value:function(){var t=this.placeholderImg.attr("src").replace(/(\?|\&)(w=)(\d+)/i,"$1$2"+this.getPlaceholderImgRect().width).replace(/(\?|\&)(h=)(\d+)/i,"$1$2"+this.getPlaceholderImgRect().height);t.search(/(\?|\&)(h=)(\d+)/i)<0&&(t=t+"&h="+this.getPlaceholderImgRect().height+"&fit=crop"),this.fullSizeImg.attr("ix-src",t),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 t=this;this.fullSizeImg.on("load",function(){return t.transitionImg()}),imgix.init()}},{key:"transitionImg",value:function(){var t=this;if(!this.placeholderImg)return!0;this.fadeOutPlaceholder(),setTimeout(function(){t.removeFullSizeImgProperties(),t.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)}},{key:"unwrapImg",value:function(){this.fullSizeImg.css("margin",this.tmpWrapper.css("margin")).unwrap()}}]),e}(),o=function(){function e(t){i(this,e),this.timeToFade=500,this.processingAttr="data-imgix-bg-processed",this.dpr=window.devicePixelRatio||1,this.largestImageWidth=0,this.el=$(t),"none"!=this.el.css("background-image")&&(this.initEl(),this.initOptimization(),this.initEventListeners())}return t(e,[{key:"initOptimization",value:function(){$("<img>").on("load",$.proxy(this.listenForIntersection,this)).attr("src",this.placeholderImgUrl)}},{key:"listenForIntersection",value:function(){new IntersectionObserver($.proxy(this.onIntersection,this)).observe(this.el[0])}},{key:"onIntersection",value:function(t,e){var i=$(t[0].target);t[0].isIntersecting&&!$(i).attr(this.processingAttr)&&($(i).attr(this.processingAttr,!0),this.renderTmpPlaceholderEl())}},{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(){if(!(this.fullSizeImgUrl&&this.el.outerWidth()*this.dpr<=this.largestImageWidth)){this.largestImageWidth=this.el.outerWidth()*this.dpr;var t=this.placeholderImgUrl.split("?"),e=t[t.length-1].split("&"),i={};for(var n in e.map(function(t){return i[t.split("=")[0]]=t.split("=")[1]}),this.el.outerWidth()>=this.el.outerHeight()?(i.w=this.largestImageWidth,delete i.h):(i.h=this.el.outerHeight()*this.dpr,delete i.w),e=[],i)e.push(n+"="+i[n]);return this.fullSizeImgUrl=t[0]+"?"+e.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 t=this;this.fadeOutTmpPlaceholderEl(),setTimeout(function(){t.updateElImg(),t.replaceElTmpCss(),t.replaceContainerTmpCss(),t.removeTmpEls()},this.timeToFade)}},{key:"fadeOutTmpPlaceholderEl",value:function(){this.tmpPlaceholderEl.fadeTo(this.timeToFade,0)}},{key:"updateElImg",value:function(){var e=this;this.setFullSizeImgUrl(),$("<img>").on("load",function(t){return e.el.css("background-image","url('"+e.fullSizeImgUrl+"')")}).attr("src",this.placeholderImgUrl)}},{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 e=this;this.initResizeEnd(),$(window).on("resizeEnd",function(t){return e.updateElImg()})}},{key:"initResizeEnd",value:function(){$(window).resize(function(){this.resizeTo&&clearTimeout(this.resizeTo),this.resizeTo=setTimeout(function(){$(this).trigger("resizeEnd")},500)})}}]),e}();!function(d,f){function a(t){this.time=t.time,this.target=t.target,this.rootBounds=t.rootBounds,this.boundingClientRect=t.boundingClientRect,this.intersectionRect=t.intersectionRect||{top:0,bottom:0,left:0,right:0,width:0,height:0},this.isIntersecting=!!t.intersectionRect;var e=this.boundingClientRect,i=e.width*e.height,n=this.intersectionRect,o=n.width*n.height;this.intersectionRatio=i?Number((o/i).toFixed(4)):this.isIntersecting?1:0}function t(t,e){var i,n,o,r=e||{};if("function"!=typeof t)throw new Error("callback must be a function");if(r.root&&1!=r.root.nodeType)throw new Error("root must be an Element");this._checkForIntersections=(i=this._checkForIntersections.bind(this),n=this.THROTTLE_TIMEOUT,o=null,function(){o||(o=setTimeout(function(){i(),o=null},n))}),this._callback=t,this._observationTargets=[],this._queuedEntries=[],this._rootMarginValues=this._parseRootMargin(r.rootMargin),this.thresholds=this._initThresholds(r.threshold),this.root=r.root||null,this.rootMargin=this._rootMarginValues.map(function(t){return t.value+t.unit}).join(" ")}function e(t,e,i,n){"function"==typeof t.addEventListener?t.addEventListener(e,i,n||!1):"function"==typeof t.attachEvent&&t.attachEvent("on"+e,i)}function i(t,e,i,n){"function"==typeof t.removeEventListener?t.removeEventListener(e,i,n||!1):"function"==typeof t.detatchEvent&&t.detatchEvent("on"+e,i)}function v(t){var e;try{e=t.getBoundingClientRect()}catch(t){}return e?(e.width&&e.height||(e={top:e.top,right:e.right,bottom:e.bottom,left:e.left,width:e.right-e.left,height:e.bottom-e.top}),e):{top:0,bottom:0,left:0,right:0,width:0,height:0}}function n(t,e){for(var i=e;i;){if(i==t)return!0;i=I(i)}return!1}function I(t){var e=t.parentNode;return e&&11==e.nodeType&&e.host?e.host:e}"IntersectionObserver"in d&&"IntersectionObserverEntry"in d&&"intersectionRatio"in d.IntersectionObserverEntry.prototype?"isIntersecting"in d.IntersectionObserverEntry.prototype||Object.defineProperty(d.IntersectionObserverEntry.prototype,"isIntersecting",{get:function(){return 0<this.intersectionRatio}}):(t.prototype.THROTTLE_TIMEOUT=100,t.prototype.POLL_INTERVAL=null,t.prototype.USE_MUTATION_OBSERVER=!0,t.prototype.observe=function(e){if(!this._observationTargets.some(function(t){return t.element==e})){if(!e||1!=e.nodeType)throw new Error("target must be an Element");this._registerInstance(),this._observationTargets.push({element:e,entry:null}),this._monitorIntersections(),this._checkForIntersections()}},t.prototype.unobserve=function(e){this._observationTargets=this._observationTargets.filter(function(t){return t.element!=e}),this._observationTargets.length||(this._unmonitorIntersections(),this._unregisterInstance())},t.prototype.disconnect=function(){this._observationTargets=[],this._unmonitorIntersections(),this._unregisterInstance()},t.prototype.takeRecords=function(){var t=this._queuedEntries.slice();return this._queuedEntries=[],t},t.prototype._initThresholds=function(t){var e=t||[0];return Array.isArray(e)||(e=[e]),e.sort().filter(function(t,e,i){if("number"!=typeof t||isNaN(t)||t<0||1<t)throw new Error("threshold must be a number between 0 and 1 inclusively");return t!==i[e-1]})},t.prototype._parseRootMargin=function(t){var e=(t||"0px").split(/\s+/).map(function(t){var e=/^(-?\d*\.?\d+)(px|%)$/.exec(t);if(!e)throw new Error("rootMargin must be specified in pixels or percent");return{value:parseFloat(e[1]),unit:e[2]}});return e[1]=e[1]||e[0],e[2]=e[2]||e[0],e[3]=e[3]||e[1],e},t.prototype._monitorIntersections=function(){this._monitoringIntersections||(this._monitoringIntersections=!0,this.POLL_INTERVAL?this._monitoringInterval=setInterval(this._checkForIntersections,this.POLL_INTERVAL):(e(d,"resize",this._checkForIntersections,!0),e(f,"scroll",this._checkForIntersections,!0),this.USE_MUTATION_OBSERVER&&"MutationObserver"in d&&(this._domObserver=new MutationObserver(this._checkForIntersections),this._domObserver.observe(f,{attributes:!0,childList:!0,characterData:!0,subtree:!0}))))},t.prototype._unmonitorIntersections=function(){this._monitoringIntersections&&(this._monitoringIntersections=!1,clearInterval(this._monitoringInterval),this._monitoringInterval=null,i(d,"resize",this._checkForIntersections,!0),i(f,"scroll",this._checkForIntersections,!0),this._domObserver&&(this._domObserver.disconnect(),this._domObserver=null))},t.prototype._checkForIntersections=function(){var l=this._rootIsInDom(),h=l?this._getRootRect():{top:0,bottom:0,left:0,right:0,width:0,height:0};this._observationTargets.forEach(function(t){var e=t.element,i=v(e),n=this._rootContainsTarget(e),o=t.entry,r=l&&n&&this._computeTargetAndRootIntersection(e,h),s=t.entry=new a({time:d.performance&&performance.now&&performance.now(),target:e,boundingClientRect:i,rootBounds:h,intersectionRect:r});o?l&&n?this._hasCrossedThreshold(o,s)&&this._queuedEntries.push(s):o&&o.isIntersecting&&this._queuedEntries.push(s):this._queuedEntries.push(s)},this),this._queuedEntries.length&&this._callback(this.takeRecords(),this)},t.prototype._computeTargetAndRootIntersection=function(t,e){if("none"!=d.getComputedStyle(t).display){for(var i,n,o,r,s,l,h,a,c=v(t),u=I(t),p=!1;!p;){var m=null,g=1==u.nodeType?d.getComputedStyle(u):{};if("none"==g.display)return;if(u==this.root||u==f?(p=!0,m=e):u!=f.body&&u!=f.documentElement&&"visible"!=g.overflow&&(m=v(u)),m&&(i=m,n=c,void 0,o=Math.max(i.top,n.top),r=Math.min(i.bottom,n.bottom),s=Math.max(i.left,n.left),l=Math.min(i.right,n.right),a=r-o,!(c=0<=(h=l-s)&&0<=a&&{top:o,bottom:r,left:s,right:l,width:h,height:a})))break;u=I(u)}return c}},t.prototype._getRootRect=function(){var t;if(this.root)t=v(this.root);else{var e=f.documentElement,i=f.body;t={top:0,left:0,right:e.clientWidth||i.clientWidth,width:e.clientWidth||i.clientWidth,bottom:e.clientHeight||i.clientHeight,height:e.clientHeight||i.clientHeight}}return this._expandRectByRootMargin(t)},t.prototype._expandRectByRootMargin=function(i){var t=this._rootMarginValues.map(function(t,e){return"px"==t.unit?t.value:t.value*(e%2?i.width:i.height)/100}),e={top:i.top-t[0],right:i.right+t[1],bottom:i.bottom+t[2],left:i.left-t[3]};return e.width=e.right-e.left,e.height=e.bottom-e.top,e},t.prototype._hasCrossedThreshold=function(t,e){var i=t&&t.isIntersecting?t.intersectionRatio||0:-1,n=e.isIntersecting?e.intersectionRatio||0:-1;if(i!==n)for(var o=0;o<this.thresholds.length;o++){var r=this.thresholds[o];if(r==i||r==n||r<i!=r<n)return!0}},t.prototype._rootIsInDom=function(){return!this.root||n(f,this.root)},t.prototype._rootContainsTarget=function(t){return n(this.root||f,t)},t.prototype._registerInstance=function(){},t.prototype._unregisterInstance=function(){},d.IntersectionObserver=t,d.IntersectionObserverEntry=a)}(window,document),"function"!=typeof Object.assign&&Object.defineProperty(Object,"assign",{value:function(t,e){if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var i=Object(t),n=1;n<arguments.length;n++){var o=arguments[n];if(null!=o)for(var r in o)Object.prototype.hasOwnProperty.call(o,r)&&(i[r]=o[r])}return i},writable:!0,configurable:!0});var e=function(){function e(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};i(this,e),this.initDependencies(),this.initOptions(t),this.optimizeImages(),this.optimizeBgImages()}return t(e,[{key:"initDependencies",value:function(){}},{key:"initOptions",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.options=t;var e={parent:"body"};for(var i in e)e.hasOwnProperty(i)&&!this.options[i]&&(this.options[i]=e[i])}},{key:"optimizeImages",value:function(){$(this.options.parent+" img[data-optimize-img]").each(function(t,e){new n(e)})}},{key:"optimizeBgImages",value:function(){return $(this.options.parent+" [data-optimize-bg-img]").each(function(t,e){new o(e)}),!0}}]),e}();window.Imgix=window.Imgix||{},Imgix.Optimizer=e}();
|
data/dist/imgix-optimizer.js
CHANGED
@@ -35,25 +35,40 @@
|
|
35
35
|
this.processingAttr = 'data-imgix-img-processed';
|
36
36
|
// The main image (pixelated placeholder).
|
37
37
|
this.placeholderImg = $(img);
|
38
|
-
//
|
39
|
-
this.
|
40
|
-
|
41
|
-
|
38
|
+
// Wait for the image to load prior to kicking off the optimization process.
|
39
|
+
if (this.placeholderImg.height() > 0) {
|
40
|
+
this.init();
|
41
|
+
} else {
|
42
|
+
this.placeholderImg.on('load', $.proxy(this.init, this));
|
43
|
+
}
|
42
44
|
}
|
43
45
|
|
44
46
|
/**
|
45
|
-
*
|
46
|
-
* placeholder image. Once that has completed, we know we're safe to begin
|
47
|
-
* listening for the image to intersect the viewport.
|
47
|
+
* Configure the main placeholder image and kick off the optimization process.
|
48
48
|
*/
|
49
49
|
|
50
50
|
|
51
51
|
createClass(Image, [{
|
52
|
+
key: 'init',
|
53
|
+
value: function init() {
|
54
|
+
this.initPlaceholder();
|
55
|
+
this.initOptimization();
|
56
|
+
}
|
57
|
+
|
58
|
+
/**
|
59
|
+
* Load an image in memory (not within the DOM) with the same source as the
|
60
|
+
* placeholder image. Once that has completed, we know we're safe to begin
|
61
|
+
* listening for the image to intersect the viewport.
|
62
|
+
*/
|
63
|
+
|
64
|
+
}, {
|
52
65
|
key: 'initOptimization',
|
53
66
|
value: function initOptimization() {
|
54
67
|
$('<img>').on('load', $.proxy(this.listenForIntersection, this)).attr('src', this.placeholderImg.attr('src'));
|
55
68
|
}
|
56
69
|
|
70
|
+
// ---------------------------------------- | Lazy Loading Control
|
71
|
+
|
57
72
|
/**
|
58
73
|
* When the placeholder image intersects the viewport, begin processing.
|
59
74
|
* (IntersectionObserver and Object.assign() are not supported by IE, but the
|
@@ -91,14 +106,34 @@
|
|
91
106
|
}, {
|
92
107
|
key: 'initPlaceholder',
|
93
108
|
value: function initPlaceholder() {
|
109
|
+
this.wrapPlaceholder();
|
94
110
|
this.setPlaceholderCss();
|
95
|
-
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* Wrap the placeholder image in a <div>. This enables better control over the
|
115
|
+
* wrapping element and provides a more fluid transition process.
|
116
|
+
*/
|
117
|
+
|
118
|
+
}, {
|
119
|
+
key: 'wrapPlaceholder',
|
120
|
+
value: function wrapPlaceholder() {
|
121
|
+
this.tmpWrapper = $('<div>').css({
|
122
|
+
position: 'relative',
|
123
|
+
height: this.placeholderImg[0].getBoundingClientRect().height,
|
124
|
+
width: this.placeholderImg[0].getBoundingClientRect().width,
|
125
|
+
margin: this.placeholderImg.css('margin')
|
126
|
+
});
|
127
|
+
this.placeholderImg.wrap(this.tmpWrapper);
|
96
128
|
}
|
97
129
|
|
98
130
|
/**
|
99
131
|
* The main image must have a position set for it to remain in front of the
|
100
132
|
* full-size image. We assume that if the element is not explicitly positioned
|
101
133
|
* absolutely, then it can safely be positioned relatively.
|
134
|
+
*
|
135
|
+
* And temporarily remove any margin from the image, as the box model gets
|
136
|
+
* delegated to the temporary wrapper during the transition period.
|
102
137
|
*/
|
103
138
|
|
104
139
|
}, {
|
@@ -107,24 +142,7 @@
|
|
107
142
|
if (this.placeholderImg.css('position') != 'absolute') {
|
108
143
|
this.placeholderImg.css('position', 'relative');
|
109
144
|
}
|
110
|
-
|
111
|
-
|
112
|
-
/**
|
113
|
-
* The parent of the image container should be relatively positioned
|
114
|
-
* (temporarily) so temp image can be absolutely positioned.
|
115
|
-
*/
|
116
|
-
|
117
|
-
}, {
|
118
|
-
key: 'setPlaceholderParentTmpCss',
|
119
|
-
value: function setPlaceholderParentTmpCss() {
|
120
|
-
this.parentStyles = {
|
121
|
-
display: this.placeholderImg.parent().css('display'),
|
122
|
-
position: this.placeholderImg.parent().css('position')
|
123
|
-
};
|
124
|
-
this.placeholderImg.parent().css({
|
125
|
-
display: 'block',
|
126
|
-
position: 'relative'
|
127
|
-
});
|
145
|
+
this.placeholderImg.css({ margin: 0 });
|
128
146
|
}
|
129
147
|
|
130
148
|
// ---------------------------------------- | Full-Size Image
|
@@ -263,8 +281,9 @@
|
|
263
281
|
this.fadeOutPlaceholder();
|
264
282
|
setTimeout(function () {
|
265
283
|
_this2.removeFullSizeImgProperties();
|
266
|
-
_this2.replacePlaceholderParentTmpCss();
|
267
284
|
_this2.removeImg();
|
285
|
+
// this.unwrapImg();
|
286
|
+
// 215 x 161.3 // 215 x 161 // 216.66 x 163
|
268
287
|
}, this.timeToFade);
|
269
288
|
}
|
270
289
|
|
@@ -291,19 +310,6 @@
|
|
291
310
|
this.fullSizeImg.removeClass('imgix-optimizing');
|
292
311
|
}
|
293
312
|
|
294
|
-
/**
|
295
|
-
* Reset the container's adjusted CSS properties.
|
296
|
-
*/
|
297
|
-
|
298
|
-
}, {
|
299
|
-
key: 'replacePlaceholderParentTmpCss',
|
300
|
-
value: function replacePlaceholderParentTmpCss() {
|
301
|
-
this.placeholderImg.parent().css({
|
302
|
-
display: this.parentStyles.display,
|
303
|
-
position: this.parentStyles.position
|
304
|
-
});
|
305
|
-
}
|
306
|
-
|
307
313
|
/**
|
308
314
|
* Remove the placeholder image from the DOM since we no longer need it.
|
309
315
|
*/
|
@@ -317,6 +323,16 @@
|
|
317
323
|
this.placeholderImg.remove();
|
318
324
|
this.placeholderImg = undefined;
|
319
325
|
}
|
326
|
+
|
327
|
+
/**
|
328
|
+
* Remove the temporary wrapper and and give the margin back to the image.
|
329
|
+
*/
|
330
|
+
|
331
|
+
}, {
|
332
|
+
key: 'unwrapImg',
|
333
|
+
value: function unwrapImg() {
|
334
|
+
this.fullSizeImg.css('margin', this.tmpWrapper.css('margin')).unwrap();
|
335
|
+
}
|
320
336
|
}]);
|
321
337
|
return Image;
|
322
338
|
}();
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
3
|
+
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
4
|
+
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
|
5
|
+
<!--[if gt IE 8]><!-->
|
6
|
+
<html class="no-js">
|
7
|
+
<!--<![endif]-->
|
8
|
+
<head>
|
9
|
+
<meta charset="utf-8" />
|
10
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
11
|
+
<title>Inline Test</title>
|
12
|
+
<meta name="description" content="" />
|
13
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
14
|
+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" />
|
15
|
+
<style>
|
16
|
+
.inline-img {
|
17
|
+
width: 250px;
|
18
|
+
margin: 30px;
|
19
|
+
}
|
20
|
+
</style>
|
21
|
+
|
22
|
+
<script
|
23
|
+
src="https://code.jquery.com/jquery-2.2.4.js"
|
24
|
+
integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI="
|
25
|
+
crossorigin="anonymous"
|
26
|
+
></script>
|
27
|
+
<script src="https://rawgit.com/imgix/imgix.js/master/dist/imgix.min.js"></script>
|
28
|
+
<script src="imgix-optimizer.js"></script>
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div class="container">
|
32
|
+
<img
|
33
|
+
class="inline-img"
|
34
|
+
src="https://images.unsplash.com/photo-1513791222152-c347a9d6c3dd?auto=format,compress&w=12&h=9&fit=crop"
|
35
|
+
data-optimize-img
|
36
|
+
/>
|
37
|
+
<img
|
38
|
+
class="inline-img"
|
39
|
+
src="https://images.unsplash.com/photo-1472457897821-70d3819a0e24?auto=format,compress&w=10&h=10&fit=crop"
|
40
|
+
data-optimize-img
|
41
|
+
/>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<script>
|
45
|
+
(function() {
|
46
|
+
new Imgix.Optimizer();
|
47
|
+
})();
|
48
|
+
</script>
|
49
|
+
</body>
|
50
|
+
</html>
|
data/dist/main.css
CHANGED
data/package.json
CHANGED
data/src/image.js
CHANGED
@@ -6,9 +6,19 @@ export default class Image {
|
|
6
6
|
this.processingAttr = 'data-imgix-img-processed';
|
7
7
|
// The main image (pixelated placeholder).
|
8
8
|
this.placeholderImg = $(img);
|
9
|
-
//
|
9
|
+
// Wait for the image to load prior to kicking off the optimization process.
|
10
|
+
if (this.placeholderImg.height() > 0) {
|
11
|
+
this.init();
|
12
|
+
} else {
|
13
|
+
this.placeholderImg.on('load', $.proxy(this.init, this));
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Configure the main placeholder image and kick off the optimization process.
|
19
|
+
*/
|
20
|
+
init() {
|
10
21
|
this.initPlaceholder();
|
11
|
-
// Kick off the optimization process.
|
12
22
|
this.initOptimization();
|
13
23
|
}
|
14
24
|
|
@@ -23,6 +33,8 @@ export default class Image {
|
|
23
33
|
.attr('src', this.placeholderImg.attr('src'));
|
24
34
|
}
|
25
35
|
|
36
|
+
// ---------------------------------------- | Lazy Loading Control
|
37
|
+
|
26
38
|
/**
|
27
39
|
* When the placeholder image intersects the viewport, begin processing.
|
28
40
|
* (IntersectionObserver and Object.assign() are not supported by IE, but the
|
@@ -51,34 +63,37 @@ export default class Image {
|
|
51
63
|
* Make necessary CSS adjustments to main placeholder image.
|
52
64
|
*/
|
53
65
|
initPlaceholder() {
|
66
|
+
this.wrapPlaceholder();
|
54
67
|
this.setPlaceholderCss();
|
55
|
-
|
68
|
+
}
|
69
|
+
|
70
|
+
/**
|
71
|
+
* Wrap the placeholder image in a <div>. This enables better control over the
|
72
|
+
* wrapping element and provides a more fluid transition process.
|
73
|
+
*/
|
74
|
+
wrapPlaceholder() {
|
75
|
+
this.tmpWrapper = $('<div>').css({
|
76
|
+
position: 'relative',
|
77
|
+
height: this.placeholderImg[0].getBoundingClientRect().height,
|
78
|
+
width: this.placeholderImg[0].getBoundingClientRect().width,
|
79
|
+
margin: this.placeholderImg.css('margin')
|
80
|
+
});
|
81
|
+
this.placeholderImg.wrap(this.tmpWrapper);
|
56
82
|
}
|
57
83
|
|
58
84
|
/**
|
59
85
|
* The main image must have a position set for it to remain in front of the
|
60
86
|
* full-size image. We assume that if the element is not explicitly positioned
|
61
87
|
* absolutely, then it can safely be positioned relatively.
|
88
|
+
*
|
89
|
+
* And temporarily remove any margin from the image, as the box model gets
|
90
|
+
* delegated to the temporary wrapper during the transition period.
|
62
91
|
*/
|
63
92
|
setPlaceholderCss() {
|
64
93
|
if (this.placeholderImg.css('position') != 'absolute') {
|
65
94
|
this.placeholderImg.css('position', 'relative');
|
66
95
|
}
|
67
|
-
|
68
|
-
|
69
|
-
/**
|
70
|
-
* The parent of the image container should be relatively positioned
|
71
|
-
* (temporarily) so temp image can be absolutely positioned.
|
72
|
-
*/
|
73
|
-
setPlaceholderParentTmpCss() {
|
74
|
-
this.parentStyles = {
|
75
|
-
display: this.placeholderImg.parent().css('display'),
|
76
|
-
position: this.placeholderImg.parent().css('position')
|
77
|
-
};
|
78
|
-
this.placeholderImg.parent().css({
|
79
|
-
display: 'block',
|
80
|
-
position: 'relative'
|
81
|
-
});
|
96
|
+
this.placeholderImg.css({ margin: 0 });
|
82
97
|
}
|
83
98
|
|
84
99
|
// ---------------------------------------- | Full-Size Image
|
@@ -190,8 +205,9 @@ export default class Image {
|
|
190
205
|
this.fadeOutPlaceholder();
|
191
206
|
setTimeout(() => {
|
192
207
|
this.removeFullSizeImgProperties();
|
193
|
-
this.replacePlaceholderParentTmpCss();
|
194
208
|
this.removeImg();
|
209
|
+
// this.unwrapImg();
|
210
|
+
// 215 x 161.3 // 215 x 161 // 216.66 x 163
|
195
211
|
}, this.timeToFade);
|
196
212
|
}
|
197
213
|
|
@@ -212,16 +228,6 @@ export default class Image {
|
|
212
228
|
this.fullSizeImg.removeClass('imgix-optimizing');
|
213
229
|
}
|
214
230
|
|
215
|
-
/**
|
216
|
-
* Reset the container's adjusted CSS properties.
|
217
|
-
*/
|
218
|
-
replacePlaceholderParentTmpCss() {
|
219
|
-
this.placeholderImg.parent().css({
|
220
|
-
display: this.parentStyles.display,
|
221
|
-
position: this.parentStyles.position
|
222
|
-
});
|
223
|
-
}
|
224
|
-
|
225
231
|
/**
|
226
232
|
* Remove the placeholder image from the DOM since we no longer need it.
|
227
233
|
*/
|
@@ -232,4 +238,11 @@ export default class Image {
|
|
232
238
|
this.placeholderImg.remove();
|
233
239
|
this.placeholderImg = undefined;
|
234
240
|
}
|
241
|
+
|
242
|
+
/**
|
243
|
+
* Remove the temporary wrapper and and give the margin back to the image.
|
244
|
+
*/
|
245
|
+
unwrapImg() {
|
246
|
+
this.fullSizeImg.css('margin', this.tmpWrapper.css('margin')).unwrap();
|
247
|
+
}
|
235
248
|
}
|