问题
So, I've been trying for the last days to get Shuffle.js
to work with my cards in Bootstrap 4
, in order to have a nice shuffling effect when searching/filtering those cards.
Here follows the structure of my HTML and my JS. You can also find here the JSFiddle.net link.
class Card {
constructor(ref) {
this.hmi_ref = ref;
// Bootstap : container type
this.BS = {}
this.BS.container = document.createElement('div');
this.BS.card = document.createElement('div');
this.BS.image = document.createElement('img');
this.BS.info = document.createElement('div');
this.BS.title = document.createElement('h4');
this.BS.link = document.createElement('a');
this.BS.card.appendChild(this.BS.link);
this.BS.link.appendChild(this.BS.image);
this.BS.card.appendChild(this.BS.title);
this.BS.container.appendChild(this.BS.card);
this.BS.container.className = 'col-4 mb-3';
this.BS.card.className = 'card h-100';
this.BS.image.className = 'card-img-top';
this.BS.title.className = 'card-title text-center align-middle';
}
add(name, image, page_link) {
this.BS.image.src = image;
this.BS.title.textContent = name;
this.BS.link.href = page_link;
let newNode = this.BS.container.cloneNode(true);
this.hmi_ref.appendChild(newNode);
}
}
let myCard = new Card( document.getElementById('card-space') );
[
{title: 'Vacanza studio Londra', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Roma', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Bangkok', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Catania', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanze studio"},
{title: 'Vacanza studio Siracusa', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Ragusa', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Trapani', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
].map(e => myCard.add(e.title, e.img, e.link, e.category));
class Shuffler {
constructor(element) {
this.shuffle = new window.Shuffle(element, {
itemSelector: '.card',
sizer: element.querySelector('.sizer'),
});
document.getElementById('searchBox').addEventListener('keyup', this._handleSearchKeyup.bind(this));
}
/**
* Filter the shuffle instance by items with a title that matches the search input.
* @param {Event} evt Event object.
*/
_handleSearchKeyup(evt) {
const searchText = evt.target.value.toLowerCase();
this.shuffle.filter(element => {
console.log('filtering...');
const titleText = element.querySelector('.card-title').textContent.toLowerCase().trim();
return titleText.indexOf(searchText) !== -1;
});
}
}
window.onload = () => {
window.demo = new Shuffler(document.querySelector('#card-space'));
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<div class="container pt-3">
<div class="row">
<div class="col">
<!-- Main column -->
<div class="row pt-4">
<div class="col-9">
<div id="card-space" class="row h-100">
<div class="col-1@sm sizer"></div>
</div>
</div>
<div class="col-3">
<div class="row">
<form class="form-inline" action="javascript:void(0);">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fa fa-search" aria-hidden="true"></i></div>
</div>
<input id="searchBox" class="form-control" type="search" placeholder="Cerca" aria-label="Cerca">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://unpkg.com/shufflejs@5"></script>
<!-- jQuery first, then Popper.js and then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
In addition, the point in which I think it definitely breaks is the following
this.shuffle.filter(element => {
const titleText = element.querySelector('.card-title').textContent.toLowerCase().trim();
return titleText.indexOf(searchText) !== -1;
});
as I cannot be able to debug inside it.
Does anyone have any ideas about the solution to this problem? I've been finding the Shuffle.js library pretty as complicate as smooth is the feeling I get when seeing the final (desired!) effect.
回答1:
Take a look at this demo. What I've done is remove the entire grid structure completely and went for Bootstrap's card-deck
.
The reason for this, because of the way this library looks for the items array to filter on.
_getItems() {
return Array.from(this.element.children)
.filter(el => matches(el, this.options.itemSelector))
.map(el => new ShuffleItem(el));
}
This basically means it takes the direct children and matches your itemSelector.
In your HTML structure it takes all the columns, and can't find any itemSelector
classes on your columns.
Another important step was to use the data-groups
and/or data-title
.
Now I've set it only for the title (name
) but I believe your goal is to add separate groups as well. You can fill those in from the category selector you've already created (with only one option tho).
this.BS.card.setAttribute('data-title', name);
this.BS.card.setAttribute('data-groups', name);
This solution enables the filter, enables the height and only left is now making .card-deck
responsive, as card-deck is great (I'm on repeat here).
Arrange multiple divs in CSS/JS?
loop every 3 row using bootstrap card
How do I add spacing between rows of a card-deck in bootstrap
responsive card-deck CSS demo
回答2:
You can filter Array
not an Object
. I do console.log
so you can see it.
class Card {
constructor(ref) {
this.hmi_ref = ref;
// Bootstap : container type
this.BS = {}
this.BS.container = document.createElement('div');
this.BS.card = document.createElement('div');
this.BS.image = document.createElement('img');
this.BS.info = document.createElement('div');
this.BS.title = document.createElement('h4');
this.BS.link = document.createElement('a');
this.BS.card.appendChild(this.BS.link);
this.BS.link.appendChild(this.BS.image);
this.BS.card.appendChild(this.BS.title);
this.BS.container.appendChild(this.BS.card);
this.BS.container.className = 'col-4 mb-3';
this.BS.card.className = 'card h-100';
this.BS.image.className = 'card-img-top';
this.BS.title.className = 'card-title text-center align-middle';
}
add ( name, image, page_link){
this.BS.image.src = image;
this.BS.title.textContent = name;
this.BS.link.href = page_link;
let newNode = this.BS.container.cloneNode(true);
this.hmi_ref.appendChild(newNode);
}
}
let myCard = new Card( document.getElementById('card-space') );
[
{title: 'Vacanza studio Londra', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Roma', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Bangkok', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Catania', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanze studio"},
{title: 'Vacanza studio Siracusa', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Ragusa', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
{title: 'Vacanza studio Trapani', img: 'https://source.unsplash.com/random/1920x1080', link: 'https://source.unsplash.com/random/1920x1080', category: "Vacanza studio"},
].map(e => myCard.add(e.title, e.img, e.link, e.category));
class Shuffler {
constructor(element) {
this.shuffle = new window.Shuffle(element, {
itemSelector: '.card',
sizer: element.querySelector('.sizer'),
});
document.getElementById('searchBox').addEventListener('keyup', this._handleSearchKeyup.bind(this));
}
/**
* Filter the shuffle instance by items with a title that matches the search input.
* @param {Event} evt Event object.
*/
_handleSearchKeyup(evt) {
const searchText = evt.target.value.toLowerCase();
Object.values(this.shuffle.element.children).filter(element => {
const titleText = element.textContent.toLowerCase().trim();
console.log(element.textContent.toLowerCase().trim(), titleText.indexOf(searchText));
return titleText.indexOf(searchText) !== -1;
});
}
}
window.onload = () => {
window.demo = new Shuffler(document.querySelector('#card-space'));
}
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container pt-3">
<div class="row">
<div class="col">
<!-- Main column -->
<div class="row pt-4">
<div class="col-9">
<div id="card-space" class="row">
<!-- <div class="col-1@sm sizer"></div> -->
</div>
</div>
<div class="col-3">
<div class="row">
<form class="form-inline" action="javascript:void(0);">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fa fa-search" aria-hidden="true"></i></div>
</div>
<input id="searchBox" class="form-control" type="search" placeholder="Cerca" aria-label="Cerca">
</div>
</form>
</div>
<div class="row">
<select class="custom-select my-3" id="eventCategories">
<option selected>Scegli una categoria</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Shuffle/5.2.3/shuffle.min.js"></script>
<!-- jQuery first, then Popper.js and then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</body>
</html>
来源:https://stackoverflow.com/questions/61296253/simple-shuffle-js-search-not-working-with-bootstrap-4-cards