Skip to content

Commit

Permalink
Fix lazy loading of responsive images (#182)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nir Maoz authored Jul 26, 2020
1 parent d4b83c4 commit c5b4bbd
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 13 deletions.
18 changes: 18 additions & 0 deletions e2e-test/cypress/integration/lazyResponsive.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
describe('Lazy Responsive Image', () => {
beforeEach(() => {
// runs before each test in the block
cy.visit('/');
cy.get('#lazyResponsiveBtn').click(); // Click on button
});
it('Should not have src attribute when not in view', () => {
cy.get('#lazyResponsive')
.should('not.be.visible')
.should('not.have.attr', 'src');
});
it('Should have src attribute when view', () => {
cy.scrollTo(0, 3000);
cy.get('#lazyResponsive')
.should('be.visible')
.should('have.attr', 'src').should('equal', 'http://res.cloudinary.com/demo/image/upload/c_scale,w_400/sample');
});
});
15 changes: 14 additions & 1 deletion e2e-test/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const tests = [
'responsive',
'placeholder',
'lazy',
'lazyPlaceholder'
'lazyPlaceholder',
'lazyResponsive'
];

function App() {
Expand Down Expand Up @@ -70,6 +71,18 @@ function App() {
</div>
</div>
}
{test === 'lazyResponsive' &&
<div>
<h1>Lazy Responsive</h1>
<div style={{marginTop: '3000px'}}>
<div style={{width: "330px"}}>
<Image id="lazyResponsive" publicId="sample" cloudName="demo" width="auto" crop="scale" loading="lazy"
responsive>
</Image>
</div>
</div>
</div>
}
</Fragment>
);
}
Expand Down
26 changes: 14 additions & 12 deletions src/components/Image/Image.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class Image extends CloudinaryComponent {
* @return attributes for the underlying <img> element.
*/
getAttributes = (additionalOptions = {}) => {
const {isInView} = this.state;
const {placeholder} = additionalOptions;
const options = {...this.getOptions(), ...additionalOptions};
const {nonCloudinaryProps} = extractCloudinaryProps(options);
Expand All @@ -69,7 +68,7 @@ class Image extends CloudinaryComponent {
}

// Set data-src if lazy loading and not in view
if (!isInView && this.shouldLazyLoad(options)) {
if (this.shouldLazyLoad()) {
attributes['data-src'] = attributes.dataSrc || attributes.src;
delete attributes.src;
}
Expand All @@ -86,15 +85,16 @@ class Image extends CloudinaryComponent {
* Update this image using cloudinary-core
*/
update = () => {
const {isInView} = this.state;

if (this.isResponsive()) {
const removeListener = makeElementResponsive(this.imgElement.current, this.getOptions());
this.listenerRemovers.push(removeListener);
}

if (!isInView && this.shouldLazyLoad(this.getExtendedProps())) {
// Handle lazy loading
if (this.shouldLazyLoad()) {
// Will set this.state.isInView = true when in view
Util.detectIntersection(this.imgElement.current, this.onIntersect);
} else {
// Handle responsive only if lazy loading wasn't requested or already handled
if (this.isResponsive()) {
const removeListener = makeElementResponsive(this.imgElement.current, this.getOptions());
this.listenerRemovers.push(removeListener);
}
}
}

Expand All @@ -115,8 +115,10 @@ class Image extends CloudinaryComponent {
}
};

shouldLazyLoad = ({loading}) => {
return loading === "lazy" || loading === "auto";
shouldLazyLoad = () => {
const {loading} = this.getExtendedProps();
const {isInView} = this.state;
return !isInView && (loading === "lazy" || loading === "auto");
}

/**
Expand Down

0 comments on commit c5b4bbd

Please sign in to comment.