Slide duplication occurs if slides == 2
kwuite opened this issue · 4 comments
Dear @davidcetinkaya ,
When I create the slider instance with 2 "c-slider__slide" classes (rows) the 2 original get duplicated.
On execution of $('#hammer-slider').HammerSlider();
the slides get duplicated to 4 rows, but with 1, 3 or more slides, no duplication occurs. This happens in the older and on the current version.
Interesting though is that the dots still show only 2 slides, even though the html shows 4 rows and since my application is quite reactive, data discrepancies occurred.
Cine Sera,
kelvin
In my original video, I have 2 slides and if you watch the console you can actually see at least 3 rows in the video:
https://drive.google.com/file/d/0B5-m3MyUcpKFUHQ5YlBZc0UyeUk/view
Hello @kwuite ,
The slider injects 2 clones if you only provide 2 slides. This happens because the slider needs room to make the infinite carousel effect work without flickering when slides get shifted and 2 slides won't provide enough room for that.
As you've mentioned the cloning part can cause issues in some cases.
You can try to set rewind to true if you only have 2 slides before initializing the slider by counting nr of elements with the class name c-slider__slide.
If you're using babel you can do:
const rewind = slides.length > 1 ? false : true;
const sliderElement = document.getElementById('hammer-slider');
const slider = HammerSlider(sliderElement, { rewind });
If not try:
var rewind = slides.length > 1 ? false : true;
var sliderElement = document.getElementById('hammer-slider');
var slider = HammerSlider(sliderElement, { rewind: rewind });
Best regards,
David
Hi @davidcetinkaya ,
This solution does not fix the problem with my page reactivity. What would definitely help me out is having function like slider.destroy()
, that destroys the hammerslider instance. This way I can create a new instance from scratch in case reactivity occurs.
The slider.destroy
should also destroy his own "Phantom Slides" (slide duplication for preventing flickering) cause these slides are not reactive and as such I am unable to know whether they exist.
The carousel on my page can go from 2 to 3 slides and then back to 2 and as you might understand that will break the slider in case you recall the this.slider instance which I have to do when a slide gets added.
Thanks.
Kelvin.
Dear @davidcetinkaya,
The way that I solved this for myself in Meteor is with the following implementation:
function generateSlider() {
const slideCount = this.data.slides.length;
const sliderElement = document.getElementById('hammer-slider');
// Prevent infinite carousel effect if there are 2 slides
const rewind = slideCount == 2;
this.slider = HammerSlider(sliderElement, {
rewind,
mouseDrag: false,
slideShow: false,
dots: true,
minimumDragDistance: 30,
dragThreshold: 10,
mouseDrag: true,
});
/* Cleanup process */
// Remove dot duplicates if they exist
this.$('.c-slider__dots').not(':last').remove();
// Remove redundant buttons if is only 1 slide
if (slideCount == 1) {
// In case of Reactive Reload remove dots
this.$('.c-slider__dots').remove();
// Remove duplicated slides
this.$('.c-slider__slide').not(':first').remove();
// Remove dots
this.$('.c-slider__btn').css('display', 'none');
// Disable animations
this.$('.c-slider__container').addClass('disable--animations');
} else {
this.slider.setupSlider(0);
this.$('.c-slider__btn').css('display', '');
// Enable animations
this.$('.c-slider__container').removeClass('disable--animations');
}
}
Template.carousel.onRendered(function onRendered() {
this.generateSlider = generateSlider.bind(this);
/* Subscribe and watch */
this.autorun(() => {
// It has to be reactive in order to reload
this.data = Template.currentData();
Tracker.afterFlush(() => {
// here you are guaranteed that any DOM modification implied by the
// each loop is finished, so you can manipulate it using jQuery
this.generateSlider();
});
});
});
Template.carousel.events({
'click #next-btn'(event, instance) {
instance.slider.next();
},
'click #prev-btn'(event, instance) {
instance.slider.prev();
},
});
In case of interest the blaze template:
<template name="carousel">
<div class="c-slider white" id="hammer-slider">
<div class="c-slider__container">
{{#each slides}}
<div class="c-slider__slide" data-value="{{@index}}">
{{> Template.dynamic template=templateName data=templateContext}}
</div>
{{/each}}
</div>
<button class="c-slider__btn c-slider__btn--left" id="prev-btn"></button>
<button class="c-slider__btn c-slider__btn--right" id="next-btn"></button>
</div>
</template>
Did a check on any memory leaks but so far even with reactively changing the dom I didnt perceive any memory leaks even though on every afterflush I call the HammerSlide instance.
Cine Sera,
Kelvin
Hello @kwuite,
Glad you managed to solve it!
I won't be adding any new features to this plugin in the near future. Maybe I'll rewrite it from scratch with better code and more features some day.
I hope you find it useful anyway.
Best regards,
David