Add class to parent if all childeren have class - javascript

So I'm creating a progress bar, but I'm running into a little problem.
The rule I'm trying to implement:
for each li.page check if li.question = li.question.done, if true .addClass .done to this
So in the HTML below, #p1 should have class done, #p2 and #p3 shouldn't.
The current JS results in adding class .done to all .page li's in the page if one .page has all questions done.
Hope someone can help me get this to work, all help is appreciated!
This is the html:
<ul class="pages">
<li id="p1" class="page">
<ul class="questions">
<li id="q2" class="question done">1</li>
<li id="q3" class="question done">2</li>
<li id="q4" class="question done">3</li>
</ul>
</li>
<li id="p2" class="page">
<ul class="questions">
<li id="q5" class="question current">4</li>
</ul>
</li>
<li id="p3" class="page">
<ul class="questions">
<li id="q6" class="question done">5</li>
<li id="q7" class="question">6</li>
</ul>
</li>
</ul>
And this JS:
var doneCheck = function(){
$(".page").each(function () {
questionsInPage = $(this).closest(".questions").find("li").length;
questionsDone = $(this).closest(".questions").find("li.done").length;
var done = questionsDone == questionsInPage;
$(".page").each(function() {
if (done) {
$(this).parent().addClass('done');
};
});
});
}

For each page I would check the number of li against the number of elements with class question and done. If they match set page to done.
var doneCheck = function() {
$(".page").each(function() {
if($('.question.done', this).length==$('ul li',this).length)
$(this).addClass('done');
});
}
doneCheck();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="pages">
<li id="p1" class="page">
<ul class="questions">
<li id="q2" class="question done">1</li>
<li id="q3" class="question done">2</li>
<li id="q4" class="question done">3</li>
</ul>
</li>
<li id="p2" class="page">
<ul class="questions">
<li id="q5" class="question current">4</li>
</ul>
</li>
<li id="p3" class="page">
<ul class="questions">
<li id="q6" class="question done">5</li>
<li id="q7" class="question">6</li>
</ul>
</li>
</ul>

Instead of finding all the done questions, count the number of not done questions. If it's zero, all the questions are done. Use this to set the done property of the page.
function doneCheck() {
$(".page").each(function() {
var allDone = $(this).find(".questions li.question:not(.done)").length == 0;
$(this).toggleClass("done", allDone);
});
}
$("#check").click(doneCheck);
.page.done {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="pages">
<li id="p1" class="page">
<ul class="questions">
<li id="q2" class="question done">1</li>
<li id="q3" class="question done">2</li>
<li id="q4" class="question done">3</li>
</ul>
</li>
<li id="p2" class="page">
<ul class="questions">
<li id="q5" class="question current">4</li>
</ul>
</li>
<li id="p3" class="page">
<ul class="questions">
<li id="q6" class="question done">5</li>
<li id="q7" class="question">6</li>
</ul>
</li>
</ul>
<button id="check">Check</button>
FYI, you can't use == to compare the results of two selectors. If you want to test whether they're equivalent, use .is:
if (questionsDone.is(questionsInPage)
But your second loop is wrong, because it sets the class on all .page elements based on the done status of the current page of the loop.

Related

Why is the length of an html collection coming as zero?

When I am using the length property over the HTML Collection,I am getting zero...Please Correct me someone..
My HTML Code:
<div class="container">
<div class="header">
<h1>To Do List</h1>
</div>
<div class="todos">
<ul class="todolist">
<li class="listItem">
<p>Doing Homework</p>
</li>
<li class="listItem">
<p>Doing Competitve Programming</p>
</li>
<li class="listItem">
<p>Doing Dynamic Programming</p>
</li>
<li class="listItem">
<p>Doing Robot Programming</p>
</li>
<li class="listItem">
<p>Doing DSA</p>
</li>
</ul>
</div>
</div>
</body>
MY JS Code:
function crossAdder() {
var todolist = document.getElementsByClassName('.listItem');
console.log(todolist.length);
}
crossAdder();
Remove . in .listItem when you input to document.getElementsByClassName function.
It accept a class name, not a CSS selector.
function crossAdder() {
var todolist = document.getElementsByClassName('listItem');
console.log(todolist.length);
}
crossAdder();
<div class="container">
<div class="header">
<h1>To Do List</h1>
</div>
<div class="todos">
<ul class="todolist">
<li class="listItem">
<p>Doing Homework</p>
</li>
<li class="listItem">
<p>Doing Competitve Programming</p>
</li>
<li class="listItem">
<p>Doing Dynamic Programming</p>
</li>
<li class="listItem">
<p>Doing Robot Programming</p>
</li>
<li class="listItem">
<p>Doing DSA</p>
</li>
</ul>
</div>
</div>
</body>
function crossAdder(){
//Use query selector if you are using .listItem
var todoList = document.querySelectorAll(".listItem")
//If you are using getElementsByClassName don't use the dot only need just listItem
var todoList = document.getElementsByClassName("listItem")
console.log(todoList)
}

Jquery Counting child in nested list, Search and Expand Collapse

I am trying to develop expand collapse, search in nested list and count of child lists but I don't know how to implement all these.
HTML
<div class="searchSection">
<form action="#" novalidate="novalidate">
<input type="text" placeholder="search here...">
</form>
<ul id="orgCat">
<li parent-id="" li-id="1">
<div class="expandBtn"><span id="count"></span>India</div>
<ul>
<li parent-id="1" li-id="2">
<div class="expandBtn"><span id="count"></span>Ap</div>
<ul>
<li parent-id="2" li-id="7">
<div class="expandBtn"><span id="count"></span>vag</div>
</li>
<li parent-id="2" li-id="8">
<div class="expandBtn"><span id="count"></span>tirupati</div>
</li>
</ul>
</li>
<li parent-id="1" li-id="3">
<div class="expandBtn"><span id="count"></span>TN</div>
<ul>
<li parent-id="3" li-id="9">
<div class="expandBtn"><span id="count"></span>chena</div>
</li>
<li parent-id="3" li-id="10">
<div class="expandBtn"><span id="count"></span>India1</div>
</li>
<li parent-id="3" li-id="11">
<div class="expandBtn"><span id="count"></span>India2</div>
</li>
<li parent-id="3" li-id="12">
<div class="expandBtn"><span id="count"></span>India3</div>
</li>
<li parent-id="3" li-id="13">
<div class="expandBtn"><span id="count"></span>India4</div>
</li>
</ul>
</li>
<li parent-id="1" li-id="4">
<div class="expandBtn"><span id="count"></span>TS</div>
<ul>
<li parent-id="4" li-id="5">
<div class="expandBtn"><span id="count"></span>Hyd</div>
</li>
<li parent-id="4" li-id="6">
<div class="expandBtn"><span id="count"></span>warangal</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
When I click on the 'div' tag it should be expand or collapse. Count of children should be appear in 'span' tag. When I search an element, it should appear from it's root directory. I hope you guys understand.
JSFIDDLE
Jquery
// counting leafs
$('.searchSection').each(function(){
$('#count').text($('ul').children().length);
})
above jquery displaying total 'li' elements but i need to display number of li elements in each ul.
I don't know how to implement Collapse and Expand functionality. I am new to Jquery.
This code should give you the expand and colapse and count of all list items under a parent.
//Search query
$("input").keyup(function() {
var searchTerms = $(this).val();
$('li').each(function() {
var $li = $(this);
var hasMatch = searchTerms.length == 0 || $li.text().toLowerCase().indexOf(searchTerms.toLowerCase()) > 0;
$li.toggle(hasMatch);
if ($li.is(":hidden")) {
$li.closest("ul").show();
}
});
});
var $expandBtns = $(".expandBtn");
$expandBtns.each(function() {
var $span = $(this).find("span#count");
var $subList = $(this).siblings("ul").find("li")
$span.text($subList.length)
});
$expandBtns.on("click", function() {
var $subList = $(this).siblings("ul");
if ($subList.is(":visible")) {
$subList.hide();
} else {
$subList.show();
}
})

Unexpected behavior of $parent.$index in AngularJS

I have a code like this :
<script type="text/ng-template" id="something.html">
<div>
Hey!
</div>
</script>
<div ng-repeat="colum in columns">
<ul>
<li ng-repeat="list in column" id="{{$parent.$index}}" ng-include="something.html">
</li>
</ul>
</div>
The ids are assigned as 1, 2, 3, 4 on the li elements. I am expecting that if columns has 4 elements then the ids for li inside a ul element should be 0,0,0,0.
Rendered DOM is something like :
<div>
<ul>
<li id="0">
</li>
<li id="1">
</li>
</ul>
</div>
<div>
<ul>
<li id="0">
</li>
<li id="1">
</li>
</ul>
</div>
My expected DOM :
<div>
<ul>
<li id="0">
</li>
<li id="0">
</li>
</ul>
</div>
<div>
<ul>
<li id="1">
</li>
<li id="1">
</li>
</ul>
</div>
Apologies if I missed something obvious.

How to set alternating color to nested and sibling divs with certain class.

I have a nested list, each list item has a container div with class R
I am trying to apply alternating colors to alternate divs. The problem is that divs with class are not always siblings.
This is my html:
<ul>
<li>
<div class="R">Bat</div>
<div class="R">description</div>
</li>
<li>
<div class="R">Cat</div>
</li>
<li>
<div class="R">Rat</div>
<ul>
<li>
<div class="R">one
<div class="R">blah</div>
<div class="R">blah blah</div>
</div>
</li>
<li>
<div class="R">two
<div>
</li>
<li>three</li>
</ul>
</li>
</ul>
This is how I want it to look(I have harcoded colors with inline css)
<ul>
<li>
<div class="R" style="background-color:red;">Bat</div>
<div class="R" style="background-color:green;">description</div>
</li>
<li>
<div class="R" style="background-color:red;">Cat</div>
</li>
<li>
<div class="R" style="background-color:green;">Rat</div>
<ul>
<li>
<div class="R" style="background-color:red;">one
<div class="R" style="background-color:green;">blah</div>
<div class="R" style="background-color:red;">blah blah</div>
</div>
</li>
<li>
<div class="R" style="background-color:green;">two
<div>
</li>
</ul>
</li>
</ul>
Try this : you can use :odd and :even jQuery selectors to get odd and even divs and apply background color accordingly. See below code
$(function() {
$('ul div.R:odd').addClass('oddColor');
$('ul div.R:even').addClass('evenColor');
});
.oddColor {
background-color: red;
}
.evenColor {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
<li>
<div class="R">Bat</div>
<div class="R">description</div>
</li>
<li>
<div class="R">Cat</div>
</li>
<li>
<div class="R">Rat</div>
<ul>
<li>
<div class="R">one
<div class="R">blah</div>
<div class="R">blah blah</div>
</div>
</li>
<li>
<div class="R">two
<div>
</li>
<li>three</li>
</ul>
</li>
</ul>
$(document).ready(function() {
$(".R:even").css("background-color", "green");
$(".R:odd").css("background-color", "red");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li>
<div class="R">Bat</div>
<div class="R">description</div>
</li>
<li>
<div class="R">Cat</div>
</li>
<li>
<div class="R">Rat</div>
<ul>
<li>
<div class="R">one
<div class="R">blah</div>
<div class="R">blah blah</div>
</div>
</li>
<li>
<div class="R">two</div>
</li>
<li>Three</li>
</ul>
</li>
</ul>
$(function() {
$('ul div.R:odd').addClass('oddRow');
$('ul div.R:even').addClass('evenRow');
});
.oddRow {
background-color: red;
}
.evenRow {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li>
<div class="R">Bat</div>
<div class="R">description</div>
</li>
<li>
<div class="R">Cat</div>
</li>
<li>
<div class="R">Rat</div>
<ul>
<li>
<div class="R">one
<div class="R">blah</div>
<div class="R">blah blah</div>
</div>
</li>
<li>
<div class="R">two</div>
</li>
<li>Three</li>
</ul>
</li>
</ul>
$('div.R').each(function(index) {
$(this).css('background-color', index % 2 === 0 ? '#cc0' : '#0cc');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<ul>
<li>
<div class="R">Bat</div>
<div class="R">description</div>
</li>
<li>
<div class="R">Cat</div>
</li>
<li>
<div class="R">Rat</div>
<ul>
<li>
<div class="R">one
<div class="R">blah</div>
<div class="R">blah blah</div>
</div>
</li>
<li>
<div class="R">two</div>
</li>
<li>three</li>
</ul>
</li>
</ul>

how to check all the children check

Hi I have the following structure:
<ul class="main">
<li class="toggle">
<input type="checkbox"> information
</li>
<ul>
<li class="modulo">
<input type="checkbox"> General
</li>
<ul>
<li class="example1">
<input type="checkbox">
</li>
<li class="example2">
<input type="checkbox">
</li>
</ul>
</ul>
</ul>
I now need to know how to set all the children checkboxes to "checked" when the main parent checkbox is checked by the user
Im using jQuery, thanks
Your can change markup like following:
<ul class="main">
<li class="toggle">
<input type="checkbox"> information
<ul>
<li class="example1">
<input type="checkbox">
</li>
<li class="example2">
<input type="checkbox">
</li>
</ul>
</li>
<li class="modulo">
<input type="checkbox"> General
<ul>
<li class="example1">
<input type="checkbox">
</li>
<li class="example2">
<input type="checkbox">
</li>
</ul>
</li>
</ul>
jQuery
$('ul.main > li > :checkbox').change(function() {
$(this).next('ul').find(':checkbox').prop('checked', this.checked);
});
If you correct your markup:
<ul class="main">
<li class="toggle">
<input type="checkbox"> information
<ul>
<li class="modulo">
<input type="checkbox"> General
<ul>
<li class="example1">
<input type="checkbox">
</li>
<li class="example2">
<input type="checkbox">
</li>
</ul>
</li>
</ul>
</li>
</ul>
...this should do it:
$(".main input[type='checkbox']").click(function() {
$(this).parent().find("input[type='checkbox']").prop("checked", this.checked);
});
Live example | source
Then you'll want to handle the converse case (unchecking the parent if you uncheck an ancestor so all ancestors are no longer checked), but I leave that as an exercise for you.
This toggles the checks: http://jsfiddle.net/
I'd suggest you indent your code for more easy reading too.

Categories

Resources