Easy Carousel

Displays posts and products in a customizable carousel.

Display estimated delivery date
PHP
/**
 * Snippet Name:     Advanced Carousel
 * Snippet Author:   coding-bunny.com
 * Description:      Displays posts and products in a customizable carousel.
 * Version:          1.1.0
 * 
 * USAGE EXAMPLES:
 * 
 * Basic usage:
 * [posts_carousel]
 * 
 * Show 8 posts with thumbnails, titles, excerpts, date and author:
 * [posts_carousel post_type="post" posts_per_page="8" show_thumbnail="true" show_title="true" show_excerpt="true" show_date="true" show_author="true"]
 * 
 * AVAILABLE PARAMETERS:
 * - posts_per_page: Number of posts to display (default: 6)
 * - post_type: Post type to query (default: 'post')
 * - category: Filter by category slug
 * - tag: Filter by tag slug
 * - taxonomy: Custom taxonomy name
 * - term: Custom taxonomy term slug
 * - autoplay: Enable autoplay (true/false, default: false)
 * - show_thumbnail: Show featured image (true/false, default: true)
 * - show_title: Show post title (true/false, default: true)
 * - show_excerpt: Show post excerpt (true/false, default: false)
 * - show_date: Show publication date (true/false, default: false)
 * - show_author: Show author with link to author archive (true/false, default: false)
 * - show_taxonomies: Show post taxonomies (true/false, default: false)
 * - show_taxonomies_type: Type of taxonomies to show 'categories' or 'tags' (default: 'categories')
 * - excerpt_length: Number of words in excerpt (default: 20)
 * - orderby: Sort posts by 'date', 'title', 'menu_order', 'rand' (default: 'date')
 * - order: Sort direction 'ASC' or 'DESC' (default: 'DESC')
 * - slides_per_view: Number of slides visible per row on desktop (default: 3, range: 1-6)
 * - image_aspect_ratio: Image aspect ratio format '1:1', '2:3', '3:2', '4:3', '3:4', '16:9', '9:16' (default: '3:2')
 * - equal_heights: Enable equal heights for all post cards (true/false, default: true)
 * 
 * WOOCOMMERCE-SPECIFIC PARAMETERS:
 * - show_price: Show product price (true/false, default: false)
 * - show_stock: Show stock status (true/false, default: false)
 * - show_rating: Show star rating (true/false, default: false)
 * - show_add_to_cart: Show add to cart button (true/false, default: false)
 * - show_sale_badge: Show sale badge for discounted products (true/false, default: false)
 * - show_sku: Show product SKU (true/false, default: false)
 */

function cbacs_register_swiper_assets() {
    wp_register_style('swiper-css', 'https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.css', [], null);
    wp_register_script('swiper-js', 'https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.js', [], null, true);
}
add_action('wp_enqueue_scripts', 'cbacs_register_swiper_assets');

function cbacs_enqueue_swiper_assets($content) {
    if (has_shortcode($content, 'posts_carousel')) {
        wp_enqueue_style('swiper-css');
        wp_enqueue_script('swiper-js');
    }
    return $content;
}
add_filter('the_content', 'cbacs_enqueue_swiper_assets');

function cbacs_aspect_ratio($aspect_ratio_string) {
    $allowed_ratios = [
        '1:1' => 100,       // Square
        '2:3' => 150,       // Portrait (2:3)
        '3:2' => 66.67,     // Landscape (3:2) - Default
        '4:3' => 75,        // Standard (4:3)
        '3:4' => 133.33,    // Portrait (3:4)
        '16:9' => 56.25,    // Widescreen (16:9)
        '9:16' => 177.78,   // Mobile/Story format (9:16)
    ];
    
    return isset($allowed_ratios[$aspect_ratio_string]) ? $allowed_ratios[$aspect_ratio_string] : $allowed_ratios['3:2'];
}

function cbacs_posts_carousel_shortcode($atts) {
    $atts = shortcode_atts([
        'posts_per_page'     => 6,
        'post_type'          => 'post',
        'category'           => '',
        'tag'                => '',
        'taxonomy'           => '',
        'term'               => '',
        'autoplay'           => 'false',
        'show_thumbnail'     => 'true',
        'show_title'         => 'true',
        'show_excerpt'       => 'false',
        'show_date'          => 'false',
        'show_author'        => 'false',
        'show_taxonomies'    => 'false',
        'show_taxonomies_type' => 'categories',
        'excerpt_length'     => 20,
        'orderby'            => 'date',
        'order'              => 'DESC',
        'slides_per_view'    => 3,
        'image_aspect_ratio' => '3:2',
        'equal_heights'      => 'true',
        
        // WooCommerce parameters
        'show_price'         => 'false',
        'show_stock'         => 'false',
        'show_rating'        => 'false',
        'show_add_to_cart'   => 'false',
        'show_sale_badge'    => 'false',
        'show_sku'           => 'false',
    ], $atts, 'posts_carousel');

    $post_type = sanitize_key($atts['post_type']);
    $category  = sanitize_title($atts['category']);
    $tag       = sanitize_title($atts['tag']);
    $taxonomy  = sanitize_key($atts['taxonomy']);
    $term      = sanitize_title($atts['term']);
    $autoplay  = filter_var($atts['autoplay'], FILTER_VALIDATE_BOOLEAN);
    $show_thumbnail = filter_var($atts['show_thumbnail'], FILTER_VALIDATE_BOOLEAN);
    $show_title = filter_var($atts['show_title'], FILTER_VALIDATE_BOOLEAN);
    $show_excerpt = filter_var($atts['show_excerpt'], FILTER_VALIDATE_BOOLEAN);
    $show_date = filter_var($atts['show_date'], FILTER_VALIDATE_BOOLEAN);
    $show_author = filter_var($atts['show_author'], FILTER_VALIDATE_BOOLEAN);
    $show_taxonomies = filter_var($atts['show_taxonomies'], FILTER_VALIDATE_BOOLEAN);
    $show_taxonomies_type = sanitize_text_field($atts['show_taxonomies_type']);
    $excerpt_length = intval($atts['excerpt_length']);
    $orderby = sanitize_key($atts['orderby']);
    $order = strtoupper(sanitize_key($atts['order'])) === 'ASC' ? 'ASC' : 'DESC';
    
    $slides_per_view = intval($atts['slides_per_view']);
    if ($slides_per_view < 1) $slides_per_view = 1;
    if ($slides_per_view > 6) $slides_per_view = 6;   
    $image_aspect_ratio = sanitize_text_field($atts['image_aspect_ratio']);
    $padding_bottom = cbacs_aspect_ratio($image_aspect_ratio);
    $equal_heights = filter_var($atts['equal_heights'], FILTER_VALIDATE_BOOLEAN);
    $show_price = filter_var($atts['show_price'], FILTER_VALIDATE_BOOLEAN);
    $show_stock = filter_var($atts['show_stock'], FILTER_VALIDATE_BOOLEAN);
    $show_rating = filter_var($atts['show_rating'], FILTER_VALIDATE_BOOLEAN);
    $show_add_to_cart = filter_var($atts['show_add_to_cart'], FILTER_VALIDATE_BOOLEAN);
    $show_sale_badge = filter_var($atts['show_sale_badge'], FILTER_VALIDATE_BOOLEAN);
    $show_sku = filter_var($atts['show_sku'], FILTER_VALIDATE_BOOLEAN);

    $is_woocommerce_active = class_exists('WooCommerce');
    $is_product_query = ($post_type === 'product' && $is_woocommerce_active);

    $args = [
        'post_type'      => $post_type,
        'posts_per_page' => intval($atts['posts_per_page']),
        'post_status'    => 'publish',
        'orderby'        => $orderby,
        'order'          => $order,
    ];

    $tax_query = [];

    if (!empty($category)) {
        if ($is_product_query) {
            $tax_query[] = [
                'taxonomy' => 'product_cat',
                'field'    => 'slug',
                'terms'    => $category,
            ];
        } else {
            $tax_query[] = [
                'taxonomy' => 'category',
                'field'    => 'slug',
                'terms'    => $category,
            ];
        }
    }

    if (!empty($tag)) {
        if ($is_product_query) {
            $tax_query[] = [
                'taxonomy' => 'product_tag',
                'field'    => 'slug',
                'terms'    => $tag,
            ];
        } else {
            $tax_query[] = [
                'taxonomy' => 'post_tag',
                'field'    => 'slug',
                'terms'    => $tag,
            ];
        }
    }

    if (!empty($taxonomy) && !empty($term)) {
        $tax_query[] = [
            'taxonomy' => $taxonomy,
            'field'    => 'slug',
            'terms'    => $term,
        ];
    }

    if (!empty($tax_query)) {
        $args['tax_query'] = $tax_query;
    }

    $query = new WP_Query($args);
    ob_start();

    if ($query->have_posts()) :
        $uid = uniqid('swiper_');
        ?>

        <div class="swiper <?php echo esc_attr($uid); ?>" data-equal-heights="<?php echo $equal_heights ? 'true' : 'false'; ?>">
            <div class="swiper-wrapper">
                <?php while ($query->have_posts()) : $query->the_post(); 
                    $product = $is_product_query ? wc_get_product(get_the_ID()) : null;
                ?>
                    <div class="swiper-slide">
                        <div class="post-slide <?php echo $is_product_query ? 'product-slide' : ''; ?>">
                            
                            <?php if ($show_thumbnail && has_post_thumbnail()) : ?>
                                <div class="post-thumbnail" data-aspect-ratio="<?php echo esc_attr($image_aspect_ratio); ?>">
                                    <?php if ($show_sale_badge && $is_product_query && $product && $product->is_on_sale()) : ?>
                                        <div class="sale-badge">
                                            <?php esc_html_e('Sale!', 'woocommerce'); ?>
                                        </div>
                                    <?php endif; ?>
                                    <a href="<?php the_permalink(); ?>">
                                        <div class="image-container">
                                            <?php the_post_thumbnail('large'); ?>
                                        </div>
                                    </a>
                                </div>
                            <?php endif; ?>

                            <?php if ($show_taxonomies) : ?>
                                <div class="<?php echo $is_product_query ? 'product-taxonomies' : 'post-taxonomies'; ?>">
                                    <?php
                                    if ($show_taxonomies_type === 'categories') {
                                        if ($is_product_query) {
                                            $categories = get_the_terms(get_the_ID(), 'product_cat');
                                            if ($categories && !is_wp_error($categories)) {
                                                $cat_names = array();
                                                foreach ($categories as $category) {
                                                    $cat_names[] = '<a href="' . esc_url(get_term_link($category)) . '">' . esc_html($category->name) . '</a>';
                                                }
                                                echo implode(' ', $cat_names);
                                            }
                                        } else {
                                            $categories = get_the_category();
                                            if ($categories && !is_wp_error($categories)) {
                                                $cat_names = array();
                                                foreach ($categories as $category) {
                                                    $cat_names[] = '<a href="' . esc_url(get_category_link($category->term_id)) . '">' . esc_html($category->name) . '</a>';
                                                }
                                                echo implode(' ', $cat_names);
                                            }
                                        }
                                    } elseif ($show_taxonomies_type === 'tags') {
                                        if ($is_product_query) {
                                            $tags = get_the_terms(get_the_ID(), 'product_tag');
                                            if ($tags && !is_wp_error($tags)) {
                                                $tag_names = array();
                                                foreach ($tags as $tag) {
                                                    $tag_names[] = '<a href="' . esc_url(get_term_link($tag)) . '">' . esc_html($tag->name) . '</a>';
                                                }
                                                echo implode(', ', $tag_names);
                                            }
                                        } else {
                                            $tags = get_the_tags();
                                            if ($tags && !is_wp_error($tags)) {
                                                $tag_names = array();
                                                foreach ($tags as $tag) {
                                                    $tag_names[] = '<a href="' . esc_url(get_tag_link($tag->term_id)) . '">' . esc_html($tag->name) . '</a>';
                                                }
                                                echo implode(', ', $tag_names);
                                            }
                                        }
                                    }
                                    ?>
                                </div>
                            <?php endif; ?>

                            <div class="post-content">
                                <?php if ($show_title) : ?>
                                    <h3 class="post-title">
                                        <a href="<?php the_permalink(); ?>"><?php echo esc_html(get_the_title()); ?></a>
                                    </h3>
                                <?php endif; ?>

                                <?php if ($show_rating && $is_product_query && $product && $product->get_average_rating()) : ?>
                                    <div class="product-rating">
                                        <?php
                                        $rating = $product->get_average_rating();
                                        $review_count = $product->get_review_count();
                                        echo wc_get_rating_html($rating);
                                        if ($review_count > 0) {
                                            echo '<span class="review-count">(' . sprintf(_n('%s review', '%s reviews', $review_count, 'woocommerce'), $review_count) . ')</span>';
                                        }
                                        ?>
                                    </div>
                                <?php endif; ?>

                                <?php if ($show_excerpt && !$is_product_query) : ?>
                                    <div class="post-excerpt">
                                        <?php
                                        $excerpt = get_the_excerpt();
                                        if (strlen($excerpt) > $excerpt_length) {
                                            $excerpt = wp_trim_words($excerpt, $excerpt_length, '...');
                                        }
                                        echo esc_html($excerpt);
                                        ?>
                                    </div>
                                <?php elseif ($show_excerpt && $is_product_query && $product) : ?>
                                    <div class="product-excerpt">
                                        <?php
                                        $description = $product->get_short_description();
                                        if (!empty($description)) {
                                            if (strlen($description) > $excerpt_length * 7) { // Rough word count estimation
                                                $description = wp_trim_words($description, $excerpt_length, '...');
                                            }
                                            echo wp_kses_post($description);
                                        }
                                        ?>
                                    </div>
                                <?php endif; ?>

                                <?php if ($show_price && $is_product_query && $product) : ?>
                                    <div class="product-price">
                                        <?php echo $product->get_price_html(); ?>
                                    </div>
                                <?php endif; ?>

                                <?php if ($show_stock && $is_product_query && $product) : ?>
                                    <div class="product-stock">
                                        <?php
                                        $stock_status = $product->get_stock_status();
                                        $stock_quantity = $product->get_stock_quantity();
                                        
                                        if ($stock_status === 'instock') {
                                            echo '<span class="stock in-stock"><span class="dashicons dashicons-yes-alt"></span>' . esc_html__('In Stock', 'woocommerce');
                                            if ($stock_quantity && $product->managing_stock()) {
                                                echo ' (' . esc_html($stock_quantity) . ' ' . esc_html__('available', 'woocommerce') . ')';
                                            }
                                            echo '</span>';
                                        } elseif ($stock_status === 'outofstock') {
                                            echo '<span class="stock out-of-stock"><span class="dashicons dashicons-dismiss"></span>' . esc_html__('Out of Stock', 'woocommerce') . '</span>';
                                        } elseif ($stock_status === 'onbackorder') {
                                            echo '<span class="stock on-backorder"><span class="dashicons dashicons-clock"></span>' . esc_html__('On Backorder', 'woocommerce') . '</span>';
                                        }
                                        ?>
                                    </div>
                                <?php endif; ?>

                                <?php if ($show_sku && $is_product_query && $product && $product->get_sku()) : ?>
                                    <div class="product-sku">
                                        <span class="sku-label"><?php esc_html_e('SKU:', 'woocommerce'); ?></span>
                                        <span class="sku"><?php echo esc_html($product->get_sku()); ?></span>
                                    </div>
                                <?php endif; ?>

                                <?php if (($show_date || $show_author) && !$is_product_query) : ?>
                                    <div class="post-meta">
                                        <?php if ($show_date) : ?>
                                            <span class="post-date">
                                                <span class="dashicons dashicons-calendar-alt"></span>
                                                <?php echo get_the_date(); ?>
                                            </span>
                                        <?php endif; ?>

                                        <?php if ($show_author) : ?>
                                            <span class="post-author">
                                                <span class="dashicons dashicons-admin-users"></span>
                                                <a href="<?php echo esc_url(get_author_posts_url(get_the_author_meta('ID'))); ?>" title="<?php echo esc_attr(sprintf(__('View all posts by %s', 'text-domain'), get_the_author())); ?>">
                                                    <?php echo get_the_author(); ?>
                                                </a>
                                            </span>
                                        <?php endif; ?>
                                    </div>
                                <?php endif; ?>

                                <?php if ($show_add_to_cart && $is_product_query && $product) : ?>
                                    <div class="product-add-to-cart">
                                        <?php
                                        if ($product->get_type() === 'simple') {
                                            woocommerce_template_loop_add_to_cart();
                                        } else {
                                            echo '<a href="' . esc_url($product->get_permalink()) . '" class="button product-type-' . esc_attr($product->get_type()) . '">' . esc_html__('Select Options', 'woocommerce') . '</a>';
                                        }
                                        ?>
                                    </div>
                                <?php endif; ?>
                            </div>
                        </div>
                    </div>
                <?php endwhile; ?>
            </div>

            <div class="swiper-button-next">
                <span class="dashicons dashicons-arrow-right-alt2"></span>
            </div>
            <div class="swiper-button-prev">
                <span class="dashicons dashicons-arrow-left-alt2"></span>
            </div>
        </div>

        <style>
        .<?php echo esc_attr($uid); ?> {
            position: relative;
            width: 100% !important;
            max-width: none !important;
        }

        .<?php echo esc_attr($uid); ?> .swiper-slide .post-slide {
            background: #ffffff;
            border: 1px solid #e1e5e9;
            border-radius: 10px;
            overflow: hidden;
            transition: all 0.3s ease;
            height: 100%;
            display: flex;
            flex-direction: column;
        }

        .<?php echo esc_attr($uid); ?> .swiper-slide .post-slide:hover {
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
            transform: translateY(-2px);
        }

        .<?php echo esc_attr($uid); ?> .post-thumbnail {
            width: 100%;
            overflow: hidden;
            position: relative;
        }

        .<?php echo esc_attr($uid); ?> .post-thumbnail .image-container {
            width: 100%;
            height: 0;
            padding-bottom: <?php echo esc_attr($padding_bottom); ?>%;
            position: relative;
            overflow: hidden;
        }

        .<?php echo esc_attr($uid); ?> .post-thumbnail .image-container img {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            object-fit: cover;
            transition: transform 0.3s ease;
        }

        .<?php echo esc_attr($uid); ?> .post-thumbnail:hover .image-container img {
            transform: scale(1.05);
        }

        .<?php echo esc_attr($uid); ?> .sale-badge {
            position: absolute;
            top: 10px;
            left: 10px;
            background: #ff4444;
            color: white;
            padding: 5px 10px;
            border-radius: 15px;
            font-size: 12px;
            font-weight: bold;
            z-index: 2;
        }

        .<?php echo esc_attr($uid); ?> .post-taxonomies {
            padding: 15px 15px 0 15px;
            font-size: 12px;
            line-height: 1.4;
            background: #ffffff;
        }

        .<?php echo esc_attr($uid); ?> .post-taxonomies a {
            color: #ffffff;
            background: #2370b0;
            padding: 5px;
            border-radius: 3px;
            text-decoration: none;
            transition: background 0.3s ease;
        }

        .<?php echo esc_attr($uid); ?> .post-taxonomies a:hover {
            background: #1d6197;
            text-decoration: none;
        }

        .<?php echo esc_attr($uid); ?> .product-taxonomies {
            padding: 15px 15px 0 15px;
            font-size: 12px;
            line-height: 1.4;
            background: #ffffff;
        }

        .<?php echo esc_attr($uid); ?> .product-taxonomies a {
            color: #000000;
            border-radius: 3px;
            text-decoration: none;
            transition: background 0.3s ease;
        }

        .<?php echo esc_attr($uid); ?> .product-taxonomies a:hover {
            color: #2370b0;
            text-decoration: none;
        }

        .<?php echo esc_attr($uid); ?> .post-content {
            padding: 15px;
            flex-grow: 1;
            display: flex;
            flex-direction: column;
        }

        .<?php echo esc_attr($uid); ?> .post-title {
            margin: 0;
            font-size: 16px;
            line-height: 1.4;
        }

        .<?php echo esc_attr($uid); ?> .post-title a {
            color: #333;
            text-decoration: none;
            transition: color 0.3s ease;
        }

        .<?php echo esc_attr($uid); ?> .post-title a:hover {
            color: #0073aa;
        }

        .<?php echo esc_attr($uid); ?> .product-rating {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .<?php echo esc_attr($uid); ?> .product-rating .star-rating {
            font-size: 14px;
        }

        .<?php echo esc_attr($uid); ?> .product-rating .review-count {
            font-size: 12px;
            color: #666;
        }

        .<?php echo esc_attr($uid); ?> .post-excerpt,
        .<?php echo esc_attr($uid); ?> .product-excerpt {
            color: #666;
            font-size: 14px;
            line-height: 1.5;
            margin-bottom: 15px;
        }

        .<?php echo esc_attr($uid); ?> .product-price {
            font-size: 18px;
            font-weight: bold;
            margin-bottom: 10px;
        }

        .<?php echo esc_attr($uid); ?> .product-price .price {
            color: #333;
        }

        .<?php echo esc_attr($uid); ?> .product-price .price del {
            color: #999;
            text-decoration: line-through;
            font-weight: normal;
        }

        .<?php echo esc_attr($uid); ?> .product-price .price ins {
            color: #77a464;
            text-decoration: none;
        }

        .<?php echo esc_attr($uid); ?> .product-stock {
            margin-bottom: 10px;
            font-size: 12px;
        }

        .<?php echo esc_attr($uid); ?> .product-stock .stock {
            display: flex;
            align-items: center;
            gap: 5px;
        }

        .<?php echo esc_attr($uid); ?> .product-stock .in-stock {
            color: #77a464;
        }

        .<?php echo esc_attr($uid); ?> .product-stock .out-of-stock {
            color: #ff4444;
        }

        .<?php echo esc_attr($uid); ?> .product-stock .on-backorder {
            color: #ffba00;
        }

        .<?php echo esc_attr($uid); ?> .product-stock .dashicons {
            font-size: 14px;
            width: 14px;
            height: 14px;
        }

        .<?php echo esc_attr($uid); ?> .product-sku {
            font-size: 11px;
            color: #999;
            margin-bottom: 10px;
        }

        .<?php echo esc_attr($uid); ?> .product-sku .sku-label {
            font-weight: bold;
        }

        .<?php echo esc_attr($uid); ?> .post-meta {
            margin-top: auto;
            padding-top: 10px;
            border-top: 1px solid #f0f0f0;
            font-size: 12px;
            color: #999;
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
        }

        .<?php echo esc_attr($uid); ?> .post-meta span {
            display: flex;
            align-items: center;
            gap: 5px;
        }

        .<?php echo esc_attr($uid); ?> .post-meta .dashicons {
            font-size: 14px;
            width: 14px;
            height: 14px;
        }

        .<?php echo esc_attr($uid); ?> .post-author a {
            color: #999;
            text-decoration: none;
            transition: color 0.3s ease;
        }

        .<?php echo esc_attr($uid); ?> .post-author a:hover {
            color: #0073aa;
            text-decoration: underline;
        }

        .<?php echo esc_attr($uid); ?> .product-add-to-cart {
            margin-top: auto;
            padding-top: 15px;
        }

        .<?php echo esc_attr($uid); ?> .product-add-to-cart .added_to_cart {
            display: none;
        }

        .<?php echo esc_attr($uid); ?> .swiper-button-next,
        .<?php echo esc_attr($uid); ?> .swiper-button-prev {
            width: 35px;
            height: 35px;
            background: rgba(0, 0, 0, 0.8);
            border-radius: 50%;
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s ease;
            margin-top: -17.5px;
            color: transparent;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .<?php echo esc_attr($uid); ?> .swiper-button-next:after,
        .<?php echo esc_attr($uid); ?> .swiper-button-prev:after {
            display: none;
        }

        .<?php echo esc_attr($uid); ?> .swiper-button-next .dashicons,
        .<?php echo esc_attr($uid); ?> .swiper-button-prev .dashicons {
            color: #ffffff;
            font-size: 16px;
            width: 16px;
            height: 16px;
        }

        .<?php echo esc_attr($uid); ?>:hover .swiper-button-next,
        .<?php echo esc_attr($uid); ?>:hover .swiper-button-prev {
            opacity: 1;
            visibility: visible;
        }

        .<?php echo esc_attr($uid); ?> .swiper-button-next:hover,
        .<?php echo esc_attr($uid); ?> .swiper-button-prev:hover {
            background: rgba(0, 0, 0, 1);
            transform: scale(1.1);
        }

        .<?php echo esc_attr($uid); ?> .swiper-button-next {
            right: 10px;
        }

        .<?php echo esc_attr($uid); ?> .swiper-button-prev {
            left: 10px;
        }

        @media (max-width: 768px) {
            .<?php echo esc_attr($uid); ?> .post-title {
                font-size: 14px;
            }
            
            .<?php echo esc_attr($uid); ?> .post-content {
                padding: 12px;
            }

            .<?php echo esc_attr($uid); ?> .post-taxonomies,
            .<?php echo esc_attr($uid); ?> .product-taxonomies {
                padding: 8px 12px;
                font-size: 11px;
            }

            .<?php echo esc_attr($uid); ?> .swiper-button-next,
            .<?php echo esc_attr($uid); ?> .swiper-button-prev {
                width: 30px;
                height: 30px;
                margin-top: -15px;
            }

            .<?php echo esc_attr($uid); ?> .swiper-button-next .dashicons,
            .<?php echo esc_attr($uid); ?> .swiper-button-prev .dashicons {
                font-size: 14px;
                width: 14px;
                height: 14px;
            }

            .<?php echo esc_attr($uid); ?> .product-price {
                font-size: 16px;
            }
        }

        @media (max-width: 480px) {
            .<?php echo esc_attr($uid); ?> .post-meta {
                flex-direction: column;
                gap: 8px;
            }

            .<?php echo esc_attr($uid); ?> .swiper-button-next,
            .<?php echo esc_attr($uid); ?> .swiper-button-prev {
                opacity: 1;
                visibility: visible;
                background: rgba(0, 0, 0, 0.6);
            }

            .<?php echo esc_attr($uid); ?> .product-rating {
                flex-direction: column;
                align-items: flex-start;
                gap: 5px;
            }

            .<?php echo esc_attr($uid); ?> .post-taxonomies,
            .<?php echo esc_attr($uid); ?> .product-taxonomies {
                padding: 6px 10px;
                font-size: 10px;
            }
        }
        </style>

        <?php
        $js = "
        document.addEventListener('DOMContentLoaded', function () {
            
            // Function to equalize heights
            function equalizeHeights(swiperElement) {
                const slides = swiperElement.querySelectorAll('.swiper-slide .post-slide');
                let maxHeight = 0;
                
                // Reset heights first
                slides.forEach(slide => {
                    slide.style.height = 'auto';
                });
                
                // Find maximum height
                slides.forEach(slide => {
                    const height = slide.offsetHeight;
                    if (height > maxHeight) {
                        maxHeight = height;
                    }
                });
                
                // Apply maximum height to all slides
                slides.forEach(slide => {
                    slide.style.height = maxHeight + 'px';
                });
            }
            
            // Initialize Swiper
            const swiperElement = document.querySelector('." . esc_js($uid) . "');
            const enableEqualHeights = swiperElement.dataset.equalHeights === 'true';
            
            const swiper = new Swiper('." . esc_js($uid) . "', {
                slidesPerView: " . $slides_per_view . ",
                spaceBetween: 30,
                loop: true,
                autoHeight: false,
                navigation: {
                    nextEl: '." . esc_js($uid) . " .swiper-button-next',
                    prevEl: '." . esc_js($uid) . " .swiper-button-prev'
                },
                " . ($autoplay ? "autoplay: { delay: 3000, disableOnInteraction: false }," : "") . "
                breakpoints: {
                    320: { 
                        slidesPerView: 1, 
                        spaceBetween: 15 
                    },
                    768: { 
                        slidesPerView: " . min($slides_per_view, 2) . ", 
                        spaceBetween: 20 
                    },
                    1024: { 
                        slidesPerView: " . $slides_per_view . ", 
                        spaceBetween: 30 
                    }
                },
                on: {
                    init: function() {
                        if (enableEqualHeights) {
                            // Small delay to ensure images are loaded
                            setTimeout(() => {
                                equalizeHeights(swiperElement);
                            }, 100);
                        }
                    }
                }
            });
            
            // Re-equalize heights on window resize
            if (enableEqualHeights) {
                let resizeTimer;
                window.addEventListener('resize', function() {
                    clearTimeout(resizeTimer);
                    resizeTimer = setTimeout(() => {
                        equalizeHeights(swiperElement);
                    }, 250);
                });
                
                // Re-equalize when images finish loading
                const images = swiperElement.querySelectorAll('img');
                let loadedImages = 0;
                
                if (images.length > 0) {
                    images.forEach(img => {
                        if (img.complete) {
                            loadedImages++;
                        } else {
                            img.addEventListener('load', () => {
                                loadedImages++;
                                if (loadedImages === images.length) {
                                    equalizeHeights(swiperElement);
                                }
                            });
                        }
                    });
                    
                    if (loadedImages === images.length) {
                        equalizeHeights(swiperElement);
                    }
                }
            }
        });
        ";

        wp_add_inline_script('swiper-js', $js);
        wp_reset_postdata();
    else :
        echo '<p>' . esc_html__('No posts found.', 'text-domain') . '</p>';
    endif;

    return ob_get_clean();
}
add_shortcode('posts_carousel', 'cbacs_posts_carousel_shortcode');

How To Implement This Solution?

Leave a Reply