How to add an if statement to a toggle function - javascript

Consider the following code, which toggles visibility of two classes with separate click() functions:
<!-- Toggles -->
<div class="a"></div>
<div class="b"></div>
<!-- Result -->
<div class="x" style="display:none"></div>
<div class="y" style="display:none"></div>
<div class="z" style="display:none"></div>
<!-- Script -->
$( ".a" ).click(function() {
var $this = $(this);
$this.siblings(".x").toggle();
});
$( ".b" ).click(function() {
var $this = $(this);
$this.siblings(".y").toggle();
});
How would I update this so that any time both x and y are visible, a third class, "z" is shown instead of both x and y?

Demo http://jsfiddle.net/Yn3L2/
API is(':visible') http://api.jquery.com/visible-selector/
Rest should fit your needs :)
Code
$(".a").click(function () {
var $this = $(this);
$this.siblings(".x").toggle();
checkZ();
});
$(".b").click(function () {
var $this = $(this);
$this.siblings(".y").toggle();
checkZ();
});
function checkZ() {
$('.z').hide();
if ($('.x').is(':visible') && $('.y').is(':visible')) {
$('.z').show();
}
}

This works as show here: http://jsfiddle.net/DKRe2/1/
HTML:
<!-- Toggles -->
<div class="a">a</div>
<div class="b">b</div>
<!-- Result -->
<div class="x" style="display:none">class x</div>
<div class="y" style="display:none">class y</div>
<div class="z" style="display:none">class z</div>
JS:
<!-- Script -->
$(".a").click(function () {
var $this = $(this);
if ($this.siblings(".y").css('display') != 'none' && $this.siblings(".x").css('display') == 'none') {
//now Hide y and show Z
$this.siblings(".y").toggle();
$this.siblings(".z").toggle();
} else {
$this.siblings(".z").css('display', 'none');
$this.siblings(".x").toggle();
}
});
$(".b").click(function () {
var $this = $(this);
if ($this.siblings(".x").css('display') != 'none' && $this.siblings(".y").css('display') == 'none') {
//now Hide y and show Z
$this.siblings(".x").toggle();
$this.siblings(".z").toggle();
} else {
$this.siblings(".z").css('display', 'none')
$this.siblings(".y").toggle();
}
});

I think this is what you really want.
Working DEMO
Added jQuery code
function checkZ() {
$('.z').hide();
if ($('.x').is(':visible') && $('.y').is(':visible')) {
$('.x').hide(500);
$('.y').hide(500)
$('.z').show();
}
}

Related

jquery If statement based on a previous element

I want to hide an element if the previous element has a number less than 0.
https://jsfiddle.net/82bysjag/2/
$(document).on("click", function() {
$(".hide").each(function() {
var prevqty = $(".hide").prev().text();
if (prevqty < 0) {
$(this).hide();
} else {}
});
});
div {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
-2
</div>
<div class="hide">
Hide
</div>
<div>
1
</div>
<div class="hide">
Hide
</div>
Is there an error with my var prevqty?
Use $(this) and parseInt to
$(".hide").each(function() {
var prevqty = parseInt($(this).prev().text(), 10);
if (prevqty < 0) {
$(this).hide();
} else {}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>-2</div>
<div class="hide">Hide</div>
The problem is from prevqty. JavaScript is seing it as a string. Convert it to number first as follows;
var prevqty = $(".hide").prev().text();
prevqty =Number(prevqty );
Then you can compare

Jquery change background colour for a selected div

I have this HTML code div in 4*4 format :
$(document).ready(function() {
$("div").click(function(e){
var id_val=this.id;
var word = id_val.split("-").pop();
alert(word)
e.preventDefault();
for(var i=1;i<=4;i++)
{
if(i!=word)
{
$("#div-"+i+"").css("background-color","white");
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div-1">
<p>div1</p>
<div id="div-2">
<p>div2</p>
<div id="div-3">
<p>div3</p>
<div id="div-4">
<p>div4</p>
</div>
</div>
</div>
</div>
I have written the jquery code when on click the particular div has to change colour to red and remaining div colour should be white
When I have executed this only the div1 has changing the colour to red and other divs are not changing the colour.
for eg :
if I click div1 change to red colour and other div2,div3,div4 should be in white
color
If I click div2 change to red colour and other div1,div3,div4 should be in white
color
You need to use e.stopPropagation(); to prevent the other div elements from triggering as well.
you didn't properly terminate the first two lines with }); at the end of the script.
$(document).ready(function() {
$("div").click(function(e) {
var id_val = this.id;
var word = id_val.split("-").pop();
if (word != null) {
alert(word)
e.stopPropagation();
for (var i = 1; i <= 4; i++) {
if (parseInt(i) === parseInt(word)) {
$("#div-" + i + "").css("background-color", "red");
} else {
$("#div-" + i + "").css("background-color", "white");
}
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="div-1">
<p>div1</p>
<div id="div-2">
<p>div2</p>
<div id="div-3">
<p>div3</p>
<div id="div-4">
<p>div4</p>
</div>
</div>
</div>
</div>
Try something Like that
$("div").click(function(e){
$("div[id^='div-']").css("background-color","white");
$(this).css("background-color","red");
}
You need to use e.stopPropagation() and not e.preventDefault(). Also since divs are nested you should give a color to the inside p tag and not the div itself. Also terminate your function correctly.
$(document).ready(function() {
$("div").click(function(e){
var id_val=this.id;
$(this).first("p").css("background-color","red")
var word = id_val.split("-").pop();
alert(word)
e.stopPropagation();
for(var i=1;i<=4;i++)
{
if(i!=word)
{
$("#div-"+i+"").css("background-color","white");
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div-1">
<p>div1</p>
<div id="div-2">
<p>div2</p>
<div id="div-3">
<p>div3</p>
<div id="div-4">
<p>div4</p>
</div>
</div>
</div>
</div>
This worked for me
$("div").click(function (e) {
$(this).css("background-color", "red");
$('div:not(#' + this.id + ')').css("background-color", "white");
e.stopImmediatePropagation();
});
Try to use this simple code
$(document).ready(function() {
$("div").click(function(e) {
$('div[id^="div-"] p').css("background-color", "white"); //change the remaining elements who's id start with div- color to white
if ($(e.target).is('p')) {
$(e.target).css("background-color", "red"); //change the clicked element color
}
});
});
$("div").click(function(e) {
$('div[id^="div-"] p').css("background-color", "white"); //change the remaining elements who's id start with div- color to white
if ($(e.target).is('p')) {
$(e.target).css("background-color", "red"); //change the clicked element color
}
});
body {
background: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div-1">
<p>div1</p>
<div id="div-2">
<p>div2</p>
<div id="div-3">
<p>div3</p>
<div id="div-4">
<p>div4</p>
</div>
</div>
</div>
</div>

Navigate through multiple divs using next/prev

So basically my DIV will look like this.
<div id="group">
<div id="one">one</div>
<div style="display:none" id="two">two</div>
<div style="display:none" id="three">three</div>
<div style="display:none" id="four">four</div>
</div>
<div id="next">next</div>
<div style="display:none" id="prev">prev</div>
<div style="display:none" id="prev">SUBMIT</div>
This is just an example, I could even have 10 or 20 divs.
I want to navigate from one to four in this example. When it reaches end it must hide the next button and show submit button. And when I navigate back to first page it must hide the prev button
Here's what I have tried so far:
$("#next").click(function () {
$("#prev").show();
$("#one").hide();
$("#one").addClass("current");
$(".current").next().addClass("current").show();
$(".current").prev().removeClass("current").hide();
});
$("#prev").click(function () {
$("#prev").show();
$("#one").hide();
$("#one").addClass("current");
$(".current").prev().addClass("current").show();
$(".current").next().removeClass("current").hide();
});
This works for certain navigation after that it gets messes up. Some guidance will be helpful to me and others.
Thanks
JSFIDDLE : http://jsfiddle.net/aVJBY/450/
I see you have an answer, but I would suggest a more structured approach that reuses a single code path:
http://jsfiddle.net/TrueBlueAussie/aVJBY/460/
function updateItems(delta)
{
var $items = $('#group').children();
var $current = $items.filter('.current');
var index = $current.index();
var newIndex = index+delta;
// Range check the new index
newIndex = (newIndex < 0) ? 0 : ((newIndex > $items.length) ? $items.length : newIndex);
if (newIndex != index){
$current.removeClass('current');
$current = $items.eq(newIndex).addClass('current');
// Hide/show the next/prev
$("#prev").toggle(!$current.is($items.first()));
$("#next").toggle(!$current.is($items.last()));
}
}
$("#next").click(function () {
updateItems(1);
});
$("#prev").click(function () {
updateItems(-1);
});
Notes:
The range capping can be simplified, but you get the idea.
You do not need to initial inline styling as that can be done in the CSS.
This is not limited in any way by the content. Here I added 6 more divs: http://jsfiddle.net/TrueBlueAussie/aVJBY/463/
Update
As I do not like situations where styling is required for initial "state" in a page, here is a new version that sets the initial state correctly too without any initial styling (using a 0 delta). I also removed a redundant var:
function updateItems(delta)
{
var $items = $('#group').children();
var $current = $items.filter('.current');
$current = $current.length ? $current : $items.first();
var index = $current.index() + delta;
// Range check the new index
index = (index < 0) ? 0 : ((index > $items.length) ? $items.length : index);
$current.removeClass('current');
$current = $items.eq(index).addClass('current');
// Hide/show the next/prev
$("#prev").toggle(!$current.is($items.first()));
$("#next").toggle(!$current.is($items.last()));
}
$("#next").click(function () {
updateItems(1);
});
$("#prev").click(function () {
updateItems(-1);
});
// Cause initial selection
updateItems(0);
JSFiddle: http://jsfiddle.net/TrueBlueAussie/aVJBY/468/
I am showing another approach where you can set the current item to any element, and it will show the next prev arrows accordingly.
$(function() {
var updateDiv = function(trigger) {
var currentDiv = $(".current");
$("#group div").removeClass("current").hide();
if (trigger.hasClass("next") && currentDiv.next("div").length > 0) {
currentDiv.next("div").addClass("current").show();
} else if (trigger.hasClass("prev") && currentDiv.prev("div").length > 0) {
currentDiv.prev("div").addClass("current").show();
}
updateNavigation();
};
var updateNavigation = function() {
var intialDiv = $(".current");
intialDiv.show();
var intialDivIndex = intialDiv.index();
intialDivIndex > 0 ? $("#prev").show() : $("#prev").hide();
intialDivIndex < totalDivs - 1 ? $("#next").show() : $("#next").hide();
};
var totalDivs = $("#group div").length;
updateNavigation();
$("#next, #prev").on("click", function() {
updateDiv($(this));
});
});
#group div {
border: 1px solid red;
width: 100px;
height: 100px;
}
#next {
margin-left: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div id="group">
<div id="one" style="display:none">one</div>
<div style="display:none" id="two">two</div>
<div style="display:none" id="three">three</div>
<div style="display:none" id="four" class="current">four</div>
<div style="display:none" id="five">five</div>
<div style="display:none" id="six">six</div>
<div style="display:none" id="seven">seven</div>
<div style="display:none" id="eight">eight</div>
</div>
<div id="next" style="display:none" class="next">next</div>
<div style="display:none" id="prev" class="prev">prev</div>
<div style="display:none" id="prev">SUBMIT</div>
I'd also like to suggest this approach though as I see the problem's been solved:
var $divs = $("#group").children("div"),
index = 0;
$("#next").click(function () {
updateStatus(1);
});
$("#prev").click(function () {
updateStatus(-1);
});
function updateStatus(a) {
$divs.eq(index).removeClass("current").hide();
index += a;
$divs.eq(index).addClass("current").show();
$("#next").toggle(index !== $divs.length - 1);
$("#prev").toggle(index !== 0);
}
Fiddle
Maybe help you below code.
Updated... again...
$( "#next" ).click(function() {
if($(".current").length!=1){
$( "#group:first-child" ).addClass("current");
}
$(".current").removeClass("current").hide().next().addClass("current").show();
if($(".current").next().length!=1){
$( "#next" ).hide();
}
$( "#prev" ).show();
});
$( "#prev" ).click(function() {
if($(".current").length!=1){
$( "#group:last-child" ).addClass("current");
}
$(".current").removeClass("current").hide().prev().addClass("current").show();
if($(".current").prev().length!=1){
$( "#prev" ).hide();
}
$( "#next" ).show();
});
Fiddle Updated
You should create a function to hide or show the prev and next buttons on click. You can use the .index() function of jQuery to check if the current div is the first or last item inside the div#group
$(function(){
var $cur = $('#group .current');
var $items = $('#group .item');
function hideButtons() {
$cur = $('#group .current');
var index = $cur.index();
if(index > 0) {
$('#prev').show();
} else {
$('#prev').hide();
}
if(index < $items.length - 1) {
$('#next').show();
} else {
$('#next').hide();
}
}
hideButtons();
$('#next').click(function(){
$cur.next().addClass('current');
$cur.removeClass('current');
hideButtons();
});
$('#prev').click(function(){
$cur.prev().addClass('current');
$cur.removeClass('current');
hideButtons();
});
});
.item {
display: none;
}
.item.current {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="group">
<div id="one" class="current item">one</div>
<div id="two" class="item">two</div>
<div id="three" class="item">three</div>
<div id="four" class="item">four</div>
</div>
<button id="next">next</button>
<button style="display:none" id="prev">prev</button>

How to toggle close all divs when another div is opened

I have a long streak of divs with the following structure:
<div id="income">
<h5 onclick="toggle_visibility('incometoggle');">INCOME</h5>
<div id="incometoggle">
<h6>Income Total</h6>
</div>
</div>
<div id="income2">
<h5 onclick="toggle_visibility('incometoggle2');">INCOME2</h5>
<div id="incometoggle2" style="display:none;">
<h6>Income Total2</h6>
</div>
</div>
<div id="income3">
<h5 onclick="toggle_visibility('incometoggle3');">INCOME3</h5>
<div id="incometoggle3" style="display:none;">
<h6>Income Total3</h6>
</div>
</div>
I have this code to make them open and close:
function toggle_visibility(id) {
var e = document.getElementById(id);
if (e.style.display == 'none') e.style.display = 'block';
else e.style.display = 'none';
}
At site load, the first div is opened, the rest is closed.
http://jsfiddle.net/txa2x9qq/3/
How can I make the first div close when the second one is opened, and so on - to have only one opened at a time?
Thank you
This way you just open the next on the close of the previus
function toggle_visibility(id,next) {
var e = document.getElementById(id);
if (e.style.display == 'none') e.style.display = 'block';
else e.style.display = 'none';
if (next != undefined)
{
toggle_visibility(next);
}
}
call it like:
<h5 onclick="toggle_visibility('incometoggle','incometoggle2');">INCOME</h5>
http://jsfiddle.net/txa2x9qq/3/
You can use jQuery Start with Selector to hide all div starting with incometoggle and use not() to exclude the current div
See below function
function toggle_visibility(id) {
var e = document.getElementById(id);
if (e.style.display == 'none') e.style.display = 'block';
else e.style.display = 'none';
// hide all div except current
$('div[id^=incometoggle]').not('#'+id).hide();
}
DEMO
EDIT - you can write whole logic in jQuery only, just bind click event to h5 elements and show / hide div next to it using toggle. And hide all div except current using jQuery Start with Selector
$(function() {
$('h5').click(function(){
var incomeDiv = $(this).next('div');
$(incomeDiv).toggle();
$('div[id^=incometoggle]').not(incomeDiv).hide();
});
});
DEMO Using JQuery
You can use jQuery more easily:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script>
function toggle_visibility(id) {
$("div[id^='incometoggle']").hide();
$('#'+id).show();
}
</script>
I would approach it slightly differently and use a class along with a jquery selector -
<div id="income">
<h5 onclick="toggle_visibility('incometoggle');">INCOME</h5>
<div id="incometoggle" class="income-total">
<h6>Income Total</h6>
</div>
</div>
...
function toggle_visibility(id) {
// hide all divs with class income-total
$('.income-total').hide();
// show the desired div
$('#' + id).show();
}
Using just Vanilla Javascript, like you're actually doing at the moment:
function toggle_visibility(id) {
// Your clicked element
var e = document.getElementById(id);
// List containing all the divs which id starts with incometoggle.
var allDivs = document.querySelectorAll('div[id^=incometoggle]');
// Loop through the list and hide the divs, except the clicked one.
[].forEach.call(allDivs, function(div) {
if (div != e) {
div.style.display = 'none';
}
else {
e.style.display = e.style.display == 'none' ? 'block' : 'none';
}
});
}
Demo
If you want to do in pure java script then this solution will work for you.
<div id="income">
<h5 onclick="toggle_visibility('incometoggle');">INCOME</h5>
<div id="incometoggle" class="income">
<h6>Income Total</h6>
</div>
</div>
<div id="income2">
<h5 onclick="toggle_visibility('incometoggle2');">INCOME2</h5>
<div id="incometoggle2" style="display:none;" class="income">
<h6>Income Total2</h6>
</div>
</div>
<div id="income3">
<h5 onclick="toggle_visibility('incometoggle3');">INCOME3</h5>
<div id="incometoggle3" style="display:none;" class="income">
<h6>Income Total3</h6>
</div>
</div>
function toggle_visibility(id) {
var e = document.getElementById(id);
var myClasses = document.querySelectorAll('.income'),
i = 0,
l = myClasses.length;
for (i; i < l; i++) {
myClasses[i].style.display = 'none';
}
if (e.style.display == 'none') e.style.display = 'block';
}
DEMO

Implementing colspan on DIVS

I have a div layout like this
Style
.l-item{
display:inline-block;
border:1px solid #CCC;
width:20px;
height:20px
}
<div id="head">
<div>
<div class="l-item">a</div>
<div class="l-item">a</div>
<div class="l-item">a</div>
<div class="l-item">a</div>
<div class="l-item">b</div>
<div class="l-item">b</div>
</div>
<div>
<div class="l-item">x</div>
<div class="l-item">y</div>
<div class="l-item">z</div>
<div class="l-item">z</div>
<div class="l-item">z</div>
<div class="l-item">x</div>
</div>
<div>
<div class="l-item">1</div>
<div class="l-item">2</div>
<div class="l-item">3</div>
<div class="l-item">4</div>
<div class="l-item">4</div>
<div class="l-item">4</div>
</div>
</div>
My requirement is to merge similar valued and sibling DIVS into single DIV as colspan. For that I have an approach like below
$('#head > div').each(function(){
$(this).find('.l-item').each(function(){
var txt = $(this).text();
$(this).siblings().filter(function(){
return $(this).text() == txt;
});
});
});
It seems like it will mess with the DOM, any other solution for this please..
Try this out:- http://jsfiddle.net/adiioo7/rnL3h/
JS:-
$('#head > div').each(function () {
$(this).find('.l-item').each(function () {
var txt = $(this).text();
var items = $(this).siblings().filter(function () {
return $(this).text() == txt;
});
if (items.length > 0) {
$(this).width($(this).width() * (items.length + 1));
items.remove();
}
});
});
Here's a little bit of help to get you started: http://jsfiddle.net/WeJmu
$('#head > div').each(function(){
$(this).find('.l-item').each(function(){
var txt = $(this).text();
var num_eaten = 0;
$(this).siblings().each(function () {
if ($(this).text() === txt) {
num_eaten++;
$(this).remove();
}
});
if (num_eaten > 0) {
$(this).width($(this).width() * (num_eaten + 1));
}
});
});
different approach with next, you can develop it with better way. demo
$('#head > div').each(function(){
$(this).find('.l-item').each(function(){
var txt = $(this).text();
if( $(this).next().text() == txt){
$(this).next().width($(this).next().width() + 20);
$(this).remove();
}
});
});
if by appearance you want consecutive divs with same text to look like a single div/column;
http://jsfiddle.net/WeJmu/2/
$('#head > div').each(function(){
$(".l-item").each(function(){
var $this=$(this);
var $next=$(this).next();
if( $this.text()==$next.text()){
$this.css({'border-right':'none'});
$next.css({'border-left':'none'});
}
});
});

Categories