feat: Add responsive layout overrides and slider settings with Swiper integration.
This commit is contained in:
BIN
admin/.DS_Store
vendored
BIN
admin/.DS_Store
vendored
Binary file not shown.
@@ -6,18 +6,18 @@
|
||||
* @package Instagram_Gallery_Sync_Pro
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Admin Controller
|
||||
*/
|
||||
const IGSPAdmin = {
|
||||
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
init: function() {
|
||||
init: function () {
|
||||
this.initColorPickers();
|
||||
this.initSliders();
|
||||
this.initLayoutSelector();
|
||||
@@ -30,9 +30,9 @@
|
||||
/**
|
||||
* Initialize color pickers
|
||||
*/
|
||||
initColorPickers: function() {
|
||||
initColorPickers: function () {
|
||||
$('.igsp-color-picker').wpColorPicker({
|
||||
change: function(event, ui) {
|
||||
change: function (event, ui) {
|
||||
// Update live preview
|
||||
IGSPAdmin.updatePreview();
|
||||
}
|
||||
@@ -42,26 +42,29 @@
|
||||
/**
|
||||
* Initialize range sliders
|
||||
*/
|
||||
initSliders: function() {
|
||||
$('input[type="range"]').on('input change', function() {
|
||||
initSliders: function () {
|
||||
$('input[type="range"]').on('input change', function () {
|
||||
const $slider = $(this);
|
||||
const $value = $slider.siblings('.igsp-slider-value');
|
||||
let value = $slider.val();
|
||||
|
||||
|
||||
// Handle special cases
|
||||
const id = $slider.attr('id');
|
||||
|
||||
|
||||
if (id === 'igsp_auto_delete_days') {
|
||||
value = value == 0 ? igspAdmin.strings.never || 'Never' : value + ' days';
|
||||
} else if (id === 'igsp_spacing' || id === 'igsp_padding' ||
|
||||
id === 'igsp_border_radius' || id === 'igsp_caption_font_size') {
|
||||
} else if (id === 'igsp_spacing' || id === 'igsp_padding' ||
|
||||
id === 'igsp_border_radius' || id === 'igsp_caption_font_size') {
|
||||
value += 'px';
|
||||
} else if (id === 'igsp_request_timeout') {
|
||||
value += 's';
|
||||
} else if (id === 'igsp_slider_delay') {
|
||||
// Convert milliseconds to seconds for display
|
||||
value = (parseInt(value) / 1000) + 's';
|
||||
}
|
||||
|
||||
|
||||
$value.text(value);
|
||||
|
||||
|
||||
// Update live preview if applicable
|
||||
if (id === 'igsp_caption_font_size') {
|
||||
IGSPAdmin.updatePreview();
|
||||
@@ -72,8 +75,8 @@
|
||||
/**
|
||||
* Initialize layout selector
|
||||
*/
|
||||
initLayoutSelector: function() {
|
||||
$('.igsp-layout-option input').on('change', function() {
|
||||
initLayoutSelector: function () {
|
||||
$('.igsp-layout-option input').on('change', function () {
|
||||
$('.igsp-layout-option').removeClass('selected');
|
||||
$(this).closest('.igsp-layout-option').addClass('selected');
|
||||
});
|
||||
@@ -82,26 +85,26 @@
|
||||
/**
|
||||
* Initialize conditional fields
|
||||
*/
|
||||
initConditionalFields: function() {
|
||||
$('[data-depends-on]').each(function() {
|
||||
initConditionalFields: function () {
|
||||
$('[data-depends-on]').each(function () {
|
||||
const $field = $(this);
|
||||
const dependsOn = $field.data('depends-on');
|
||||
const dependsValue = $field.data('depends-value');
|
||||
|
||||
|
||||
function checkVisibility() {
|
||||
const $input = $('[name="' + dependsOn + '"]:checked, [name="' + dependsOn + '"]').filter(':checked, select');
|
||||
const currentValue = $input.val();
|
||||
|
||||
|
||||
if (currentValue === dependsValue) {
|
||||
$field.show();
|
||||
} else {
|
||||
$field.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Initial check
|
||||
checkVisibility();
|
||||
|
||||
|
||||
// Listen for changes
|
||||
$('[name="' + dependsOn + '"]').on('change', checkVisibility);
|
||||
});
|
||||
@@ -110,29 +113,29 @@
|
||||
/**
|
||||
* Initialize sync button
|
||||
*/
|
||||
initSyncButton: function() {
|
||||
$('#igsp-sync-now').on('click', function() {
|
||||
initSyncButton: function () {
|
||||
$('#igsp-sync-now').on('click', function () {
|
||||
const $button = $(this);
|
||||
const $progress = $('#igsp-sync-progress');
|
||||
const $result = $('#igsp-sync-result');
|
||||
|
||||
|
||||
// Disable button
|
||||
$button.prop('disabled', true);
|
||||
$progress.show();
|
||||
$result.hide();
|
||||
|
||||
|
||||
// Animate progress bar
|
||||
const $fill = $progress.find('.igsp-progress-fill');
|
||||
$fill.css('width', '0%');
|
||||
|
||||
|
||||
// Simulate progress
|
||||
let progress = 0;
|
||||
const progressInterval = setInterval(function() {
|
||||
const progressInterval = setInterval(function () {
|
||||
progress += Math.random() * 15;
|
||||
if (progress > 90) progress = 90;
|
||||
$fill.css('width', progress + '%');
|
||||
}, 500);
|
||||
|
||||
|
||||
// Make AJAX request
|
||||
$.ajax({
|
||||
url: igspAdmin.ajaxUrl,
|
||||
@@ -141,25 +144,25 @@
|
||||
action: 'igsp_manual_sync',
|
||||
nonce: igspAdmin.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
success: function (response) {
|
||||
clearInterval(progressInterval);
|
||||
$fill.css('width', '100%');
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
setTimeout(function () {
|
||||
$progress.hide();
|
||||
$result.removeClass('success error');
|
||||
|
||||
|
||||
if (response.success) {
|
||||
$result.addClass('success').html(response.data.message).show();
|
||||
IGSPAdmin.updateSyncStatus();
|
||||
} else {
|
||||
$result.addClass('error').html(response.data.message || igspAdmin.strings.syncError).show();
|
||||
}
|
||||
|
||||
|
||||
$button.prop('disabled', false);
|
||||
}, 500);
|
||||
},
|
||||
error: function() {
|
||||
error: function () {
|
||||
clearInterval(progressInterval);
|
||||
$progress.hide();
|
||||
$result.addClass('error').html(igspAdmin.strings.syncError).show();
|
||||
@@ -172,57 +175,57 @@
|
||||
/**
|
||||
* Initialize tool buttons
|
||||
*/
|
||||
initToolButtons: function() {
|
||||
initToolButtons: function () {
|
||||
// Clear cache
|
||||
$('#igsp-clear-cache').on('click', function() {
|
||||
$('#igsp-clear-cache').on('click', function () {
|
||||
const $button = $(this);
|
||||
$button.prop('disabled', true).text(igspAdmin.strings.processing);
|
||||
|
||||
|
||||
$.post(igspAdmin.ajaxUrl, {
|
||||
action: 'igsp_clear_cache',
|
||||
nonce: igspAdmin.nonce
|
||||
}, function(response) {
|
||||
}, function (response) {
|
||||
if (response.success) {
|
||||
$button.text(igspAdmin.strings.done);
|
||||
setTimeout(function() {
|
||||
setTimeout(function () {
|
||||
$button.prop('disabled', false).html('<span class="dashicons dashicons-trash"></span> Clear Cache');
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Reset data
|
||||
$('#igsp-reset-data').on('click', function() {
|
||||
$('#igsp-reset-data').on('click', function () {
|
||||
if (!confirm(igspAdmin.strings.confirmReset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const $button = $(this);
|
||||
$button.prop('disabled', true).text(igspAdmin.strings.processing);
|
||||
|
||||
|
||||
$.post(igspAdmin.ajaxUrl, {
|
||||
action: 'igsp_reset_data',
|
||||
nonce: igspAdmin.nonce
|
||||
}, function(response) {
|
||||
}, function (response) {
|
||||
if (response.success) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Clear logs
|
||||
$('#igsp-clear-logs').on('click', function() {
|
||||
$('#igsp-clear-logs').on('click', function () {
|
||||
if (!confirm(igspAdmin.strings.confirmClearLogs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const $button = $(this);
|
||||
$button.prop('disabled', true);
|
||||
|
||||
|
||||
$.post(igspAdmin.ajaxUrl, {
|
||||
action: 'igsp_clear_logs',
|
||||
nonce: igspAdmin.nonce
|
||||
}, function(response) {
|
||||
}, function (response) {
|
||||
if (response.success) {
|
||||
location.reload();
|
||||
}
|
||||
@@ -233,11 +236,11 @@
|
||||
/**
|
||||
* Update sync status
|
||||
*/
|
||||
updateSyncStatus: function() {
|
||||
updateSyncStatus: function () {
|
||||
$.post(igspAdmin.ajaxUrl, {
|
||||
action: 'igsp_get_sync_status',
|
||||
nonce: igspAdmin.nonce
|
||||
}, function(response) {
|
||||
}, function (response) {
|
||||
if (response.success) {
|
||||
$('#igsp-total-posts').text(response.data.total_posts);
|
||||
$('#igsp-last-sync').text(response.data.last_sync);
|
||||
@@ -249,27 +252,27 @@
|
||||
/**
|
||||
* Update live preview
|
||||
*/
|
||||
updatePreview: function() {
|
||||
updatePreview: function () {
|
||||
const primaryColor = $('#igsp_primary_color').val() || '#e1306c';
|
||||
const hoverColor = $('#igsp_hover_color').val() || '#c13584';
|
||||
const textColor = $('#igsp_text_color').val() || '#ffffff';
|
||||
const fontSize = $('#igsp_caption_font_size').val() || 14;
|
||||
|
||||
|
||||
$('.igsp-preview-item').css({
|
||||
'--primary': primaryColor,
|
||||
'--hover': hoverColor,
|
||||
'--text': textColor
|
||||
});
|
||||
|
||||
|
||||
$('.igsp-preview-caption').css('font-size', fontSize + 'px');
|
||||
},
|
||||
|
||||
/**
|
||||
* Tab persistence
|
||||
*/
|
||||
initTabPersistence: function() {
|
||||
initTabPersistence: function () {
|
||||
// Store current tab in localStorage
|
||||
$('.igsp-tab-link').on('click', function() {
|
||||
$('.igsp-tab-link').on('click', function () {
|
||||
const tab = $(this).attr('href').split('tab=')[1];
|
||||
if (tab) {
|
||||
localStorage.setItem('igsp_active_tab', tab);
|
||||
@@ -279,7 +282,7 @@
|
||||
};
|
||||
|
||||
// Initialize when document is ready
|
||||
$(document).ready(function() {
|
||||
$(document).ready(function () {
|
||||
IGSPAdmin.init();
|
||||
});
|
||||
|
||||
|
||||
@@ -116,6 +116,21 @@ if (!defined('ABSPATH')) {
|
||||
</fieldset>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="igsp-conditional" data-depends-on="igsp_show_instagram_btn" data-depends-value="yes">
|
||||
<th scope="row">
|
||||
<label
|
||||
for="igsp_instagram_btn_text"><?php esc_html_e('Button Text', 'instagram-gallery-sync-pro'); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" id="igsp_instagram_btn_text" name="igsp_instagram_btn_text"
|
||||
value="<?php echo esc_attr(get_option('igsp_instagram_btn_text', 'Follow on Instagram')); ?>"
|
||||
class="regular-text" placeholder="Follow on Instagram">
|
||||
<p class="description">
|
||||
<?php esc_html_e('Text displayed on the button below the gallery.', 'instagram-gallery-sync-pro'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -80,6 +80,132 @@ if (!defined('ABSPATH')) {
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-top: 30px;">
|
||||
<?php esc_html_e('Responsive Layout Override', 'instagram-gallery-sync-pro'); ?>
|
||||
</h3>
|
||||
<p class="description" style="margin-bottom: 15px;">
|
||||
<?php esc_html_e('Optionally use a different layout type on smaller screens.', 'instagram-gallery-sync-pro'); ?>
|
||||
</p>
|
||||
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="igsp_layout_type_tablet">
|
||||
<?php esc_html_e('Layout on Tablet', 'instagram-gallery-sync-pro'); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<?php $layout_tablet = get_option('igsp_layout_type_tablet', 'same'); ?>
|
||||
<select id="igsp_layout_type_tablet" name="igsp_layout_type_tablet">
|
||||
<option value="same" <?php selected($layout_tablet, 'same'); ?>>
|
||||
<?php esc_html_e('Same as Desktop', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
<option value="grid" <?php selected($layout_tablet, 'grid'); ?>>
|
||||
<?php esc_html_e('Grid', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
<option value="masonry" <?php selected($layout_tablet, 'masonry'); ?>>
|
||||
<?php esc_html_e('Masonry', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
<option value="slider" <?php selected($layout_tablet, 'slider'); ?>>
|
||||
<?php esc_html_e('Slider', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
<option value="list" <?php selected($layout_tablet, 'list'); ?>>
|
||||
<?php esc_html_e('List', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
</select>
|
||||
<p class="description"><?php esc_html_e('768px - 1023px', 'instagram-gallery-sync-pro'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="igsp_layout_type_mobile">
|
||||
<?php esc_html_e('Layout on Mobile', 'instagram-gallery-sync-pro'); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<?php $layout_mobile = get_option('igsp_layout_type_mobile', 'same'); ?>
|
||||
<select id="igsp_layout_type_mobile" name="igsp_layout_type_mobile">
|
||||
<option value="same" <?php selected($layout_mobile, 'same'); ?>>
|
||||
<?php esc_html_e('Same as Desktop/Tablet', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
<option value="grid" <?php selected($layout_mobile, 'grid'); ?>>
|
||||
<?php esc_html_e('Grid', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
<option value="slider" <?php selected($layout_mobile, 'slider'); ?>>
|
||||
<?php esc_html_e('Slider', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
<option value="list" <?php selected($layout_mobile, 'list'); ?>>
|
||||
<?php esc_html_e('List', 'instagram-gallery-sync-pro'); ?>
|
||||
</option>
|
||||
</select>
|
||||
<p class="description"><?php esc_html_e('< 767px', 'instagram-gallery-sync-pro'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="igsp-section">
|
||||
<h2>
|
||||
<?php esc_html_e('Slider Settings', 'instagram-gallery-sync-pro'); ?>
|
||||
</h2>
|
||||
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="igsp_slider_autoplay">
|
||||
<?php esc_html_e('Auto-Rotate', 'instagram-gallery-sync-pro'); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<?php $slider_autoplay = get_option('igsp_slider_autoplay', 'yes'); ?>
|
||||
<label class="igsp-toggle">
|
||||
<input type="checkbox" id="igsp_slider_autoplay" name="igsp_slider_autoplay" value="yes" <?php checked($slider_autoplay, 'yes'); ?>>
|
||||
<span class="igsp-toggle-slider"></span>
|
||||
</label>
|
||||
<p class="description">
|
||||
<?php esc_html_e('Automatically rotate slides', 'instagram-gallery-sync-pro'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="igsp_slider_delay">
|
||||
<?php esc_html_e('Rotation Delay', 'instagram-gallery-sync-pro'); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<?php $slider_delay = get_option('igsp_slider_delay', 4000); ?>
|
||||
<div class="igsp-slider-wrapper">
|
||||
<input type="range" id="igsp_slider_delay" name="igsp_slider_delay" min="1000" max="10000"
|
||||
step="500" value="<?php echo esc_attr($slider_delay); ?>">
|
||||
<span class="igsp-slider-value"><?php echo esc_html($slider_delay / 1000); ?>s</span>
|
||||
</div>
|
||||
<p class="description">
|
||||
<?php esc_html_e('Time between slides in seconds (1-10)', 'instagram-gallery-sync-pro'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="igsp_slider_pause_hover">
|
||||
<?php esc_html_e('Pause on Hover', 'instagram-gallery-sync-pro'); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<?php $pause_hover = get_option('igsp_slider_pause_hover', 'yes'); ?>
|
||||
<label class="igsp-toggle">
|
||||
<input type="checkbox" id="igsp_slider_pause_hover" name="igsp_slider_pause_hover" value="yes"
|
||||
<?php checked($pause_hover, 'yes'); ?>>
|
||||
<span class="igsp-toggle-slider"></span>
|
||||
</label>
|
||||
<p class="description">
|
||||
<?php esc_html_e('Pause autoplay when mouse hovers over slider', 'instagram-gallery-sync-pro'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="igsp-section">
|
||||
|
||||
@@ -86,6 +86,8 @@ class IGSP_Admin
|
||||
|
||||
// Layout settings
|
||||
register_setting('igsp_layout_settings', 'igsp_layout_type', 'sanitize_text_field');
|
||||
register_setting('igsp_layout_settings', 'igsp_layout_type_tablet', 'sanitize_text_field');
|
||||
register_setting('igsp_layout_settings', 'igsp_layout_type_mobile', 'sanitize_text_field');
|
||||
register_setting('igsp_layout_settings', 'igsp_columns_desktop', 'absint');
|
||||
register_setting('igsp_layout_settings', 'igsp_columns_tablet', 'absint');
|
||||
register_setting('igsp_layout_settings', 'igsp_columns_mobile', 'absint');
|
||||
@@ -96,12 +98,18 @@ class IGSP_Admin
|
||||
register_setting('igsp_layout_settings', 'igsp_border_radius', 'absint');
|
||||
register_setting('igsp_layout_settings', 'igsp_hover_effect', 'sanitize_text_field');
|
||||
|
||||
// Slider settings
|
||||
register_setting('igsp_layout_settings', 'igsp_slider_autoplay', 'sanitize_text_field');
|
||||
register_setting('igsp_layout_settings', 'igsp_slider_delay', 'absint');
|
||||
register_setting('igsp_layout_settings', 'igsp_slider_pause_hover', 'sanitize_text_field');
|
||||
|
||||
// Display settings
|
||||
register_setting('igsp_display_settings', 'igsp_display_limit', 'absint');
|
||||
register_setting('igsp_display_settings', 'igsp_order', 'sanitize_text_field');
|
||||
register_setting('igsp_display_settings', 'igsp_show_caption', 'sanitize_text_field');
|
||||
register_setting('igsp_display_settings', 'igsp_caption_position', 'sanitize_text_field');
|
||||
register_setting('igsp_display_settings', 'igsp_show_instagram_btn', 'sanitize_text_field');
|
||||
register_setting('igsp_display_settings', 'igsp_instagram_btn_text', 'sanitize_text_field');
|
||||
register_setting('igsp_display_settings', 'igsp_link_behavior', 'sanitize_text_field');
|
||||
register_setting('igsp_display_settings', 'igsp_lightbox', 'sanitize_text_field');
|
||||
register_setting('igsp_display_settings', 'igsp_lazy_loading', 'sanitize_text_field');
|
||||
|
||||
@@ -95,10 +95,18 @@ class IGSP_Shortcode
|
||||
wp_register_style(
|
||||
'igsp-gallery-slider',
|
||||
IGSP_PLUGIN_URL . 'public/css/gallery-slider.css',
|
||||
array('igsp-gallery-base'),
|
||||
array('igsp-gallery-base', 'igsp-swiper-css'),
|
||||
IGSP_VERSION
|
||||
);
|
||||
|
||||
// Swiper CSS (required for slider)
|
||||
wp_register_style(
|
||||
'igsp-swiper-css',
|
||||
IGSP_PLUGIN_URL . 'public/css/swiper.min.css',
|
||||
array(),
|
||||
'11.0.5'
|
||||
);
|
||||
|
||||
// Lightbox
|
||||
wp_register_style(
|
||||
'igsp-lightbox',
|
||||
@@ -162,35 +170,41 @@ class IGSP_Shortcode
|
||||
// Sanitize attributes
|
||||
$atts = $this->sanitize_atts($atts);
|
||||
|
||||
// Check cache
|
||||
// Check cache for gallery content (without dynamic elements like button)
|
||||
$cache_key = 'igsp_gallery_' . md5(serialize($atts));
|
||||
$cache_duration = (int) get_option('igsp_cache_duration', 3600);
|
||||
|
||||
$cached = get_transient($cache_key);
|
||||
if ($cached !== false && !is_admin()) {
|
||||
$this->enqueue_assets($atts);
|
||||
return $cached;
|
||||
}
|
||||
$gallery_output = get_transient($cache_key);
|
||||
|
||||
// Get posts from database
|
||||
$database = new IGSP_Database();
|
||||
$posts = $database->get_posts(array(
|
||||
'limit' => $atts['limit'],
|
||||
'order' => $atts['order'],
|
||||
));
|
||||
if ($gallery_output === false || is_admin()) {
|
||||
// Get posts from database
|
||||
$database = new IGSP_Database();
|
||||
$posts = $database->get_posts(array(
|
||||
'limit' => $atts['limit'],
|
||||
'order' => $atts['order'],
|
||||
));
|
||||
|
||||
if (empty($posts)) {
|
||||
return $this->render_empty_state();
|
||||
if (empty($posts)) {
|
||||
return $this->render_empty_state();
|
||||
}
|
||||
|
||||
// Render gallery (without button - that's rendered separately)
|
||||
$gallery_output = $this->render_gallery($posts, $atts);
|
||||
|
||||
// Cache gallery output
|
||||
set_transient($cache_key, $gallery_output, $cache_duration);
|
||||
}
|
||||
|
||||
// Enqueue assets
|
||||
$this->enqueue_assets($atts);
|
||||
|
||||
// Render gallery
|
||||
$output = $this->render_gallery($posts, $atts);
|
||||
// Build final output with non-cached elements
|
||||
$output = $gallery_output;
|
||||
|
||||
// Cache output
|
||||
set_transient($cache_key, $output, $cache_duration);
|
||||
// Add Instagram button (not cached, so it reflects current settings)
|
||||
if (get_option('igsp_show_instagram_btn', 'yes') === 'yes') {
|
||||
$output .= $this->render_instagram_button();
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
@@ -229,10 +243,14 @@ class IGSP_Shortcode
|
||||
*/
|
||||
private function enqueue_assets($atts)
|
||||
{
|
||||
// Get responsive layout settings
|
||||
$layout_tablet = get_option('igsp_layout_type_tablet', 'same');
|
||||
$layout_mobile = get_option('igsp_layout_type_mobile', 'same');
|
||||
|
||||
// Base CSS
|
||||
wp_enqueue_style('igsp-gallery-base');
|
||||
|
||||
// Layout-specific CSS
|
||||
// Main layout-specific CSS
|
||||
switch ($atts['layout']) {
|
||||
case 'masonry':
|
||||
wp_enqueue_style('igsp-gallery-masonry');
|
||||
@@ -247,6 +265,19 @@ class IGSP_Shortcode
|
||||
wp_enqueue_style('igsp-gallery-grid');
|
||||
}
|
||||
|
||||
// Also load slider assets if slider is set for tablet or mobile
|
||||
if ($layout_tablet === 'slider' || $layout_mobile === 'slider') {
|
||||
wp_enqueue_style('igsp-gallery-slider');
|
||||
wp_enqueue_script('igsp-swiper');
|
||||
}
|
||||
|
||||
// Also load masonry assets if masonry is set for tablet
|
||||
if ($layout_tablet === 'masonry') {
|
||||
wp_enqueue_style('igsp-gallery-masonry');
|
||||
wp_enqueue_script('igsp-masonry');
|
||||
wp_enqueue_script('igsp-imagesloaded');
|
||||
}
|
||||
|
||||
// Lightbox
|
||||
if ($atts['lightbox']) {
|
||||
wp_enqueue_style('igsp-lightbox');
|
||||
@@ -257,10 +288,23 @@ class IGSP_Shortcode
|
||||
wp_enqueue_script('igsp-gallery-frontend');
|
||||
|
||||
// Pass settings to JS
|
||||
$layout_tablet = get_option('igsp_layout_type_tablet', 'same');
|
||||
$layout_mobile = get_option('igsp_layout_type_mobile', 'same');
|
||||
|
||||
wp_localize_script('igsp-gallery-frontend', 'igspFrontend', array(
|
||||
'lightbox' => $atts['lightbox'],
|
||||
'layout' => $atts['layout'],
|
||||
'layoutTablet' => $layout_tablet === 'same' ? $atts['layout'] : $layout_tablet,
|
||||
'layoutMobile' => $layout_mobile === 'same' ? ($layout_tablet === 'same' ? $atts['layout'] : $layout_tablet) : $layout_mobile,
|
||||
'autoplay' => $atts['autoplay'],
|
||||
'columns' => $atts['columns'],
|
||||
'columnsTablet' => get_option('igsp_columns_tablet', 2),
|
||||
'columnsMobile' => get_option('igsp_columns_mobile', 1),
|
||||
'spacing' => $atts['spacing'],
|
||||
// Slider settings
|
||||
'sliderAutoplay' => get_option('igsp_slider_autoplay', 'yes') === 'yes',
|
||||
'sliderDelay' => (int) get_option('igsp_slider_delay', 4000),
|
||||
'sliderPauseHover' => get_option('igsp_slider_pause_hover', 'yes') === 'yes',
|
||||
));
|
||||
|
||||
// Add inline custom CSS
|
||||
@@ -356,11 +400,6 @@ class IGSP_Shortcode
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
||||
<?php if (get_option('igsp_show_instagram_btn', 'yes') === 'yes'): ?>
|
||||
<?php echo $this->render_instagram_button(); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
@@ -430,20 +469,15 @@ class IGSP_Shortcode
|
||||
?>
|
||||
<div class="<?php echo esc_attr($item_class); ?>">
|
||||
<?php if (!empty($link_url)): ?>
|
||||
<a href="<?php echo esc_url($link_url); ?>" class="<?php echo esc_attr($prefix . '-link'); ?>" <?php echo $link_target; ?>
|
||||
<?php echo $lightbox_attr; ?>
|
||||
title="
|
||||
<a href="<?php echo esc_url($link_url); ?>" class="<?php echo esc_attr($prefix . '-link'); ?>" <?php echo $link_target; ?> <?php echo $lightbox_attr; ?> title="
|
||||
<?php echo esc_attr($caption); ?>">
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="<?php echo esc_attr($prefix . '-image-wrapper'); ?>">
|
||||
<img src="<?php echo $lazy_loading ? '' : esc_url($display_url); ?>" <?php echo $lazy_loading ? 'data-src="' . esc_url($display_url) . '"' : ''; ?>
|
||||
class="
|
||||
<img src="<?php echo $lazy_loading ? '' : esc_url($display_url); ?>" <?php echo $lazy_loading ? 'data-src="' . esc_url($display_url) . '"' : ''; ?> class="
|
||||
<?php echo esc_attr($prefix . '-image'); ?>
|
||||
<?php echo $lazy_loading ? 'lazyload' : ''; ?>"
|
||||
alt="
|
||||
<?php echo esc_attr($caption); ?>"
|
||||
<?php echo $lazy_loading ? 'loading="lazy"' : ''; ?>>
|
||||
<?php echo $lazy_loading ? 'lazyload' : ''; ?>" alt="
|
||||
<?php echo esc_attr($caption); ?>" <?php echo $lazy_loading ? 'loading="lazy"' : ''; ?>>
|
||||
|
||||
<?php if ($caption_position === 'overlay' && $atts['captions'] && !empty($caption)): ?>
|
||||
<div class="<?php echo esc_attr($prefix . '-overlay'); ?>">
|
||||
@@ -487,6 +521,7 @@ class IGSP_Shortcode
|
||||
{
|
||||
$prefix = get_option('igsp_css_prefix', 'igsp');
|
||||
$username = get_option('igsp_username', '');
|
||||
$button_text = get_option('igsp_instagram_btn_text', __('Follow on Instagram', 'instagram-gallery-sync-pro'));
|
||||
|
||||
if (empty($username)) {
|
||||
return '';
|
||||
@@ -501,7 +536,7 @@ class IGSP_Shortcode
|
||||
<path
|
||||
d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z" />
|
||||
</svg>
|
||||
<?php esc_html_e('Follow on Instagram', 'instagram-gallery-sync-pro'); ?>
|
||||
<?php echo esc_html($button_text); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
@@ -9,23 +9,52 @@
|
||||
.igsp-slider {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
display: block !important;
|
||||
/* Override grid display */
|
||||
}
|
||||
|
||||
.igsp-slider .swiper {
|
||||
padding-bottom: 40px;
|
||||
padding: 0 0 50px 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-wrapper {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-slide {
|
||||
width: auto;
|
||||
height: auto;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* When items are wrapped dynamically, ensure proper sizing */
|
||||
.igsp-slider .swiper-slide.igsp-item {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-slide .igsp-item,
|
||||
.igsp-slider .swiper-slide.igsp-item {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-slide .igsp-image-wrapper {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
.igsp-slider .igsp-image-wrapper {
|
||||
width: 100%;
|
||||
padding-bottom: 100%;
|
||||
/* 1:1 aspect ratio */
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-slide .igsp-image {
|
||||
.igsp-slider .igsp-image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
@@ -36,22 +65,32 @@
|
||||
.igsp-slider .swiper-button-next {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
transition: all 0.3s ease;
|
||||
top: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-prev::after,
|
||||
.igsp-slider .swiper-button-next::after {
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-prev {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-next {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-prev:hover,
|
||||
.igsp-slider .swiper-button-next:hover {
|
||||
background: var(--igsp-primary);
|
||||
background: var(--igsp-primary, #E1306C);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-prev:hover::after,
|
||||
@@ -61,29 +100,57 @@
|
||||
|
||||
.igsp-slider .swiper-button-disabled {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Pagination */
|
||||
.igsp-slider .swiper-pagination {
|
||||
bottom: 0;
|
||||
bottom: 10px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-pagination-bullet {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #ccc;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
opacity: 1;
|
||||
transition: all 0.3s ease;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-pagination-bullet-active {
|
||||
background: var(--igsp-primary);
|
||||
background: var(--igsp-primary, #E1306C);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
/* Dynamic bullets */
|
||||
.igsp-slider .swiper-pagination-bullets-dynamic .swiper-pagination-bullet {
|
||||
transform: scale(0.66);
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-main {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
/* Cards style slides */
|
||||
.igsp-slider .igsp-item {
|
||||
background: #fff;
|
||||
border-radius: var(--igsp-radius, 8px);
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.igsp-slider .igsp-item:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Centered slides option */
|
||||
.igsp-slider.centered .swiper-slide {
|
||||
opacity: 0.5;
|
||||
opacity: 0.6;
|
||||
transform: scale(0.9);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
@@ -95,18 +162,22 @@
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 1024px) {
|
||||
.igsp-slider .swiper-slide .igsp-image-wrapper {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
|
||||
.igsp-slider .swiper-button-prev,
|
||||
.igsp-slider .swiper-button-next {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-prev::after,
|
||||
.igsp-slider .swiper-button-next::after {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.igsp-slider .swiper-slide .igsp-image-wrapper {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
height: auto;
|
||||
padding-bottom: 100%;
|
||||
.igsp-slider .swiper {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-prev,
|
||||
@@ -117,15 +188,66 @@
|
||||
|
||||
.igsp-slider .swiper-button-prev::after,
|
||||
.igsp-slider .swiper-button-next::after {
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-prev {
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-button-next {
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.igsp-slider .swiper-pagination-bullet {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide navigation on touch devices */
|
||||
@media (hover: none) {
|
||||
/* Hide navigation on touch devices (optional, keeps them visible by default) */
|
||||
@media (pointer: coarse) {
|
||||
|
||||
.igsp-slider .swiper-button-prev,
|
||||
.igsp-slider .swiper-button-next {
|
||||
display: none;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.igsp-slider:hover .swiper-button-prev,
|
||||
.igsp-slider:hover .swiper-button-next {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loading state */
|
||||
.igsp-slider:not(.loaded) {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.igsp-slider:not(.loaded)::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: -20px 0 0 -20px;
|
||||
border: 3px solid #f3f3f3;
|
||||
border-top: 3px solid var(--igsp-primary, #E1306C);
|
||||
border-radius: 50%;
|
||||
animation: igsp-spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes igsp-spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.igsp-slider.loaded::after {
|
||||
display: none;
|
||||
}
|
||||
13
public/css/swiper.min.css
vendored
Normal file
13
public/css/swiper.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Instagram Gallery Sync Pro - Frontend Script
|
||||
*
|
||||
* Handles gallery initialization, masonry, lightbox, and lazy loading
|
||||
* Handles gallery initialization, masonry, lightbox, slider and responsive layouts
|
||||
*
|
||||
* @package Instagram_Gallery_Sync_Pro
|
||||
*/
|
||||
@@ -14,6 +14,11 @@
|
||||
*/
|
||||
const IGSPGallery = {
|
||||
|
||||
// Current viewport layout
|
||||
currentLayout: null,
|
||||
swiperInstance: null,
|
||||
masonryInstance: null,
|
||||
|
||||
/**
|
||||
* Initialize all galleries on page
|
||||
*/
|
||||
@@ -23,6 +28,95 @@
|
||||
// Wait for DOM ready
|
||||
$(document).ready(function () {
|
||||
self.initGalleries();
|
||||
self.setupResponsiveHandling();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get current viewport type
|
||||
*/
|
||||
getViewport: function () {
|
||||
const width = window.innerWidth;
|
||||
if (width < 768) return 'mobile';
|
||||
if (width < 1024) return 'tablet';
|
||||
return 'desktop';
|
||||
},
|
||||
|
||||
/**
|
||||
* Get layout for current viewport
|
||||
*/
|
||||
getLayoutForViewport: function () {
|
||||
if (typeof igspFrontend === 'undefined') return 'grid';
|
||||
|
||||
const viewport = this.getViewport();
|
||||
switch (viewport) {
|
||||
case 'mobile':
|
||||
return igspFrontend.layoutMobile || igspFrontend.layout;
|
||||
case 'tablet':
|
||||
return igspFrontend.layoutTablet || igspFrontend.layout;
|
||||
default:
|
||||
return igspFrontend.layout;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup responsive handling
|
||||
*/
|
||||
setupResponsiveHandling: function () {
|
||||
const self = this;
|
||||
let resizeTimeout;
|
||||
|
||||
$(window).on('resize', function () {
|
||||
clearTimeout(resizeTimeout);
|
||||
resizeTimeout = setTimeout(function () {
|
||||
self.handleResize();
|
||||
}, 250);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle resize events for responsive layouts
|
||||
*/
|
||||
handleResize: function () {
|
||||
const newLayout = this.getLayoutForViewport();
|
||||
|
||||
// Only reinitialize if layout type changed
|
||||
if (newLayout !== this.currentLayout) {
|
||||
this.reinitializeGalleries(newLayout);
|
||||
} else if (this.masonryInstance) {
|
||||
// Just re-layout masonry if needed
|
||||
this.masonryInstance.layout();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reinitialize galleries with new layout
|
||||
*/
|
||||
reinitializeGalleries: function (newLayout) {
|
||||
const self = this;
|
||||
|
||||
// Destroy existing instances
|
||||
if (this.swiperInstance) {
|
||||
this.swiperInstance.destroy(true, true);
|
||||
this.swiperInstance = null;
|
||||
}
|
||||
if (this.masonryInstance) {
|
||||
this.masonryInstance.destroy();
|
||||
this.masonryInstance = null;
|
||||
}
|
||||
|
||||
this.currentLayout = newLayout;
|
||||
|
||||
// Reinitialize with new layout
|
||||
$('.igsp-gallery').each(function () {
|
||||
const $gallery = $(this);
|
||||
|
||||
// Update layout classes
|
||||
$gallery.removeClass('igsp-grid igsp-masonry igsp-slider igsp-list');
|
||||
$gallery.addClass('igsp-' + newLayout);
|
||||
$gallery.attr('data-layout', newLayout);
|
||||
|
||||
self.initGalleryLayout($gallery, newLayout);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -34,23 +128,24 @@
|
||||
|
||||
$('.igsp-gallery').each(function () {
|
||||
const $gallery = $(this);
|
||||
const layout = $gallery.data('layout');
|
||||
const serverLayout = $gallery.data('layout') || 'grid';
|
||||
const responsiveLayout = self.getLayoutForViewport();
|
||||
|
||||
self.currentLayout = responsiveLayout;
|
||||
|
||||
// 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);
|
||||
// If responsive layout differs from server layout, update classes
|
||||
if (responsiveLayout !== serverLayout) {
|
||||
$gallery.removeClass('igsp-grid igsp-masonry igsp-slider igsp-list igsp-justified');
|
||||
$gallery.addClass('igsp-' + responsiveLayout);
|
||||
$gallery.attr('data-layout', responsiveLayout);
|
||||
}
|
||||
|
||||
// Initialize based on viewport layout
|
||||
self.initGalleryLayout($gallery, responsiveLayout);
|
||||
|
||||
// Initialize lightbox if enabled
|
||||
if (typeof igspFrontend !== 'undefined' && igspFrontend.lightbox) {
|
||||
self.initLightbox($gallery);
|
||||
@@ -61,12 +156,32 @@
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize gallery with specific layout
|
||||
*/
|
||||
initGalleryLayout: function ($gallery, layout) {
|
||||
switch (layout) {
|
||||
case 'masonry':
|
||||
this.initMasonry($gallery);
|
||||
break;
|
||||
case 'slider':
|
||||
this.initSlider($gallery);
|
||||
break;
|
||||
case 'list':
|
||||
this.initList($gallery);
|
||||
break;
|
||||
default:
|
||||
this.initGrid($gallery);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set responsive CSS variables
|
||||
*/
|
||||
setResponsiveVariables: function ($gallery) {
|
||||
const columnsTablet = $gallery.data('columns-tablet') || 2;
|
||||
const columnsMobile = $gallery.data('columns-mobile') || 1;
|
||||
const settings = typeof igspFrontend !== 'undefined' ? igspFrontend : {};
|
||||
const columnsTablet = settings.columnsTablet || $gallery.data('columns-tablet') || 2;
|
||||
const columnsMobile = settings.columnsMobile || $gallery.data('columns-mobile') || 1;
|
||||
|
||||
$gallery.css({
|
||||
'--columns-tablet': columnsTablet,
|
||||
@@ -81,10 +196,19 @@
|
||||
$gallery.addClass('loaded');
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize list layout
|
||||
*/
|
||||
initList: function ($gallery) {
|
||||
$gallery.addClass('loaded');
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize masonry layout
|
||||
*/
|
||||
initMasonry: function ($gallery) {
|
||||
const self = this;
|
||||
|
||||
if (typeof Masonry === 'undefined' || typeof imagesLoaded === 'undefined') {
|
||||
// Fallback to CSS-only masonry
|
||||
$gallery.addClass('no-js loaded');
|
||||
@@ -101,7 +225,7 @@
|
||||
// Calculate item width
|
||||
const columnWidth = Math.floor(($gallery.width() - (spacing * (columns - 1))) / columns);
|
||||
|
||||
const msnry = new Masonry($gallery[0], {
|
||||
self.masonryInstance = new Masonry($gallery[0], {
|
||||
itemSelector: '.igsp-item',
|
||||
columnWidth: columnWidth,
|
||||
gutter: spacing,
|
||||
@@ -110,15 +234,6 @@
|
||||
});
|
||||
|
||||
$gallery.removeClass('loading').addClass('masonry-initialized loaded');
|
||||
|
||||
// Handle responsive
|
||||
let resizeTimeout;
|
||||
$(window).on('resize', function () {
|
||||
clearTimeout(resizeTimeout);
|
||||
resizeTimeout = setTimeout(function () {
|
||||
msnry.layout();
|
||||
}, 250);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -126,53 +241,119 @@
|
||||
* Initialize slider layout
|
||||
*/
|
||||
initSlider: function ($gallery) {
|
||||
const self = this;
|
||||
|
||||
if (typeof Swiper === 'undefined') {
|
||||
console.warn('IGSP: Swiper library not loaded');
|
||||
$gallery.addClass('loaded');
|
||||
return;
|
||||
}
|
||||
|
||||
const $swiperContainer = $gallery.find('.swiper');
|
||||
let $swiperContainer = $gallery.find('.swiper');
|
||||
|
||||
if (!$swiperContainer.length) {
|
||||
// Wrap items in swiper structure if not already
|
||||
this.wrapItemsInSwiper($gallery);
|
||||
$swiperContainer = $gallery.find('.swiper');
|
||||
}
|
||||
|
||||
if (!$swiperContainer.length) {
|
||||
console.warn('IGSP: Could not create swiper container');
|
||||
$gallery.addClass('loaded');
|
||||
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
|
||||
}
|
||||
// Force load any lazy images in the slider
|
||||
$gallery.find('.igsp-image.lazyload').each(function () {
|
||||
const $img = $(this);
|
||||
if ($img.data('src')) {
|
||||
$img.attr('src', $img.data('src'));
|
||||
}
|
||||
$img.removeClass('lazyload').addClass('loaded');
|
||||
});
|
||||
|
||||
$gallery.addClass('loaded');
|
||||
// Also ensure images without lazyload class are visible
|
||||
$gallery.find('.igsp-image').addClass('loaded');
|
||||
|
||||
const settings = typeof igspFrontend !== 'undefined' ? igspFrontend : {};
|
||||
const sliderAutoplay = settings.sliderAutoplay !== undefined ? settings.sliderAutoplay : true;
|
||||
const sliderDelay = parseInt(settings.sliderDelay) || 4000;
|
||||
const sliderPauseHover = settings.sliderPauseHover !== undefined ? settings.sliderPauseHover : true;
|
||||
const spacing = parseInt($gallery.data('spacing')) || 10;
|
||||
const columns = parseInt(settings.columns) || parseInt($gallery.data('columns')) || 3;
|
||||
const columnsTablet = parseInt(settings.columnsTablet) || 2;
|
||||
const columnsMobile = parseInt(settings.columnsMobile) || 1;
|
||||
|
||||
// Small delay to ensure DOM is ready
|
||||
setTimeout(function () {
|
||||
// Initialize Swiper with proper configuration
|
||||
self.swiperInstance = new Swiper($swiperContainer[0], {
|
||||
slidesPerView: columnsMobile,
|
||||
spaceBetween: spacing,
|
||||
loop: $gallery.find('.swiper-slide').length > columns,
|
||||
grabCursor: true,
|
||||
autoplay: sliderAutoplay ? {
|
||||
delay: sliderDelay,
|
||||
disableOnInteraction: false,
|
||||
pauseOnMouseEnter: sliderPauseHover
|
||||
} : false,
|
||||
pagination: {
|
||||
el: $gallery.find('.swiper-pagination')[0],
|
||||
clickable: true,
|
||||
dynamicBullets: true
|
||||
},
|
||||
navigation: {
|
||||
nextEl: $gallery.find('.swiper-button-next')[0],
|
||||
prevEl: $gallery.find('.swiper-button-prev')[0]
|
||||
},
|
||||
breakpoints: {
|
||||
768: {
|
||||
slidesPerView: columnsTablet,
|
||||
spaceBetween: spacing
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: columns,
|
||||
spaceBetween: spacing
|
||||
}
|
||||
},
|
||||
on: {
|
||||
init: function () {
|
||||
$gallery.addClass('loaded swiper-initialized');
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 50);
|
||||
},
|
||||
|
||||
/**
|
||||
* Wrap gallery items in Swiper structure
|
||||
*/
|
||||
wrapItemsInSwiper: function ($gallery) {
|
||||
const $items = $gallery.find('.igsp-item');
|
||||
|
||||
if (!$items.length) return;
|
||||
|
||||
// Remove any existing swiper structure first
|
||||
$gallery.find('.swiper').remove();
|
||||
|
||||
// Clone items before moving them
|
||||
const $wrapper = $('<div class="swiper-wrapper"></div>');
|
||||
|
||||
// Move items into wrapper as slides (clone to avoid issues)
|
||||
$items.each(function () {
|
||||
const $item = $(this);
|
||||
$item.addClass('swiper-slide');
|
||||
$wrapper.append($item);
|
||||
});
|
||||
|
||||
// Create swiper structure
|
||||
const $swiper = $('<div class="swiper"></div>');
|
||||
$swiper.append($wrapper);
|
||||
$swiper.append('<div class="swiper-pagination"></div>');
|
||||
$swiper.append('<div class="swiper-button-prev"></div>');
|
||||
$swiper.append('<div class="swiper-button-next"></div>');
|
||||
|
||||
$gallery.append($swiper);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -184,7 +365,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const lightbox = GLightbox({
|
||||
GLightbox({
|
||||
selector: '.igsp-gallery [data-gallery="igsp-lightbox"]',
|
||||
touchNavigation: true,
|
||||
loop: true,
|
||||
|
||||
Reference in New Issue
Block a user