I imported the keen slider js into our current project and configured an own javascript to form and initialize the sliders. It works quite fine for most of the sliders, just not for this specific case: a javascript which alters an array of elements based on the users actions. The keen slider seemingly cant deal with this (instead of one row, the slider renders multiple rows ontop of each other. The arrows are insanely buggy too.) and i just cant seem to figure out why. I will post 1: The javascript which renders the slider items after document ready // whenever the user searches something and the function of the delete button on the slides, which works flawlessly at least. 2: the keenslider.js i wrote myself to initialize the sliders. It just feels like im missing something silly since im rather new to javascript and jquery. Im also sorry if this question is put terribly, i dont know which informations are important to give yet.
1:
/**
* renders markup for the last searches from the array of the last history items
* @param searchHistoryData
* @return {string|null}
*/
renderSearchHistoryContainers(searchHistoryData) {
if (searchHistoryData === null) return null;
var containers = [];
for (var k in searchHistoryData) {
if (searchHistoryData.hasOwnProperty(k)) {
var sh = searchHistoryData[k];
// Regionsgruppen als [] beachten
// var locationId = ($.type(sh.loc_id) === 'array' ? sh.loc_id.join('-') : sh.loc_id);
// var id = k + '_' + sh.loc_key + '_' + locationId;
var imageId = this.createDestinationImageKey(k, sh);
var markup = '<div class="keen-slider__slide mb-1">n' +
'<div class="col">n' +
'<div class="card offer-card shadow-sm">n' +
'<div class="d-flex"> ' +
'<div class="text-dark text-truncate pt-2 ps-2"> ' + sh.title + '</div>' +
'<i data-key="' + k + '" class="ms-auto p-2 ps-4 far fa-xmark my-auto fw-light cursor-p searchHistoryDeleteButton" style="z-index: 99;"></i>n' +
'</div>n' +
'<a class="row g-0 p-2 text-decoration-none stretched-link" href="' + sh.url + '" title="Suche nach ' + sh.title + ' ausführen">n' +
'<div class="col-auto">n' +
'<div class="d-flex justify-content-center overflow-hidden rounded-2" style="width: 4.5rem; height: 4.5rem;">n' +
'<img id="' + imageId + '" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" style="height: 4.5rem;" alt="Destinationsbild" title="' + sh.title + '">n' +
'</div>n' +
'</div>n' +
'<div class="col text-muted ms-2 text-truncate">n' +
'<div class="line-clamp-3">n' + sh.text +
'</div>n' +
'</div>n' +
'</a>n' +
'</div></div></div>';
containers.push(markup);
}
}
if (containers.length === 0)
return null;
return containers.join('');
},
/**
* renders markup for the placeholder container id="search-history-holderie" for the searchHistory
* @return {string}
*/
renderSearchHistoryHolderContainer() {
let localData = JSON.parse(localStorage.getItem('searchHistoryData'));
if (localData.length !== 0) {
return '' +
'<div class="container mt-4">' +
'<div id="historyIndicator" class="h4 col-form-label w-100">Vergangene Suchanfragen</div>' +
'<div class="row keen-slider keen-slider-dynamic" id="search-history-holder" data-slides="3" data-slides-xl="3" data-slides-lg="3" data-slides-md="3" data-slides-sm="2" data-slides-xs="1">' +
'</div>';
}
}
$(document).on('click', '.searchHistoryDeleteButton', function () {
let searchHistoryHolder = $('#search-history-holder');
let optionen = searchHistoryHolder.data('keenSliderOptions');
let navigation = searchHistoryHolder.data('keenSliderNavigation');
let slide_index = $(this).parents(".keen-slider__slide").index('.keen-slider__slide');
let localData = JSON.parse(localStorage.getItem('searchHistoryData'));
localData.splice(slide_index, 1);
localStorage.setItem('searchHistoryData', JSON.stringify(localData));
searchHistory.renderSearchHistoryContainers(searchHistory.createSearchHistoryData(6));
searchHistoryHolder.data('keenSliderObject').destroy();
searchHistoryHolder.children().eq(slide_index).remove();
var slider = new KeenSlider('#search-history-holder', optionen, [navigation]);
searchHistoryHolder.data('keenSliderObject', slider);
console.log('Der slider wurde neu erstellt.');
if (localData.length === 0) {
searchHistoryHolder.slideUp();
$('#historyIndicator').remove();
}
$().showToast({
text: 'Ihre vergangene Suchanfrage wurde gelöscht.',
class: 'text-white bg-success',
btnClass: 'btn-close-white'
});
return false;
});
2:
$(document).ready(function() {
var keenSliders = $(".keen-slider");
keenSliders.each(function() {
var keenCarousel = $(this),
responsive = {},
slides = keenCarousel.attr("data-slides"),
slidesLg = keenCarousel.attr("data-slides-lg"),
slidesMd = keenCarousel.attr("data-slides-md"),
slidesSm = keenCarousel.attr("data-slides-sm"),
slidesXs = keenCarousel.attr("data-slides-xs");
if (slidesXs !== undefined) {
if (slidesXs === '1') {
slidesXs = 1.2;
responsive["(max-width: 576px)"] = { slides: {origin: "center", perView: slidesXs, spacing: 0}};
} else {
responsive["(max-width: 576px)"] = { slides: {perView: slidesXs, spacing: 0}};
}
}
if (slidesSm !== undefined) {
if (slidesSm === '1') {
slidesSm = 1.2;
responsive["(min-width: 576px)"] = { slides: {origin: "center", perView: slidesSm, spacing: 0}};
} else {
responsive["(min-width: 576px)"] = { slides: {perView: slidesSm, spacing: 0}};
}
}
if (slidesMd !== undefined) {
if (slidesMd === '1') {
slidesMd = 1.2;
responsive["(min-width: 768px)"] = { slides: {origin: "center", perView: slidesMd, spacing: 0}};
} else {
responsive["(min-width: 768px)"] = { slides: {perView: slidesMd, spacing: 0}};
}
}
if (slidesLg !== undefined) {
responsive["(min-width: 1200px)"] = { slides: {perView: slidesLg, spacing: 0}};
}
if (slides !== undefined) {
responsive["(min-width: 1400px)"] = { slides: {perView: slides, spacing: 0}};
}
// suche slides über selector
let childSelector = '.keen-slider__slide';
var options = {
loop: true,
mode: "free-snap",
perView: 1.2,
breakpoints: responsive,
selector: childSelector
};
createKeenSlider(keenCarousel, options);
});
/**
*
* @param element
* @param options
*/
function createKeenSlider(element, options) {
var slider = new KeenSlider(element[0], options, [navigation]);
element.data('keenSliderObject', slider);
element.data('keenSliderOptions', options);
element.data('keenSliderNavigation', navigation);
}
function navigation(slider) {
let wrapper, dots, arrowLeft, arrowRight;
// Funktion zum aufrufen aller Markups
function markup(remove) {
let result = true;
wrapperMarkup(remove);
if(!dotMarkup(remove)) return;
arrowMarkup(remove);
}
//Funktion zum Entfernen eines Elementes
function removeElement(elment) {
elment.parentNode.removeChild(elment);
}
function createDiv(className) {
var div = document.createElement("div");
var classNames = className.split(" ");
classNames.forEach((name) => div.classList.add(name));
return div;
}
// Funktion zum Erstellen des HTML-Markups für Pfeile
function arrowMarkup(remove) {
if (remove) {
removeElement(arrowLeft);
removeElement(arrowRight);
return;
}
arrowLeft = createDiv("arrow arrow--left");
arrowLeft.addEventListener("click", function() {
var newIndex = parseInt(slider.track.details.abs) - parseInt(slider.options.slides.perView);
slider.moveToIdx(newIndex, true);
});
arrowRight = createDiv("arrow arrow--right");
arrowRight.addEventListener("click", function() {
var newIndex = parseInt(slider.track.details.abs) + parseInt(slider.options.slides.perView);
slider.moveToIdx(newIndex, true);
});
wrapper.appendChild(arrowLeft);
wrapper.appendChild(arrowRight);
}
// Funktion zum Erstellen des HTML-Markups für Wrapper
function wrapperMarkup(remove) {
if (remove) {
var parent = wrapper.parentNode;
while (wrapper.firstChild)
parent.insertBefore(wrapper.firstChild, wrapper);
removeElement(wrapper);
return;
}
wrapper = createDiv("navigation-wrapper");
slider.container.parentNode.appendChild(wrapper);
wrapper.appendChild(slider.container);
}
// Funktion zum Erstellen des HTML-Markups für Punkte (Dots)
function dotMarkup(remove) {
if (remove) {
removeElement(dots);
return true;
}
dots = createDiv("dots");
if(slider.track.details == null){
return false;
}
var numDots = Math.ceil(slider.track.details.slides.length / Math.floor(slider.options.slides.perView));
// Erzeugung der Punkte (Dots) und Zuweisung der Klick-Handler
for (var i = 0; i < numDots; i++) {
var dot = createDiv("dot");
dot.addEventListener(
"click",
(function (page) {
return function () {
// Berechnung des Zielindex basierend auf der gewählten Seite
var targetIndex = page * Math.floor(slider.options.slides.perView);
slider.moveToIdx(targetIndex);
};
})(i)
);
dots.appendChild(dot);
}
// Hinzufügen der Punkte (Dots) zum Wrapper-Element
wrapper.appendChild(dots);
return true;
}
// Funktion zum Aktualisieren der CSS-Klassen basierend auf dem aktuellen Slider-Status
function updateClasses() {
if(slider.track.details == null){
document.getElementById("search-history-holder").classList.add("d-none");
document.getElementById("historyIndicator").classList.add("d-none");
return false;
}
var activePageIndex = Math.floor(slider.track.details.rel / Math.floor(slider.options.slides.perView));
var dotArray = Array.from(dots.children);
dotArray.forEach(function (dot, idx) {
idx === Math.floor(activePageIndex)
? dot.classList.add("dot--active")
: dot.classList.remove("dot--active");
});
return true;
}
// Event-Handler‚
slider.on("created", () => {
markup();
updateClasses();
});
slider.on("optionsChanged", () => {
markup(true);
markup();
updateClasses();
});
slider.on("slideChanged", () => {
updateClasses();
});
slider.on("destroyed", () => {
markup(true);
});
}
});




