Javascript - Toggle Multiple Classes onclick - javascript

I am trying to toggle multiple classes onclick using vanilla Javascript. What i am trying to do is when a btn is clicked two classes to toggle with another two classes. I have 5 classes in total which are: .menu_btn , .main_nav, .btn_active, .container, .container_active. When i press the .menu_btn i would like the classes .main_nav to toggle with .btn_active and at the same time i would like to have the .container to toggle with .container_active. The class .container is the only one that has 5 elements of that class, the others are single. I have done this using jQuery but i would like to know the way using vanilla Javascript. Hopefully someone can help.
One thing to point out is when i console.log the .btn_active and .container_active i get back [ ] an empty array. Those 2 css classes are not assigned to any element of my project. They are existing only in the css and their purpose is for toggle.
Thanks
jQuery Code:
$(function(){
$(".menu_btn").on("click", function(){
$(".main_nav").toggleClass("btn_active");
$(".container").toggleClass("container_active");
});
});
Vanilla Javascript Code:
var menuBtn = document.getElementsByClassName("menu_btn");
var mainNav = document.getElementsByClassName("main_nav");
var btnActive = document.getElementsByClassName("btn_active");
var container = document.getElementsByClassName("container");
var containerActive = document.getElementsByClassName("container_active");
menuBtn.onclick = function(){
mainNav.classList.toggle(btnActive);
for ( index = 0; index <= container.lenght -1; index++ ){
container[index].classList.toggle(containerActive);
}
};

I have modified your script and created a fiddle so you see how it works: https://jsfiddle.net/eyrpdsc2/
The toggle accepts a string as a parameter, not a Node. So you need to pass 'btn_active' instead of btnActive. Also keep in mind that querySelectorAll returns a NodeList (not an array) so you cannot use forEach.
var menuBtn = document.querySelectorAll(".menu_btn");
var mainNav = document.querySelectorAll(".main_nav");
var container = document.querySelectorAll(".container");
for (var i = 0; i < menuBtn.length; ++i) {
menuBtn[i].addEventListener('click', toggleClasses);
}
function toggleClasses() {
var i = 0;
for (i = 0; i < mainNav.length; ++i) {
mainNav[i].classList.toggle('btn_active');
}
for (i = 0; i < container.length; ++i) {
container[i].classList.toggle('container_active');
}
}

Related

Remove class based on elements but not others

I have these sections on this side scrolling site. And want to add a class which will change styling depending if you're on a certain section.
I'm working on this function. The top is what determines the section of the side scroller you are viewing.
The let variables and below is where it stops working. I'm trying to have it so if a nonHome ID section is clicked, for example "slide-1", then add the class 'nav-visibilty'. If they are a match "slide-2" and "slide-2" then remove said class. Am I close?
https://codepen.io/mikayp-the-styleful/pen/NWPxoXR?editors=1111
setTimeout(function(){
for (i=0; i < nonHome.length; i++ ){
if (nonHome[i].id != nonHomeID){
nonHome[i].classList.add("nav-visibility");
console.log('add')
} else{
nonHomeID.classList.remove("nav-visibility");
console.log('rem')
}
}
I am still not totally clear on the behavior that you want, but there are two errors in the code that can be fixed:
It seems like you are always using 'slide-2' instead of the slideId in your event handler.
As mentioned in a comment, nonHomeID is being used incorrectly in your comparison (it is either a string or an element, but you are using it as if it was a string in the if condition, and as the element in the else branch.) Here I have kept it as an element and renamed it for clarity.
Fixing these errors results in code that applies the nav-visibility class to all slides except the one selected by the button. Is that the desired behavior?
let nonHome = document.querySelectorAll(".slide-container section");
let nonHomeSelected = document.getElementById(slideId);
var i;
setTimeout(function() {
for (i = 0; i < nonHome.length; i++) {
if (nonHome[i] != nonHomeSelected) {
nonHome[i].classList.add("nav-visibility");
console.log("add");
} else {
nonHome[i].classList.remove("nav-visibility");
console.log("rem");
}
}
}, 1000);
Edit to add: If the goal is to add nav-visibility to all only the specific slideId, you should not be adding in a loop, i.e. you need to pull your check for whether the slide is Home outside the loop. There are conceptually two steps here: remove the class from all elements that are no longer to have it, then add the class to the element that needs it.
let slideToAddVisibilityTo = document.getElementById(slideId)
let homeSlide = document.getElementById('slide-2')
let allSlides = document.querySelectorAll(".slide-container section")
for (let i = 0; i < allSlides.length; ++i)
allSlides[i].classList.remove('nav-visiblity')
if (slideToAddVisibilityTo != homeSlide)
slideToAddVisibilityTo.classList.add('nav-visibility')
Just hide them all, then show the clicked one:
function showSection(id) {
var sections = document.getElementsByTagName("section");
for(var i=0; i<sections.length; i++) sections[i].classList.remove("nav-visibility");
var current = document.getElementById(id);
current.classList.add("nav-visibility");
}
Example: showSection("foo") will remove nav-visibility from all sections, then add it to the section with id foo.

Dynamical Calculator Javascript

It is a calculator which has spans from which I want to take a values(1,2,3, etc.) and two fields: First for displaying what user is typing and the second is for result of calculation.
The question how to get values so when I click on spans it will show it in the second field
Here is the code.
http://jsfiddle.net/ovesyan19/vb394983/2/
<span>(</span>
<span>)</span>
<span class="delete">←</span>
<span class="clear">C</span>
<span>7</span>
<span>8</span>
<span>9</span>
<span class="operator">÷</span>
....
JS:
var keys = document.querySelectorAll(".keys span");
keys.onclick = function(){
for (var i = 0; i < keys.length; i++) {
alert(keys[i].innerHTML);
};
}
var keys = document.querySelectorAll(".keys span");
for (var i = 0; i < keys.length; i++) {
keys[i].onclick = function(){
alert(this.innerHTML);
}
}
keys is a NodeList so you cannot attach the onclick on that. You need to attach it to each element in that list by doing the loop. To get the value you can then simple use this.innerHTML.
Fiddle
This should get you started.. you need to get the value of the span you are clicking and then append it into your result field. Lots more to get this calculator to work but this should get you pointed in the right direction.
Fiddle Update: http://jsfiddle.net/vb394983/3/
JavaScript (jQuery):
$(".keys").on("click","span",function(){
var clickedVal = $(this).text();
$(".display.result").append(clickedVal);
});
You can set a click event on the span elements if you use JQuery.
Eg:
$("span").click(
function(){
$("#calc").val($("#calc").val() + $(this).text());
});
See:
http://jsfiddle.net/vb394983/6/
That's just to answer your question but you should really give the numbers a class such as "valueSpan" and the operators a class such as "operatorSpan" and apply the events based on these classes so that the buttons behave as you'd expect a calculator to.
http://jsfiddle.net/vb394983/7/
var v="",
max_length=8,
register=document.getElementById("register");
// attach key events for numbers
var keys = document.querySelectorAll(".keys span");
for (var i = 0; l = keys.length, i < l; i++) {
keys[i].onclick = function(){
cal(this);
}
};
// magic display number and decimal, this formats like a cash register, modify for your own needs.
cal = function(e){
if (v.length === self.max_length) return;
v += e.innerHTML;
register.innerHTML = (parseInt(v) / 100).toFixed(2);
}
Using JQuery will make your life much easier:
$('.keys span').click(function() {
alert(this.innerHTML);
});

How do I filter an unorderded list to display only selected items using Javascript?

I have this JSFiddle where I am trying to make it so that the items in an unordered list are visible only if the option selected in a drop down matches their class. List items may have multiple classes, but so long as at least one class matches, the item should be made visible.
The Javascript looks like this:
function showListCategories() {
var selection = document.getElementById("listDisplayer").selectedIndex;
var unHidden = document.getElementsByClassName(selection);
for (var i = 0; i < unHidden.length; i++) {
unHidden[i].style.display = 'visible';
}
};
The idea is that it gets the current selection from the drop down, creates an array based on the matching classes, then cycles through each item and sets the CSS to be hidden on each one.
However, it's not working. Can anyone tell me where I'm going wroing?
Note that I haven't yet coded the "show all" option. I think I'll probably be able to figure that out once I have this first problem solved.
In your fiddle change load script No wrap - in <head>.
Just change your function like following
function showListCategories() {
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
lis[i].style.display = 'none';
}
//above code to reset all lis if they are already shown
var selection = document.getElementById("listDisplayer").value;
lis = document.getElementsByClassName(selection);
for (var i = 0; i < lis.length; i++) {
lis[i].style.display = 'block';
}
};
and in css it should be none not hidden
.cats, .rats, .bats {
display: none;
}
If you want to show all li when showAll is selected, add all classes to all lis.
You have a few things going on. First, your fiddle is not setup correctly, if you open the console you'll see:
Uncaught ReferenceError: showListCategories is not defined
This means that the function doesn't exist at the point you attach the event or that the function is out of scope, because by default jsFiddle will wrap your code in the onLoad event. To fix it you need to load the script as No wrap - in <body>.
Second, there's no such thing as a display:visible property in CSS. The property you want to toggle is display:none and display:list-item, as this is the default style of <li> elements.
Now, to make this work, it is easier if you add a common class to all items, let's say item, that way you can hide them all, and just show the one you want by checking if it has a certain class, as opposed to querying the DOM many times. You should cache your selectors, it is not necessary to query every time you call the function:
var select = document.getElementById('listDisplayer');
var items = document.getElementsByClassName('item');
function showListCategories() {
var selection = select.options[select.selectedIndex].value;
for (var i=0; i<items.length; i++) {
if (items[i].className.indexOf(selection) > -1) {
items[i].style.display = 'list-item';
} else {
items[i].style.display = 'none';
}
}
}
Demo: http://jsfiddle.net/E2DKh/28/
First there is no property in Css like display:hidden; it should be display: none;
here is the solution please not that i am doing it by targeting id finished
Js function
var selection = document.getElementById("listDisplayer");
var list = document.getElementsByTagName('li');
selection.onchange = function () {
var value = selection.options[selection.selectedIndex].value; // to get Value
for (var i = 0; i < list.length; i++) {
if (list[i].className.indexOf(value) > -1) {
list[i].style.display = "list-item";
} else {
list[i].style.display = "none"
}
}
}
css Code
.cats, .rats, .bats {
display: none;
}
JSFIDDLE
You have many things wrong in your code and a wrong setting in the jsFiddle. Here's a working version that also implements the "all" option:
Working demo: http://jsfiddle.net/jfriend00/5Efc5/
function applyToList(list, fn) {
for (var i = 0; i < list.length; i++) {
fn(list[i], list);
}
}
function hide(list) {
applyToList(list, function(item) {
item.style.display = "none";
});
}
function show(list) {
applyToList(list, function(item) {
item.style.display = "block";
});
}
function showListCategories() {
var value = document.getElementById("listDisplayer").value;
var itemList = document.getElementById("itemList");
var items = itemList.getElementsByTagName("li");
if (value === "all") {
show(items);
} else {
// hide all items by default
hide(items);
show(itemList.getElementsByClassName(value));
}
}
Changes made:
You have to fetch the .value of the select to see what the value was of the option that was picked. You were using the selectedIndex which is just a number.
A common technique for displaying only a set of objects is to hide all of them, then show just the ones you want. Since the browser only does one repaint for the entire operation, this is still visually seamless.
When finding items that match your class, you should be searching only the <ul>, not the entire document. I added an id to that <ul> tag so it can be found and then searched.
To save code, I added some utility functions for operating on an HTMLCollection or nodeList.
Tests for the "all" option and shows them all if that is selected
Changed the jsFiddle to the Head option so the code is available in the global scope so the HTML can find your change handler function.
Switched style settings to "block" and "none" since "visible" is not a valid setting for style.display.

JS call code block upon clicking one of many items with specific class

I have a page with a bunch of buttons that all have a class (actually two classes, each separated by a space; I can use either or both). I need to call a function or a block of code (let's say an alert for this example) when the user clicks one of these buttons with this class. I do not have access to the HTML so the link itself can't call the function. I don't need to know which button. How do I do this with pure JavaScript (no jQuery)?
you can do something like this:
var btns = document.getElementsByClassName('test');
for (var i = 0; i < btns.length; i++){
btns[i].onclick = function(){
alert(this.innerHTML)
}
}
demo
Just loop through each one by class and bind the event handler.
var elems = document.getElementsByClassName('cls');
for(var i = 0; i < elems.length; i++) {
elems[i].onclick = function() {
alert('Clicked');
};
}

Use javascript to add a CSS class to all elements with another class name

I am trying to use javascript to add a Class to all elements with a different Class. I know you might think this is redundant but for the situation i am in it is needed. i need a way to look though all elements with that class name and add the class but I don't understand how to get a count? I am working with a cms to where I cannot change the styling in the class it self.
$(document).ready(function () {
var ClassBtn = document.getElementsByClassName("buttonSubmit");
ClassBtn.className = ClassBtn.className + " btn";
});
Since it appears you are using jQuery:
Live Demo
$(document).ready(function () {
$('.buttonSubmit').addClass('btn');
});
Without jQuery:
Live Demo
window.onload = function() {
var buttons = document.getElementsByClassName("buttonSubmit"),
len = buttons !== null ? buttons.length : 0,
i = 0;
for(i; i < len; i++) {
buttons[i].className += " btn";
}
}

Categories

Resources