UNPKG

4.62 kBJavaScriptView Raw
1import { GlIntersectionObserver } from '../../../index';
2import readme from './intersection_observer.md';
3
4const components = {
5 GlIntersectionObserver,
6};
7
8const commonData = () => ({
9 isInView: false,
10});
11
12const commonMethods = {
13 appear() {
14 this.isInView = true;
15 },
16 disappear() {
17 this.isInView = false;
18 },
19};
20
21const generateItems = (startingId = 0) => {
22 const items = Array.from(Array(20).keys());
23 return items.map((index) => {
24 const id = index + startingId + 1;
25
26 return {
27 id,
28 title: `Item ${id}`,
29 };
30 });
31};
32
33export const Default = () => ({
34 components,
35 data: commonData,
36 methods: commonMethods,
37 computed: {
38 visibility() {
39 return this.isInView ? 'The observer is in view' : 'The observer is not in view';
40 },
41 },
42 template: `
43 <div style="height: 200px; overflow-y: scroll;">
44 <h1>{{ visibility }}</h1>
45 <p>This one is a hard one to demonstrate as it's invisible by nature.</p>
46 <p>Underneath this block of text is an invisible component, <code>&lt;gl-observer /&gt;</code> that has the power to tell the vue app when it's visible, and when it's not.</p>
47 <p><strong>{{ visibility }}</strong> at the moment but if you scroll and arrange your window just right, this can be changed and will be reflected in the title.</p>
48 <p :class="{'gl-text-green-600': isInView }">To make it even more clear, this line of text will be green when the element scrolls into view.</p>
49 <p>This line appears just before the observer.</p>
50 <gl-intersection-observer
51 @appear="appear"
52 @disappear="disappear"
53 />
54 <p>This line appears just after the observer.</p>
55 </div>
56 `,
57});
58
59export const BigTable = () => ({
60 components,
61 data() {
62 return {
63 values: Array(100)
64 .fill(1)
65 .map(() => Array(10).fill(0)),
66 };
67 },
68 methods: {
69 update(row, col, { intersectionRatio }) {
70 this.$set(this.values[row], col, intersectionRatio);
71 },
72 disappear(row, col) {
73 this.values[row][col] = 0;
74 },
75 },
76 template: `
77 <div style="height: 600px; overflow-y: scroll;">
78 <table>
79 <tr v-for="(cols, row) in values" :key="row">
80 <td v-for="(value, col) in cols" :key="row + '_' + col">
81 <gl-intersection-observer @update="update(row, col, $event)">
82 <span :style="{ display: 'inline-block', width: '50px' }">{{ value.toString().substr(0, 3) }}</span>
83 </gl-intersection-observer>
84 </td>
85 </tr>
86 </table>
87 </div>
88 `,
89});
90
91export const LazyLoadedImage = () => ({
92 components,
93 data: commonData,
94 methods: commonMethods,
95 computed: {
96 imageUrl() {
97 // If the image is in view, return the high res one. If not return nothing, or a low res one
98 return this.isInView
99 ? '../../img/gitlab-summit-south-africa.jpg'
100 : '../../img/gitlab-summit-south-africa-min.jpg';
101 },
102 },
103 template: `
104 <div>
105 <p>The image below will load a low-res version until it appears on the poage, then it will switch out for a higher res version.</p>
106 <p>It's also set up to switch back to the low res version when it disappears off the page. This is not what you would usually do for lazily loaded images, but it helps to demonstrate the effect in this example.</p>
107 <gl-intersection-observer
108 @appear="appear"
109 @disappear="disappear"
110 >
111 <img :src="imageUrl" style="max-width: 100%; height: auto;"/>
112 </gl-intersection-observer>
113 </div>
114 `,
115});
116
117export const InfiniteScrolling = () => ({
118 components,
119 data: () => ({
120 items: generateItems(),
121 }),
122 computed: {
123 lastItemId() {
124 return this.items[this.items.length - 1].id;
125 },
126 endOfList() {
127 return this.lastItemId >= 1000;
128 },
129 },
130 methods: {
131 fetchMoreItems() {
132 if (!this.endOfList) {
133 this.items.push(...generateItems(this.lastItemId));
134 }
135 },
136 },
137 template: `
138 <div>
139 <h2>Infinitely scrollable list</h2>
140 <p>This data will procedurally generate 1000 items, 20 at a time</p>
141 <ul>
142 <li v-for="item in items" :key="item.id">{{ item.title }}</li>
143 </ul>
144 <gl-intersection-observer v-if="!endOfList" @appear="fetchMoreItems">
145 <button @click="fetchMoreItems">Fetch more items</button>
146 </gl-intersection-observer>
147 </div>
148`,
149});
150
151export default {
152 title: 'utilities/intersection-observer',
153 component: GlIntersectionObserver,
154 parameters: {
155 storyshots: { disable: true },
156 docs: {
157 description: {
158 component: readme,
159 },
160 },
161 },
162};