Files
Instagram-Gallery-Sync-Pro/public/js/gallery-frontend.js

258 lines
7.9 KiB
JavaScript

/**
* Instagram Gallery Sync Pro - Frontend Script
*
* Handles gallery initialization, masonry, lightbox, and lazy loading
*
* @package Instagram_Gallery_Sync_Pro
*/
(function ($) {
'use strict';
/**
* Gallery Controller
*/
const IGSPGallery = {
/**
* Initialize all galleries on page
*/
init: function () {
const self = this;
// Wait for DOM ready
$(document).ready(function () {
self.initGalleries();
});
},
/**
* Initialize individual galleries
*/
initGalleries: function () {
const self = this;
$('.igsp-gallery').each(function () {
const $gallery = $(this);
const layout = $gallery.data('layout');
// Set responsive CSS variables
self.setResponsiveVariables($gallery);
// Initialize based on layout
switch (layout) {
case 'masonry':
self.initMasonry($gallery);
break;
case 'slider':
self.initSlider($gallery);
break;
default:
self.initGrid($gallery);
}
// Initialize lightbox if enabled
if (typeof igspFrontend !== 'undefined' && igspFrontend.lightbox) {
self.initLightbox($gallery);
}
// Initialize lazy loading
self.initLazyLoad($gallery);
});
},
/**
* Set responsive CSS variables
*/
setResponsiveVariables: function ($gallery) {
const columnsTablet = $gallery.data('columns-tablet') || 2;
const columnsMobile = $gallery.data('columns-mobile') || 1;
$gallery.css({
'--columns-tablet': columnsTablet,
'--columns-mobile': columnsMobile
});
},
/**
* Initialize grid layout
*/
initGrid: function ($gallery) {
$gallery.addClass('loaded');
},
/**
* Initialize masonry layout
*/
initMasonry: function ($gallery) {
if (typeof Masonry === 'undefined' || typeof imagesLoaded === 'undefined') {
// Fallback to CSS-only masonry
$gallery.addClass('no-js loaded');
return;
}
$gallery.addClass('loading');
// Wait for images to load
imagesLoaded($gallery[0], function () {
const columns = parseInt($gallery.data('columns')) || 3;
const spacing = parseInt($gallery.data('spacing')) || 10;
// Calculate item width
const columnWidth = Math.floor(($gallery.width() - (spacing * (columns - 1))) / columns);
const msnry = new Masonry($gallery[0], {
itemSelector: '.igsp-item',
columnWidth: columnWidth,
gutter: spacing,
percentPosition: false,
transitionDuration: '0.3s'
});
$gallery.removeClass('loading').addClass('masonry-initialized loaded');
// Handle responsive
let resizeTimeout;
$(window).on('resize', function () {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function () {
msnry.layout();
}, 250);
});
});
},
/**
* Initialize slider layout
*/
initSlider: function ($gallery) {
if (typeof Swiper === 'undefined') {
console.warn('IGSP: Swiper library not loaded');
return;
}
const $swiperContainer = $gallery.find('.swiper');
if (!$swiperContainer.length) {
return;
}
const autoplay = typeof igspFrontend !== 'undefined' && igspFrontend.autoplay;
new Swiper($swiperContainer[0], {
slidesPerView: 'auto',
spaceBetween: parseInt($gallery.data('spacing')) || 10,
loop: true,
centeredSlides: false,
autoplay: autoplay ? {
delay: 4000,
disableOnInteraction: false
} : false,
pagination: {
el: '.swiper-pagination',
clickable: true
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev'
},
breakpoints: {
320: {
slidesPerView: 1,
centeredSlides: true
},
640: {
slidesPerView: 2,
centeredSlides: false
},
1024: {
slidesPerView: 3,
centeredSlides: false
}
}
});
$gallery.addClass('loaded');
},
/**
* Initialize lightbox
*/
initLightbox: function ($gallery) {
if (typeof GLightbox === 'undefined') {
console.warn('IGSP: GLightbox library not loaded');
return;
}
const lightbox = GLightbox({
selector: '.igsp-gallery [data-gallery="igsp-lightbox"]',
touchNavigation: true,
loop: true,
autoplayVideos: false,
openEffect: 'zoom',
closeEffect: 'zoom',
cssEfects: {
fade: { in: 'fadeIn', out: 'fadeOut' },
zoom: { in: 'zoomIn', out: 'zoomOut' }
}
});
},
/**
* Initialize lazy loading
*/
initLazyLoad: function ($gallery) {
const $lazyImages = $gallery.find('.igsp-image.lazyload');
if (!$lazyImages.length) {
return;
}
// Use native lazy loading if supported
if ('loading' in HTMLImageElement.prototype) {
$lazyImages.each(function () {
const $img = $(this);
$img.attr('src', $img.data('src'));
$img.removeClass('lazyload').addClass('loaded');
});
return;
}
// Fallback: Intersection Observer
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazyload');
img.classList.add('loaded');
observer.unobserve(img);
}
});
}, {
rootMargin: '100px'
});
$lazyImages.each(function () {
observer.observe(this);
});
} else {
// Fallback: Load all images immediately
$lazyImages.each(function () {
const $img = $(this);
$img.attr('src', $img.data('src'));
$img.removeClass('lazyload').addClass('loaded');
});
}
}
};
// Initialize
IGSPGallery.init();
// Make available globally
window.IGSPGallery = IGSPGallery;
})(jQuery);