Skip to content

Commit 9f39283

Browse files
authored
Fixed placeholder when using responsive lazy load (#256)
1 parent afa2047 commit 9f39283

3 files changed

Lines changed: 82 additions & 11 deletions

File tree

projects/angular-cld/src/lib/cloudinary-image.component.spec.ts

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -824,8 +824,8 @@ describe('CloudinaryImage', () => {
824824
tick();
825825
fixture.detectChanges();
826826
const img = des[0].children[0].nativeElement as HTMLImageElement;
827-
expect(img.attributes.getNamedItem('src').value).toEqual('http://res.cloudinary.com/' +
828-
'@@fake_angular2_sdk@@/image/upload/c_fit,w_30/ar_1,b_auto,c_pad,w_iw_div_2/c_crop,g_north_east,h_10,w_10/c_fill,h_ih,w_iw/f_auto,q_auto/bear');
827+
expect(img.attributes.getNamedItem('src').value).toEqual('http://res.cloudinary.com/@@fake_angular2_sdk@@/image/' +
828+
'upload/c_fit,w_30/$currWidth_w,$currHeight_h/ar_1,b_auto,c_pad,w_iw_div_2/c_crop,g_north_east,h_10,w_10/c_fill,h_$currHeight,w_$currWidth/f_auto,q_auto/bear');
829829
}));
830830
});
831831
describe('placeholder type vectorize', () => {
@@ -977,5 +977,64 @@ describe('CloudinaryImage', () => {
977977
}
978978
});
979979
});
980-
});
980+
describe('cl-image with responsive and placeholder on lazy load', async () => {
981+
@Component({
982+
template: `<div class="startWindow"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
983+
<div style="margin-top: 700px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
984+
<div style="margin-top: 700px"><cl-image loading="lazy" public-id="bear" responsive width="auto" crop="scale">
985+
<cl-placeholder></cl-placeholder>
986+
</cl-image></div>
987+
<div style="margin-top: 700px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
988+
<div style="margin-top: 700px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
989+
<div style="margin-top: 700px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
990+
<div style="margin-top: 700px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
991+
<div class="endWindow" style="margin-top: 700px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>`
992+
})
993+
class TestComponent {}
994+
995+
let fixture: ComponentFixture<TestComponent>;
996+
let des: DebugElement[]; // the elements w/ the directive
997+
let placeholder: DebugElement[];
998+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
999+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
1000+
beforeEach(fakeAsync(() => {
1001+
fixture = TestBed.configureTestingModule({
1002+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, LazyLoadDirective, CloudinaryPlaceHolder],
1003+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
1004+
}).createComponent(TestComponent);
1005+
1006+
fixture.detectChanges(); // initial binding
1007+
// all elements with an attached CloudinaryImage
1008+
des = fixture.debugElement.queryAll(By.directive(CloudinaryImage));
1009+
placeholder = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
1010+
tick();
1011+
fixture.detectChanges();
1012+
}));
1013+
it('Placeholder width should equal img width on Firefox', async () => {
1014+
const placeholderimg = placeholder[0].children[0].nativeElement as HTMLImageElement;
1015+
const img = des[2].children[0].nativeElement as HTMLImageElement;
1016+
1017+
const delay = 300;
1018+
const wait = (ms) => new Promise(res => setTimeout(res, ms));
1019+
const count = async () => document.querySelectorAll('.startWindow').length;
1020+
const scrollDown = async () => {
1021+
document.querySelector('.endWindow')
1022+
.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'end' });
1023+
}
1024+
1025+
let preCount = 0;
1026+
let postCount = 0;
1027+
do {
1028+
preCount = await count();
1029+
await scrollDown();
1030+
await wait(delay);
1031+
postCount = await count();
1032+
} while (postCount > preCount);
1033+
await wait(delay);
9811034

1035+
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
1036+
expect(placeholderimg.attributes.getNamedItem('width')).toEqual(img.attributes.getNamedItem('width'));
1037+
}
1038+
});
1039+
});
1040+
});

projects/angular-cld/src/lib/cloudinary-image.component.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export class CloudinaryImage
126126
delete options['responsive'];
127127
}
128128
if (this.placeholderComponent) {
129-
this.placeholderHandler(options);
129+
this.placeholderHandler(options, image);
130130
}
131131
if (this.accessibility) {
132132
this.options = options;
@@ -148,12 +148,23 @@ export class CloudinaryImage
148148
});
149149
}
150150

151-
placeholderHandler(options) {
152-
const placeholderOptions = {};
153-
154-
Object.keys(options).forEach(name => {
155-
placeholderOptions[name] = (name === 'width' && !options[name].startsWith('auto') || name === 'height') ? Math.ceil(parseInt(options[name], 10) * 0.1) : options[name];
156-
});
151+
/**
152+
* Handles placeholder options
153+
* In case of responsive sets width from resize
154+
* In case width or height is known takes 10% of original dimension
155+
*/
156+
placeholderHandler(options, image) {
157+
const placeholderOptions = { ...options };
158+
if (placeholderOptions['width']) {
159+
if (placeholderOptions['width'] === 'auto') {
160+
placeholderOptions['width'] = image.getAttribute('data-width');
161+
} else {
162+
placeholderOptions['width'] = Math.ceil(parseInt(options['width'], 10) * 0.1);
163+
}
164+
}
165+
if (placeholderOptions['height']) {
166+
placeholderOptions['height'] = Math.ceil(parseInt(options['height'], 10) * 0.1);
167+
}
157168
this.placeholderComponent.options = placeholderOptions;
158169
}
159170

projects/angular-cld/src/lib/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ export const predominantColorTransformPxl = [
1111
{fetch_format: 'auto', quality: 'auto'}];
1212

1313
export const predominantColorTransform = [
14+
{variables: [['$currWidth', 'w'], ['$currHeight', 'h']]},
1415
{width: 'iw_div_2', aspect_ratio: 1, crop: 'pad', background: 'auto'},
1516
{crop: 'crop', width: 10, height: 10, gravity: 'north_east'},
16-
{width: 'iw', height: 'ih', crop: 'fill'},
17+
{width: '$currWidth', height: '$currHeight', crop: 'fill'},
1718
{fetch_format: 'auto', quality: 'auto'}];
1819

1920
export const placeholderImageOptions = {

0 commit comments

Comments
 (0)