【问题标题】:Simple Shuffle.js search not working with Bootstrap 4 cards简单的 Shuffle.js 搜索不适用于 Bootstrap 4 卡
【发布时间】:2020-08-01 09:48:18
【问题描述】:

所以,最近几天我一直在尝试让Shuffle.js 使用我在Bootstrap 4 中的卡片,以便在搜索/过滤这些卡片时产生良好的洗牌效果。

下面是我的 HTML 和我的 JS 的结构。您还可以在此处找到JSFiddle.net 链接。

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>

另外,我认为它肯定坏的地方如下

this.shuffle.filter(element => {
    const titleText = element.querySelector('.card-title').textContent.toLowerCase().trim();
    return titleText.indexOf(searchText) !== -1;
});

因为我无法在其中进行调试。

有人对这个问题的解决方案有任何想法吗?我一直发现 Shuffle.js 库非常复杂,就像我看到最终(想要的!)效果时的感觉一样流畅。

【问题讨论】:

  • 嗨@NishargShah 感谢您的编辑!我已经使用包含和需要的所有 js 的工作版本编辑了帖子。让我知道这是否有帮助!
  • 我试图让你的 sn-p 工作但仍然无法工作,我认为你需要在 codepen 或 jsFiddle 中创建一个 sn-p
  • @NishargShah 我已经在 jsfiddle 上添加了代码,它的行为与我的代码相同。我这里贴出来,在贴子里编辑给大家看看:jsfiddle.net/8srk391z
  • 初始化new window.Shuffle后,#card-space的高度设置为0。接下来,filter内部的items数组为0。
  • @NishargShah 如果您检查页面@TimVermaelen,html 应该显示应该在 HTML 中的卡片。感谢您让我注意到。你对如何解决它有什么建议吗?我不会使用 css,但会调整 new window.Shuffle 以解决它。关于filter,你指的是哪个items数组?

标签: javascript html css twitter-bootstrap bootstrap-4


【解决方案1】:

看看这个demo。我所做的是完全删除整个网格结构并使用 Bootstrap 的card-deck。 之所以会这样,是因为这个库查找要过滤的 items 数组的方式。

_getItems() {
    return Array.from(this.element.children)
        .filter(el => matches(el, this.options.itemSelector))
        .map(el => new ShuffleItem(el));
}

这基本上意味着它采用直接子代并匹配您的 itemSelector。 在您的 HTML 结构中,它包含所有列,并且在您的列中找不到任何 itemSelector 类。

另一个重要步骤是使用data-groups 和/或data-title。 现在我只为标题 (name) 设置了它,但我相信您的目标也是添加单独的组。您可以从您已经创建的类别选择器中填写这些内容(只有一个选项)。

this.BS.card.setAttribute('data-title', name);
this.BS.card.setAttribute('data-groups', name);

这个解决方案启用了过滤器,启用了高度,并且只剩下现在使 .card-deck 响应,因为卡片组很棒(我在这里重复)。

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

【讨论】:

  • 好兄弟,你解决了他/她的问题? +1
  • 谢谢蒂姆,这太棒了!我现在会尝试稍微调整一下,以获得更“类似网格”的布局,但这确实做到了
  • 不客气,请随时查看Bootstrap card-layout 切换布局。如今,卡片组,-columns(砌体)样式都是可能的。
【解决方案2】:

您可以过滤 Array 而不是 Object。我是console.log,所以你可以看到它。

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>

【讨论】:

  • 谢谢@NishargShah,这解决了items 数组为空的问题,但是当尝试在search 输入中输入字符串时它仍然无法过滤:(
  • 兄弟,你需要自己解决这个问题,因为为此我需要阅读整个文档和太多东西,才能应用该配置。
  • 好吧,无论如何感谢您的帮助,这已经是一个很大的进步!我会支持你的解决方案
  • 尝试一下,如果不行,请在 StackOverflow 上发布另一个问题,谢谢!!
猜你喜欢
  • 2020-11-02
  • 2016-05-03
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-07
  • 2021-06-20
相关资源
最近更新 更多