Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions e2e-test/cypress/integration/placeholder.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ describe('Placeholder Image', () => {
cy.visit('/');
cy.get('#placeholderBtn').click();
});

/**
* Cypress seems to be not fast enough to catch the placeholder render.
* So we test that the placeholder is rendered in out Unit Tests,
* So we test that the placeholder is rendered in our Unit Tests,
* And here we make sure that eventually we render the original image.
*/
it('Show original image', () => {
Expand Down
19 changes: 19 additions & 0 deletions e2e-test/cypress/integration/responsivePlaceholder.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
describe('Responsive Placeholder Image', () => {
beforeEach(() => {
// runs before each test in the block
cy.visit('/');
cy.get('#responsivePlaceholderBtn').click();
});

/**
* Cypress seems to be not fast enough to catch the placeholder render.
* So we test that the placeholder is rendered in our Unit Tests,
* And here we make sure that eventually we render the responsive image.
* The image width was updated to be w_400.
*/
it('Show original image', () => {
cy.get('#responsivePlaceholder')
.should('be.visible')
.should('have.attr', 'src').should('equal', 'http://res.cloudinary.com/demo/image/upload/c_scale,w_400/sample')
});
});
14 changes: 13 additions & 1 deletion e2e-test/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const tests = [
'placeholder',
'lazy',
'lazyPlaceholder',
'lazyResponsive'
'lazyResponsive',
'responsivePlaceholder'
];

function App() {
Expand Down Expand Up @@ -83,6 +84,17 @@ function App() {
</div>
</div>
}
}
{test === 'responsivePlaceholder' &&
<div>
<h1>Responsive Placeholder</h1>
<div style={{width: "330px"}}>
<Image id="responsivePlaceholder" publicId="sample" cloudName="demo" width="auto" crop="scale" responsive>
<Placeholder/>
</Image>
</div>
</div>
}
</Fragment>
);
}
Expand Down
30 changes: 24 additions & 6 deletions src/components/Image/Image.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Image extends CloudinaryComponent {
constructor(props, context) {
super(props, context);
this.imgElement = createRef();
this.placeholderElement = createRef();
this.state = {isLoaded: false}
this.listenerRemovers = [];
}
Expand Down Expand Up @@ -96,8 +97,18 @@ class Image extends CloudinaryComponent {
} 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);
const options = this.getOptions();
const placeholder = this.getPlaceholderType();

// Make placeholder responsive
if (placeholder) {
const removePlaceholderListener = makeElementResponsive(this.placeholderElement.current, {...options, placeholder});
this.listenerRemovers.push(removePlaceholderListener);
}

// Make original image responsive
const removeImgListener = makeElementResponsive(this.imgElement.current, options);
this.listenerRemovers.push(removeImgListener);
}
}
}
Expand Down Expand Up @@ -158,17 +169,18 @@ class Image extends CloudinaryComponent {
});
};


renderPlaceholder = (placeholder, attributes) => {
attributes.style = {...(attributes.style || {}), opacity: 0, position: 'absolute'}
attributes.onLoad = this.handleImageLoaded;
const placeholderWrapperStyle = {display: 'inline'}
const placeholderAttributes = this.getAttributes({placeholder: placeholder.props.type});
const placeholderAttributes = this.getAttributes({placeholder});

return (
<Fragment>
{this.renderImage(attributes)}
<div style={placeholderWrapperStyle}>
<img {...placeholderAttributes}/>
<img ref={this.placeholderElement} {...placeholderAttributes}/>
</div>
</Fragment>
);
Expand All @@ -178,11 +190,17 @@ class Image extends CloudinaryComponent {
return <img ref={this.attachRef} {...attributes}/>
}

render() {
const {isLoaded} = this.state;
getPlaceholderType = () => {
const {children} = this.getExtendedProps();
const placeholder = this.getChildPlaceholder(children);

return placeholder ? placeholder.props.type : null;
}

render() {
const {isLoaded} = this.state;
const attributes = this.getAttributes();
const placeholder = this.getPlaceholderType();

//If image wasn't loaded and there's a child placeholder then we render it.
if (!isLoaded && placeholder) {
Expand Down
15 changes: 15 additions & 0 deletions test/ImageTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,21 @@ describe('Image', () => {
].join(''));
});
});
describe('Responsive Placeholder', () => {
let tag = shallow(
<Image publicId="sample" cloudName="demo" width="auto" crop="scale" responsive>
<Placeholder/>
</Image>
);
it('should have data-src for placeholder and image', function () {
expect(tag.html()).to.equal([
`<img data-src="http://res.cloudinary.com/demo/image/upload/c_scale,w_auto/sample" style="opacity:0;position:absolute"/>`,
`<div style="display:inline">`,
`<img data-src="http://res.cloudinary.com/demo/image/upload/c_scale,w_auto/e_blur:2000,f_auto,q_1/sample"/>`,
`</div>`
].join(''));
});
});
describe('Responsive Placeholder With Lazy Loading', () => {
let tag = shallow(
<Image publicId="sample" cloudName="demo" loading="lazy" width="auto" crop="scale" responsive>
Expand Down