remove class name using pure js - javascript

<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

Related

CSS: Error in Toggle Classes By using Class name

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>

hover over one div to show the nearest div of a certain class

i want to hover over one div and use jquery to find the nearest div by the name and to show that div.
<div class="entry">
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
</div>
all the .footer classes will be hidden but i want to make it so that when i over over the .body class, only the nearest .footer class shows. [ meaning : if i hover over the first .body class, only the first .footer will be shown. ]
my current code isn't working and i'm starting to wonder if it's something wrong with it.
current jquery code :
$('.footer').hide();
$('.body').hover(function(){
$(this).closest('.footer').find('.footer').show();
});
While the problem is the same as this question, the reason is slightly different.
When you use .closest(".class") it's the equivalent of .parents().filter(".class").first() (or .last(), I don't recall exactly which way parents() works as that's what closest is for).
ie it goes up the tree
So $(".body").closest(".entry") would give you an element for your HTML.
In this case, you want siblings, but more specifically the next one. There's a jquery method .next() which looks like it's correct, but as detailed in the link above, this only gives the very next one (in your HTML this would be the date div) even if a filter is applied - so $(this).next(".footer") would give an empty set (as it's not .date).
The work around is:
$(this).nextAll(".footer").first()
Once you get this working, your will find that your hover does not work as expected as the footers are not hiding again - as you're using .hover rather than mouseenter mouseout, you just need to move the .hide() call inside the second event handler, giving:
// startup
$(".footer").hide();
// event
$(".body").hover(function() {
$(this).nextAll(".footer").first().show();
}, function() {
$(".footer").hide();
});
div > div { width: 100px; height: 10px }
.body { border: 1px solid red; }
.date { border: 1px solid blue; }
.footer { border: 1px solid green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
</div>
$(this).closest('.footer')
You should start to use console.log() sometimes to check elements you would like to get. This does not find anything so nothing further to search and to show.
If you possibly can separate bodies and footers into containers you can do smth like
this.
Try to make use of nextUntil(".footer").next(); as below
$('.body').hover(function() {
$(this).nextUntil(".footer").next().show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
IF your html is gonna keep those triads layout, you don't need jQuery for it.
Just use CSS to select the second div after the .body on hover
div{width:100px; height:100px; background-color:lime; margin:10px; float:left}
.body{background:yellow; clear:left;}
.footer{display:none;}
.body:hover + div + div{
display:block;
background:red;
}
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
The answer by freedomn-m offered a good explanation and good solution in case you want the nearest NEXT .footer, which seems to be the case from your example HTML.
However, if you want your request strictly, so you want exact NEAREST .footer, then his solution will not work for you. And I don't think there is a jQuery built-in functionality that can give you that, so you'll have to do it manually. Get the list of the children of the parent (don't use the siblings as they don't include the current element) and go through the list to calculate the distance from your current element using the indexes and then select the .footer that is really the nearest.
$('.body').hover(function() {
var children = $(this).parent().children();
var index = children.index(this);
var closest = children.length;
var footer = -1;
children.each(function(i, child) {
if (i !== index && $(child).hasClass("footer")) {
var distance = Math.abs(index - i);
if (distance < closest) {
closest = distance;
footer = i;
}
}
});
if (footer > -1)
children.eq(footer).show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
If you don't care much about the performance, you can shorten the code a bit by selecting the list of .footer instead of the children of the parent, and then let jQuery give you the index of each of them. Not very efficient, but shorter code:
$('.body').hover(function() {
var index = $(this).index();
var closest = 9999;
var footer;
$(this).siblings(".footer").each(function(i, sibling) {
var distance = Math.abs(index - $(sibling).index());
if (distance < closest) {
closest = distance;
footer = sibling;
}
});
if (footer !== undefined)
$(footer).show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
Inspired by freedomn-m's comment, we can also use the .prevAll() and .nextAll() methods to get the previous and next .footer siblings. These two methords return the siblings ordered by the closest, so we simply pick the first one of each list, subtract their indexes from our element's index (to find the distance), compare them together, and return the closest. This solution is also less efficient than the first one, but you may find the code easier to read:
$('.body').hover(function() {
var me = $(this);
var prev = me.prevAll(".footer").first();
var next = me.nextAll(".footer").first();
if (prev.length == 0)
next.show();
else if (next.length == 0)
prev.show();
else {
index = me.index();
if (Math.abs(prev.index() - index) < Math.abs(next.index() - index))
prev.show();
else
next.show();
}
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>

Event handler for loop with dynamic jQuery selectors

What I want is to click on #bt-1 and change the color of #target-1, click on #bt-2 and change the color of #target-2...
I started writing a particular click event handler for each #bt-n / #target-n but as the site got bigger I thought about using a loop. My approach was using a for loop with variables in jQuery selectors. Here is my code:
$(document).ready(function() {
var total = $('.target').length;
for(n=1; n<=total; n++) {
var num = String(n);
$('#bt-'+num).on('click', function() {
$('#target-'+num).toggleClass('yellow');
});
}
});
.wrapper {
display: flex;
text-align: center;
}
.button, .target {
padding: 20px;
margin: 10px;
}
.button {
background: gray;
}
#target-1 {
background: red;
}
#target-2 {
background: green;
}
#target-3 {
background: blue;
}
.yellow {
background: yellow !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div id="bt-1" class="button">
<h1>Button 1</h1>
</div>
<div id="target-1" class="target">
<h1>Target 1</h1>
</div>
</div>
<div class="wrapper">
<div id="bt-2" class="button">
<h1>Button 2</h1>
</div>
<div id="target-2" class="target">
<h1>Target 2</h1>
</div>
</div>
<div class="wrapper">
<div id="bt-3" class="button">
<h1>Button 3</h1>
</div>
<div id="target-3" class="target">
<h1>Target 3</h1>
</div>
</div>
I don't understand why it only targets the last #target-n as the loop seems to be working on #bt-n. I also thought about using an array but can't figure out how to implement it.
I managed to make it work using $(this).siblings('.target')... which do not require the for loop and ids but a parent element for each .button / .target, in this case .wrapper Code Here. Although this was a good solution, I would like to understand what I did wrong and how to properly implement a loop to achieve this without using the parent .wrapper. Thank you.
The reason that only the last item gets affected is because the loop has completed before any event fires. Therefore n holds the last value in the loop. To fix this you need to use a closure:
for (n = 1; n <= total; n++) {
(function(n) {
$('#bt-' + n).on('click', function() {
$('#target-' + n).toggleClass('yellow');
});
})(n);
}
That said, a much better approach would be avoid the loop and to use DOM traversal to find the .target related to the clicked .button, like this:
$('.button').click(function() {
$(this).next('.target').toggleClass('yellow');
});
.wrapper {
display: flex;
text-align: center;
}
.button,
.target {
padding: 20px;
margin: 10px;
}
.button {
background: gray;
}
#target-1 {
background: red;
}
#target-2 {
background: green;
}
#target-3 {
background: blue;
}
.yellow {
background: yellow !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div id="bt-1" class="button">
<h1>Button 1</h1>
</div>
<div id="target-1" class="target">
<h1>Target 1</h1>
</div>
</div>
<div class="wrapper">
<div id="bt-2" class="button">
<h1>Button 2</h1>
</div>
<div id="target-2" class="target">
<h1>Target 2</h1>
</div>
</div>
<div class="wrapper">
<div id="bt-3" class="button">
<h1>Button 3</h1>
</div>
<div id="target-3" class="target">
<h1>Target 3</h1>
</div>
</div>
It is unwise to register a lot of event handlers. You can bind one event handler and perform action for given specific idx read from element id, eg:
$('body').on('click', function (event) {
if (!event.target.id.match(/^bt-\d+/)) {
return; //id of clicked element does not match bt-{number}
}
var idx = event.target.id.replace('bt-', ''); //remove prefix "bt-" and leave only numeric postfix
$('#target-' + idx).toggleClass('yellow');
});
Explanation:
When you bind click on body element You are getting access to all click events from child elements that not cancelled passing that event up. Element that has been clicked in saved inside event.target and it has property id in event.target.id.
On this id property I call match function with regular expression - it will match string which starts ^ from bt- and have any number \d at least one one + .
if (!event.target.id.match(/^bt-\d+/)) {
return; //id of clicked element does not match bt-{number}
}
There is negation of this statement, so If this id is not in format bt-someNumber it will not go further.
var idx = event.target.id.replace('bt-', '');
Than takes id and replaces bt- part in it with empty string ''
$('#target-' + idx).toggleClass('yellow');
Finally You are toggling class on element with same number as button but with different prefix target- instead of bt-.
Happy hacking!

Using jQuery '.eq()' with multiple classes

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/

CSS/JS: Targeting :nth-child consistant across 2 parent elements?

Let's say we have a setup like this:
.col:nth-child(2n+1) {
background: red;
}
/* Style the div's for testing */
div.row {
width: 100%;
border: 1px solid blue;
}
div.col {
padding: 12px 0;
width: 100%;
}
<div class="row"><!-- The .col's in this row are dynamically generated -->
<div class="col 1"></div>
<div class="col 2"></div>
<div class="col 3"></div>
<div class="col 4"></div>
<div class="col 5"></div>
</div>
<div class="row">
<div class="col 1"></div>
<div class="col 2"></div>
<div class="col 3"></div>
<div class="col 4"></div>
</div>
Here's a working Fiddle: https://jsfiddle.net/1L4rodh4/
Now... the Nth selector is working as it should. The problem is that I want to get the elements styled consistently. so that it appears to be seamless between the 2 .row's. The .col's in the first .row are dynamically generated and could end up being even or odd.
Please ask me for clarification if I wasn't clear. I couldn't find any information about this elsewhere. This is something that seems so simple, yet it seems to be impossible.
Is there a better way of doing this, or am I stuck?
I understand I could use JS to get the number of "col"'s in the first "row" and change the selector in the second row. That just seems way too hack-ish for this though.
EDIT: I will accept a JS solution.
The following is a working example of how this can be done with a simple plain JS script, based on the code in the selected answer below.
var cols = document.querySelectorAll('.table.js-fix .tr');
for (var i = 0; i < cols.length; i++) {
cols[i].classList.add(i % 2 == 0 ? 'even' : 'odd');
}
.table.js-fix .tr:nth-child(2n + 1), /* :nth-child fallback */
.table.js-fix .tr.even {
background: red;
}
.table.js-fix .tr.odd {
background: #fff;
}
/* Style for testing */
.table {
width: 100%;
border: 1px solid blue;
}
.tr {
padding: 12px 0;
width: 100%;
}
<div class="row"><!-- The .tr in this row is just used as a thead -->
<div class="col">
<div class="table">
<div class="tr">Section Title</div>
</div>
</div>
</div>
<div class="row"><!-- The .tr's in this row are dynamically generated -->
<div class="col">
<div class="table js-fix">
<div class="tr"></div>
<div class="tr"></div>
<div class="tr"></div>
</div>
</div>
</div>
<div class="row"><!-- There will always be 5 .tr's in this row -->
<div class="col">
<div class="table js-fix">
<div class="tr"></div>
<div class="tr"></div>
<div class="tr"></div>
<div class="tr"></div>
<div class="tr"></div>
</div>
</div>
</div>
JSFiddle with the above example: https://jsfiddle.net/n12h70j6/
You can do that with CSS.
See this or this.
.col:first-child:nth-last-child(even) ~ .col:nth-child(2n + 1),
.col:first-child:nth-last-child(even){
background-color: red;
}
.col:first-child:nth-last-child(odd) ~ .col:nth-child(2n + 2){
background-color: red;
}
This checks if the number of children are even or odd and styles them appropriately.
Update: Inspite of what it might look like. This will not work for cases when a parent with odd number of children directly follows another parent with odd number of children (which was the whole point). However I am leaving this here for someone else to get ideas running in their heads.
Since it is still an answer, CSS alone cannot do this, so one must resort to javascript / jQuery.
This could be one way to do this with plain JS
var cols = document.querySelectorAll('.col');
for(var i = 0; i < cols.length; i++)
cols[i].classList.add(i % 2 == 0 ? 'some-class' : 'alternate-class');
No, there is no CSS-only way of doing this.
The reason is that CSS rules can only be qualified based on directly preceding children, or ancestors. In you case, you want to qualify the second group based on what is inside the previous sibling (the first <div> group).
The only way to handle this is by means of something like adding a class to the first <div> that indicates whether it has an even or odd number of children.

Categories

Resources