Search code examples
javascriptjqueryuislider

How to use two Ui Range Sliders to sort the same data


I am new guy here. Nice to meet you. I wish you to ask about the problem I cannot solve by myself.

I am trying to sort some data using to UI Range Sliders. I want first to sort price, and then when the items are sorted i want to sort them next by their quality. But there is a problem. When first sorting action is done properly then the second is not working. I cannot find out what is wrong with my code. I'm new in JS. I did not find any answer yet. I am using JQuery and UI.

Please help.

<p>
<label for="amount">Price</label>
<input type="text" id="amount" readonly style="border:0; color:#f6931f; font-weight:bold;">
<div class="slider" id="price"></div>
</p>

<p>
<label for="amount2">Quality</label>
<input type="text" id="amount2" readonly style="border:0; color:#f6931f; font-weight:bold;">
<div class="slider" id="quality"></div>
</p>

<ul id="products">
<li data-price="10" data-quality="1"> product - 10 zł q1</li>
<li data-price="50" data-quality="3"> product - 50 zł q3</li>
<li data-price="100" data-quality="6"> product - 100 zł q6</li>
<li data-price="150" data-quality="12"> product - 150 zł q12</li>
<li data-price="200" data-quality="24"> product - 200 zł q24</li>
</ul>

And Scripts:

<script>
function showProducts(minQ, maxQ) {
$("#products li").filter(function() {
var quality = parseInt($(this).data("quality"), 10);
if(quality >= minQ && quality <= maxQ){
$(this).removeClass('slider1Hide');
} else {
$(this).addClass('slider1Hide');
}
});
}


$(function() {
var options = {
range: true,
min: 1,
max: 36,
step: 1,
values: [3, 24],
slide: function( event, ui ) {
$( "#amount2" ).val(  ui.values[ 0 ] + " - " + ui.values[ 1 ] );
},
change: function(event, ui) {
var minQ = $("#quality").slider("values", 0);
var maxQ = $("#quality").slider("values", 1);
showProducts(minQ, maxQ);
}

};

$("#quality").slider(options);
$( "#amount2" ).val( $( "#quality" ).slider( "values", 0 ) +
" - " + $( "#quality" ).slider( "values", 1 ) );
});


</script>

<script>
function showProducts(minP, maxP) {
$("#products li").filter(function() {
var price = parseInt($(this).data("price"), 10);
if(price >= minP && price <= maxP){
$(this).removeClass('slider1Hide');
} else {
$(this).addClass('slider1Hide');
}
});
}


$(function() {
var options = {
range: true,
min: 0,
max: 250,
step: 1,
values: [100, 200],
slide: function( event, ui ) {
$( "#amount" ).val(ui.values[ 0 ] + " zł - " + ui.values[ 1 ] + " zł" );
},
change: function(event, ui) {
var minP = $("#price").slider("values", 0);
var maxP = $("#price").slider("values", 1);
showProducts(minP, maxP);
}

};

$("#price").slider(options);
$( "#amount" ).val( $( "#price" ).slider( "values", 0 ) +
" zł - " + $( "#price" ).slider( "values", 1 ) + " zł" );
});


</script>

Solution

  • The problem is that the modification of one slider is removing the class that was added by the other one. To make it work, you need to launch both updates after a slider move.

    So, here is how I've done to make it work:
    I merged the two showProducts() functions to get only one, without parameters.
    The min and max values of each slider are recovered and used to filter.
    I also created a data_filter() function to simplify the filtering, and to avoid duplicate code.

    Here is a snippet:

    // Added this function
    function data_filter(mini, maxi, data_name){
      $("#products li").filter(function() {
        var value = parseInt($(this).data(data_name), 10);
        if (value > maxi || value < mini) {
          $(this).addClass('slider1Hide');
        }
      });
    }
    
    function showProducts() {
      // Reset filters
      $("#products li").removeClass('slider1Hide');
      // Price
      var minP = $("#price").slider("values", 0);
      var maxP = $("#price").slider("values", 1);
      data_filter(minP, maxP, "price"); // Call the new function
      // Quality
      var minQ = $("#quality").slider("values", 0);
      var maxQ = $("#quality").slider("values", 1);
      data_filter(minQ, maxQ, "quality"); // Call the new function
    }
    
    // Below here, there's no change    
    
    $(function() {
      var options = {
        range: true,
        min: 1,
        max: 36,
        step: 1,
        values: [3, 24],
        slide: function(event, ui) {
          $("#amount2").val(ui.values[0] + " - " + ui.values[1]);
        },
        change: function(event, ui) {
          showProducts();
        }
    
      };
    
      $("#quality").slider(options);
      $("#amount2").val($("#quality").slider("values", 0) +
        " - " + $("#quality").slider("values", 1));
    });
    
    
    $(function() {
      var options = {
        range: true,
        min: 0,
        max: 250,
        step: 1,
        values: [100, 200],
        slide: function(event, ui) {
          $("#amount").val(ui.values[0] + " zł - " + ui.values[1] + " zł");
        },
        change: function(event, ui) {
          showProducts();
        }
    
      };
    
      $("#price").slider(options);
      $("#amount").val($("#price").slider("values", 0) +
        " zł - " + $("#price").slider("values", 1) + " zł");
    });
    .slider1Hide {
      display: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" />
    <div><!-- DIV here, no P -->
      <label for="amount">Price</label>
      <input type="text" id="amount" readonly style="border:0; color:#f6931f; font-weight:bold;">
      <div class="slider" id="price"></div>
    </div><!-- DIV here, no P -->
    
    <div><!-- DIV here, no P -->
      <label for="amount2">Quality</label>
      <input type="text" id="amount2" readonly style="border:0; color:#f6931f; font-weight:bold;">
      <div class="slider" id="quality"></div>
    </div><!-- DIV here, no P -->
    
    <ul id="products">
      <li data-price="10" data-quality="1"> product - 10 zł q1</li>
      <li data-price="50" data-quality="3"> product - 50 zł q3</li>
      <li data-price="100" data-quality="6"> product - 100 zł q6</li>
      <li data-price="150" data-quality="12"> product - 150 zł q12</li>
      <li data-price="200" data-quality="24"> product - 200 zł q24</li>
    </ul>

    Hope it helps.