Skip to content

Commit 5485067

Browse files
author
Nir Maoz
authored
Fix responsive placeholder (#185)
1 parent bb18025 commit 5485067

File tree

5 files changed

+73
-9
lines changed

5 files changed

+73
-9
lines changed

e2e-test/cypress/integration/placeholder.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ describe('Placeholder Image', () => {
44
cy.visit('/');
55
cy.get('#placeholderBtn').click();
66
});
7-
7+
88
/**
99
* Cypress seems to be not fast enough to catch the placeholder render.
10-
* So we test that the placeholder is rendered in out Unit Tests,
10+
* So we test that the placeholder is rendered in our Unit Tests,
1111
* And here we make sure that eventually we render the original image.
1212
*/
1313
it('Show original image', () => {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
describe('Responsive Placeholder Image', () => {
2+
beforeEach(() => {
3+
// runs before each test in the block
4+
cy.visit('/');
5+
cy.get('#responsivePlaceholderBtn').click();
6+
});
7+
8+
/**
9+
* Cypress seems to be not fast enough to catch the placeholder render.
10+
* So we test that the placeholder is rendered in our Unit Tests,
11+
* And here we make sure that eventually we render the responsive image.
12+
* The image width was updated to be w_400.
13+
*/
14+
it('Show original image', () => {
15+
cy.get('#responsivePlaceholder')
16+
.should('be.visible')
17+
.should('have.attr', 'src').should('equal', 'http://res.cloudinary.com/demo/image/upload/c_scale,w_400/sample')
18+
});
19+
});

e2e-test/src/App.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const tests = [
77
'placeholder',
88
'lazy',
99
'lazyPlaceholder',
10-
'lazyResponsive'
10+
'lazyResponsive',
11+
'responsivePlaceholder'
1112
];
1213

1314
function App() {
@@ -83,6 +84,17 @@ function App() {
8384
</div>
8485
</div>
8586
}
87+
}
88+
{test === 'responsivePlaceholder' &&
89+
<div>
90+
<h1>Responsive Placeholder</h1>
91+
<div style={{width: "330px"}}>
92+
<Image id="responsivePlaceholder" publicId="sample" cloudName="demo" width="auto" crop="scale" responsive>
93+
<Placeholder/>
94+
</Image>
95+
</div>
96+
</div>
97+
}
8698
</Fragment>
8799
);
88100
}

src/components/Image/Image.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class Image extends CloudinaryComponent {
1919
constructor(props, context) {
2020
super(props, context);
2121
this.imgElement = createRef();
22+
this.placeholderElement = createRef();
2223
this.state = {isLoaded: false}
2324
this.listenerRemovers = [];
2425
}
@@ -96,8 +97,18 @@ class Image extends CloudinaryComponent {
9697
} else {
9798
// Handle responsive only if lazy loading wasn't requested or already handled
9899
if (this.isResponsive()) {
99-
const removeListener = makeElementResponsive(this.imgElement.current, this.getOptions());
100-
this.listenerRemovers.push(removeListener);
100+
const options = this.getOptions();
101+
const placeholder = this.getPlaceholderType();
102+
103+
// Make placeholder responsive
104+
if (placeholder) {
105+
const removePlaceholderListener = makeElementResponsive(this.placeholderElement.current, {...options, placeholder});
106+
this.listenerRemovers.push(removePlaceholderListener);
107+
}
108+
109+
// Make original image responsive
110+
const removeImgListener = makeElementResponsive(this.imgElement.current, options);
111+
this.listenerRemovers.push(removeImgListener);
101112
}
102113
}
103114
}
@@ -158,17 +169,18 @@ class Image extends CloudinaryComponent {
158169
});
159170
};
160171

172+
161173
renderPlaceholder = (placeholder, attributes) => {
162174
attributes.style = {...(attributes.style || {}), opacity: 0, position: 'absolute'}
163175
attributes.onLoad = this.handleImageLoaded;
164176
const placeholderWrapperStyle = {display: 'inline'}
165-
const placeholderAttributes = this.getAttributes({placeholder: placeholder.props.type});
177+
const placeholderAttributes = this.getAttributes({placeholder});
166178

167179
return (
168180
<Fragment>
169181
{this.renderImage(attributes)}
170182
<div style={placeholderWrapperStyle}>
171-
<img {...placeholderAttributes}/>
183+
<img ref={this.placeholderElement} {...placeholderAttributes}/>
172184
</div>
173185
</Fragment>
174186
);
@@ -178,11 +190,17 @@ class Image extends CloudinaryComponent {
178190
return <img ref={this.attachRef} {...attributes}/>
179191
}
180192

181-
render() {
182-
const {isLoaded} = this.state;
193+
getPlaceholderType = () => {
183194
const {children} = this.getExtendedProps();
184195
const placeholder = this.getChildPlaceholder(children);
196+
197+
return placeholder ? placeholder.props.type : null;
198+
}
199+
200+
render() {
201+
const {isLoaded} = this.state;
185202
const attributes = this.getAttributes();
203+
const placeholder = this.getPlaceholderType();
186204

187205
//If image wasn't loaded and there's a child placeholder then we render it.
188206
if (!isLoaded && placeholder) {

test/ImageTest.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,21 @@ describe('Image', () => {
205205
].join(''));
206206
});
207207
});
208+
describe('Responsive Placeholder', () => {
209+
let tag = shallow(
210+
<Image publicId="sample" cloudName="demo" width="auto" crop="scale" responsive>
211+
<Placeholder/>
212+
</Image>
213+
);
214+
it('should have data-src for placeholder and image', function () {
215+
expect(tag.html()).to.equal([
216+
`<img data-src="http://res.cloudinary.com/demo/image/upload/c_scale,w_auto/sample" style="opacity:0;position:absolute"/>`,
217+
`<div style="display:inline">`,
218+
`<img data-src="http://res.cloudinary.com/demo/image/upload/c_scale,w_auto/e_blur:2000,f_auto,q_1/sample"/>`,
219+
`</div>`
220+
].join(''));
221+
});
222+
});
208223
describe('Responsive Placeholder With Lazy Loading', () => {
209224
let tag = shallow(
210225
<Image publicId="sample" cloudName="demo" loading="lazy" width="auto" crop="scale" responsive>

0 commit comments

Comments
 (0)