The Event "changed.owl.carousel" has a wrong/invalid index in event.item.index when loop is enabled.
Object { count=5, index=3}
Object { count=5, index=4}
Object { count=5, index=5}
Object { count=5, index=6}
Object { count=5, index=7}
I have the following Options:
animateOut: "fadeOut",
items: 1,
itemsDesktop: false,
itemsDesktopSmall: false,
itemsTablet: false,
itemsTabletSmall: false,
itemsMobile: false,
singleItem : true,
itemsScaleUp: true,
pagination: false,
navigation: false,
autoplay: true,
loop: true,
autoplayTimeout: 5000,
slideSpeed: 300
:+1: Same issue with loop: true option (1 or multiple items)
+1 I always have issues when I use the loop:true option
It's also blocking for me, in the same condition (loop:true)
same issue here when loop: true
if the carousel is set to autoplay the index starts at 3
if the carousel is not set to autoplay the index starts at 2
not yet sure if this is consistent, if so, easily fixed in my own code
Here is a JSFIDDLE showing the error:
http://jsfiddle.net/louiswalch/rt3qkpb6/1/
Yes, I am getting this issue too.
It seems that when loop is set to true, Owl Carousel adds in "clone" slides and then mistakenly includes these when calculating the index. I have a carousel with 4 full-width slides. When loop is set to false, the index.count returns 0,1,2,3 (correct) and when loop is set to true, it returns 3,4,5,6,3,4,5,6... etc. (incorrect)
A quick fix for now (that might be worth implementing into the actual Owl Carousel) is:
var current_slide_in_loop = e.page.index - (e.relatedTarget._clones.length / 2)
Updated fiddle based on post by @louiswalch
Same problem also.
Fix above does not seem to work with version 2.1.6.
I had to use this formula:
index = owlEvent.item.index;
if(options.loop) {
var tempFix = index - (owlEvent.relatedTarget.clones().length / 2);
if(tempFix > 0) {
index = tempFix;
}
}
Not a good way to fix it definatelly if its fixed one day.
Will this ever be fixed? It's setting the active class to the wrong item in my case :( @Rouche Where did you add this code? Furthermore I'm using the NG2 Wrapper version of this... so doing this inside the Component class would be much more preferable:
if (this.homeCarousel.options.loop)
????
options is the options pased to owl init function owlCarousel()
options.onChanged(
(owlEvent: OwlCarouselEvent, scope: ScopeCarrousel) => {
if (!owlEvent.item.index) {
return;
}
//Bug index loop : https://github.com/OwlCarousel2/OwlCarousel2/issues/1203
scope.item = owlEvent.item.index;
if(scope.options.loop) { //We are using loop option
var tempFix: number = scope.itemCourant - (owlEvent.relatedTarget.clones().length / 2)
if(tempFix >= 0) {
scope.itemCourant = tempFix;
}
}
scope.currentItem++;
//Do stuff with correct index
...
}
);
Thanks for your post, this got me all excited but to no avail... I am now getting this:
ERROR Error: Uncaught (in promise): TypeError: this.homeCarousel.options.onChanged is not a function
I get my homeCarousel like this:
@ViewChild('homeCarousel') homeCarousel: OwlCarousel
template:
package.json
"ng2-owl-carousel": "^0.1.15",
I'm doing the this.homeCarousel.options.onChanged stuff in the ngOnInit
Thanks for your help!
For NG2 wrapped carousel... you can do this:
(I'm doing it in the ngOnInit)
(<any>this.homeCarousel.$owlChild).el.nativeElement.onchange = function(e) {
setTimeout(() => {
var item = e.item;
var owl = e.relatedTarget;
let itemCount = 0;
for(let i = 0; i < owl.$stage[0].childNodes.length; i++)
{
owl.$stage[0].childNodes[i].className = owl.$stage[0].childNodes[i].className.replace(' active', '');
if (owl.$stage[0].childNodes[i].className.indexOf('clone') == -1)
{
if (itemCount == item.index - 1)
owl.$stage[0].childNodes[i].className += ' active';
else
itemCount++;
}
}
}, 100);
}
The problem remains still that the initially loaded frame is not getting the active applied to it... only on the second round trip it does.
For this who care, again this is for the NG2 wrapper of OwlCarousel 2, here you go:
```
ngOnInit() {
setTimeout(() => this.fixCourouselActiveBug() , 100);
}
private fixCourouselActiveBug() {
let owl: any;
for(let key in (
{
if (typeof (
{
owl = (
break;
}
}
this.fixChildNodes(owl);
(<any>this.homeCarousel.$owlChild).el.nativeElement.onchange = () => {
setTimeout(() => this.fixChildNodes(owl), 100);
}
}
private fixChildNodes(owl: any, fixAmount: number = 2) {
let itemCount = 0;
for(let i = 0; i < owl.$stage[0].childNodes.length; i++)
{
owl.$stage[0].childNodes[i].className = owl.$stage[0].childNodes[i].className.replace(' active', '');
if (owl.$stage[0].childNodes[i].className.indexOf('clone') == -1)
{
if (itemCount == owl._current - fixAmount)
owl.$stage[0].childNodes[i].className += ' active';
else
itemCount++;
}
};
}
```
It's definitely a jimmy-rig, but it lets me keep going...
I managed to sync two infinite owl carousels based on your pretty good idea, thank you @Rouche!
I simplified your code (removed if (index > 0) thing) because synced carousel remained still when going from the last slide to first.
const loop = true, $carousels = $('.synced-carousels');
$carousels.owlCarousel({
/* whatever config */
loop: loop
}).on('translated.owl.carousel', function(e) {
let targetIndex = e.item.index;
if (loop) {
targetIndex -= e.relatedTarget.clones().length / 2;
}
$carousels.not(this).trigger('to.owl.carousel', [targetIndex]);
})
You guys are awesome, thanks. One remark is that / 2 won't work as expected when active item is the first item in the carousel and you're dragging in the reverse direction so the next active item will be the last item in the carousel. In this situation there'll be +1 clone before index, so the only way we have is to get the exact number of clones before index. And there's a useful jQuery function prevAll for it. Also
$carousels.not(this) means all other carousels on the page which is not what I needed, so I trigger strictly the previous carousel as it's main to this one. Here's the code:
.on('changed.owl.carousel', function (e) {
var index = e.item.index;
var offset = $(e.target).find('.active:first').prevAll('.cloned').length;
$(e.target.parentElement.previousElementSibling).trigger('to.owl.carousel', index-offset);
});
This is still not working properly if displayed item is not 1. Numbers repeat in my case :(
I'm still experiencing the issue
++1 still experiencing issue
I'm having the same issue, in place of 4 existing items i see 8 cloned. Any fix?
function fixOwlCurrentIdx(event) {
let current = (event.item.index + 1) - event.relatedTarget._clones.length / 2;
let itemsCount = event.item.count;
if (current > itemsCount || current == 0) {
current = itemsCount - (current % itemsCount);
}
return current - 1;
}
Example: jsfiddle.net/yunusga/4zvpns6j/
function syncPosition2(el) {
if (syncedSecondary) {
let current = (el.item.index + 1) - el.relatedTarget._clones.length / 2;
let itemsCount = el.item.count;
if (current > itemsCount || current == 0) {
current = itemsCount - (current % itemsCount);
}
bigimage.data("owl.carousel").to(current - 1, 100, true);
}
}
Any updates on this? Quite an important issue, yet still open 4 years later
@szymsza the project has now been depreciated, so you'll need to either find an actively maintained fork, or migrate to a different slider - TinySlider seems the common recommendation (as mentioned in the updated README.md)
Most helpful comment
function syncPosition2(el) {
if (syncedSecondary) {
let current = (el.item.index + 1) - el.relatedTarget._clones.length / 2;
let itemsCount = el.item.count;