JQuery: Alternative to each() for conditional check against selected checkbox values - javascript

1) Checkboxes has five values: GRA, RRA, FRA, MRA, CHDA
2) Checkbox class Name is oops. Common for all 5.
3) We shall throw an exception if FRA, MRA, CHDA value is not selected
4) Following is snippet i am using to achieve this:
var availability = false;
$(".oops:checked").each(function() {
if($(this).val() === 'FRA' || $(this).val() === 'MRA' || $(this).val() === 'CHDA') {
availability = true;
}
});
if (!availability) {
errors.push('There is no selected among FRA MRA CHRA');
}
Do we have other better approach to handle this instead of using three or operators and check it in each() function?

You can create a array data structure for all the allowed values for the checkbox and check the selected values against them:
var availability = false;
var alloweValues = ['FRA', 'MRA', 'CHDA'];
$(".oops:checked").each(function() {
if(alloweValues.includes($(this).val())) {
availability = true;
}
});
if (!availability) {
errors.push('There is no selected among FRA MRA CHRA');
}
You can further refactor your code to:
var availability = false;
var alloweValues = ['FRA', 'MRA', 'CHDA'];
$(".oops:checked").each(function() {
availability = alloweValues.includes($(this).val());
});
if (!availability) {
errors.push('There is no selected among FRA MRA CHRA');
}
You can also replace includes() with indexOf() like
alloweValues.indexOf($(this).val()) !== -1
As, includes() do not work in IE browser.

Create an array to store each checked value like follows:
var checkvalues=[];
$(".oops:checked").each(function(){
checkvalues.push($(this).val());
});
after that you can use includes() method to check like above code.

Related

Check if all values of array are equal to number

I want to see if there is a better way to check if all values of array are equal to number. I have it working with a foreach but wanted to see if I can do this anyway else?
let valid = true;
$.each(data.resultStatus, function (index, resultStatus) {
if (resultStatus.ResultCode == "2") {
valid = false;
}
});

How to check if localStorage value is in array?

Based on this answer I should be using $.inArray, therefore I do:
var curPostId = $(".my_post_id").attr("data-id");
if($.inArray(curPostId, lines)) {
$('#'+localStorage.getItem('saveButton')).attr('disabled', true);
}
If I do: console.log(curPostId); I get 248 which is correct. Then if I do console.log(lines); I get [242, 248]
Lines is defined like this:
var lines = localStorage.getItem("lines") ? JSON.parse(localStorage.getItem("lines")) : [];
But the check if it's in Array doesn't happen as this it's not applied $('#'+localStorage.getItem('saveButton')).attr('disabled', true);
This is how I set daveButton on local storage
$(".save_post").on("click", function() {
if (counter >= 2) {
alert('nope');
return;
} else {
$(this).attr("disabled", "true");
localStorage.setItem('saveButton', $(this).attr('id'));
var thisId = $(".my_post_id").attr("data-id");
lines.push(thisId);
localStorage.setItem("lines", JSON.stringify(lines));
}
});
This question is a follow up to my previous question how to keep button state across different pages which has an answer that works but only partly.
Just use the Array.includes method instead - it's less confusing, more appropriately matches what you're looking for, and doesn't require jQuery.
if (lines.includes(curPostId)) {
// ...
Also note that you can simplify your syntax by assigning and getting from localStorage's dot properties directly, for example:
var lines = JSON.parse(localStorage.lines || '[]');
// ...
localStorage.saveButton = $(this).attr('id');
// ...
localStorage.lines = JSON.stringify(lines);
$.inArray return index of element so what happens is, your element is at '0' th index and if condition will be false if value is 0
So you can use
if($.inArray(curPostId, lines) !== -1) {
or Use includes method of ES6
if (lines.includes(curPostId)) {

Using Jquery Filter as a way to filter links on a page

I have a list of links on a page and a set of checkboxes that should filter the links so that only the ones that have the specific criteria will be active. My rudimentary attempt to do this involves creating an array of all the filter options that are active and running a .filter(Array) to make those active and a .not(Array) to disable the other links.
The problem is that if more than one filter options is selected any link that matches either filter option will be active. When in reality what i want is only the links that match ALL the filter options to be active.
Here is my stripped down version in jsFiddle
var filterAll = ["filter-F_0", "filter-F_1", "filter-F_2", "filter-F_3", "filter-F_4", "filter-P_0", "filter-P_1", "filter-P_2", "filter-P_3", ]
var filterActive = [];
function filterApps(){
if(filterActive.length == 0)
{
filterReset();
return;
}
var arrActive = $.map(filterActive, function (val) {
return '[' + val + ']'
}).join(",")
addToLog("arr = " + arrActive);
$(".appLink").filter(arrActive).css(activeAppCSS).addClass("active").removeClass("disable");
$(".appLink").not(arrActive).css(disabledAPPCSS).addClass("disable").removeClass("active");}
You have complicated many things here, using attribute's name for filtering the elements is a terrible idea (sorry), you could use data-* attributes that store the filtering criteria in an array. If I have understood the question correctly something like the following should work, this solution reads the attributes' name using attributes property, it should be noted that it's not the most efficient way of doing the task and as Array object's .filter() method is used it doesn't work in older browsers that don't support ES5, for supporting those browsers you can use a shim.
var $links = $('.appLink');
var $checkboxes = $('input[type=checkbox]').on('change', function () {
// Creating an array of values
var checked = $checkboxes.filter(':checked').map(function () {
return this.value.toLowerCase();
}).get();
// Filtering the .appLink elements by reading the attributes
// and comparing the filtered array's length with the checked one
$links.removeClass('matched').filter(function () {
return [].slice.call(this.attributes).filter(function (a) {
return a.name.indexOf('filter') === 0;
}).filter(function(f) {
return $.inArray(f.name.replace('filter-', ''), checked) > -1;
}).length === checked.length;
}).addClass('matched');
});
http://jsfiddle.net/85tTp/
In case that you want to use data-* properties, you can define an attribute like data-filter='["f1", "f2", ""]' for the elements and use jQuery .data() method for reading them:
$links.removeClass('matched').filter(function () {
return $(this).data('filter').filter(function(f) {
return $.inArray(f, checked) > -1;
}).length === checked.length;
}).addClass('matched');

breaking out of an underscore each

I am trying to find a model within a collection with an attribute equal to html select option value.
<div id="hospital-details">
<select name="hospitalnames">
<option><%- model.get('name') %></option>
</select>
</div>
whenever hospital name is changed, jquery change callback is triggered to find locationModel with selected option value as attribute value as shown below,
$('select[name="hospitalnames"]').change(function() {
var name = $(this).val();
locationListCollection.each(function(locationModel) {
if ($.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
return false; // control is returned to underscore.min.js
}
});
});
console.log(that.locationModel); // this is not being displayed at all
After the locationModel with an attribute is found, I am unable to come out the loop. Any help ? At this moment I have looked into
this but without success.
You're using the wrong method if you're searching for the first match. Collections have lots of Underscore methods mixed in, in particular they have find mixed in:
find _.find(list, iterator, [context])
Looks through each value in the list, returning the first one that passes a truth test (iterator), or undefined if no value passes the test.
Something like this:
var name = $.trim($(this).val());
that.locationModel = locationListCollection.find(function(locationModel) {
return $.trim(locationModel.get('name')) == name;
});
and if the names in your model are pre-trimmed and nice and clean, then you could use findWhere:
findWhere collection.findWhere(attributes)
Just like where, but directly returns only the first model in the collection that matches the passed attributes.
like this:
var name = $.trim($(this).val());
that.locationModel = locationListCollection.findWhere({ name: name });
BTW, this:
console.log(locationModel);
won't give you anything because locationModel and that.locationModel are different things.
You can always go oldschool.
$('select[name="hospitalnames"]').change(function() {
var name = $(this).val();
for (var i = 0; i < locationListCollection.length; ++i) {
var locationModel = locationListCollection.models[i];
if ($.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
break;
}
}
});
Try this,
var name = $(this).val();
var flag=true;
locationListCollection.each(function(locationModel) {
if (flag && $.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
flag=false;
//return false;// to break the $.each loop
}
});
The short is no.
If you take a look at underscore's source you'll see that they use a breaker object to quickly stop a .each() but that is only available internally.
I would not recommend this but you could always modify the source to expose this breaker object (see baseline setup in the annotated source
http://underscorejs.org/docs/underscore.html). Then you would just return this object instead of returning false. But you would probably need to remove the native forEach call to keep the behaviour consistent. So it's not worth it!
_.each(function(arr) {
if(condition) {
return _.breaker; // Assuming you changed the source.
}
});
Since you are searching for a single item instead of .each() use:
var locationModel = _.find(arr, function(item) {
return $.trim(locationModel.get('name')) == $.trim(name);
));

validate 2 dropdowns (only some combinations valid)

I am completely new to JavaScript.
I have size and color dropdowns on a page for users to order a product, but only certain combinations are available i.e. pink is the only color in large sizes.
I thought I'd make an array of allowed sizes and test the user input against these.
If the choice is invalid then I want a popup to tell the user why.
In the real world I'll use SQL & PHP to create the array of allowed choices, in the example below I've hard coded 3 valid choices for testing. Unfortunately the code below doesn't do anything.
I'm sure it's a simple newb mistake. I really don't know what I'm doing :)
Can somebody help me out?
The validation function is supposed to happen when user clicks the form submit...
<form id="form1" name="form1" method="post" onsubmit="return validate_form()"
action="cart.php">
Here's the function:
<script type="text/javascript">
function validate_form() {
var allowed = new Array();
allowed[0]="10,beige";
allowed[1]="10,black";
allowed[2]="10,pink";
var chosenColInd = document.getElementById("colID");
var chosenColText = colID.options[colID.selectedIndex].text;
var chosenSizeInd = document.getElementById("sizeID");
var chosenSizeText = sizeID.options[sizeID.selectedIndex].text;
var chosenSizeCol = chosenSizeText+","+chosenColText;
var found = "false";
for ( var i = 0; i < allowed.length; i++ ) {
if (allowed[i]=chosenSizeCol) {
found = "true";
}
}
if (found = "false") {
alert( 'The variation you have selected is currently unavailable. Please select another.' );
return false;
} else {
return true;
}
}
</script>
There are a few lines where you use the assignment operator (that is single equals =) instead of one of the equality operators (that is double or triple equals, triple is usually preferred in JavaScript). Example:
if (found = "false") {
Would appear to be the problem at first sight - it's an assignment not a comparison :) use triple equals === instead of single:
if(found === "false") {
Also, consider the following (commented) updates to your code, which reflects more the typical style of JavaScript code:
function validate_form() {
//no need to use new Array(), use array literal instead
var allowed = [
"10,beige",
"10,black",
"10,pink"
];
var chosenColInd = document.getElementById("colID");
var chosenColText = colID.options[colID.selectedIndex].text;
var chosenSizeInd = document.getElementById("sizeID");
var chosenSizeText = sizeID.options[sizeID.selectedIndex].text;
var chosenSizeCol = chosenColText+","+chosenSizeText;
var found = "false";
for ( var i = 0; i < allowed.length; i++ ) {
//use equality operator instead of assignment
if (allowed[i]===chosenSizeCol) {
found = true; //may as well use a boolean rather than string
break; //exit loop early, no need to continue if we've already found
}
}
if (!found) { //no need to do a comparison with already boolean values
alert( 'The variation you have selected is currently unavailable. Please select another.' );
}
//may as well just return found here now that we're using a boolean
return found;
}

Categories

Resources