jQuery multi-faceted filter issue. - javascript

I'm building a simple faceted filter to help users find the right condo. A few days ago I got a basic slider to filter out condos by square footage. The next part was getting the checkboxes to work which I posted to SO here and got some help from icecub. Since then I've been working on getting them to work in tandem (for example, checking 2 bedrooms and sliding the slider down to 800 sqft filters the condos by both variables). Got this to work yesterday.
The only issue I'm having is that now the slider only works when one of the two checkbox's are checked. If both or none are checked the slider doesn't work. I'm not sure exactly where my logic is flawed.
Here's a fiddle https://jsfiddle.net/baskinco/mwqkztn8/
and here's the JS
// FUNCTIONS
//make slider textbox equal to slider value
function printValue(sliderID, textbox) {
var x = document.getElementById(textbox);
var y = document.getElementById(sliderID);
x.value = y.value;
}
//get bdrm and slider values
function getValues() {
var bdrm1 = false;
var bdrm2 = false;
var sliderValue;
if($("#1bdrm").is(':checked')){
bdrm1 = true;
}
if ($("#2bdrm").is(':checked')){
bdrm2 = true;
}
sliderValue = $("#rangeValue").val();
runFilter(bdrm1, bdrm2, sliderValue);
}
function runFilter(bdrm1, bdrm2, sliderValue) {
$.each($('.condo-box'), function() {
$this = $(this);
condoData = $this.data();
if(bdrm1 && !bdrm2){
if ((condoData.bdrms == 1) && (condoData.sqft <= sliderValue)){
$this.show();
} else {
$this.hide();
}
} else if(bdrm2 && !bdrm1){
if ((condoData.bdrms == 2) && (condoData.sqft <= sliderValue)){
$this.show();
} else {
$this.hide();
}
} else {
$this.show();
}
});
}
// Set values for units
$('#jackson').data({
id:1,
sqft:897,
bdrms:2
});
$('#nicholl').data({
id:2,
sqft:808,
bdrms:2
});
$('#atwood').data({
id:3,
sqft:1020,
bdrms:2
});
//etc
//MAIN SCRIPT
$(document).ready(function() {
//print slider value to slider textbox
printValue('slider','rangeValue');
//when a bdrm box is checked ..
$("#1bdrm, #2bdrm").click(function(){
getValues();
});
//when the slider is moved
$("#slider").change(function() {
getValues();
});
});

Your else condition isn't checking the sqft and slider, it should be:
else {
if ((condoData.sqft <= sliderValue)){
$this.show();
} else {
$this.hide();
}
}
https://jsfiddle.net/mwqkztn8/1/
Or, even simpler, that whole thing could just be:
$.each($('.condo-box'), function() {
$this = $(this);
condoData = $this.data();
var sqftFilter = (condoData.sqft <= sliderValue);
var bedFilter = (!bdrm1 && !bdrm2) || (condoData.bdrms == 1 && bdrm1) || (condoData.bdrms == 2 && bdrm2);
$this.toggle(sqftFilter && bedFilter);
});
https://jsfiddle.net/mwqkztn8/3/

Related

jQuery checkbox filter, working but want to reset when unchecked

I'm building a filter for a selection of condos. I've figured out how to filter using a slider and now also need to filter by number of bedrooms using two checkboxes.
<form name="filter" method="post" action="">
<p>Bedrooms
<input id="1bdrm" type="checkbox" value="1bdrm" />1 Bedroom
<input id="2bdrm" type="checkbox" value="2bdrm" />2 Bedroom
</p>
</form>
So far I have the filter limiting the selection to show only 1 bedroom units, but can't figure out how to reset and show all units when unchecking the checkbox.
// Set values for units
$('#cohen').data({
id: 4,
sqft: 976,
bdrms: 2
});
$('#curnoe').data({
id: 5,
sqft: 572,
bdrms: 2
});
$('#richler').data({
id: 6,
sqft: 624,
bdrms: 2
});
$('#carr').data({
id: 7,
sqft: 544,
bdrms: 1
});
$('#lawrence').data({
id: 10,
sqft: 467,
bdrms: 1
});
//filter by number of bedrooms
$(document).ready(function() {
var theValue;
$("#1bdrm").click(function() {
filterItems();
});
});
function filterItems() {
$.each($('.condo-box'), function() {
$this = $(this);
itemData = $this.data();
if (itemData.bdrms == 1) {
$this.show();
itemData.matching = true;
} else {
$this.hide();
itemData.matching = false;
}
});
}
Here's a fiddle link.. https://jsfiddle.net/3y9vz1q1/ I'm using the .data method to store unique attributes on each unit so that i can filter for each attribute (example: I have another script written for a slider that limits condos by sqft.
Hoping the community can point me in the right direction! Thanks in advance.
Marc.
You are marking elements that have the data tag bdrms set to 1 as invisible. This does not change. So once they are invisible, they will remain that way.
There are several ways to solve this, one being a seperate function that's being called when the checkbox isn't checked:
if($(this).is(':checked')){
filterItems();
} else {
resetAll();
}
After that it's a simple matter of writing a function that resets the invisble elements back to visible:
function resetAll()
{
$.each($('.condo-box'), function() {
$this = $(this);
if($this.is(":hidden")){
$this.show();
}
});
}
So updating your fiddle would be: https://jsfiddle.net/3y9vz1q1/1/ Which works fine.
UPDATE:
A far better solution would be to make both checkboxes work and use a single function:
$(document).ready(function() {
$("#1bdrm, #2bdrm").click(function() {
var bdrm1 = false;
var bdrm2 = false;
if($("#1bdrm").is(':checked')){
bdrm1 = true;
}
if($("#2bdrm").is(':checked')){
bdrm2 = true;
}
filterItems(bdrm1, bdrm2);
});
});
function filterItems(bdrm1, bdrm2){
$.each($('.condo-box'), function() {
$this = $(this);
itemData = $this.data();
if(bdrm1 && !bdrm2){
if(itemData.bdrms == 1){
$this.show();
itemData.matching = true;
} else {
$this.hide();
itemData.matching = false;
}
}
else if(bdrm2 && !bdrm1){
if(itemData.bdrms == 2){
$this.show();
itemData.matching = true;
} else {
$this.hide();
itemData.matching = false;
}
} else {
$this.show();
itemData.matching = true;
}
});
}
Fiddle update: https://jsfiddle.net/3y9vz1q1/2/
Always, when you click to checkbox, filter funtion started and because last item
$('#lawrence').data({
id: 10,
sqft: 467,
bdrms: 1
});
has 1, list don't reset
Try it:
$(document).ready(function() {
var theValue;
$("#1bdrm").click(function() {
if(this.checked){
filterItems(false);
}else{
filterItems(true);
}
});
});
function filterItems(reset)
{
$.each($('.condo-box'), function() {
$this = $(this);
itemData = $this.data();
if(itemData.bdrms == 1 || reset === true){
$this.show();
itemData.matching = true;
} else {
$this.hide();
itemData.matching = false;
}
});
}

Change background color with checkbox, limited number of checkboxes selectable

Desired: User can only click on 2 out of 3 displayed checkboxes; when the user clicks on a checkbox, the checkbox background turns orange.
Currently: The first checkbox selected acts as desired. The second checkbox ticks, but does not change background color. Upon clicking again, it un-ticks and changes to the desired background color (yet it is not selected). A 3rd checkbox is not selectable whilst two are already selected.
Requesting: Help to achieve the desired, thank you!
Fiddle: http://jsfiddle.net/0fkn1xs4/
Code:
$('input.playerCheckbox').on('change', function(event) {
var selectableFriends = 2;
if($('.playerCheckbox:checked').length > selectableFriends) {
this.checked = false;
}
numberCurrentlySelected = $('.playerCheckbox:checked').length;
if(numberCurrentlySelected < selectableFriends) {
$(this).closest("li").toggleClass("checked");
}
});
$('input.playerCheckbox').on('change', function(event) {
var selectableFriends = 2;
if($('.playerCheckbox:checked').length > selectableFriends) {
this.checked = false;
}
$(this).closest("li").toggleClass("checked", this.checked);
});
A slightly cleaner implementation that does what you want. Check out the JSFiddle
Try this:
$('input.playerCheckbox').on('change', function (event) {
var selectableFriends = 2;
if ($('.playerCheckbox:checked').length > selectableFriends) {
this.checked = false;
} else {
$(this).closest("li").toggleClass("checked");
}
numberCurrentlySelected = $('.playerCheckbox:checked').length;
});
Check it out here: JSFIDDLE
$('input.playerCheckbox').on('change', function(event) {
var selectableFriends = 2;
var numberCurrentlySelected = $('.playerCheckbox:checked').length;
if(numberCurrentlySelected > selectableFriends) {
this.checked = false;
}
if(numberCurrentlySelected <= selectableFriends) {
$(this).closest("li").toggleClass("checked");
}
});
I just changed the second part to <= rather than < and then created the numberCurrentlySelected variable earlier on so that you aren't calling querying more than once. Caeths is better though instead of using a second if statement it just uses an else, makes sense and gets rid of a comparison.
DEMO
$('input.playerCheckbox').on('change', function(event) {
var selectableFriends = 2;
numberCurrentlySelected = $('.playerCheckbox:checked').length;
if(numberCurrentlySelected <= selectableFriends) {
$(this).closest("li").toggleClass("checked");
}
if($('.playerCheckbox:checked').length > selectableFriends) {
this.checked = false;
$(this).closest("li").removeClass('checked');
}
});
This works in Fiddler for ya.
$('.playerCheckbox').change(function() {
if($('.playerCheckbox:checked').length > 2) {this.checked = false; }
else{
if( this.checked == true ) {$(this).closest("li").addClass("checked");}
if( this.checked == false ) {$(this).closest("li").removeClass("checked");}
}
});

How to make random selector only pick shown items?

Yeah not very familiar with JQuery and I'm trying to make a random lunch picker for our web team.
http://jsfiddle.net/vy8RL/1/
I want to hide certain items. For example when you hit the "Quick Eats" button it only displays 4 options and when you hit "EAT ME" it still selects the LI's that are hidden. Is there any way to allow it only to select options that are visible?
$(document).ready(function() {
$("#button").click(function(){
random();
});
$("#unhealthy-food").click(function(){
$(".unhealthy").hide();
});
$("#all").click(function(){
$("li").show();
});
$("#fast-food").click(function(){
$(".food").hide();
$(".fast").show();
});
});
function random() {
$("li.selected").removeClass("selected");
var menuItems = $("ul#list li");
var numItems = menuItems.length;
if(window.sessionStorage && window.sessionStorage.getItem("selected")) {
previous = Number(window.sessionStorage.getItem("selected"));
} else {
previous = -1;
}
var selected = Math.floor(Math.random()*numItems);
while(selected === previous && numItems > 1) {
selected = Math.floor(Math.random()*numItems);
}
if(window.sessionStorage) window.sessionStorage.setItem("selected", selected);
$("ul#list li:nth-child("+(selected+1)+")").addClass("selected");
}
You can use the :visible selector:
function random() {
$("li.selected").removeClass("selected");
var menuItems = $("#list li").filter(':visible');
var numItems = menuItems.length;
// ...
menuItems.eq(selected).addClass("selected");
}
Please note that I have replaced the $("ul#list li:nth-child("+(selected+1)+")") with the cached collection + eq() method.
http://jsfiddle.net/3n9ex/
here you go. I just added tracking of menu preference. Also added $(".food").show(); in line 9 to correct a bug.
$(document).ready(function() {
var user_choice = ".food";
$("#button").click(function(){
random(user_choice);
});
$("#unhealthy-food").click(function(){
user_choice = "li:not(.unhealthy)";
$(".food").show();
$(".unhealthy").hide();
});
$("#all").click(function(){
$("li").show();
user_choice = ".food";
});
$("#fast-food").click(function(){
$(".food").hide();
$(".fast").show();
user_choice = ".fast";
});
});
function random(user_choice) {
$("li.selected").removeClass("selected");
var menuItems = $(user_choice);
console.log(menuItems);
var numItems = menuItems.length;
if(window.sessionStorage && window.sessionStorage.getItem("selected")) {
previous = Number(window.sessionStorage.getItem("selected"));
} else {
previous = -1;
}
var selected = Math.floor(Math.random()*numItems);
while(selected === previous && numItems > 1) {
selected = Math.floor(Math.random()*numItems);
}
if(window.sessionStorage) window.sessionStorage.setItem("selected", selected);
$(menuItems[selected]).addClass("selected");
}
http://jsfiddle.net/vy8RL/19/

.each function () for cloned inputs

Trying to create the Preview form and do not understand why each function () not working in this script. Or works but only for the last cloned row and ignore the zero values ​​in the previously cloned inputs.
$('input[id^=Mult_factor_]').each(function () {
var MultFactor = $(this).val();
var TotPoints = $('#Tot_points').val();
var exp1 = "Overload";
var exp2 = "Load is: ";
if (MultFactor < 1 || TotPoints > 100) {
$('#ExemptionLimitsText').text(exp1).show();
$('#PrwTotPointsText').hide();
} else {
$('#ExemptionLimitsText').text(exp2).show();
$('#PrwTotPointsText').text($('#Tot_points').val()).show();
}
});
JSfiddle
I need: If at least one of cloned MultiFactor value is zero show "Overload"
Based on your comment, you want to display the word "Overload" if either the "Additional" field is over 100 or if any of the multifactor fields is 0.
However, your loop continues to process if either of these conditions are met.
Do not use a loop, instead search specifically for a multifaktor value of 0.
var totalPoints = parseInt($('#Tot_points').val());
if(totalPoints > 100 || $('input[name="MultFaktor"]').filter(function(){return this.value=='0'}).length > 0) {
$('#ExemptionLimitsText').text("Overload").show();
$('#PrwTotPointsText').hide();
} else {
$('#ExemptionLimitsText').text("Load is: ").show();
$('#PrwTotPointsText').text(totalPoints).show();
}
Return false on overload
var valid = true;
var exp1 = "Overload";
var exp2 = "Load is: ";
var TotPoints = $('#Tot_points').val();
$('input[name=MultFaktor]').each(function () {
var $this = $(this);
if ($.trim($(this).val()) == '0' || TotPoints > 100) {
valid = false;
} else {
$('#ExemptionLimitsText').text(exp2).show();
$('#PrwTotPointsText').text($('#Tot_points').val()).show();
}
});
if (valid == false) {
e.preventDefault();
$('#ExemptionLimitsText').text(exp1).show();
$('#PrwTotPointsText').hide();
}

limit javascript toggle according to select box value

Here is link of my current fiddle
jsFiddle
JS --
$('.click').on({
'click': function () {
var origsrc = $(this).attr('src');
var src = '';
if (origsrc == 'http://imageshack.us/a/img703/8236/l6hu.png') src = 'http://imageshack.us/a/img20/1651/fibz.png';
if (origsrc == 'http://imageshack.us/a/img20/1651/fibz.png') src = 'http://imageshack.us/a/img703/8236/l6hu.png';
$(this).attr('src', src);
}
});
i am able to toggle image onclick with another image and vice versa. This is okay, but i want to limit the toggle only when green image is already selected. If i select 3 from select box then i can toggle white image into green image only 3 times, not more than 3. I also need help for another scenerio - if i select 3 from select box and toggle first 3 image and next moment i change the 2nd image into white and click 5th image to turn green then it will be possible. I am week in javascript or jquery, so need proper information about this problem. So plz help me out.
Here is a more comprehensive approach fiddle which will keep your limit in sync and handle discrepancies when the limit changes.
var quantity = 0; // will maintain limit
var stack = []; // will maintain ordered green buttons
$("#select").change(runWrapper);
function runWrapper() {
quantity = Number($("#select").val()); // set the limit
groom(); // turn off those that were turned on last
//run(); // this is your run function, uncomment
}
function groom(){
// let's test if we are over the limit
while(stack.length > quantity) {
// remove last which was set to green
$(stack.pop()).trigger("click")
// to remove the oldest/first set to green use
// $(stack.shift()).trigger("click")
}
}
$('.click').on({
'click': function () {
var origsrc = $(this).attr('src');
var src = '';
if (origsrc == 'http://imageshack.us/a/img703/8236/l6hu.png') {
// limit reached
if(stack.length >= quantity) {
alert(quantity + " limit reached!");
return;
}
src = 'http://imageshack.us/a/img20/1651/fibz.png';
// turning green push the DOM reference to the top of the stack
stack.push(this);
}
if (origsrc == 'http://imageshack.us/a/img20/1651/fibz.png') {
src = 'http://imageshack.us/a/img703/8236/l6hu.png';
// turning white remove the DOM reference from stack
var self = this;
stack = $.grep(stack, function(val) {
return self != val;
})
console.warn(stack);
}
$(this).attr('src', src);
}
});
You can update the function like this - fiddle is here - http://jsfiddle.net/4QkM8/5/
I changed id of select box to selQty
var selectedCount = 0;
$('.click').on({
'click': function () {
var origsrc = $(this).attr('src');
var src = '';
if (origsrc == 'http://imageshack.us/a/img703/8236/l6hu.png'){ if (selectedCount < $('#selQty').val()){src = 'http://imageshack.us/a/img20/1651/fibz.png';
selectedCount ++;
} }
if (origsrc == 'http://imageshack.us/a/img20/1651/fibz.png') {src = 'http://imageshack.us/a/img703/8236/l6hu.png';selectedCount --;}
$(this).attr('src', src == '' ? origsrc : src);
}
});
use a variable to keep track of how many items have been selected, and compare it to the quantity in the select box.
var count = 0;
var unselected_img = 'http://imageshack.us/a/img703/8236/l6hu.png';
var selected_img = 'http://imageshack.us/a/img20/1651/fibz.png';
$('.click').on({
'click': function () {
var max_allowed = parseInt($("#select").val(), 10);
var origsrc = $(this).attr('src');
var src = '';
if (origsrc == unselected_img && count < max_allowed) {
src = selected_img;
count++;
} else if (origsrc == selected_img) {
src = unselected_img;
count--;
} else {
alert("Too many selected.");
}
if (src) {
$(this).attr('src', src);
}
}
});
DEMO

Categories