skip to Main Content

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".

3

Answers


  1. It sounds like you want to dynamically change the flex order of the .item divs based on the selected option in the box using jQuery. You can achieve this by modifying the order property of each .item based on their score values. Here’s how you can do it:

    //js
    $(document).ready(function() {
      // Initial sorting based on score
      sortItems();
    
      // Handle select box change event
      $('#sort-select').change(function() {
        sortItems();
      });
    });
    
    function sortItems() {
      var selectedValue = $('#sort-select').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;
        } else if (selectedValue === 'worst') {
          return aScore - bScore;
        }
      });
    
      $('#wrapper').empty(); // Clear the current items
    
      // Re-append sorted items to the wrapper
      $items.forEach(function(item) {
        $('#wrapper').append(item);
      });
    }
    #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.7.0/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>

    I’ve added a step to empty the #wrapper container and then re-append the sorted items. This effectively reorders the items based on the updated sorting order without affecting any additional scripts associated with them. Please give this code a try, and if you encounter any issues, let me know the specifics, and I’ll be glad to assist further.

    working example

    Login or Signup to reply.
  2. 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>
    Login or Signup to reply.
  3. You don’t need JQuery to implement this. Modern browsers can handle what you’re using JQuery for (at least in this case anyway).


    Solution

    I wouldn’t try to solve it in one step (it would make maintenance a PITA later).

    1. First you collect the elements in a list by extracting the relevant value.
    2. Then, you sort this list the way you want (based on the extracted value).
    3. As a third step, you apply the flexbox order based on the result of your sorting.

    This way your DOM structure won’t change, just the style property of each element.

    Don’t specify a flexbox order out of the box. Let the script handle that.

    I used ES 6 syntax (I’m more used to it, and it’s way easier to work with).

    function sortItems() {
      // get the list DOM elements
      const items = document.querySelectorAll('.item');
    
      // collect them as a key-value pair (the DOM element is the key, 
      // the sorting criteria is the value)
      const data = [];
      items.forEach((element) => {
        data.push({
          element,
          value: parseInt(element.querySelector('.score').innerText),
        });
      });
      
      // get the value of the select element
      const sorter = document.querySelector('#sorting select');
      const value = sorter.value;
    
      // sort based on it
      switch (value) {
        default: 
        case ".best":
          data.sort((a, b) => {
            if (a.value === b.value)
              return 0;
            return a.value < b.value ? 1 : -1;
          });
          break;
        case ".worst": 
          data.sort((a, b) => {
            if (a.value === b.value) 
              return 0;
            return a.value < b.value ? -1 : 1;
          });
          break;
      }
    
      // add the flexbox order based on the list order
      for (let i = 0; i < data.length; i++) {
        data[i].element.style.order = i;
      }
    }
    
    // change event
    document.querySelector('#sorting select').addEventListener('change', sortItems);
    // just to reflect the state of the selector
    sortItems();
    #wrapper {
        display: flex;
        flex-wrap: wrap;
        width: 100%;
    }
    
    #wrapper > .item {
        flex: 0 0 100%;
        padding: 20px;
        box-sizing: border-box;
        background-color: #ccc;
        margin: 10px 0;
    }
    <div id="sorting">
      <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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search