i am trying to toggle classes by using class name.
My code is working fine when i am toggling using id.
how can i make it work only one red should be visible at one time.
function hideshowmenu() {
var element = document.getElementsByClassName("box");
element.classList.toggle("bg-red");
}
.bg-red {
margin-top: 10px;
background-color: red;
height: 20px;
}
<div class="mainmenu " onclick="hideshowmenu()">RED1</div>
<div id="submenu" class="submenu">
<div class="mainmenu " onclick="hideshowmenu()">RED2</div>
<div id="box" class="box"> </div>
</div>
As the name of getElementsByClassName suggest, it returns elementS, so you are getting HTMLCollection, not one element. Query the first one, like this:
function hideshowmenu() {
var element = document.getElementsByClassName("box")[0];
element.classList.toggle("bg-red");
}
or:
function hideshowmenu() {
var elements = document.getElementsByClassName("box");
elements[0].classList.toggle("bg-red");
}
What is returned by document.getElementsByClassName("box"); is a collection. You need to specify the index to access the classList property.
You are doing:
var element = document.getElementsByClassName("box");
element.classList.toggle("bg-red");
When you should be doing
var element = document.getElementsByClassName("box");
element[0].classList.toggle("bg-red");
You could also loop through the elements if you want to toggle multiple values.
Example code fiddle
https://jsfiddle.net/agy5jtb0/1/
getElementsByClassName("box") return a collection of elements, but you considered it as a single element that is your mistake.
I suggest something like this:
html:
<div class="mainmenu " onclick="hideshowmenu(this)">RED1</div>
<div id="submenu" class="submenu">
<div class="mainmenu" onclick="hideshowmenu(this)">RED2</div>
<div id="box" class="box"></div>
</div>
js:
function hideshowmenu(el) {
el.classList.toggle("bg-red");
}
Check this (not sure If is this what you need):
function hideshowmenu() {
var elements = document.getElementsByClassName("box");
for (let a of elements) {
a.classList.toggle("bg-red");
}
}
.bg-red{
margin-top:10px;
background-color:red;
height:20px;
}
<div class="mainmenu " onclick="hideshowmenu(this)">RED1</div>
<div id="submenu" class="submenu">
<div class="mainmenu" onclick="hideshowmenu(this)">RED2</div>
<div id="box" class="box"></div>
</div>
Related
I have a set of div elements inside a container, .div-to-hide is displayed by default whilst .div-to-show is hidden.
When I click in .set, .div-to-hide should hide and .div-to-show should be visible. Next click should return the previous clicked element to its default state.
I need to display to buttons on click inside on .div-to-show.
<div class="container">
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
</div>
So far I have this:
let lastClicked;
$('.container').on('click', function(e) {
if (this == lastClicked) {
lastClicked = '';
$('.div-to-hide').show();
$(this).children('.div-to-hide').hide();
} else {
lastClicked = this;
$('.div-to-hide').hide();
$(this).children('.div-to-hide').show();
$(this).children('.div-to-show').hide();
}
});
Can't get it to work properly tho.. I don't know what I am missing...
Any help is deeply appreciated!
UPDATE: got it working! Thanks everyone!
First, you are not using delegation (second parameter on the $.on() function) to define the .set element as your this inside the function.
If I understood correctly, you want to show the elements on the last one clicked and hide the rest. You don't really need to know which one you last clicked to do that
$('.container').on('click', '.set', function (e) {
// Now "this" is the clicked .set element
var $this = $(this);
// We'll get the children of .set we want to manipulate
var $div_to_hide = $this.find(".div-to-hide");
var $div_to_show = $this.find(".div-to-show");
// If it's already visible, there's no need to do anything
if ($div_to_show.is(":visible")) {
$div_to_hide.show();
$div_to_show.hide();
}
// Now we get the other .sets
var $other_sets = $this.siblings(".set");
// This second way works for more complex hierarchies. Uncomment if you need it
// var $other_sets = $this.closest(".container").find(".set").not(this);
// We reset ALL af them
$other_sets.find(".div-to-show").hide();
$other_sets.find(".div-to-hide").show();
});
Consider using class toggling instead.
$('.set').on('click', function(e) {
$('.set').removeClass('hidden-child');
$(this).addClass('hidden-child');
});
css:
.hidden-child .div-to-hide, .div-to-show {
display: none;
}
.hidden-child .div-to-show, .div-to-hide {
display: block;
}
This will make your code easier to reason about, and lets css control the display (style) rules.
Edit: changed class name for clarity; expanded explanation; corrected answer to conform to question
Try to make use of siblings() jQuery to hide and show other divs and toggle() jQuery to show and hide itself and also you will need to set click() event on .set, not in .container
$(document).on('click', '.set', function(e) {
$(this).find('.hide').toggle();
$(this).find('.show').toggle();
$(this).siblings('.set').find('.hide').show();
$(this).siblings('.set').find('.show').hide();
});
.show {
display: none;
}
.set div {
padding: 10px;
font: 13px Verdana;
font-weight: bold;
background: red;
color: #ffffff;
margin-bottom: 10px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="set">
<div class="hide">1 Hide</div>
<div class="show">1 Show</div>
</div>
<div class="set">
<div class="hide">2 Hide</div>
<div class="show">2 Show</div>
</div>
<div class="set">
<div class="hide">3 Hide</div>
<div class="show">3 Show</div>
</div>
</div>
so the problem I have is quite simple.
I have a span <span class=""spDetails>Show More</span> and with this element I am expanding a section to show more text.
The problem I have is that I want to use this function in other sections of the page.
This is the jquery code which I am using to toggleClass active.
$(".spDetails").click(function() {
$(".divFees").toggleClass("feesActive");
});
My question is: I don't want to write this line of code for every element using this toggle, is there a way to create this for multiple elements with different class names or IDs? Thanks.
Right, so here is my HTML: (shortened version!)
<div id="optionOne" class="elementOne">
<div class="divFees">
<p>Text Text</p>
</div>
<span class="showMore">Show More</span>
</div>
<div id="optionTwo" class="elementTwo">
<div class="divFees">
<p>Text Text</p>
</div>
<span class="showMore">Show More</span>
</div>
I m trying to hide and display <div class="divFees"></div> only when there child <span> is clicked.
You can just append your desired elements in the selector using ,.
$(".divFees , .otherOnes , #otherOneWithId").toggleClass("feesActive");
If the toggleable section comes after the toggling span :
$(".spDetails").on("click", function(e) {
$(this).next().toggleClass("active");
});
[id*='div'] {
height: 60px;
background: #f2f2f2;
border: #f6f6f6;
}
.active {
background: #555555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<span class="spDetails" data-toggle="#div1">Toggle 1</span>
<div id="div1"></div>
<span class="spDetails" data-toggle="#div2">Toggle 2</span>
<div id="div2"></div>
</section>
Or with extra attributes to specify the target:
$(".spDetails").on("click", function(e) {
var target = $($(this).data("toggle"));
target.toggleClass("active");
});
[id*='div'] {
height: 60px;
background: #f2f2f2;
border: #f6f6f6;
}
.active {
background: #555555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<span class="spDetails" data-toggle="#div1">Toggle 1</span>
<div id="div1"></div>
<span class="spDetails" data-toggle="#div2">Toggle 2</span>
<div id="div2"></div>
</section>
I imagine two ways:
Easy way:
Make function with args for your event. Example:
function setToogleClass(button, toggleElement, toggleClass) {
$('.' + button).click(function() {
$('.' + toggleElement).toggleClass(toggleClass);
});
}
setToggleClass("spDetails", "divFees", "feesActive")
Hard way:
Set event function by all classes who has className and who found child or parent or current elements.
function initToggleEvents() {
var toggleButtons = $('toggle-button');
var activeClassName = 'toggle-active';
toggleButtons.forEach(function(toggleButton) {
toggleButton.click(function(event) {
// if event.target has parentNode that toggleClass(activeClassName)
// else another rules
}
}
}
How can I properly use the 'eq' function on multiple classes? Because, the div's with class 'a' are not subsequent, I cannot use the 'eq' function to updated their class. If the divs with class "b", are removed, the function works perfectly. Here's a fiddle https://jsfiddle.net/9w8zhg7d/4/. I have the following HTML:
<div class="a current">
</div>
<div class="a">
</div>
<div class="b">
</div>
<div class="b">
</div>
<div class="a">
</div>
<div class="a">
</div>
and the following javascript:
Class = {
a: ".a",
highlighted: ".a.current",
init: function() {
$(this.a).click(this.toggleA.bind(this));
},
toggleA: function(e) {
e.preventDefault();
$(this.highlighted).removeClass("current");
var target = $(e.target);
var clickedA = target.closest(this.a);
var clickedIndex = clickedA.index();
$(".a").eq(clickedIndex).addClass("current");
console.log(clickedIndex);
$(".b").eq(clickedIndex).css("display", "inline-block");
}
};
Class.init();
Any help is much appreciated!
If I understand your question correctly, you want to know the index of the particular .a element that was clicked, ignoring all other elements. If so you just have to use the .index() method correctly:
var clickedIndex = $(this.a).index(e.target);
When you call .index() with no arguments as in your code, it finds the index of the first element in the jQuery object relative to its siblings, not relative to other elements in the jQuery object. The code I've shown says to first select all of the .a elements, then within those elements only figure out the position of the e.target element.
You've also overcomplicated the setting of the current class - it doesn't make sense to use .closest(), because that is for navigating up through the DOM and all of your elements are siblings. You can just say:
$(e.target).addClass("current");
I don't understand how you want to apply the index of the clicked .a element to the .b elements, because there are four .a's and only two .b's, but still putting what I've said above together with your code gives something like this:
Class = {
a: ".a",
highlighted: ".a.current",
init: function() {
$(this.a).click(this.toggleA.bind(this));
},
toggleA: function(e) {
e.preventDefault();
$(this.highlighted).removeClass("current");
var target = $(e.target).addClass("current");
var clickedIndex = $(this.a).index(e.target);
console.log(clickedIndex);
$(".b").removeClass("current").eq(clickedIndex).addClass("current");
$(".c").removeClass("current").eq(clickedIndex).addClass("current");
}
}
Class.init();
.a,.b { width:50px; height:50px; background:black; display:inline-block; }
.c { width:20px; height:20px; background:blue; display:inline-block; }
.a.current{ background:red; }
.c.current, .b.current{ background:green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="a current"></div>
<div class="a"></div>
<div class="b"></div>
<div class="b"></div>
<div class="a"></div>
<div class="a"></div>
<div class="related">
<div class="c"></div> <div class="c"></div> <div class="c"></div> <div class="c"></div>
</div>
(Or an updated version of your fiddle: https://jsfiddle.net/9w8zhg7d/8/)
Okay, I feel like the solution you're proposing may be overcomplicated. Have you considered this solution?
HTML:
<div class="container">
<div class="a current"></div>
<div class="a"></div>
<div class="b"></div>
<div class="b"></div>
<div class="a"></div>
<div class="a"></div>
</div>
CSS:
.container {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.container > div {
width:50px;
margin: 1em;
height:50px;
background:black;
}
.a.current{
background:red;
}
Javascript:
$('.container > div').on('click', function() {
$('.container > div').removeClass("current");
$(this).addClass('current')
});
This will just apply .current to the one clicked and while removing it from all. Targeting the parent allows you to have that functionality without needing to work with the class specificity of the children div's.
JsFiddle: https://jsfiddle.net/9w8zhg7d/7/
I have 3 divs with the same class (i can't use IDs on them). I find all of them by targeting their class and then - on click - i want to apply some stuff (e.g. change background-color). i only managed to change all of them, but not only the one i'm actually clicking. what am i missing?
var thisDiv = $('.thisDiv');
thisDiv.click(function() {
var i = thisDiv.index(this);
console.log(i);
console.log(thisDiv.css('background-color'));
// this changes all of the div, not only the clicked one
thisDiv.css('background-color', 'red');
// console msg for the code below: Uncaught TypeError: thisDiv[i].css is not a function
// thisDiv[i].css('background-color', 'red');
// i also tried these, which didn't work...
//console.log(thisDiv[i].css('background-color'));
//console.log(thisDiv.eq[i].css('background-color'));
});
.thisDiv{width:50px;height:50px;background-color:lightgrey;float:left;margin:15px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="thisDiv">div 0</div>
<div class="thisDiv">div 1</div>
<div class="thisDiv">div 2</div>
use $(this) will give you the div which you have clicked
$(this).css('background-color', 'red');
use .eq():
thisDiv.eq(i)
as thisDiv is a collection of objects, you can get the specific ones with $(this) or .eq(i).
var thisDiv = $('.thisDiv');
thisDiv.click(function() {
var i = thisDiv.index(this);
thisDiv.eq(i).css('background-color', 'red');
});
.thisDiv {
width: 50px;
height: 50px;
background-color: lightgrey;
float: left;
margin: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="thisDiv">div 0</div>
<div class="thisDiv">div 1</div>
<div class="thisDiv">div 2</div>
<div class="wrap">
</div>
my css
.wrap{
overflow-x:hidden;
}
should I do like this in js?
document.getElementById("whatever").className = "";
where to get the id in this case? since I use .wrap not #wrap.
I think you're looking for the DOM function getElementByClassName().
For example, if you run var x = document.getElementByClassName('wrap') in your case, x will be a list of all dom elements which have the class 'wrap' .
source: w3schools
Your question is a bit confusing, but to give you an easy example, have a look at this:
var divs = document.getElementsByClassName('wrap');
for (var i=0; i<divs.length; i++) {
divs[i].addEventListener('click', removemyclass);
}
function removemyclass () {
this.className = '';
}
.wrap {
height:50px;
width: 100%;
border: 2px solid #aaa;
}
<div class="wrap">
</div>
<div class="wrap">
</div>
<div class="wrap">
</div>
<div class="wrap">
</div>
<div class="wrap">
</div>
<div class="wrap">
</div>
<div class="wrap">
</div>
This will find the one ( this ) element you are clicking on and remove its class Name, so that it doesn't have a border anymore, but you can still find it in your console as an element in the DOM