多个复选框过滤可缩小搜索范围

时间:2019-04-17 17:37:52

标签: javascript html vue.js search filtering

谢谢Khalid Ali到目前为止对我的帮助。

因此,我有一系列包含说明,关键字等的歌曲。我想使用许多复选框来优化搜索。基本上,如果有人选中“流行”复选框,它将显示所有具有“流行”流派的歌曲。但是,如果我还选择“史诗预告片”,它将返回其流派中所有带有“ pop”的歌曲和所有带有“ epictrailers”的歌曲。我想要的是只返回两种流派的歌曲。例如-体裁:“流行,后代”,

在下面的数组中,您将看到歌曲2和歌曲3都具有“戏剧性”的情绪。但是歌曲2也有“紧张”,歌曲3也有“飙升”。因此,如果我选中“戏剧性和飙升”复选框,那么我应该只会看到歌曲3。由于两首歌曲都带有“戏剧性”,因此目前两首歌曲都显示出来。

因此,简而言之,我希望它只返回包含所有复选框的歌曲。

我希望这是有道理的...

HTML片段:

<div id="app">
  <div class="search-music">
    <input type="text" v-model="search" placeholder="Enter a keyword to refine your search"/>
  </div>

  <div class='filterboxes'>
            <div class="genres"><h1>GENRES</h1><br>
            <input type="checkbox" id="rock" key="genre" value="rock" v-model="checkboxFilter">
            <label for="rock">Rock</label><br>
            <input type="checkbox" id="Pop" key="genre" value="pop" v-model="checkboxFilter">
            <label for="Pop">Pop</label><br>
            <input type="checkbox" id="funk" key="genre" value="funk" v-model="checkboxFilter">
            <label for="funk">Funk</label><br>
            <input type="checkbox" id="Jazz" key="genre" value="jazz" v-model="checkboxFilter">
            <label for="Jazz">Jazz</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Dubstep" key="genre" value="dubstep" v-model="checkboxFilter">
            <label for="Dubstep">Dubstep</label><br>
            <input type="checkbox" id="Classical" key="genre" value="classical" v-model="checkboxFilter">
            <label for="Classical">Classical</label><br>
            <input type="checkbox" id="Country" key="genre" value="country" v-model="checkboxFilter">
            <label for="Country">Country</label><br>
            <input type="checkbox" id="Blues" key="genre" value="blues" v-model="checkboxFilter">
            <label for="Blues">Blues</label><br>
          </div>
          <div class="genres"><P></P><br>
            <input type="checkbox" id="Hip Hop" key="genre" value="hiphop" v-model="checkboxFilter">
            <label for="Hip Hop">Hip Hop</label><br>
            <input type="checkbox" id="Orchestral" key="genre" value="orchestral" v-model="checkboxFilter">
            <label for="Orchestral">Orchestral</label><br>
            <input type="checkbox" id="Epic Trailer" key="genre" value="epictrailer" v-model="checkboxFilter">
            <label for="Epic Trailer">Epic Trailer</label><br>
            <input type="checkbox" id="EDM" key="genre" value="edm" v-model="checkboxFilter">
            <label for="EDM">EDM</label><br>
            </div>
            <div class="genres"><h1>MOODS</h1><br>
            <input type="checkbox" id="Melancholy" key="moods" value="melancholy" v-model="checkboxFilter">
            <label for="Melancholy">Melancholy</label><br>
            <input type="checkbox" id="Upbeat" key="moods" value="upbeat" v-model="checkboxFilter">
            <label for="Upbeat">Upbeat</label><br>
            <input type="checkbox" id="Playful" key="moods" value="playful" v-model="checkboxFilter">
            <label for="Playful">Playful</label><br>
            <input type="checkbox" id="Hopeful" key="moods" value="hopeful" v-model="checkboxFilter">
            <label for="Hopeful">Hopeful</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Dramatic" key="moods" value="dramatic" v-model="checkboxFilter">
            <label for="Dramatic">Dramatic</label><br>
            <input type="checkbox" id="Disturbing" key="moods" value="disturbing" v-model="checkboxFilter">
            <label for="Disturbing">Disturbing</label><br>
            <input type="checkbox" id="Uplifting" key="moods" value="uplifting" v-model="checkboxFilter">
            <label for="Uplifting">Uplifting</label><br>
            <input type="checkbox" id="Tense" key="moods" value="tense" v-model="checkboxFilter">
            <label for="Tense">Tense</label><br>
          </div>
          <div class="genres"><P></P><br>
            <input type="checkbox" id="Crazy" key="moods" value="crazy" v-model="checkboxFilter">
            <label for="Crazy">Crazy</label><br>
            <input type="checkbox" id="Funny" key="moods" value="funny" v-model="checkboxFilter">
            <label for="Funny">Funny</label><br>
            <input type="checkbox" id="Soaring" key="moods" value="soaring" v-model="checkboxFilter">
            <label for="Soaring">Soaring</label><br>
            <input type="checkbox" id="Childish" key="moods" value="childish" v-model="checkboxFilter">
            <label for="Childish">Childish</label><br>
            </div>
            <div class="genres"><h1>TEMPO</h1><br>
            <input type="checkbox" id="vfast" key="tempo" value="vfast" v-model="checkboxFilter">
            <label for="vfast">Very Fast</label><br>
            <input type="checkbox" id="fast" key="tempo" value="fast" v-model="checkboxFilter">
            <label for="fast">Fast</label><br>
            <input type="checkbox" id="moderate" key="tempo" value="moderate" v-model="checkboxFilter">
            <label for="moderate">Moderate</label><br>
            <input type="checkbox" id="slow" key="tempo" value="slow" v-model="checkboxFilter">
            <label for="slow">Slow</label><br>
          </div>
            <div class="genres"><h1>THEMES</h1><br>
            <input type="checkbox" id="Corporate" key="theme" value="corporate" v-model="checkboxFilter">
            <label for="Corporate">Corporate</label><br>
            <input type="checkbox" id="Technology" key="theme" value="technology" v-model="checkboxFilter">
            <label for="Technology">Technology</label><br>
            <input type="checkbox" id="Food" key="theme" value="food" v-model="checkboxFilter">
            <label for="Food">Food</label><br>
            <input type="checkbox" id="Education" key="theme" value="education" v-model="checkboxFilter">
            <label for="Education">Education</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Travel" key="theme" value="travel" v-model="checkboxFilter">
            <label for="Travel">Travel</label><br>
            <input type="checkbox" id="Sport" key="theme" value="sport" v-model="checkboxFilter">
            <label for="Sport">Sport</label><br>
            <input type="checkbox" id="Fashion" key="theme" value="fashion" v-model="checkboxFilter">
            <label for="Fashion">Fashion</label><br>
            <input type="checkbox" id="Landscape" key="theme" value="landscape" v-model="checkboxFilter">
            <label for="Landscape">Landscape</label><br>
          </div>
          </div>


  <template v-for='song in filteredSongs'>
    <div class="songlayout" >
      <div class='wrapper'>
        <div>
          <img :src="song.cover_art_url" alt="" class='img-fluid rounded'>
        </div>
        <button class="button_7" @click='openLicense(song.license_url)'>License</button>
        <h1 class='song-title'>{{song.title}}</h1>
        <p class="song-description" >{{song.description}}</p>

        <div class="overlay-play text-center" v-if="isPlaying && (currentSong.id === song.id )" @click='pause'>
          <i class="icon ion-ios-pause"></i>
        </div>

        <div class="overlay-play text-center" @click='play(song)' v-else>
          <i class="icon ion-ios-play"></i>
        </div>
      </div>
    </div>
  </template>
</div>

JS SNIPPET:

new Vue({
  el: '#app',
  data: {
    songs: [
            {
        id: 1,
        title: "Track 1",
        description: "Description 1",
        url:"./mp3/track1.mp3",
        keywords: "achievement, advertising, background, beautiful, beauty, business, business music, commercial, company, confident, corporate, corporate background, corporate presentation, corporate presentations music, corporate video, corporation, corporative, happy",
        genre:"pop, rock",
        moods:"uplifting, upbeat, playful",
        tempo:"moderate",
        theme:"corporate",
      },

      {
        id: 2,
        title: "Track 2",
        description: "Description 2",
        url:"./mp3/track2.mp3",
        keywords: "scary, horror, Armageddon, Big Ending, Dramatic, End Of The World, Escape, Fantasy, Film, Film Score, Foreboding, Haunted House, Haunting, Nervous, Nightmare, Pensive",
        genre:"epictrailer",
        moods:"tense, dramatic, disturbing",
        tempo:"moderate",
        theme:"landscape",
      },
      {
        id: 3,
        title: "Track 3",
        description: "Description 3",
        url: "./mp3/track3.mp3",
        keywords:"Armageddon, Battle, Big Ending, Bomb, Break Out, Busy, Chase, Chilled, Covert Ops, Detective,",
        genre:"epictrailer",
        moods:"dramatic, soaring, hopeful",
        tempo:"moderate",
        theme:"sport",
      },
          ],

    search: "",
    checkboxFilter: [],
  },
  computed: {
    filteredSongs: function(value, key){
    let fltrdSongs;
    if(this.checkboxFilter.length > 0) {
      fltrdSongs = this.songs.filter((song) => {
        let length = this.checkboxFilter.length;
        while(length--){
          if ((song.genre + song.moods + song.theme + song.tempo).indexOf(this.checkboxFilter[length])!=-1)
           {return true;}

        }
      });
    } else {
      fltrdSongs = this.songs;
    }

    return fltrdSongs.filter((song) => {
      return song.keywords.toLowerCase().match(this.search.toLowerCase()) ||
             song.title.toLowerCase().match(this.search.toLowerCase()) ||
             song.description.toLowerCase().match(this.search.toLowerCase())
    });
},},

1 个答案:

答案 0 :(得分:0)

由于filteredSongs语句之前,您的this.checkboxFilter.length 计算属性永远不会到达return if语句。

将您的filteredSongs计算属性替换为以下内容:

filteredSongs: function(value, key){
    let fltrdSongs;
    if(this.checkboxFilter.length > 0)
      fltrdSongs = this.songs.filter((song) => (song.genre)
                                     .includes(this.checkboxFilter.toString()));
    else
      fltrdSongs = this.songs;

    return fltrdSongs.filter((song) => {
      return song.keywords.toLowerCase().match(this.search.toLowerCase()) ||
             song.title.toLowerCase().match(this.search.toLowerCase()) ||
             song.description.toLowerCase().match(this.search.toLowerCase())
    });
}

响应jeanpegg's comment

使用以下计算属性通过多个复选框过滤歌曲

filteredSongs: function(value, key){
    let fltrdSongs;
    if(this.checkboxFilter.length > 0) {
      fltrdSongs = this.songs.filter((song) => {
        let length = this.checkboxFilter.length;
        while(length--){
          if ((song.genre).indexOf(this.checkboxFilter[length])!=-1) {
            return true;
          }
        }
      });
    } else {
      fltrdSongs = this.songs;
    }

    return fltrdSongs.filter((song) => {
      return song.keywords.toLowerCase().match(this.search.toLowerCase()) ||
             song.title.toLowerCase().match(this.search.toLowerCase()) ||
             song.description.toLowerCase().match(this.search.toLowerCase())
    });
}

响应jeanpegg's comment

我已经编辑了代码以与流派心情一起使用。

HTML:将v-model="checkboxFilter"更改为v-model="checkboxFilter.genre"v-model="checkboxFilter.moods"

JS:将checkboxFilter 数据属性更改为checkboxFilter: {genre: [], moods: []}。还更改了filteredSongs 计算属性

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script><div id="app">
  <div class="search-music">
    <input type="text" v-model="search" placeholder="Enter a keyword to refine your search"/>
  </div>

  <div class='filterboxes'>
            <div class="genres"><h1>GENRES</h1><br>
            <input type="checkbox" id="rock" key="genre" value="rock" v-model="checkboxFilter.genre">
            <label for="rock">Rock</label><br>
            <input type="checkbox" id="Pop" key="genre" value="pop" v-model="checkboxFilter.genre">
            <label for="Pop">Pop</label><br>
            <input type="checkbox" id="funk" key="genre" value="funk" v-model="checkboxFilter.genre">
            <label for="funk">Funk</label><br>
            <input type="checkbox" id="Jazz" key="genre" value="jazz" v-model="checkboxFilter.genre">
            <label for="Jazz">Jazz</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Dubstep" key="genre" value="dubstep" v-model="checkboxFilter.genre">
            <label for="Dubstep">Dubstep</label><br>
            <input type="checkbox" id="Classical" key="genre" value="classical" v-model="checkboxFilter.genre">
            <label for="Classical">Classical</label><br>
            <input type="checkbox" id="Country" key="genre" value="country" v-model="checkboxFilter.genre">
            <label for="Country">Country</label><br>
            <input type="checkbox" id="Blues" key="genre" value="blues" v-model="checkboxFilter.genre">
            <label for="Blues">Blues</label><br>
          </div>
          <div class="genres"><P></P><br>
            <input type="checkbox" id="Hip Hop" key="genre" value="hiphop" v-model="checkboxFilter.genre">
            <label for="Hip Hop">Hip Hop</label><br>
            <input type="checkbox" id="Orchestral" key="genre" value="orchestral" v-model="checkboxFilter.genre">
            <label for="Orchestral">Orchestral</label><br>
            <input type="checkbox" id="Epic Trailer" key="genre" value="epictrailer" v-model="checkboxFilter.genre">
            <label for="Epic Trailer">Epic Trailer</label><br>
            <input type="checkbox" id="EDM" key="genre" value="edm" v-model="checkboxFilter.genre">
            <label for="EDM">EDM</label><br>
            </div>
            <div class="genres"><h1>MOODS</h1><br>
            <input type="checkbox" id="Melancholy" key="moods" value="melancholy" v-model="checkboxFilter.moods">
            <label for="Melancholy">Melancholy</label><br>
            <input type="checkbox" id="Upbeat" key="moods" value="upbeat" v-model="checkboxFilter.moods">
            <label for="Upbeat">Upbeat</label><br>
            <input type="checkbox" id="Playful" key="moods" value="playful" v-model="checkboxFilter.moods">
            <label for="Playful">Playful</label><br>
            <input type="checkbox" id="Hopeful" key="moods" value="hopeful" v-model="checkboxFilter.moods">
            <label for="Hopeful">Hopeful</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Dramatic" key="moods" value="dramatic" v-model="checkboxFilter.moods">
            <label for="Dramatic">Dramatic</label><br>
            <input type="checkbox" id="Disturbing" key="moods" value="disturbing" v-model="checkboxFilter.moods">
            <label for="Disturbing">Disturbing</label><br>
            <input type="checkbox" id="Uplifting" key="moods" value="uplifting" v-model="checkboxFilter.moods">
            <label for="Uplifting">Uplifting</label><br>
            <input type="checkbox" id="Tense" key="moods" value="tense" v-model="checkboxFilter.moods">
            <label for="Tense">Tense</label><br>
          </div>
          <div class="genres"><P></P><br>
            <input type="checkbox" id="Crazy" key="moods" value="crazy" v-model="checkboxFilter.moods">
            <label for="Crazy">Crazy</label><br>
            <input type="checkbox" id="Funny" key="moods" value="funny" v-model="checkboxFilter.moods">
            <label for="Funny">Funny</label><br>
            <input type="checkbox" id="Soaring" key="moods" value="soaring" v-model="checkboxFilter.moods">
            <label for="Soaring">Soaring</label><br>
            <input type="checkbox" id="Childish" key="moods" value="childish" v-model="checkboxFilter.moods">
            <label for="Childish">Childish</label><br>
            </div>
            <div class="genres"><h1>TEMPO</h1><br>
            <input type="checkbox" id="vfast" key="tempo" value="vfast" v-model="checkboxFilter">
            <label for="vfast">Very Fast</label><br>
            <input type="checkbox" id="fast" key="tempo" value="fast" v-model="checkboxFilter">
            <label for="fast">Fast</label><br>
            <input type="checkbox" id="moderate" key="tempo" value="moderate" v-model="checkboxFilter">
            <label for="moderate">Moderate</label><br>
            <input type="checkbox" id="slow" key="tempo" value="slow" v-model="checkboxFilter">
            <label for="slow">Slow</label><br>
          </div>
            <div class="genres"><h1>THEMES</h1><br>
            <input type="checkbox" id="Corporate" key="theme" value="corporate" v-model="checkboxFilter">
            <label for="Corporate">Corporate</label><br>
            <input type="checkbox" id="Technology" key="theme" value="technology" v-model="checkboxFilter">
            <label for="Technology">Technology</label><br>
            <input type="checkbox" id="Food" key="theme" value="food" v-model="checkboxFilter">
            <label for="Food">Food</label><br>
            <input type="checkbox" id="Education" key="theme" value="education" v-model="checkboxFilter">
            <label for="Education">Education</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Travel" key="theme" value="travel" v-model="checkboxFilter">
            <label for="Travel">Travel</label><br>
            <input type="checkbox" id="Sport" key="theme" value="sport" v-model="checkboxFilter">
            <label for="Sport">Sport</label><br>
            <input type="checkbox" id="Fashion" key="theme" value="fashion" v-model="checkboxFilter">
            <label for="Fashion">Fashion</label><br>
            <input type="checkbox" id="Landscape" key="theme" value="landscape" v-model="checkboxFilter">
            <label for="Landscape">Landscape</label><br>
          </div>
          </div>


  <template v-for='song in filteredSongs'>
    <div class="songlayout" >
      <div class='wrapper'>
        <div>
          <img :src="song.cover_art_url" alt="" class='img-fluid rounded'>
        </div>
        <button class="button_7" @click='openLicense(song.license_url)'>License</button>
        <h1 class='song-title'>{{song.title}}</h1>
        <p class="song-description" >{{song.description}}</p>

        <div class="overlay-play text-center" v-if="isPlaying && (currentSong.id === song.id )" @click='pause'>
          <i class="icon ion-ios-pause"></i>
        </div>

        <div class="overlay-play text-center" @click='play(song)' v-else>
          <i class="icon ion-ios-play"></i>
        </div>
      </div>
    </div>
  </template>
</div>
new Vue({
  el: '#app',
  data: {
    isPlaying: '',
    songs: [
            {
        id: 1,
        title: "Track 1",
        description: "Description 1",
        url:"./mp3/track1.mp3",
        keywords: "achievement, advertising, background, beautiful, beauty, business, business music, commercial, company, confident, corporate, corporate background, corporate presentation, corporate presentations music, corporate video, corporation, corporative, happy",
        genre:"pop, rock",
        moods:"uplifting, upbeat, playful",
        tempo:"moderate",
        theme:"corporate",
      },

      {
        id: 2,
        title: "Track 2",
        description: "Description 2",
        url:"./mp3/track2.mp3",
        keywords: "scary, horror, Armageddon, Big Ending, Dramatic, End Of The World, Escape, Fantasy, Film, Film Score, Foreboding, Haunted House, Haunting, Nervous, Nightmare, Pensive",
        genre:"epictrailer",
        moods:"tense, dramatic, disturbing",
        tempo:"moderate",
        theme:"landscape",
      },
      {
        id: 3,
        title: "Track 3",
        description: "Description 3",
        url: "./mp3/track3.mp3",
        keywords:"Armageddon, Battle, Big Ending, Bomb, Break Out, Busy, Chase, Chilled, Covert Ops, Detective,",
        genre:"epictrailer",
        moods:"dramatic, soaring, hopeful",
        tempo:"moderate",
        theme:"sport",
      },
          ],

    search: "",
    checkboxFilter: {genre: [], moods: []},
  },
computed: {
  filteredSongs: function(value, key){
    let fltrdSongs = this.songs;
    // checking if "genre" and "moods" arrays have elements in any of them
    if(this.checkboxFilter.genre.length + this.checkboxFilter.moods.length > 0) {
      // checking if "genre" array has elements
      if (this.checkboxFilter.genre.length > 0) {
        fltrdSongs = this.songs.filter((song) => {
          let length = this.checkboxFilter.genre.length;
          while(length--){
            if ((song.genre).indexOf(this.checkboxFilter.genre[length])!=-1) {
              return true;
            }
          }
        });
      }
      // checking if "moods" array has elements
      if(this.checkboxFilter.moods.length > 0) {
        fltrdSongs = fltrdSongs.filter((song) => {
          let length = this.checkboxFilter.moods.length;
          while(length--){
            if ((song.moods).indexOf(this.checkboxFilter.moods[length])!=-1) {
              return true;
            }
          }
        });
      }
    }

    return fltrdSongs.filter((song) => {
      return song.keywords.toLowerCase().match(this.search.toLowerCase()) ||
             song.title.toLowerCase().match(this.search.toLowerCase()) ||
             song.description.toLowerCase().match(this.search.toLowerCase())
      });
   }
  }
});