Skip to content

Commit

Permalink
feat(vue-masonry): add proper image handling
Browse files Browse the repository at this point in the history
  • Loading branch information
devCrossNet committed Feb 19, 2022
1 parent 8eac1d1 commit 350f3e8
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 21 deletions.
38 changes: 30 additions & 8 deletions src/components/layout/VueMasonry/VueMasonry.spec.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,43 @@
import { render, RenderResult } from '@testing-library/vue';
import { fireEvent, render } from '@testing-library/vue';
import VueMasonry from './VueMasonry.vue';

describe('VueMasonry.vue', () => {
let harness: RenderResult;

beforeEach(() => {
harness = render(VueMasonry, {
test('renders component with images', async () => {
const { getByText, getByTestId } = render(VueMasonry, {
stubs: ['nuxt-link'],
slots: {
default: '<div>VueMasonry</div>',
default:
'<div><img data-testid="image" alt="test" src="https://images.unsplash.com/photo-1567017469553-d1b219af5831?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8bW9udGFpbnN8ZW58MHx8MHx8&auto=format&fit=crop&w=900&q=60" />VueMasonry</div>',
},
});

getByText('VueMasonry');

const image = getByTestId('image');

await fireEvent.load(image);
expect(image.style.display).toBe('initial');

await fireEvent.error(image);
expect(image.style.display).toBe('none');
});

test('renders component', () => {
const { getByText } = harness;
test('renders component with images and calls original events', async () => {
const { getByText, getByTestId } = render(VueMasonry, {
stubs: ['nuxt-link'],
slots: {
default:
'<div><img data-testid="image" alt="test" src="https://images.unsplash.com/photo-1567017469553-d1b219af5831?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8bW9udGFpbnN8ZW58MHx8MHx8&auto=format&fit=crop&w=900&q=60" onload="this.style.height=`24px`" onerror="this.style.width=`24px`" />VueMasonry</div>',
},
});
const image = getByTestId('image');

await fireEvent.load(image);
await fireEvent.error(image);

getByText('VueMasonry');

expect(image.style.height).toBe('24px');
expect(image.style.width).toBe('24px');
});
});
41 changes: 28 additions & 13 deletions src/components/layout/VueMasonry/VueMasonry.stories.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,49 @@
import { storiesOf } from '@storybook/vue';
import { getIntInRange } from '@vuesion/utils/dist/randomGenerator';
import ComponentDocs from '@/assets/design-system/docs/components/ComponentDocs.vue';
import VueStack from '@/components/layout/VueStack/VueStack.vue';
import VueSlider from '@/components/input-and-actions/VueSlider/VueSlider.vue';
import VueMasonry from './VueMasonry.vue';

const story = storiesOf('Foundation|Layout/Masonry', module) as any;

story.add(
'Default',
() => ({
components: { ComponentDocs, VueMasonry },
components: { ComponentDocs, VueMasonry, VueStack, VueSlider },
data(): any {
return {
numberOfImages: [12],
};
},
template: `<component-docs
component-name="Masonry"
usage="Display items in 3 rows with their actual height stacked on top of each other."
story="Show Masonry layout component."
>
<vue-masonry>
<div v-for="index in 12" :key="index" :style="{height: getRandomHeight(), background: getRandomBackground()}"></div>
</vue-masonry>
<vue-stack>
<vue-slider id="max" v-model="numberOfImages" :max="96" :min="3" label="Number of elements" style="width: 450px" />
<vue-masonry>
<div v-for="index in numberOfImages[0]" :key="index" style="display: flex;flex-direction: column;gap: 4px;">
<img
:src="getRandomImage()" :alt="'image-' + index"
style="width:100%;"
/>
This is Image number #{{ index }}
</div>
</vue-masonry>
</vue-stack>
</component-docs>`,
methods: {
getRandomHeight() {
return ['250px', '350px', '500px', '300px', '550px'][getIntInRange(0, 4)];
},
getRandomBackground() {
getRandomImage() {
return [
'var(--brand-primary)',
'var(--brand-success)',
'var(--brand-info)',
'var(--brand-warning)',
'var(--brand-danger)',
'https://images.unsplash.com/photo-1567017469553-d1b219af5831?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8bW9udGFpbnN8ZW58MHx8MHx8&auto=format&fit=crop&w=900&q=60',
'https://images.unsplash.com/photo-1548588681-adf41d474533?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3275&q=80',
'https://images.unsplash.com/photo-1600283177630-bc1ba1c7a985?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MjB8fG1vbnRhaW5zfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=900&q=60',
'https://images.unsplash.com/photo-1507929632612-bff9cd17f808?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mjd8fG1vbnRhaW5zfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=900&q=60',
'https://images.unsplash.com/photo-1566635285855-7f9bba12309f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NDh8fG1vbnRhaW5zfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=900&q=60',
][getIntInRange(0, 4)];
},
},
Expand Down
37 changes: 37 additions & 0 deletions src/components/layout/VueMasonry/VueMasonry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,41 @@ export default defineComponent({
actualHeight.value = Math.max(col1Height, col2Height, col3Height);
};
const checkForImages = () => {
let loadedImages = 0;
const images = wrapper.value.querySelectorAll('img');
const imageCount = images.length;
const imageLoaded = () => {
loadedImages += 1;
if (imageCount === loadedImages) {
calculateHeight();
}
};
images.forEach((image) => {
image.style.display = 'none';
const originalLoadEvent = image.onload;
const originalErrorEvent = image.onerror;
image.onload = function (ev: Event) {
image.style.display = 'initial';
imageLoaded();
if (originalLoadEvent) {
originalLoadEvent.apply(this, ev);
}
};
image.onerror = function (ev: Event) {
image.style.display = 'none';
imageLoaded();
if (originalLoadEvent) {
originalErrorEvent.apply(this, ev);
}
};
});
};
onMounted(() => {
calculateHeight();
Expand All @@ -46,6 +81,8 @@ export default defineComponent({
observer = new MutationObserver(calculateHeight);
observer.observe(wrapper.value, { attributes: true, childList: true, characterData: true, subtree: true });
checkForImages();
});
onUpdated(() => calculateHeight);
onBeforeUnmount(() => {
Expand Down

0 comments on commit 350f3e8

Please sign in to comment.