I saw a request recently for a repeater to be able to manage a slide show or a repeater to perform as a slide show.
None of these options is trivial if you try to use the $w.Repeater or $w.Slideshow APIs. Using them is probably a little bit of over kill anyway when all you want to do is change a single container and some key property elements using data from a data set.
Here is one approach.
Step 1:
Create your slideshow data collection and populate it with whatever you want in your slide show.
Then in the Wix Editor connect
up the datacollection using a dataset connector. We will name the dataset
'#slideContent'. We can adjust the number of items per page depending on the number of elements we are showing.
Step 2:
Create the baseline element with the property elements that you want. So for this example we will use a $w.ColumnStrip. The columnStrip will have a single $w.Text element for an image title and we will use the $w.ColumnStrip background image to render an image in our slider.
Step 3:
Clone the Strip by right clicking the
$w.ColumnStrip element and selecting "Duplicate". Now name the $w.ColumnStrip and the $w.Text elements something
that makes sense for your site.
I have used #columnStrip1 which contains #title1, and #columnStrip2 which contains #title2. Make sure that the two $w.ColumnStrips overlap each other (one is superimposed on the other). We will use these to create the slide show effect.
Step 4:
Create a slide change control to manage slide transition. I did this using a $w.Box that slightly overlaps the $w.ColumnStrip elements. This prevents the editor from adding the controls as children of the top most $w.ColumnStrip which we don't want.
Make the $w.Box background transparent by setting the opacity to 0.
I chose an arrow design $w.VectorImage for the left and right arrows and named the elements #left and #right.
Step 5:
We need to wire up the arrows for our controls to move the slides left and right. You can do this in two ways. Firstly you can add onClick() handlers into the $w.onReady() function override OR you can bind the element via its property page. I chose the latter. Which results in the Wix Editor adding a function hook into the code page for you
external function right_click()
Step 6:
Now we can add some code to the page to create our SlideShow:
let isOdd = true;
$w.onReady(function () {
// Make sure our slide data is loaded before we try to load up our
// first slide
$w('#slideContent').onReady(() => {
showNewItem($w('#slideContent').getCurrentItem());
});
});
/*
function: showNextItem
description: Uses data from our data set to populate the
next slide and when loaded swaps it with the
one currently visible
arguments: item - the database record
direction - which way to animate our slide
*/
function showNewItem(item, direction) {
if (item && item['title'] && item['photo']) {
let nextSlide = getNextStrip();
let strip = nextSlide[0];
let title = nextSlide[1];
strip.background.src = item['photo'];
title.text = item['title'];
swapSlides(direction);
}
}
/*
function: getNextStrip
description: Simple toggle function to select the elements we
need to populate for the next slide. The 'isOdd'
property is used to choose which elements we are
interested in. It gets toggled before we exit.
arguments: none
*/
function getNextStrip() {
let result = [];
if (isOdd) {
result.push($w('#columnStrip1'));
result.push($w('#title1'));
} else {
result.push($w('#columnStrip2'));
result.push($w('#title2'));
}
// Toggle the element selector
isOdd = !isOdd;
return result;
}
/*
Function: swapSlides
Description: This function performs the slide show rendering
It makes use of the fact that effects are performed
using Promises and collects the effect promises
show() and hide() in a super promise using the all()
function. Direction is flowed down to the show and hide
methods which control animation
Arguments: direction - either 'left' or 'right'
*/
function swapSlides(direction) {
let keepMyPromise = null;
if (isOdd) {
keepMyPromise = Promise.all(
[
hide($w('#columnStrip1'), direction),
show($w('#columnStrip2'), direction)
]);
} else {
keepMyPromise = Promise.all(
[
show($w('#columnStrip1'), direction),
hide($w('#columnStrip2'), direction)
]);
}
// Returns the Promise we created in case the calling function
// has something else to do after
return keepMyPromise;
}
/*
Function: hide
Description: Creates a simple overlay on the normal $w.HiddenMixIn
API to apply Effect filters to the hide() function
Arguments: element - the $w() element that we are hiding
direction - 'left' or 'right' for slide egress direction
*/
function hide(element, direction) {
let slideEffect = {
"direction": 'right'
};
if (direction === 'right') {
slideEffect.direction = 'left';
}
// Note we are using 'fade' here. It was originally 'slide' but the
// effect was not a good one if you want to use slide then remove
// the fade and uncomment out this code:
// return element.hide('slide', slideEffect);
return element.hide('fade');
}
/* Function: hide
Description: Creates a simple overlay on the normal
$w.HiddenMixIn API to apply Effect filters
to the hide() function
Arguments: element - the $w() element that we are showing
direction - 'left' or 'right' for slide egress
direction
*/
function show(element, direction) {
let slideEffect = {
"direction": 'left'
};
if (direction === 'left') {
slideEffect.direction = 'right';
}
return element.show('slide', slideEffect);
}
/*
****** Element handler functions
Function: right_click
Description: fires when the right $w.VectorImage is clicked.
Used to advance the slide show to the right by
using the dataset $w('#slideContent') next() function
or resetting the dataset index to 0 if we have reached
the end of the data set. This creates a circular
slide effect.
Arguments: event - the event object associated with the click
$w - the page scope variable for our element management
Returns: a promise that should resolve to the next item from
the data set which is ".then()" passed to our
showNewItem function where the slide show effect happens!
*/
export function right_click(event, $w) {
let dataset = $w('#slideContent');
let keepMyPromise = null;
if (dataset.getCurrentItemIndex() === dataset.getTotalCount() - 1) {
// We need to reset to the start of the slide show
keepMyPromise = dataset.setCurrentItemIndex(0)
.then(() => {
return Promise.resolve(dataset.getCurrentItem());
});
} else {
// Get the next item
keepMyPromise = dataset.next();
}
return keepMyPromise
.then((newItem) => {
showNewItem(newItem, 'right');
});
}
/*
Function: right_click
Description: fires when the right $w.VectorImage is clicked.
Used to advance the slide show to the right by
using the dataset $w('#slideContent') previous()
function or resetting the dataset index to the end of
the dataset if we have reached the beginning of the
dataset. This creates a reverse circular slideshow effect.
Arguments: event - the event object associated with the click
$w - the page scope variable for our element management
Returns: a promise that should resolve to the next item from
the data set which is ".then()" passed to our
showNewItem function where the slide show effect happens!
*/
export function left_click(event, $w) {
let dataset = $w('#slideContent');
let keepMyPromise = null;
if (dataset.getCurrentItemIndex() === 0) {
// We need to reset to the start of the slide show
keepMyPromise = dataset.setCurrentItemIndex(dataset.getTotalCount() - 1)
.then(() => {
return Promise.resolve(dataset.getCurrentItem());
});
} else {
// Get the next item
keepMyPromise = dataset.previous();
}
return keepMyPromise
.then((newItem) => {
showNewItem(newItem, 'left');
});
}
I hope some of you find this useful.
Steve
You can do this much more simply: https://www.wix.com/velo/example/dynamic-slideshow
anyone can help me? i try to do the same steps but it doesn't work. The slider display only the first slide without the cursor and it don't go on :(
Thank you stcroppe - a massive help.
Slight tweaks to swapSlides() makes the slide effect work better.
The incoming slide has to slide in from the opposite side (counter-intuitively), and a small delay leaves a blank space between the slides.
function swapSlides(direction) { let keepMyPromise = null; var opposite = "right" if (direction === "right") { opposite = "left"; } if (isOdd) { keepMyPromise = Promise.all( [ hide($w('#columnStrip1'), direction), setTimeout(function() { show($w('#columnStrip2'), opposite) }, 500) ]); } else { keepMyPromise = Promise.all( [ hide($w('#columnStrip2'), direction), setTimeout(function() { show($w('#columnStrip1'), opposite) }, 500) ]); } // Returns the Promise we created in case the calling function // has something else to do after return keepMyPromise; }
Thank you very much for taking the time to share this. It's working really well to show my featured blog posts. I'd really appreciate it if you could tell me how to create a strip column that is less than the full page width.
I know I'm late to the party here but I'm trying to apply the same methodology you're saying to do except on 4 total columns at a time, and loading 1 at a time instead of all 4 again for my dynamic slideshow.
I'd like to also note that I did everything you suggested step by step and have to say I'm very proud of myself in accomplishing that and making it work so far, thank you very much for that :D
Hi Matt:
Im not sure exactly what you are experiencing.
I did have problems with getting the slide effect to work. I think that your may be using a slide show control?
Because the initial target for this was a mobile device and wix doesn't support mobile devices I used an element swap method using show and hide effects to get a sliding effect. The way I avoided what you may be experiencing was to hide the displayed 'slide' using a fade effect while showing the replacement slide using a fly in effect. I also played with the effect timings.
hey stcroppe, I made soomethign very similar for a client but couldn't get past the 'slide' transition effect problem. I just tried your code (which is excellent by the way) but it looks like you ran into something similar. Do you know of any way to stop the scroll bar at the bottom of the page from popping up when you slide a strip off screen?
Thank you so much, you don’t know what you did for me.
You are welcome!
thanks for the ideas and for the excellent documentation