imgix-optimizer 0.0.6 → 0.0.7
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 +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
|
}
|