How to put Slider together with additional checkbo

2019-08-20 19:33发布

问题:

I have a problem with working together Ui Slider and checkbox filter. It should working like this:

When I use slider to set price target I'm getting some results. Then want those results to be sorted by additional filter using checkboxes. After all I should get exact match to my request.

Instead of that I'm getting wrong match. After using slider I get what I want but then when using checkboxes everything crush. I only get checkboxes results, without slider effect. I don't know how to force them to work together.

I also would like to see information about number of found results if only slider has been used (without clicking checkboxes).

Here's jsfiddle example: http://jsfiddle.net/m1z930r5/15/

HTML:

<input type="text" id="amount" readonly>
<div class="slider" id="price"></div>

<br><br>

<div class="tabela-wrap">
  <label style="number"><input type="checkbox" name="fl-1" value="1" id="1" /> 1</label>
  <label style="number"><input type="checkbox" name="fl-2" value="2" id="2" /> 2</label>
  <label style="number"><input type="checkbox" name="fl-3" value="3" id="3" /> 3</label>
  <label style="number"><input type="checkbox" name="fl-4" value="4" id="4" /> 4</label>
  <label style="number"><input type="checkbox" name="fl-5" value="5" id="5" /> 5</label>
  <label style="number"><input type="checkbox" name="fl-6" value="6" id="6" /> 6</label>
  <label style="number"><input type="checkbox" name="fl-7" value="7" id="7" /> 7</label>
  <label style="number"><input type="checkbox" name="fl-8" value="8" id="8" /> 8</label>
</div>

<br><br>

<ul class="tabela lokata" id="products">
  <li class="tabelki" data-price="10000" data-category="1 2 3 4 ">10 000 USD contains 1 2 3 4</li>
  <li class="tabelki" data-price="12000" data-category="2 3">12 000 USD contains 2 3</li>
  <li class="tabelki" data-price="13000" data-category="4 5">13 000 USD contains 4 5</li>
  <li class="tabelki" data-price="14000" data-category="5 6 ">14 000 USD contains 5 6</li>
  <li class="tabelki" data-price="12000" data-category="5">12 000 USD contains 5</li>
  <li class="tabelki" data-price="14000" data-category="1 2">14 000 USD contains 1 2</li>
  <li class="tabelki" data-price="16000" data-category="1 2 3">16 000 USD contains 1 2 3</li>
  <li class="tabelki" data-price="20000" data-category="7 8">20 000 USD contains 7 8</li>

</ul>

<div class="tabela-wrap">
  <label id="found"></label>
</div>

CSS:

.ui-slider {
  position: relative;
  text-align: left;
}

.ui-slider .ui-slider-handle {
  position: absolute;
  z-index: 2;
  width: 1.2em;
  height: 1.2em;
  cursor: default;
}

.ui-slider .ui-slider-range {
  position: absolute;
  z-index: 1;
  font-size: .7em;
  display: block;
  border: 0;
  background-position: 0 0;
}

.ui-slider-horizontal {
  height: .8em;
}

.ui-slider-horizontal .ui-slider-handle {
  top: -0.5em;
  margin-left: -.6em;
}

.ui-slider-horizontal .ui-slider-range {
  top: 0;
  height: 100%;
}

.ui-slider-horizontal .ui-slider-range-min {
  left: 0;
}

.ui-slider-horizontal .ui-slider-range-max {
  right: 0;
}

.ui-slider-vertical {
  width: .8em;
  height: 100px;
}

.ui-slider-vertical .ui-slider-handle {
  left: -.3em;
  margin-left: 0;
  margin-bottom: -.6em;
}

.ui-slider-vertical .ui-slider-range {
  left: 0;
  width: 100%;
}

.ui-slider-vertical .ui-slider-range-min {
  bottom: 0;
}

.ui-slider-vertical .ui-slider-range-max {
  top: 0;
}

.ui-widget-content {
  border: 1px solid #aaaaaa;
  background: white 50% 50% repeat-x;
  color: #222222;
}

.ui-widget {
  font-family: Verdana, Arial, sans-serif;
  font-size: 1.1em;
}

.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default {
  width: 30px;
  height: 30px;
  border: 3px solid #2F3D44;
  border-radius: 20px;
  background: white 50% 50% repeat-x;
  font-weight: normal;
  color: #555555;
}

.slider1Hide {
  display: none;
}

JavaScript:

! function(a) {
  function f(a, b) {
    if (!(a.originalEvent.touches.length > 1)) {
      a.preventDefault();
      var c = a.originalEvent.changedTouches[0],
        d = document.createEvent("MouseEvents");
      d.initMouseEvent(b, !0, !0, window, 1, c.screenX, c.screenY, c.clientX, c.clientY, !1, !1, !1, !1, 0, null), a.target.dispatchEvent(d)
    }
  }
  if (a.support.touch = "ontouchend" in document, a.support.touch) {
    var e, b = a.ui.mouse.prototype,
      c = b._mouseInit,
      d = b._mouseDestroy;
    b._touchStart = function(a) {
      var b = this;
      !e && b._mouseCapture(a.originalEvent.changedTouches[0]) && (e = !0, b._touchMoved = !1, f(a, "mouseover"), f(a, "mousemove"), f(a, "mousedown"))
    }, b._touchMove = function(a) {
      e && (this._touchMoved = !0, f(a, "mousemove"))
    }, b._touchEnd = function(a) {
      e && (f(a, "mouseup"), f(a, "mouseout"), this._touchMoved || f(a, "click"), e = !1)
    }, b._mouseInit = function() {
      var b = this;
      b.element.bind({
        touchstart: a.proxy(b, "_touchStart"),
        touchmove: a.proxy(b, "_touchMove"),
        touchend: a.proxy(b, "_touchEnd")
      }), c.call(b)
    }, b._mouseDestroy = function() {
      var b = this;
      b.element.unbind({
        touchstart: a.proxy(b, "_touchStart"),
        touchmove: a.proxy(b, "_touchMove"),
        touchend: a.proxy(b, "_touchEnd")
      }), d.call(b)
    }
  }
}(jQuery);


// 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
}

$(function() {
  var options = {

    min: 500,
    max: 100000,
    step: 500,
    values: [10000],
    slide: function(event, ui) {
      $("#amount").val(ui.values[0] + " USD");
    },
    change: function(event, ui) {
      showProducts();
    }

  };

  $("#price").slider(options);
  $("#amount").val($("#price").slider("values", 0) + " USD");
});

//Checkboxes script


var byProperty = [],
  byColor = [],
  byLocation = [];

$("input[name=fl-1]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});

$("input[name=fl-2]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});
$("input[name=fl-3]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});
$("input[name=fl-4]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});
$("input[name=fl-5]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});
$("input[name=fl-6]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});
$("input[name=fl-7]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});
$("input[name=fl-8]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});

$("input").on("change", function() {
  var str = "Include items \n";
  var selector = '',
    cselector = '',
    nselector = '';

  var $lis = $('.tabela > li'),
    $checked = $('input:checked');

  if ($checked.length) {

    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=fl-1]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=fl-1]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }

    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=fl-2]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=fl-2]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }
    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=fl-3]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=fl-3]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }
    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=fl-4]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=fl-4]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }
    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=fl-5]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=fl-5]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }
    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=fl-6]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=fl-6]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }
    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=fl-7]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=fl-7]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }
    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=fl-8]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=fl-8]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }


    $lis.hide();
    console.log(selector);
    console.log(cselector);
    console.log(nselector);

    if (cselector === '' && nselector === '') {
      $('.tabela > li').filter(selector).show();
    } else if (cselector === '') {
      $('.tabela > li').filter(selector).filter(nselector).show();
    } else if (nselector === '') {
      $('.tabela > li').filter(selector).filter(cselector).show();
    } else {
      $('.tabela > li').filter(selector).filter(cselector).filter(nselector).show();
    }

  } else {
    $lis.show();
  }

  $("#result").html(str);

});

$("input").on("change", function() {
  var numberOfItems = $("li.tabelki:visible").length;

  if (numberOfItems > 0) {
    var label = "We found " + numberOfItems + " results";
  } else {
    var label = "No results found";
  }

  $("#found").text(label);
});

function removeA(arr) {
  var what, a = arguments,
    L = a.length,
    ax;
  while (L > 1 && arr.length) {
    what = a[--L];
    while ((ax = arr.indexOf(what)) !== -1) {
      arr.splice(ax, 1);
    }
  }
  return arr;
}

Is anybody able to solve that case?

回答1:

Try this out:

I refactored your code a lot to make it easier to read/understand and keep things DRY. I was able to reduce the line count from 273 lines to 73.

$(document).ready(function(){
  // cache ref to all checkbox elements
  var checkboxes = $('input:checkbox'),
      // cache ref to results
      results = $('#results'),
      // cache ref to our list
      listItems = $('.tabela > li'),
      // cache amount ref
      amount = $('#amount'),
      // collection of selected checkbox elements
      selectedItems = [],
      // slider config
      slideOptions = {
        min: 500,
        max: 100000,
        step: 500,
        values: [10000],
        slide: function(event, ui) {
          amount.val(ui.values[0] + " USD");
        },
        change: function(event, ui) {
          updateList();
        }
      };
      
  // render our slider      
  var slider = $("#price").slider(slideOptions);
  
  amount.val($("#price").slider("values", 0) + " USD");
  
  checkboxes.on('change', function(){
    var id = this.id;

    if(this.checked){
      // push the element vs the value
      selectedItems.push(this.value);
    }else{
      // remove items on uncheck
      selectedItems.splice(selectedItems.indexOf(this.value), 1);
    }

    updateList();
  });

  var updateList = function(){
    // create map of values for joining
    var selectedItemsValues = selectedItems.sort().join(' '),
        // min value
        minPrice = slider.slider('values', 0);

    // filter list items         
    listItems.hide().filter(function(){
      // get data attributes
      var data = this.dataset;
      // restrict list to price band and selections
      return Number(data.price) > minPrice && (selectedItems.length ? data.category.includes(selectedItemsValues) : true);
    })
    .show();

    // count visible li only
    var total = $('.tabela li:visible').length;

    if(total === 0){
      results.html('We did not find any matches.');
    }else{
      results.html('We found ' + total + (total === 1 ? ' match' : ' matches' ) + '!');
    }
  }
});
.ui-slider {
  position: relative;
  text-align: left;
}
.ui-slider .ui-slider-handle {
  position: absolute;
  z-index: 2;
  width: 1.2em;
  height: 1.2em;
  cursor: default;
}
.ui-slider .ui-slider-range {
  position: absolute;
  z-index: 1;
  font-size: .7em;
  display: block;
  border: 0;
  background-position: 0 0;
}
.ui-slider-horizontal {
  height: .8em;

}
.ui-slider-horizontal .ui-slider-handle {
  top: -0.5em;
  margin-left: -.6em;
}
.ui-slider-horizontal .ui-slider-range {
  top: 0;
  height: 100%;
}
.ui-slider-horizontal .ui-slider-range-min {
  left: 0;
}
.ui-slider-horizontal .ui-slider-range-max {
  right: 0;
}
.ui-slider-vertical {
  width: .8em;
  height: 100px;
}
.ui-slider-vertical .ui-slider-handle {
  left: -.3em;
  margin-left: 0;
  margin-bottom: -.6em;
}
.ui-slider-vertical .ui-slider-range {
  left: 0;
  width: 100%;
}
.ui-slider-vertical .ui-slider-range-min {
  bottom: 0;
}
.ui-slider-vertical .ui-slider-range-max {
  top: 0;
}
.ui-widget-content {
  border: 1px solid #aaaaaa;
  background: white 50% 50% repeat-x;
  color: #222222;
}
.ui-widget {
  font-family: Verdana,Arial,sans-serif;
  font-size: 1.1em;
}
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
  width: 30px;
  height: 30px;
  border: 3px solid #2F3D44;
  border-radius: 20px;
  background: white 50% 50% repeat-x;
  font-weight: normal;
  color: #555555;
}
.slider1Hide {
  display: none;
}
<script src="https://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.8.21/jquery-ui.min.js"></script>

<input type="text" id="amount" readonly>
<div class="slider" id="price"></div>

<br><br>

<div class="tabela-wrap">   
  <label for="1"><input type="checkbox" name="fl-1" value="1" id="1" /> 1</label>
  <label for="2"><input type="checkbox" name="fl-2" value="2" id="2" /> 2</label>
  <label for="3"><input type="checkbox" name="fl-3" value="3" id="3" /> 3</label>
  <label for="4"><input type="checkbox" name="fl-4" value="4" id="4" /> 4</label>
  <label for="5"><input type="checkbox" name="fl-5" value="5" id="5" /> 5</label>
  <label for="6"><input type="checkbox" name="fl-6" value="6" id="6" /> 6</label>
  <label for="7"><input type="checkbox" name="fl-7" value="7" id="7" /> 7</label>
  <label for="8"><input type="checkbox" name="fl-8" value="8" id="8" /> 8</label> 
</div>

<br><br>

<ul class="tabela lokata" id="products">
  <li class="tabelki" data-price="10000" data-category="1 2 3 4 ">10 000 USD contains 1 2 3 4</li>
  <li class="tabelki" data-price="12000" data-category="2 3">12 000 USD contains 2 3</li>
  <li class="tabelki" data-price="13000" data-category="4 5">13 000 USD contains 4 5</li>
  <li class="tabelki" data-price="14000" data-category="5 6 ">14 000 USD contains 5 6</li>
  <li class="tabelki" data-price="12000" data-category="5">12 000 USD contains 5</li>
  <li class="tabelki" data-price="14000" data-category="1 2">14 000 USD contains 1 2</li>
  <li class="tabelki" data-price="16000" data-category="1 2 3">16 000 USD contains 1 2 3</li>
  <li class="tabelki" data-price="20000" data-category="7 8">20 000 USD contains 7 8</li>
</ul>

<div id="results"></div>

JSFiddle



回答2:

The problem is that you are adding and removing a class slider1Hide to show/hide objects out of range of the slider, but using an inline style display: list-item/display: none for the checkboxes. Inline css styles always take precedent over styles defined in a class, so even if one of your items has slider1Hide, it will still display if it has display: list-item. You can observe this with your browser's inspector-you'll see a line through the display attribute of slider1Hide:

Anyways, to solve your problem I have updated your javascript. The two functions filterPrice() and filterCheckboxes() take in the list of products and filter out the ones that should remain hidden. The code then show()'s the remaining products.

!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);

function filterPrice(products) {
  let minP = $("#price").slider("values", 0);
  let maxP = $("#price").slider("values", 1);
  return products.filter(function() {
    let value = parseInt($(this).data("price"), 10);
    return !(value > maxP || value < minP);
  });
}

function filterCheckboxes(products) {
  checkboxes = $("input:checked").filter(function() {
    return $.inArray($(this).attr("name"), ['fl-1', 'fl-2', 'fl-3', 'fl-4', 'fl-5', 'fl-6', 'fl-7', 'fl-8']) != -1;
  }).map(function() {
    return this.value;
  });

  // If no checkboxes are checked, don't filter with them
  if (checkboxes.length == 0) {
    return products;
  }

  return products.filter(function() {
    categories = $(this).data("category").toString().split(" ");
    let val = true;
    checkboxes.each(function() {
      if (!categories.includes(this[0])) {
        val = false;
        return;
      }
    });
    return val;
  });

}

function filterProducts() {
  // Reset filters
  products = $("#products li");
  products.hide();
  products = filterPrice(products);
  products = filterCheckboxes(products);
  products.show();

  let numItems = products.length;

  if (numItems > 0) {
    label = "We found " + numItems + " results";
  } else {
    label = "No results found";
  }

  $("#found").text(label);
}

$(function() {
  let options = {

    min: 500,
    max: 100000,
    step: 500,
    values: [10000],
    slide: function(event, ui) {
      $("#amount").val(ui.values[0] + " USD");
    },
    change: function(event, ui) {
      filterProducts();
    }

  };

  $("input").filter(function() {
    return $.inArray($(this).attr("name"), ['fl-1', 'fl-2', 'fl-3', 'fl-4', 'fl-5', 'fl-6', 'fl-7', 'fl-8']) != -1;
  }).change(filterProducts);

  $("#price").slider(options);
  $("#amount").val($("#price").slider("values", 0) + " USD");

});

http://jsfiddle.net/m1z930r5/84/