问题
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/
来源:https://stackoverflow.com/questions/51880678/how-to-put-slider-together-with-additional-checkbox-filter