|
1 | 1 | <script> |
2 | | - import Virtual from "./vue/virtual" |
| 2 | + import Virtual from "./virtual" |
3 | 3 | import Item from "./Item.svelte" |
4 | 4 | import {createEventDispatcher, onDestroy, onMount} from "svelte" |
5 | 5 |
|
|
30 | 30 | let shepherd |
31 | 31 | const dispatch = createEventDispatcher() |
32 | 32 |
|
33 | | - onMount(() => { |
34 | | - if (start) { |
35 | | - scrollToIndex(start) |
36 | | - } else if (offset) { |
37 | | - scrollToOffset(offset) |
38 | | - } |
39 | | -
|
40 | | - if (pageMode) { |
41 | | - updatePageModeFront() |
42 | | -
|
43 | | - document.addEventListener("scroll", onScroll, { |
44 | | - passive: false, |
45 | | - }) |
46 | | - } |
47 | | - }) |
48 | | -
|
49 | | - onDestroy(() => { |
50 | | - virtual.destroy() |
51 | | - if (pageMode) { |
52 | | - document.removeEventListener("scroll", onScroll) |
53 | | - } |
54 | | - }) |
55 | | -
|
56 | | - function getUniqueIdFromDataSources() { |
57 | | - return data.map((dataSource) => dataSource[key]) |
58 | | - } |
59 | | -
|
60 | | - function onItemResized({id, size, type}) { |
61 | | - if (type === "item") |
62 | | - virtual.saveSize(id, size) |
63 | | - else { |
64 | | - if (id === "header") |
65 | | - virtual.updateParam("slotHeaderSize", size) |
66 | | - else if (id === "footer") |
67 | | - virtual.updateParam("slotFooterSize", size) |
68 | | -
|
69 | | - virtual.handleSlotSizeChange() |
70 | | - } |
| 33 | + export function getSize(id) { |
| 34 | + return virtual.sizes.get(id) |
71 | 35 | } |
72 | 36 |
|
73 | | - function onRangeChanged(range_) { |
74 | | - range = range_ |
75 | | - paddingStyle = paddingStyle = isHorizontal ? `0px ${range.padBehind}px 0px ${range.padFront}px` : `${range.padFront}px 0px ${range.padBehind}px` |
76 | | - displayItems = data.slice(range.start, range.end + 1) |
77 | | - } |
78 | | -
|
79 | | - function onScroll(event) { |
80 | | - const offset = getOffset() |
81 | | - const clientSize = getClientSize() |
82 | | - const scrollSize = getScrollSize() |
83 | | -
|
84 | | - // iOS scroll-spring-back behavior will make direction mistake |
85 | | - if (offset < 0 || (offset + clientSize > scrollSize + 1) || !scrollSize) { |
86 | | - return |
87 | | - } |
88 | | -
|
89 | | - virtual.handleScroll(offset) |
90 | | - emitEvent(offset, clientSize, scrollSize, event) |
| 37 | + export function getSizes() { |
| 38 | + return virtual.sizes.size |
91 | 39 | } |
92 | 40 |
|
93 | 41 | export function getOffset() { |
|
125 | 73 | } |
126 | 74 | } |
127 | 75 |
|
128 | | - function emitEvent(offset, clientSize, scrollSize, event) { |
129 | | - dispatch("scroll", {event, range: virtual.getRange()}) |
130 | | -
|
131 | | - if (virtual.isFront() && !!data.length && (offset - topThreshold <= 0)) { |
132 | | - dispatch("top") |
133 | | - } else if (virtual.isBehind() && (offset + clientSize + bottomThreshold >= scrollSize)) { |
134 | | - dispatch("bottom") |
135 | | - } |
136 | | - } |
137 | | -
|
138 | 76 | export function scrollToOffset(offset) { |
139 | 77 | if (pageMode) { |
140 | 78 | document.body[directionKey] = offset |
|
145 | 83 | } |
146 | 84 |
|
147 | 85 | export function scrollToIndex(index) { |
148 | | - // scroll to bottom |
149 | 86 | if (index >= data.length - 1) { |
150 | 87 | scrollToBottom() |
151 | 88 | } else { |
|
154 | 91 | } |
155 | 92 | } |
156 | 93 |
|
157 | | - /** |
158 | | - * set current scroll position to bottom |
159 | | - */ |
160 | 94 | export function scrollToBottom() { |
161 | 95 | if (shepherd) { |
162 | 96 | const offset = shepherd[isHorizontal ? "offsetLeft" : "offsetTop"] |
|
173 | 107 | } |
174 | 108 | } |
175 | 109 |
|
| 110 | + onMount(() => { |
| 111 | + if (start) { |
| 112 | + scrollToIndex(start) |
| 113 | + } else if (offset) { |
| 114 | + scrollToOffset(offset) |
| 115 | + } |
| 116 | +
|
| 117 | + if (pageMode) { |
| 118 | + updatePageModeFront() |
| 119 | +
|
| 120 | + document.addEventListener("scroll", onScroll, { |
| 121 | + passive: false, |
| 122 | + }) |
| 123 | + } |
| 124 | + }) |
| 125 | +
|
| 126 | + onDestroy(() => { |
| 127 | + virtual.destroy() |
| 128 | + if (pageMode) { |
| 129 | + document.removeEventListener("scroll", onScroll) |
| 130 | + } |
| 131 | + }) |
| 132 | +
|
| 133 | + function getUniqueIdFromDataSources() { |
| 134 | + return data.map((dataSource) => dataSource[key]) |
| 135 | + } |
| 136 | +
|
| 137 | + function onItemResized({id, size, type}) { |
| 138 | + if (type === "item") |
| 139 | + virtual.saveSize(id, size) |
| 140 | + else { |
| 141 | + if (id === "header") |
| 142 | + virtual.updateParam("slotHeaderSize", size) |
| 143 | + else if (id === "footer") |
| 144 | + virtual.updateParam("slotFooterSize", size) |
| 145 | +
|
| 146 | + virtual.handleSlotSizeChange() |
| 147 | + } |
| 148 | + } |
| 149 | +
|
| 150 | + function onRangeChanged(range_) { |
| 151 | + range = range_ |
| 152 | + paddingStyle = paddingStyle = isHorizontal ? `0px ${range.padBehind}px 0px ${range.padFront}px` : `${range.padFront}px 0px ${range.padBehind}px` |
| 153 | + displayItems = data.slice(range.start, range.end + 1) |
| 154 | + } |
| 155 | +
|
| 156 | + function onScroll(event) { |
| 157 | + const offset = getOffset() |
| 158 | + const clientSize = getClientSize() |
| 159 | + const scrollSize = getScrollSize() |
| 160 | +
|
| 161 | + // iOS scroll-spring-back behavior will make direction mistake |
| 162 | + if (offset < 0 || (offset + clientSize > scrollSize + 1) || !scrollSize) { |
| 163 | + return |
| 164 | + } |
| 165 | +
|
| 166 | + virtual.handleScroll(offset) |
| 167 | + emitEvent(offset, clientSize, scrollSize, event) |
| 168 | + } |
| 169 | +
|
| 170 | + function emitEvent(offset, clientSize, scrollSize, event) { |
| 171 | + dispatch("scroll", {event, range: virtual.getRange()}) |
| 172 | +
|
| 173 | + if (virtual.isFront() && !!data.length && (offset - topThreshold <= 0)) { |
| 174 | + dispatch("top") |
| 175 | + } else if (virtual.isBehind() && (offset + clientSize + bottomThreshold >= scrollSize)) { |
| 176 | + dispatch("bottom") |
| 177 | + } |
| 178 | + } |
| 179 | +
|
176 | 180 | $: scrollToOffset(offset) |
177 | 181 | $: scrollToIndex(start) |
178 | 182 | $: { |
|
182 | 186 | $: handleDataSourcesChange(data) |
183 | 187 |
|
184 | 188 | async function handleDataSourcesChange(dataSources) { |
185 | | - // TODO: fix jump on top added data |
186 | | - console.log("data change") |
187 | 189 | virtual.updateParam("uniqueIds", getUniqueIdFromDataSources()) |
188 | 190 | virtual.handleDataSourcesChange() |
189 | | - onRangeChanged(range) |
190 | 191 | } |
191 | 192 | </script> |
192 | 193 |
|
|
197 | 198 | </Item> |
198 | 199 | {/if} |
199 | 200 | <div style="padding: {paddingStyle}"> |
200 | | - {#each displayItems as data} |
| 201 | + {#each displayItems as data (data[key])} |
201 | 202 | <Item |
202 | 203 | on:resize={(e) => onItemResized(e.detail)} |
203 | 204 | uniqueKey={data[key]} |
|
0 commit comments