A wrapping method must be specified for any Freighter carousel,
and there are 3 to choose from.
What is Wrapping?
The term 'wrapping' in the context of a Freighter carousel is
used to describe the behavior of a carousel when it is scrolled
in either direction past the available elements. When a user
scrolls to the last carousel items in your carousel, how should
the container respond to another scroll to the right? This is
the question that can be answered by the 'wrapping method' of
your carousel.
The wrapping method for a Freighter carousel is indicated in the
constructor, as the third parameter. See the code block below
that demonstrates how to utilize the wrapping method
wrap-simple in the carousel
myCarousel:
const myCarousel = new Freighter(
'myCarousel', // Specify the container ID here.
'none', // Specify the desired resizing method here.
'wrap-simple', // Specify the desired wrapping method here.
{}, // Dymamic properties can be specified here.
);
One important thing to note is that the wrapping is one of 3
carousel properties not specified within the
CarouselProperties object passed to the
constructor. This is because the
CarouselProperties object only contains the
properties that can be changed after the carousel is
initialized. Wrapping is a fixed property that must be
specified at initialization, and therefore does not belong
inside of this object.
Wrapping Methods
Freighter offers 3 wrapping methods: none,
wrap-simple, and wrap-smart. For the
most part, these methods will behave as you might expect. There
are a few quirks to each of them, however, that are worth
noting.
none
The first and simplest wrapping method
disallows scrolling to the left beyond the first item
or scrolling to the right beyond the last item. This wrapping
method guarantees that the order of carousel items will always
be preserved; an carousel item with a lower index will never be
displayed after an carousel item with a higher index. It also
guarantees that the carousel will never display an empty space
where an item should be.
Take for example the carousel created from the code below. This
code presupposes that
<div id="myCarousel"> already exists in the
DOM, and has 9 carousel items as children. Notice that the
carousel cannot be scrolled to the left until it has been
scrolled right at least once.
This is all works fine. In the example above, the number of
items (9) was evenly divisible by the scrollBy and
numItemsVisible values (both 3). How would a
carousel with a wrapping method of none behave if
this isn't the case?
Let's start by increasing scrollBy to 4. This
carousel can scroll to the right by 4 elements: the first scroll
will set the visible elements to '5 6 7'. Attempting to scroll
again would set the visible elements to '9 10 11' if they
existed, but our carousel only contains 9 elements. Try
scrolling the carousel to see how the wrapping method
none behaves in this situation:
1
2
3
4
5
6
7
8
9
Clearly, wrapping method none does not scroll past
the first or last element! This means that the
scrollBy property is actually treated as the
maximum number of elements that can be scrolled in
either direction, but can be less than this if there are not
enough elements to scroll that far.
What if there are fewer carousel items than the
numItemsVisible value? Well, because there are no
more elements to either the left or right of the currently
visible elements, the carousel won't be able to scroll at all:
1
2
When items are added or removed from a carousel using the
wrapping method of none, the 'empty space'
principle must be maintained: the carousel must never display an
empty space if an item is available to fill it.
Adding new items does not put the carousel in risk of violating
this principle, but removing them does. What if a carousel with
9 items is scrolled all the way to the right (displaying '7 8
9'), and the last two items are removed? In order to preserve
the 'empty space' principle, the carousel must be scrolled back
to the left until all empty spaces are filled.
Try it for yourself - scroll to the end of the carousel, remove
the last two elements, and see how the carousel is automatically
shifted back in order to prevent the introduction of unneccesary
empty slots.
1
2
3
4
5
6
7
8
9
The same is done with a carousel whose items are removed from
the start when scrolled all the way to the left:
1
2
3
4
5
6
7
8
9
wrap-simple
The second wrapping method is more powerful that
none, allowing for a simple infinite scrolling
experience. The scrollBy value is always treated as
the exact number of items to scroll by, regardless of
how many items are available to scroll. This means that the
carousel's absolute ordering of items may change, though its
relative order will be preserved.
Below is the code required to set up a carousel with the
wrap-simple wrapping method. This code presupposes
that <div id="myCarousel"> already exists in
the DOM, and has 9 carousel items as children. Try scrolling
left from the first item, or right from the last item.
Much like the wrapping method none, a carousel with
a total number of items (9) that is evenly divisible by the
scrollBy and
numItemsVisible properties (both 3) works out
nicely. Let's see how the carousel's behavior changes when this
isn't the case. Below is the same carousel with a
scrollBy value of 2:
1
2
3
4
5
6
7
8
9
In this case, you'll notice that it takes a few full traversals
of the carousel for the '1 2 3' items to be restored. This is
also the first time we've seen the carousel's absolute ordering
of items change: scrolling left from the original position shows
'8 9 1' as the visible carousel items.
Allowing wrapping with this method means that there is always a
next (or previous) set of items to display in the carousel . As
a result of this, carousels with the
wrap-simple wrapping method will not have
empty spaces. For example, take a look at the carousel below,
which has a numItemsVisible of 4, but only 3 items
in the carousel:
1
2
3
Because the carousel is allowed to wrap, it means that there
will always be another item to add to the end of the
carousel, and it will always be the first items in the
carousel.
The behavior of the wrap-simple wrapping method
means that carousel items may be duplicated in the DOM. If you
inspect this page, you will notice that duplicate carousel items
have the same IDs. If you write code that is dependent on the
IDs of elements contained within carousel items, you may run
into issues.
One way to avoid this issue is to ensure that the number of
items in the carousel is always evenly divisible by the
numItemsVisible and scrollBy values.
If you want your carousel to wrap, but you want the absolute
order of carousel items to be preserved (i.e. not the previous
example), you should make sure that the total number of items in
the carousel is evenly divisible by the
numItemsVisible and scrollBy values.
The ability to wrap around in either direction means that
removing carousel items will never result in blank spaces in the
carousel, unless the carousel is emptied completely:
1
2
3
4
5
6
7
8
9
wrap-smart
The third and final wrapping method is much easier to understand
if you already know how the previous wrapping methods work. In
short, wrap-smart is almost like the combination of
the above wrapping methods. Like none,
wrap-smart will initially treat
scrollBy as a maximum, ensuring that scrolling will
not disrupt the relative order of items in the carousel.
However, once the end of the carousel is reached,
wrap-smart will scroll by however much is needed to
fully wrap to the other side of the carousel.
If this isn't clear at first, the examples below should help you
understand what's going on.
First, here's how a carousel with the
wrap-smart wrapping method can be created. Again,
this code presupposes that
<div id="myCarousel"> already exists in the
DOM, and has 9 carousel items as children.
Imediately, you'll notice that this carousel is behaving in
exactly the same way as the one before it that used
wrap-simple. This is true: both of the variations
of wrap (wrap-simple and wrap-smart)
behave the same when the number of carousel items is evenly
divisible by the numItemsVisible and
scrollBy values. Let's see what happens when we
change scrollBy to be 2:
1
2
3
4
5
6
7
8
9
When the end of the carousel is hit (visible items are '7 8 9'),
rather than just scrolling by the scrollBy value of
2, the carousel is scrolled by 3 so that the absolute
positioning of carousel items does not change.
Let's try one more example, this time with a
scrollBy value of 4:
1
2
3
4
5
6
7
8
9
Now, the amount that the carousel scrolls changes with each
subsequent scroll! If you scroll right 3 times, the carousel
will first scroll by 4, then 2, then 3. What's going on?
The wrap-smart wrapping method treats the
scrollBy value as a maximum, meaning that
it will always try to scroll that much, but may stop earlier to
avoid scrolling past either end of the carousel. When one of the
ends is reached, the next scroll will wrap over to the other end
of the carousel as much as it needs in order to keep the
absolute ordering of the carousel items. This is why this
wrapping method is called wrap-smart: yes, your carousel will wrap, but it will do so intelligently
in order to prevent items from losing their absolute ordering.
One of the most common use cases for this wrapping method is a
carousel that only scrolls by 1 item, but should 'snap' back to
the beginning when wrapping. Below is the code and resulting
carousel for such a use case:
No extra code, no event listeners for when the carousel hits the
end, and no fear of the absolute order being altered.
There are a few cautions to be aware of when using
wrap-smart, many of which are fully explained in
their respective sections on the cautions page. These include
carousels whose wrapping methods may
change from wrap-smart to
wrap-simple under specific circumstances
, as well as the possibility of the absolute ordering being
temporarily altered when adding or removing items.