Asserting all checkboxes are checked - javascript

I have 5 checkboxes with the same name property relative-view.
I want to assert that all of them are checked. I can do this to check the first and last one
expect(element.find('input[name="relative-view"]').first().prop("checked")).toBe(true);
expect(element.find('input[name="relative-view"]').last().prop("checked")).toBe(true);
But I don't know how to check them all. I have tried the following but I get an error saying undefined is not a function
expect(element.find('input[name="relative-view"]')[0].prop("checked")).toBe(true);
expect(element.find('input[name="relative-view"]')[1].prop("checked")).toBe(true);
expect(element.find('input[name="relative-view"]')[2].prop("checked")).toBe(true);
expect(element.find('input[name="relative-view"]')[3].prop("checked")).toBe(true);
expect(element.find('input[name="relative-view"]')[4].prop("checked")).toBe(true);
How can I do this?

[n] notation returns DOM elements which don't have .prop() - that's jQuery API. Use .eq():
var boxes = element.find('input[name="relative-view"]');
expect(boxes.eq(0).prop("checked")).toBe(true);
expect(boxes.eq(1).prop("checked")).toBe(true);
expect(boxes.eq(2).prop("checked")).toBe(true);
expect(boxes.eq(3).prop("checked")).toBe(true);
expect(boxes.eq(4).prop("checked")).toBe(true);
An alternative approach would be to use the standard .checked property:
var boxes = element.find('input[name="relative-view"]').get();
expect(boxes[0].checked).toBe(true);
expect(boxes[1].checked).toBe(true);
expect(boxes[2].checked).toBe(true);
expect(boxes[3].checked).toBe(true);
expect(boxes[4].checked).toBe(true);
Also, try just iterating over the jQuery collection:
$('input[name="relative-view"]', element).each(function () {
expect(this.checked).toBe(true);
});

You can write a function which will go through all checkboxes and return false if any of them is not checked. Use:
function CheckAllCheckboxes(){
var _RetValue = true;
$('input[name="relative-view"]').each(function(){
if($(this).prop("checked") != true)
_RetValue = false;
return false; // quit from each()
}
return _RetValue;
}
Then you can use
expect(CheckAllCheckboxes()).toBe(true);

Related

Using parent() in a for loop

I am creating a chrome extension that blocks all porn results on all torrent search engine sites.
So I am trying to retrieve the name of the torrents and check them against the array of strings containing blocked (adult/porn) words that I created. If it matches the array word then it should set the display of the parent element to none. But parent() from jQuery doesn't seem to work around this in a for loop. This is the code that I am using.
// 'blockedWords' is the array.
// '$("dl dt")' contains the words that I am checking against strings from
// the array 'blockedWords'.
for (var i = 0; i < $("dl dt").length; i++) {
for (var j = 0; j < blockedWords.length; j++) {
if($("dl dt")[i].innerText.indexOf(blockedWords[j]) > -1){
$(this).parent().style.display= "none"; // 1st Method or
$("dl dt")[i].parent().style.display= "none"; // 2nd Method
}
}
}
// 1st Method shows the error 'Cannot set property 'display' of undefined'
// 2nd Method shows the error '$(...)[i].parent is not a function'
// '$("dl dt")[i].parent().style.display' doesn't work but
// '$("dl dt").parent().style.display' doesn't work either
// '$("dl dt")[i].style.display' works perfectly without parent().
I have also tried 'parents()'.
Any help will be appreciated :).
As a newbie, I am also open to any other suggestions or recommendations.
And I would be really grateful if you could explain your code as well :)
And by the way, can you believe there are more than 500 porn companies out there :o :P :D
Since you have jQuery, you can avoid using nested for-loops using jQuery's filter() and JavaScript reduce(s,v):
// Filter function removes elements that return a false/falsey value like 0
$("dl dt").filter(function() {
// Save current element's innerText so we can use it within the reduce function
var str = $(this).text();
// Return sum of reduce function
return blockedWords.reduce(function(s, v) {
// For each item in blockedWords array, check whether it exists in the string. Add to total number of matches.
return s + !!~str.indexOf(v);
}, 0); // 0 = intial value of reduce function (number of matches)
}).parent().hide(); // Hide elements which pass through the filter function
Demo:
var blockedWords = [
'shit', 'fuck', 'sex'
];
$("dl dt").filter(function() {
var str = $(this).text();
return blockedWords.reduce(function(s, v) {
return s + !!~str.indexOf(v);
}, 0);
}).parent().hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<dl><dt>this is shit</dt></dl>
<dl><dt>this is okay</dt></dl>
<dl><dt>fuck this</dt></dl>
<dl><dt>no problem</dt></dl>
<dl><dt>sex videos</dt></dl>
EDIT: I apologize for the earlier answer if you saw it, as it was incomplete. I have also added a snippet for demonstration purposes. For further explanation of the reduce algorithm, check this answer out (basically it converts the value of indexOf to either a 0 or 1, because indexOf returns -1 if not found, or another 0-indexed integer of the position if found).
JQuery's parent function returns a JQuery object with the parent element inside of it. If you want to access the element from this object you need to retrieve the element from the object using the bracket notation.
If you were to provide some HTML I would be able to test this and make sure it works, but here is some code that could get you pointed in the right direction to use mostly JQuery instead of relying on for loops with JavaScript.
JQuery Rewrite
$("dl dt").each(function(index, element){
if($.inArray(blockedWords,$(element).text()) > -1) {
$(this).parent().css("display", "block");
$(element).parent().css("display", "block");
}
})
The Answer To Your Specific Question
Change this:
$(this).parent().style.display= "none"; // 1st Method or
$("dl dt")[i].parent().style.display= "none"; // 2nd Method
to this:
$(this).parent()[0].style.display= "none"; // 1st Method or
$($("dl dt")[i]).parent()[0].style.display= "none"; // 2nd Method
optionally, you can instead use JQuery's css function like this:
$(this).parent().css("display", "none"); // 1st Method or
$($("dl dt")[i]).parent().css("display","none"); // 2nd Method

Javascript Enabled input type when checkbox checked and disable when checkbox unchecked

my javascript is here:
function enable(id) {
var i = (document.getElementById('haha').checked);
if(i= true) {
document.getElementById("nama_"+id).disabled= false;
document.getElementById("ket_"+id).disabled= false;
}else{
document.getElementById("nama_"+id).disabled= true;
document.getElementById("ket_"+id).disabled= true;
}
}
when i checked checkbox, the textbox will enabled, but when i unchecked, that textbox still enable, i want to this textbox go disabled after i unchecked. how can i fix this problem?
= is assignment (setting the value of a variable), so if (i = true) sets i to true and then branches into the if block. To do a comparison, normally you'd use == or ===, but with booleans, that's never necessary; just check the value directly:
if (i) {
// Enable it
} else {
// Disable it
}
In this case, though, you can just use i directly:
document.getElementById("nama_"+id).disabled = !i;
document.getElementById("ket_"+id).disabled = !i;
There's also no need for the () around your check of checked.
I'd probably do this:
function enable(id) {
var disabled = !document.getElementById('haha').checked;
document.getElementById("nama_"+id).disabled = disabled;
document.getElementById("ket_"+id).disabled = disabled;
}
There, I'm getting the value of the checkbox and inverting it, then using that as the disabled flag on the other inputs. I'd do it like that because it's nice and easy to debug, I can see the disabled value easily in the debugger when I'm stepping through code.
Some folks really, really like to do things in one expression. (I think that's very overrated.) They might do this:
function enable(id) {
document.getElementById("nama_"+id).disabled =
document.getElementById("ket_"+id).disabled =
!document.getElementById('haha').checked;
}
...since the result of an assignment is the value that was assigned.
function chkBox(obj) {
console.log(obj);
$(obj).parents("tr").find("input[type='number']").prop('disabled', !$(obj).is(":checked"));
$(obj).parents("tr").find("input[type='hidden']").prop('disabled', !$(obj).is(":checked"));
}
call the function and pass this.
onclick="chkBox(this)"

Check if checkbox has a class and is checked

I'm handling a checkbox.
if ($(this).hasClass("select")) { // To check class name
if ($(this).is(':checked')) { // to check whether it is checked
// some code
}
}
Now I have two if statements. How to merge them in a single condition?
I've tried:
1)
if ($(this).hasClass("select").is(':checked')) {
//statements
}
It gave me an error: .hasClass("...").is('...') is not a function.
2)
if ($(this).hasClass("select") && $(this).is(':checked')) {
// some code
}
else if ($(this).hasClass("select") && $(this).not(':checked')) {
// some code
}
It's working.
How to merge these two in single statement in a simplified manner? Can we simplify the condition?
You can do it by,
var cond = $(this).is(".select:checked");
var val = parseInt($(this).parent().next().text());
sum += (cond ? val : -(val));
You can move the class checking into .is():
if ($(this).is(".select:checked"))
$(this).hasClass("select").is(':checked') doesn't work because .hasClass() returns boolean, not the $(this) object, so you can't chain jQuery methods on it.

How to add class to a jQuery element if a condition is true and remove the same class if the condition is false?

Is there a shorter way to do the following?
var select_all_checkbox = $("input.select_all");
var is_checked = select_all_checkbox.prop("checked");
if (is_checked) {
select_all_checkbox.parent().addClass("selected");
} else {
select_all_checkbox.parent().removeClass("selected");
}
Use toggleClass, passing a second argument (a boolean) that specifies whether the class should be added or not:
select_all_checkbox.parent().toggleClass("selected", is_checked);
If you have multiple elements selected by input.select_all, you have to iterate over them though:
$("input.select_all").each(function() {
$(this).parent().toggleClass('selected', this.checked);
});
Absolutely! You can choose between the methods (addClass/removeClass) programmatically, and use the one that is returned when an expression is executed.
Like this:
var select_all_checkbox = $("input.select_all");
var is_checked = select_all_checkbox.prop("checked");
select_all_checkbox.parent()[is_checked ? "addClass" : "removeClass"]("selected");

resetting fields with jQuery

I am trying to reset fields (selects and textboxes) in a partial. Here is what I have so far:
var $inputs = $('#StudentTable :select');
$inputs.each(function () {
if ($(this).name = "TeachingAsstSelect") {
$('select[name="TeachingAsstSelect"]').each(function () {
$(this).text("");
})
}
else {
$(this).val("Select");
}
});
Here "TeachingAsstSelect" is being cleared, but other selects are not reset. Am I missing something? More importantly, Am I doing it the right way?
If you are trying to test equality of a string, you should use == or ===. See here form more on that: Which equals operator (== vs ===) should be used in JavaScript comparisons?
Also, as #Raminson suggests, try use the attr() method instead.
if ($(this).attr('name') == "TeachingAsstSelect") {
Or better yet, nesting .each() twice like that may not perform as well as other solutions.
I also notice that you are testing name in your if condition then using a jquery selector to match again on [name="TeachingAsstSelect"]. What about simplifying like this:
var $teachingAsstInputs = $('#StudentTable :select[name="TeachingAsstSelect"]');
$($teachingAsstInputs).text("");
var $otherInputs = $('#StudentTable :select').not('[name="TeachingAsstSelect"]');
$($otherInputs).val("Select");
For jQuery objects you should use attr() method, name is one of the DOM Element properties.
Change this:
if ($(this).name = "TeachingAsstSelect") {
to:
if ($(this).attr('name') == "TeachingAsstSelect") {
also note that for comparison you should use == operator, currently you are setting the value.

Categories