Define default columns count
Hi,
I love using bootscore with the additional plugins. I've a question for the swiper plugin. Can you make it possible to define a default columns count dependent on the screen size? Currently it's hard coded in the javascript file. With every update I have to fix it for my personal use.
Regards Joerg
Hi,
Currently it's hard coded in the javascript file. With every update I have to fix it for my personal use.
Why not dequeue the init script and enqueue own in child as discussed here https://github.com/orgs/bootscore/discussions/768?
Can you make it possible to define a default columns count dependent on the screen size?
That's a good point! And I am having something like this in mind since a while to add more options to the shortcode to control the columns and more. For example all Bootstrap columns xs, sm, md, lg, xl and xxl can be added to the shortcode cols="2,3,4,5,6,8". If they are not added, the columns fallback to the default settings:
[bs-swiper-card type="post" category="post-templates" cols="2,3,4,5,6,8"]
[bs-swiper-card type="post" category="post-templates"]
Please check the modified PHP and init JS (default card template):
PHP
// Card Slider Shortcode
add_shortcode('bs-swiper-card', 'bootscore_swiper');
function bootscore_swiper($atts) {
ob_start();
$atts = shortcode_atts(array(
'type' => 'post',
'post_status' => 'publish',
'order' => 'date',
'orderby' => 'date',
'posts' => -1,
'category' => '',
'post_parent' => '',
'tax' => '',
'terms' => '',
'id' => '',
'excerpt' => 'true',
'tags' => 'true',
'categories' => 'true',
'cols' => '', // new attribute: e.g., "2,3,4,6"
), $atts);
$options = array(
'post_type' => sanitize_text_field($atts['type']),
'order' => sanitize_text_field($atts['order']),
'orderby' => sanitize_text_field($atts['orderby']),
'posts_per_page' => is_numeric($atts['posts']) ? (int) $atts['posts'] : -1,
'category_name' => sanitize_text_field($atts['category']),
'post_parent' => is_numeric($atts['post_parent']) ? (int) $atts['post_parent'] : '',
);
$tax = trim(sanitize_text_field($atts['tax']));
$terms = trim(sanitize_text_field($atts['terms']));
if ($tax != '' && $terms != '') {
$terms = array_map('trim', explode(',', $terms));
$terms = array_filter($terms);
$terms = array_unique($terms);
unset($options['category_name']);
$options['tax_query'] = array(array(
'taxonomy' => $tax,
'field' => 'slug',
'terms' => $terms,
));
}
if (!empty($atts['id'])) {
$ids = array_map('intval', explode(',', $atts['id']));
$ids = array_filter($ids);
$ids = array_unique($ids);
$options['post__in'] = $ids;
}
// Handle cols attribute and map to breakpoints
$breakpoints = [];
$bps = [0, 576, 768, 992, 1200, 1400]; // xs, sm, md, lg, xl, 2xl
if (!empty($atts['cols'])) {
$cols = array_map('intval', explode(',', $atts['cols']));
foreach ($cols as $i => $val) {
if (isset($bps[$i])) {
$breakpoints[$bps[$i]] = ['slidesPerView' => $val];
}
}
} else {
// Default: 1 slide on xs/sm, 2 on md, 3 on lg, 4 on xl+, etc.
$breakpoints = [
0 => ['slidesPerView' => 1],
576 => ['slidesPerView' => 1],
768 => ['slidesPerView' => 2],
992 => ['slidesPerView' => 3],
1200 => ['slidesPerView' => 4],
1400 => ['slidesPerView' => 4],
];
}
$data_breakpoints = htmlspecialchars(json_encode($breakpoints), ENT_QUOTES, 'UTF-8');
$query = new WP_Query($options);
if ($query->have_posts()) : ?>
<!-- Swiper -->
<div class="px-5 position-relative">
<div class="cards swiper-container swiper position-static" data-swiper-breakpoints="<?= $data_breakpoints; ?>">
<div class="swiper-wrapper">
<?php while ($query->have_posts()) : $query->the_post(); ?>
<div class="swiper-slide card h-auto mb-5">
<?php if (has_post_thumbnail()) : ?>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium', ['class' => 'card-img-top']); ?>
</a>
<?php endif; ?>
<div class="card-body d-flex flex-column">
<?php if ($atts['categories'] === 'true') : bootscore_category_badge(); endif; ?>
<a class="text-body text-decoration-none" href="<?php the_permalink(); ?>">
<?php the_title('<h2 class="blog-post-title h5">', '</h2>'); ?>
</a>
<?php if (get_post_type() === 'post') : ?>
<p class="meta small mb-2 text-body-secondary">
<?php
bootscore_date();
bootscore_author();
bootscore_comments();
bootscore_edit();
?>
</p>
<?php endif; ?>
<?php if ($atts['excerpt'] === 'true') : ?>
<p class="card-text">
<a class="text-body text-decoration-none" href="<?php the_permalink(); ?>">
<?= strip_tags(get_the_excerpt()); ?>
</a>
</p>
<?php endif; ?>
<p class="card-text mt-auto">
<a class="read-more" href="<?php the_permalink(); ?>">
<?= __('Read more »', 'bootscore'); ?>
</a>
</p>
<?php if ($atts['tags'] === 'true') : bootscore_tags(); endif; ?>
</div>
</div>
<?php endwhile; wp_reset_postdata(); ?>
</div>
<!-- Add Pagination -->
<div class="swiper-pagination"></div>
<!-- Add Arrows -->
<div class="swiper-button-next end-0"></div>
<div class="swiper-button-prev start-0"></div>
</div>
</div>
<!-- Swiper End -->
<?php
return ob_get_clean();
endif;
}
Init JS
// Cards
document.addEventListener('DOMContentLoaded', function () {
const bsSwiper = document.querySelectorAll('.cards');
for (let i = 0; i < bsSwiper.length; i++) {
const el = bsSwiper[i];
el.classList.add('cards-' + i);
let breakpoints = {
slidesPerView: 1, // xs
576: { slidesPerView: 1 }, // sm
768: { slidesPerView: 2 }, // md
992: { slidesPerView: 3 }, // lg
1200: { slidesPerView: 4 }, // xl
1400: { slidesPerView: 4 }, // 2xl (xxl will be renamed into 2xl in Bootstrap 6)
};
const bpData = el.getAttribute('data-swiper-breakpoints');
if (bpData) {
try {
breakpoints = JSON.parse(bpData);
} catch (e) {
console.warn('Invalid Swiper breakpoints JSON:', bpData);
}
}
new Swiper('.cards-' + i, {
slidesPerView: 1,
spaceBetween: 20,
loop: true,
grabCursor: true,
pagination: {
el: '.swiper-pagination',
clickable: true,
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
breakpoints: breakpoints
});
}
});
This will allow to remove templates which is better for maintenance in the long-term. But this will include breaking changes which leads into bs Swiper v6.
From my experience, it's a massive effort to lift a plugin to the next major version and I'm not sure if I have the energy to do this (alone) yet. Question: @Jonowa Are you willing and able to work on this as well?
Basti
Edit, More options:
- infinite-loop="true"
- fade="true"
- autoplay="true"
- transition="1500"
- ...
Just to add some input from myself to that issue. I do understand that it is tempting to fix the cols in js and work from there. The issue that then occurs is that you get CLS issues as soon as the slider is above the fold. So if a rework of the swiper stuff is done I think CLS should be considered as well in the thought process.
I have plenty ideas to rework this plugin into a more flexible and better one. But thinking about turning this from free into a commercial plugin as well.