I’m having trouble with scroll positioning. I am working in Wix Editor. Using a CMS connected to a repeater and a dynamic page. I am building a site for an artist: The repeater displays all the artworks, when you click on one artwork it opens a dynamic page to display the single artwork with details.
The issue I have is that when you click the “back button” on the dynamic page it navigates you back to the top of the All Artworks page. I need it to navigate you back to exactly where you were in the scroll navigation.
An important note: the repeater only displays 6 artworks at a time (with a Load More button to display more) and so I need to code to take that into consideration and correctly navigate you back to where you were in the repeater’s load.
Site page link:
Please note that I am new to Velo code and do not know how to code well so am asking for kindness of help to ideally give me the exact snippets of code I would need to paste on the All Artworks page and the Dynamic Item page.
Thank you so much for your help
Hi Talia, this is very doable, no need to touch the CMS/repeater setup itself.
Idea: save the scroll position (and how many items you’ve loaded via “Load More”) to session storage right before the user clicks into an artwork, then restore both when they land back on the All Artworks page.
On the All Artworks page code:
javascript
import wixStorage from 'wix-storage';
import wixWindow from 'wix-window';
let loadedCount = 6; // matches your repeater's initial page size
$w.onReady(function () {
const savedCount = wixStorage.session.getItem('artworksLoadedCount');
const savedScroll = wixStorage.session.getItem('artworksScrollY');
if (savedCount) {
loadedCount = parseInt(savedCount, 10);
loadItems(loadedCount).then(() => {
if (savedScroll) {
wixWindow.scrollTo(0, parseInt(savedScroll, 10));
}
});
}
$w('#loadMoreButton').onClick(() => {
loadedCount += 6;
wixStorage.session.setItem('artworksLoadedCount', loadedCount.toString());
loadItems(loadedCount);
});
$w('#artworksRepeater').onItemReady(($item) => {
$item('#artworkBox').onClick(() => {
$w('#artworksRepeater').getBoundingRect().then((rect) => {
wixStorage.session.setItem('artworksScrollY', rect.scroll.y.toString());
});
});
});
});
function loadItems(count) {
// however you currently page your data in - e.g. a dataset's loadMore(),
// or a wixData query with a limit of `count`. Just make sure it resolves
// a promise so the scroll restore waits for the items to render first.
return $w('#dataset1').loadMore();
}
```
The two pieces doing the real work: wix-storage's session storage survives the trip to the dynamic page and back (clears when the tab closes, which is what you want here), and wixWindow.scrollTo() puts them back where they were once the extra items have actually rendered - that's why the scroll restore has to wait on the loadItems() promise, otherwise you'll scroll before the repeater has the height to support it.
If Load More is wired to something other than a dataset (straight wixData query, custom array, etc.) the loadItems() function is the only bit that changes - happy to help fit it to your exact setup if you share how it's coded.
Thank you so much for your swift help, I really appreciate it. I pasted the code on to my All Artworks page and unfortunately it isn’t working. I tried to change some of the IDs to match my elements as thought that might be the issue. Please let me know if you are able to help me troubleshoot this? I would not be surprised if it is very simple but because I do not know how to code it is a foreign and difficult language for me!
My elements are named the following in case this helps:
#repeater1 (repeater containing all artworks)
#box1 (which is a hover box containing #image1)
#image1 (image connected to CMS which displays each artwork)
#button1 (load more button below the repeater connected to CMS to load more images)
Am I correct in understanding there is no code that needs to be put on the dynamic page, only on the all artworks page? (I did email the Wix Velo support team yesterday and they said code would be needed on both but perhaps you have a simpler way to achieve what I am after. I can send their message over if needed).
I also have a piece of code on the all artworks page that makes all the images fixed width and since pasting in the code from you the fixed width code stopped working so if you wouldn’t mind letting me know how to resolve that too I would greatly appreciate it.
Pasting screenshots below of current code on the all artworks page.
Hi Talia, found it, and it’s not you, your element names are right. Two things happened when it got pasted in:
-
The code landed nested inside your existing $w.onReady, and the ```javascript fence marks from my post got copied in as literal text too. Both of those break the script before it can run at all.
-
$w('#dataset1') in my loadItems() was a placeholder, not a real ID. Since your Load More is wired straight to the CMS connection panel rather than a Dataset you added yourself, you need the actual dataset element ID, click your repeater in the Editor and check the Layers panel, the connected dataset shows up there with its own ID.
Here’s it merged into one clean block for the All Artworks page, replacing everything currently there:
import wixStorage from 'wix-storage';
import wixWindow from 'wix-window';
$w.onReady(function () {
$w('#image1').fitMode = "fixedWidth";
let loadedCount = 6;
const savedCount = wixStorage.session.getItem('artworksLoadedCount');
const savedScroll = wixStorage.session.getItem('artworksScrollY');
if (savedCount) {
loadedCount = parseInt(savedCount, 10);
loadItems(loadedCount).then(() => {
if (savedScroll) {
wixWindow.scrollTo(0, parseInt(savedScroll, 10));
}
});
}
$w('#button1').onClick(() => {
loadedCount += 6;
wixStorage.session.setItem('artworksLoadedCount', loadedCount.toString());
loadItems(loadedCount);
});
$w('#repeater1').onItemReady(($item) => {
$item('#image1').onClick(() => {
$w('#repeater1').getBoundingRect().then((rect) => {
wixStorage.session.setItem('artworksScrollY', rect.scroll.y.toString());
});
});
});
});
function loadItems(count) {
return $w('#dataset1').loadMore(); // swap #dataset1 for your real dataset ID
}
```
The two imports have to sit at the very top of the code panel, above everything else, not inside onReady.
And yes, you had it right: no code needed on the dynamic item page for this, it all lives on the All Artworks list page.
If this helped, please mark it as Solved.