diff --git a/e2e-test/cypress/integration/lazyResponsive.spec.js b/e2e-test/cypress/integration/lazyResponsive.spec.js new file mode 100644 index 0000000..0daf214 --- /dev/null +++ b/e2e-test/cypress/integration/lazyResponsive.spec.js @@ -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'); + }); +}); \ No newline at end of file diff --git a/e2e-test/src/App.js b/e2e-test/src/App.js index 79e3444..e584eef 100644 --- a/e2e-test/src/App.js +++ b/e2e-test/src/App.js @@ -6,7 +6,8 @@ const tests = [ 'responsive', 'placeholder', 'lazy', - 'lazyPlaceholder' + 'lazyPlaceholder', + 'lazyResponsive' ]; function App() { @@ -70,6 +71,18 @@ function App() { } + {test === 'lazyResponsive' && +
+

Lazy Responsive

+
+
+ + +
+
+
+ } ); } diff --git a/src/components/Image/Image.js b/src/components/Image/Image.js index 86d6dd7..80c727b 100644 --- a/src/components/Image/Image.js +++ b/src/components/Image/Image.js @@ -50,7 +50,6 @@ class Image extends CloudinaryComponent { * @return attributes for the underlying element. */ getAttributes = (additionalOptions = {}) => { - const {isInView} = this.state; const {placeholder} = additionalOptions; const options = {...this.getOptions(), ...additionalOptions}; const {nonCloudinaryProps} = extractCloudinaryProps(options); @@ -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; } @@ -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); + } } } @@ -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"); } /**