class GalleryCarousel {
options = {
elementClickTriggerSelector: null,
slideIdAttrName: null,
dataTableInstance: null,
};
constructor(modalId, options = null) {
this.modalId = modalId;
let elementClickTriggerSelector = this.$modal.data('element-click-trigger-selector');
this.options.elementClickTriggerSelector = elementClickTriggerSelector;
if (options) {
this.options = { ...this.options, ...options };
}
this.currentGalleryIndex = 0;
this.initEvents();
if (this.options.elementClickTriggerSelector) {
$(this.options.elementClickTriggerSelector).on('click', (e) => {
e.preventDefault();
const index = $(e.target).data('gallery-index');
this.open(index);
});
}
if (this.options.slideIdAttrName && this.options.dataTableInstance) {
this.setGalleryIndexRetriever((increment, slideElement, currentGalleryIndex) => {
let tableData = this.options.dataTableInstance.getAllFilteredTableData();
let itemIdColIndex = this.options.dataTableInstance.getColumnIndexByColumnId('id');
if (itemIdColIndex === -1) {
throw new Error("Item ID column not found in data table");
}
let curTableRowIndex = null;
let curItemId = parseInt($(slideElement).attr(this.options.slideIdAttrName));
for (let i = 0; i < tableData.length; i++) {
let tableRowItemId = parseInt(tableData[i][itemIdColIndex]);
if (tableRowItemId === curItemId) {
curTableRowIndex = i;
break;
}
}
if (curTableRowIndex === null) {
throw new Error("Current slide id not found in filtered table data");
}
//find next or prev slide index in filtered table data
curTableRowIndex += increment;
if (curTableRowIndex < 0) {
curTableRowIndex = tableData.length - 1;
} else if (curTableRowIndex >= tableData.length) {
curTableRowIndex = 0;
}
let nextItemId = parseInt(tableData[curTableRowIndex][itemIdColIndex]);
//find gallery index by item id
for (let j = 0; j < this.$slides.length; j++) {
let itemId = parseInt($(this.$slides[j]).attr(this.options.slideIdAttrName));
if (itemId === nextItemId) {
return j;
}
}
return 0
});
}
}
get $modal() {
return $('#' + this.modalId);
}
get $slides() {
return this.$modal.find('.gallery-slide');
}
get $title() {
return this.$modal.find('.gallery-title');
}
get $slide() {
return this.$slides.eq(this.currentGalleryIndex);
}
initEvents() {
$(document).on('click', `#${this.modalId} .gallery-next-btn`, () => this.next());
$(document).on('click', `#${this.modalId} .gallery-prev-btn`, () => this.prev());
// Support keyboard navigation
$(document).on('keydown', `#${this.modalId}`, (e) => {
if (e.key === "ArrowRight") {
this.next();
} else if (e.key === "ArrowLeft") {
this.prev();
}
});
// Focus modal on show to enable keyboard events
$(document).on('shown.bs.modal', `#${this.modalId}`, () => {
this.$modal.trigger('focus');
});
}
updateGallery() {
const $slides = this.$slides;
$slides.addClass('d-none').removeClass('d-flex');
if (this.currentGalleryIndex < 0) {
this.currentGalleryIndex = $slides.length - 1;
} else if (this.currentGalleryIndex >= $slides.length) {
this.currentGalleryIndex = 0;
}
const $currentSlide = $slides.eq(this.currentGalleryIndex);
if ($currentSlide.length) {
$currentSlide.removeClass('d-none').addClass('d-flex');
// Update title
let isPermanentTitle = this.$title.hasClass('permanent');
if (!isPermanentTitle) {
let slideText = $currentSlide.data('slide-text');
const name = slideText || ('Изображение ' + (this.currentGalleryIndex + 1));
this.$title.text(name);}
}
}
setGalleryIndexRetriever(callback) {
this.galleryIndexRetriever = callback;
}
open(index) {
this.currentGalleryIndex = index;
this.updateGallery();
this.$modal.modal('show');
}
next() {
if (this.$slides.length > 0) {
if (this.galleryIndexRetriever) {
this.currentGalleryIndex = this.galleryIndexRetriever(1, this.$slide, this.currentGalleryIndex);
} else {
this.currentGalleryIndex++;
}
this.updateGallery();
}
}
prev() {
if (this.$slides.length > 0) {
if (this.galleryIndexRetriever) {
this.currentGalleryIndex = this.galleryIndexRetriever(-1, this.$slide, this.currentGalleryIndex);
} else {
this.currentGalleryIndex--;
}
this.updateGallery();
}
}
}