legnaleama legnaleama - 9 days ago 7
HTML Question

Categories menu using JQuery on a static page

Here's my case:

I'm building a classic layout with a side menu on the left with a list of categories and a list of tiles on the main wrapper that get filtered depending on what category the user choses.

Now, the page is a static site so all content is already there (no need of Json, AJAX or anything fancy) and each "tile" can have more than one category attached, so I think a simple Jquery script should do the trick. Having said that, I'm quite clueless when it comes to JQuery and though my code works very nicely I feel it's not very optimized.

Could someone lend a hand and maybe teach me a couple of things? I would really appreciated it.

Here's the fiddle:
https://jsfiddle.net/6hmnk5od/

And here's the code:

JS

$(document).ready(function() {

// Reset
$('.cat-tree-reset').click(function() {
$('.cat-active').removeClass('cat-active');
$('.tiles-list').children('.tile-item').show();
});

// Show/hide projects
$('.cat-1').click(function() {
$('.cat-active').removeClass('cat-active');
$(this).addClass('cat-active');
$('.tiles-list').children('li.tile-item, :not(.cat-1-item)').hide();
$('.tiles-list').children('.cat-1-item').show();
});

$('.cat-2').click(function() {
$('.cat-active').removeClass('cat-active');
$(this).addClass('cat-active');
$('.tiles-list').children('li.tile-item, :not(.cat-2-item)').hide();
$('.tiles-list').children('.cat-2-item').show();
});

$('.cat-3').click(function() {
$('.cat-active').removeClass('cat-active');
$(this).addClass('cat-active');
$('.tiles-list').children('li.tile-item, :not(.cat-3-item)').hide();
$('.tiles-list').children('.cat-3-item').show();
});

$('.cat-4').click(function() {
$('.cat-active').removeClass('cat-active');
$(this).addClass('cat-active');
$('.tiles-list').children('li.tile-item, :not(.cat-4-item)').hide();
$('.tiles-list').children('.cat-4-item').show();
});

$('.cat-5').click(function() {
$('.cat-active').removeClass('cat-active');
$(this).addClass('cat-active');
$('.tiles-list').children('li.tile-item, :not(.cat-5-item)').hide();
$('.tiles-list').children('.cat-5-item').show();
});

$('.cat-6').click(function() {
$('.cat-active').removeClass('cat-active');
$(this).addClass('cat-active');
$('.tiles-list').children('li.tile-item, :not(.cat-6-item)').hide();
$('.tiles-list').children('.cat-6-item').show();
});

$('.cat-7').click(function() {
$('.cat-active').removeClass('cat-active');
$(this).addClass('cat-active');
$('.tiles-list').children('li.tile-item, :not(.cat-7-item)').hide();
$('.tiles-list').children('.cat-7-item').show();
});

$('.cat-8').click(function() {
$('.cat-active').removeClass('cat-active');
$(this).addClass('cat-active');
$('.tiles-list').children('li.tile-item, :not(.cat-8-item)').hide();
$('.tiles-list').children('.cat-8-item').show();
});

});


HTML

<div class="categories-list">
<label>Categories</label>

<div class="cat-tree-reset">Clear</div>

<ul class="cat-tree-wrapper">
<li>
<span class="cat-tree-item cat-1">Category 1</span>
</li>
<li>
<span class="cat-tree-item cat-2">Category 2</span>
</li>
<li>
<span class="cat-tree-item cat-3">Category 3</span>
</li>
<li>
<span class="cat-tree-item cat-4">Category 4</span>
</li>
<li>
<span class="cat-tree-item cat-5">Category 5</span>
</li>
<li>
<span class="cat-tree-item cat-6">Category 6</span>
</li>
<li>
<span class="cat-tree-item cat-7">Category 7</span>
</li>
<li>
<span class="cat-tree-item cat-8">Category 8</span>
</li>
</ul>
</div>

<hr>


<ul class="row tile-card-wrapper tiles-list" id="container">
<li class="tile-item cat-3-item cat-7-item cat-2-item">
Tile A
</li>
<li class="cat-2-item tile-item cat-3-item cat-7-item cat-6-item">
Tile B
</li>
<li class="cat-1-item tile-item cat-3-item cat-6-item cat-7-item">
Tile C
</li>
<li class="cat-2-item tile-item cat-7-item">
Tile D
</li>
<li class="tile-item cat-3-item cat-6-item cat-7-item">
Tile E
</li>
<li class="tile-item cat-6-item">
Tile F
</li>
<li class="tile-item cat-5-item">
Tile G
</li>
<li class="tile-item cat-1-item cat-3-item">
Tile H
</li>
<li class="tile-item cat-3-item cat-4-item cat-7-item">
Tile I
</li>
<li class="tile-item cat-3-item cat-6-item cat-7-item">
Tile J
</li>
<li class="tile-item cat-3-item cat-7-item cat-5-item">
Tile K
</li>
<li class="tile-item cat-3-item cat-7-item cat-2-item">
Tile L
</li>
<li class="tile-item cat-3-item cat-6-item cat-7-item">
Tile M
</li>
<li class="tile-item cat-3-item cat-6-item cat-7-item">
Tile N
</li>
<li class="tile-item cat-1-item cat-4-item">
Tile O
</li>
<li class="tile-item cat-3-item cat-7-item cat-8-item">
Tile P
</li>
<li class="tile-item cat-3-item">
Tile Q
</li>
<li class="tile-item cat-3-item cat-1-item">
Tile R
</li>
<li class="tile-item cat-3-item cat-4-item cat-8-item">
Tile S
</li>
</ul>


Thank you very much!

Answer

We can make your code substantially shorter and easier to maintain.

HTML: I have removed a lot of classes, and added a single data attribute to each span, data-cat, which is just the category number.

The tile items themselves no longer have multiple classes, but a single data-cats attribute which contains an array of the categories they belong to.

<div class="categories-list" >
<label>Categories</label>

<div class="cat-tree-reset">Clear</div>

<ul class="cat-tree-wrapper">
  <li>
    <span data-cat="1">Category 1</span>
  </li>
  <li>
    <span data-cat="2">Category 2</span>
  </li>
  <li>
    <span data-cat="3">Category 3</span>
  </li>
  <li>
    <span data-cat="4">Category 4</span>
  </li>
  <li>
    <span data-cat="5">Category 5</span>
  </li>
  <li>
    <span data-cat="6">Category 6</span>
  </li>
  <li>
    <span data-cat="7">Category 7</span>
  </li>
  <li>
    <span data-cat="8">Category 8</span>
  </li>
</ul>
</div>

<hr>


<ul class="row tile-card-wrapper tiles-list" id="container">
  <li class="tile-item" data-cats="[2,3,7]">
    Tile A        
  </li>
  <li class="tile-item" data-cats="[2,3,6,7]">
    Tile B
  </li>
  <li class="tile-item" data-cats="[1,3,6,7]">
    Tile C
  </li>
  <li class="tile-item" data-cats="[2,7]">
    Tile D
  </li>
  <li class="tile-item" data-cats="[3,6,7]">
    Tile E
  </li>
  <li class="tile-item" data-cats="[6]">
    Tile F
  </li>
  <li class="tile-item" data-cats="[5]">
    Tile G
  </li>
  <li class="tile-item" data-cats="[3]">
    Tile H
  </li>
  <li class="tile-item" data-cats="[4,8]">
    Tile I
  </li>
</ul>

JavaScript: We are just putting one click handler on all the clickable spans, and using their new data-cat attribute to filter the tile-items.

$(document).ready(function () {

  // Reset
  $('.cat-tree-reset').click(function() {
      $('.tile-item').show();
  });

  $('.cat-tree-wrapper > li > span').click(function() {
    //get the data-cat value for the span we clicked on
    var category = $(this).data('cat');

    // hide all tile items
    $('.tile-item').hide();

    // the function passed to filter returns true if the current tile item
    // contains the category we obtained earlier, or false if it doesn't
    // leaving us with only the tile items in that category, which we show.
    $('.tile-item').filter(function() {
        return $(this).data('cats').includes(category);
    }).show();
  });      
});

JSFiddle

Comments