Skip to content

Commit 58e096f

Browse files
committed
Converting LazyImage to use values
1 parent d894cf9 commit 58e096f

File tree

4 files changed

+90
-28
lines changed

4 files changed

+90
-28
lines changed

src/LazyImage/README.md

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,35 @@ page has been rendered:
3434
```twig
3535
<img
3636
src="{{ asset('image/small.png') }}"
37-
{{ stimulus_controller('symfony/ux-lazy-image/lazy-image') }}
38-
data-hd-src="{{ asset('image/large.png') }}"
39-
40-
srcset="{{ asset('image/small.png') }} 1x, {{ asset('image/small2x.png') }} 2x"
41-
data-hd-srcset="{{ asset('image/large.png') }} 1x, {{ asset('image/large2x.png') }} 2x"
37+
{{ stimulus_controller('symfony/ux-lazy-image/lazy-image', {
38+
hdSrc: asset('image/large.png')
39+
}) }}
4240
4341
{# Optional but avoids having a page jump when the image is loaded #}
4442
width="200"
4543
height="150"
44+
>
45+
```
46+
47+
With this setup, the user will initially see `images/small.png`. Then,
48+
once the page has loaded and the user's browser has downloaded the larger
49+
image, the `src` attribute will change to `image/large.png`.
50+
51+
There is also support for the `srcset` attribute by passing an
52+
`hdSrcset` value to the controller:
53+
54+
```twig
55+
<img
56+
src="{{ asset('image/small.png') }}"
57+
srcset="{{ asset('image/small.png') }} 1x, {{ asset('image/small2x.png') }} 2x"
58+
59+
{{ stimulus_controller('symfony/ux-lazy-image/lazy-image', {
60+
hdSrc: asset('image/large.png'),
61+
hdSrcset: {
62+
'1x': asset('image/large.png'),
63+
'2x': asset('image/large2x.png')
64+
}
65+
}) }}
4666
/>
4767
```
4868

@@ -55,8 +75,9 @@ the BlurHash algorithm to create a light, blurred, data-uri thumbnail of the ima
5575
```twig
5676
<img
5777
src="{{ data_uri_thumbnail('public/image/large.png', 100, 75) }}"
58-
{{ stimulus_controller('symfony/ux-lazy-image/lazy-image') }}
59-
data-hd-src="{{ asset('image/large.png') }}"
78+
{{ stimulus_controller('symfony/ux-lazy-image/lazy-image', {
79+
hdSrc: asset('image/large.png')
80+
}) }}
6081
6182
{# Using BlurHash, the size is required #}
6283
width="200"
@@ -112,9 +133,10 @@ Then in your template, add your controller to the HTML attribute:
112133
src="{{ data_uri_thumbnail('public/image/large.png', 100, 75) }}"
113134
{{ stimulus_controller({
114135
mylazyimage: {},
115-
'symfony/ux-lazy-image/lazy-image': {}
136+
'symfony/ux-lazy-image/lazy-image': {
137+
hdSrc: asset('image/large.png')
138+
}
116139
}) }}
117-
data-hd-src="{{ asset('image/large.png') }}"
118140
119141
{# Using BlurHash, the size is required #}
120142
width="200"
Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,40 @@
11
import { Controller } from '@hotwired/stimulus';
22

3-
class controller extends Controller {
3+
class default_1 extends Controller {
44
connect() {
55
const hd = new Image();
6+
const srcsetString = this._calculateSrcsetString();
67
hd.addEventListener('load', () => {
7-
this.element.src = this.element.getAttribute('data-hd-src');
8-
if (this.element.getAttribute('data-hd-srcset')) {
9-
this.element.srcset = this.element.getAttribute('data-hd-srcset');
8+
this.element.src = this.hdSrcValue;
9+
if (srcsetString) {
10+
this.element.srcset = srcsetString;
1011
}
1112
this._dispatchEvent('lazy-image:ready', { hd });
1213
});
13-
hd.src = this.element.getAttribute('data-hd-src');
14-
if (this.element.getAttribute('data-hd-srcset')) {
15-
hd.srcset = this.element.getAttribute('data-hd-srcset');
14+
hd.src = this.hdSrcValue;
15+
if (srcsetString) {
16+
hd.srcset = srcsetString;
1617
}
1718
this._dispatchEvent('lazy-image:connect', { hd });
1819
}
20+
_calculateSrcsetString() {
21+
if (!this.hasHdSrcsetValue) {
22+
return '';
23+
}
24+
const sets = Object.keys(this.hdSrcsetValue).map((size => {
25+
return `${this.hdSrcsetValue[size]} ${size}`;
26+
}));
27+
return sets.join(', ').trimEnd();
28+
}
1929
_dispatchEvent(name, payload = null, canBubble = false, cancelable = false) {
2030
const userEvent = document.createEvent('CustomEvent');
2131
userEvent.initCustomEvent(name, canBubble, cancelable, payload);
2232
this.element.dispatchEvent(userEvent);
2333
}
2434
}
35+
default_1.values = {
36+
hdSrc: String,
37+
hdSrcset: Object
38+
};
2539

26-
export { controller as default };
40+
export { default_1 as default };

src/LazyImage/Resources/assets/src/controller.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,44 @@
1212
import { Controller } from '@hotwired/stimulus';
1313

1414
export default class extends Controller {
15+
static values = {
16+
hdSrc: String,
17+
hdSrcset: Object
18+
};
19+
1520
connect() {
1621
const hd = new Image();
1722

23+
const srcsetString = this._calculateSrcsetString();
24+
1825
hd.addEventListener('load', () => {
19-
this.element.src = this.element.getAttribute('data-hd-src');
20-
if (this.element.getAttribute('data-hd-srcset')) {
21-
this.element.srcset = this.element.getAttribute('data-hd-srcset');
26+
this.element.src = this.hdSrcValue;
27+
if (srcsetString) {
28+
this.element.srcset = srcsetString;
2229
}
2330
this._dispatchEvent('lazy-image:ready', { hd });
2431
});
2532

26-
hd.src = this.element.getAttribute('data-hd-src');
27-
if (this.element.getAttribute('data-hd-srcset')) {
28-
hd.srcset = this.element.getAttribute('data-hd-srcset');
33+
hd.src = this.hdSrcValue;
34+
if (srcsetString) {
35+
hd.srcset = srcsetString;
2936
}
3037

3138
this._dispatchEvent('lazy-image:connect', { hd });
3239
}
3340

41+
_calculateSrcsetString(): string {
42+
if (!this.hasHdSrcsetValue) {
43+
return '';
44+
}
45+
46+
const sets = Object.keys(this.hdSrcsetValue).map((size => {
47+
return `${this.hdSrcsetValue[size]} ${size}`;
48+
}));
49+
50+
return sets.join(', ').trimEnd();
51+
}
52+
3453
_dispatchEvent(name, payload = null, canBubble = false, cancelable = false) {
3554
const userEvent = document.createEvent('CustomEvent');
3655
userEvent.initCustomEvent(name, canBubble, cancelable, payload);

src/LazyImage/Resources/assets/test/controller.test.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ import LazyImageController from '../src/controller';
1717
// Controller used to check the actual controller was properly booted
1818
class CheckController extends Controller {
1919
connect() {
20-
this.element.addEventListener('lazy-image:connect', () => {
20+
this.element.addEventListener('lazy-image:connect', (event) => {
21+
// the Image won't natively have its "load" method in this test
22+
// so we trigger it manually, to "fake" the Image loading.
23+
event.detail.hd.dispatchEvent(new Event('load'));
2124
this.element.classList.add('connected');
2225
});
2326
}
@@ -38,8 +41,8 @@ describe('LazyImageController', () => {
3841
src="https://symfony.com/logos/symfony_black_02.png"
3942
srcset="https://symfony.com/logos/symfony_black_02.png 1x, https://symfony.com/logos/symfony_black_02.png 2x"
4043
data-testid="img"
41-
data-hd-src="https://symfony.com/logos/symfony_black_03.png"
42-
data-hd-srcset="https://symfony.com/logos/symfony_black_03.png 1x, https://symfony.com/logos/symfony_black_03.png 2x"
44+
data-lazy-image-hd-src-value="https://symfony.com/logos/symfony_black_03.png"
45+
data-lazy-image-hd-srcset-value="{&quot;1x&quot;: &quot;https://symfony.com/logos/symfony_black_03.png&quot;, &quot;2x&quot;: &quot;https://symfony.com/logos/symfony_black_03_2x.png&quot;}"
4346
data-controller="check lazy-image" />
4447
`);
4548
});
@@ -49,9 +52,13 @@ describe('LazyImageController', () => {
4952
});
5053

5154
it('connect', async () => {
52-
expect(getByTestId(container, 'img')).not.toHaveClass('connected');
55+
const img = getByTestId(container, 'img');
56+
expect(img).not.toHaveClass('connected');
57+
expect(img).toHaveAttribute('src', 'https://symfony.com/logos/symfony_black_02.png');
5358

5459
startStimulus();
55-
await waitFor(() => expect(getByTestId(container, 'img')).toHaveClass('connected'));
60+
await waitFor(() => expect(img).toHaveClass('connected'));
61+
expect(img).toHaveAttribute('src', 'https://symfony.com/logos/symfony_black_03.png');
62+
expect(img).toHaveAttribute('srcset', 'https://symfony.com/logos/symfony_black_03.png 1x, https://symfony.com/logos/symfony_black_03_2x.png 2x');
5663
});
5764
});

0 commit comments

Comments
 (0)