Search code examples
javascriptcssalgorithmsortingevent-handling

Change order of divs by "flex order number" on filter select with jquery


Instead of changing the order of divs by jquery only, I just want to "change the flex order number" of every div, after selecting a sort method, with jquery.

For example, my select box:

<div id="sorting">
  <select>
    <option value=".best">Best</option>
    <option value=".worst">Worst</option>
  </select>
</div>

My list structure:

<div id="wrapper">
  <div class="item">
    <div class="score">12</div>
  </div>
  <div class="item">
    <div class="score">7</div>
  </div>
  <div class="item">
    <div class="score">42</div>
  </div>
  <!-- and so on -->
</div>

The css for the list:

#wrapper {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
}

#wrapper > .item {
    order: 0;
    flex: 0 0 100%;
    padding: 20px;
    box-sizing: border-box;
    background-color: #ccc;
    margin: 10px 0;
}

What I want:

On selecting ".best", the div with the highest score should get the lowest "flex order number" and so on (for each div). On selecting ".worst", the div with the lowest score should get the lowest "flex order number" aso.

My current "jquery only" way:

var best = $('#wrapper > .item').sort(function(b, a) {
    var a1 = $(a).find('.score').text(), b1 = $(b).find('.score').text();
    return a1.localeCompare(b1, false, {numeric: true})
});

The problem is, that I have to reinitialize all scripts for the ".item" divs after changing the order. That's something I want to prevent by the changing just the "flex order number".


Solution

  • You can achieve the this by changing the flex order of each .item element based on the selected sorting option using jQuery.

    Try below Code

    $(document).ready(function () {
      $("#sort-select").change(function () {
        var selectedValue = $(this).val();
        var items = $("#wrapper > .item").toArray();
    
        items.sort(function (a, b) {
          var aScore = parseInt($(a).find(".score").text());
          var bScore = parseInt($(b).find(".score").text());
    
          if (selectedValue === ".best") {
            return bScore - aScore; // Sort in descending order for best
          } else {
            return aScore - bScore; // Sort in ascending order for worst
          }
        });
    
        // Update the flex order based on the sorted order
        for (var i = 0; i < items.length; i++) {
          $(items[i]).css("order", i);
        }
      });
      $("#sort-select").trigger("change");
    });
    #wrapper {
        display: flex;
        flex-wrap: wrap;
        width: 100%;
    }
    
    #wrapper > .item {
        order: 0;
        flex: 0 0 100%;
        padding: 20px;
        box-sizing: border-box;
        background-color: #ccc;
        margin: 10px 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div id="sorting">
        <select id="sort-select">
            <option value=".best">Best</option>
            <option value=".worst">Worst</option>
        </select>
    </div>
    
    <div id="wrapper">
        <div class="item">
            <div class="score">12</div>
        </div>
        <div class="item">
            <div class="score">7</div>
        </div>
        <div class="item">
            <div class="score">42</div>
        </div>
        <!-- and so on -->
    </div>