JavaScript If and else statement w/function calls not producing expected result - javascript

I have a mobile menu that includes four list items. When you click on the "Features" list item, another unordered list is supposed to populate below it, and when you click it again, it's supposed to close it.
Here's my issue:
Inside the addEventListener function, I am calling two other functions (displayType and displayTypeCheck) inside the if, and else statement. When I do this and click on the "Features" list item, it opens but does not close when I click it again.
If I don't use the displayType and displayTypeCheck functions in the if and else statement and click on the "Features" list item, the UL will both open and close.
Why does the if and else statement that calls the other two functions not work, and how do I get it to work?
In the provided Javascript code below, the if and else statement that's commented out works, and the block that's not commented out is the code that doesn't entirely work.
const menuIcon = document.querySelector(".mobile-menu-icon");
const mobileMenu = document.querySelector(".mobile-menu");
const closeMenuIcon = document.querySelector(".close-menu-icon");
const featuresMobile = document.querySelector(".features-mobile");
const featuresMobileDropdown = document.querySelector(".features-mobile-dropdown");
const overlay = document.querySelector(".overlay");
function displayType(element, displayValue) {
element.style.display = displayValue;
}
function displayTypeCheck(element, displayValue) {
element.style.display === displayValue;
}
menuIcon.addEventListener("click", function () {
displayType(mobileMenu, 'block');
displayType(overlay, 'block');
});
closeMenuIcon.addEventListener("click", function () {
displayType(mobileMenu, 'none');
displayType(overlay, 'none');
});
featuresMobile.addEventListener("click", function () {
// if (featuresMobileDropdown.style.display === "block") {
// featuresMobileDropdown.style.display = "none";
// } else {
// featuresMobileDropdown.style.display = "block";
// }
if (displayTypeCheck(featuresMobileDropdown, "block")) {
displayType(featuresMobileDropdown, "none");
} else {
displayType(featuresMobileDropdown, "block");
}
});
#import url("https://fonts.googleapis.com/css2?family=Epilogue:wght#500;700&display=swap");
:root {
--almostWhite: hsl(0, 0%, 98%);
--mediumGray: hsl(0, 0%, 41%);
--almostBlack: hsl(0, 0%, 8%);
--navDropDownColor: #e9ecef;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
list-style: none;
}
body {
min-height: 100vh;
font-family: "Epilogue", sans-serif;
background-color: var(--almostWhite);
}
header {
padding: .9375rem 2.5rem .9375rem 2.5rem;
max-width: 100rem;
margin: auto;
}
header nav {
display: flex;
align-items: center;
justify-content: flex-end;
}
header nav ul li {
cursor: pointer;
}
.register {
border: .125rem solid var(--mediumGray);
padding: .625rem .9375rem;
border-radius: .8125rem;
}
.mobile-menu-icon {
height: 3.125rem;
}
.mobile-menu-icon {
display: block;
cursor: pointer;
}
.mobile-menu .mobile-nav-links {
margin-top: 4.375em;
padding-left: .9375em;
color: var(--mediumGray);
}
.mobile-menu ul li {
padding: .625em;
}
.mobile-menu .mobile-nav-links li ul {
margin-left: .625em;
margin-top: .625em;
display: none;
}
.mobile-menu {
background-color: white;
width: 18.75em;
height: 100vh;
position: absolute;
top: 0;
right: 0;
z-index: 2;
display: none;
}
.close-menu-icon {
margin-left: auto;
margin-right: 1.25em;
margin-top: 1.25em;
display: block;
cursor: pointer;
height: 3.125em;
}
.login-register-mobile-container {
color: var(--mediumGray);
width: 90%;
margin: 3.125em auto;
}
.login-register-mobile-container span {
display: block;
text-align: center;
cursor: pointer;
}
.login-register-mobile-container span:first-child {
margin-bottom: 1.25em;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(.1875rem);
z-index: 1;
display: none;
}
<header>
<nav>
<img class="mobile-menu-icon" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/2048px-Hamburger_icon.svg.png" alt="" />
<div class="mobile-menu">
<img
class="close-menu-icon"
src="https://cdn4.iconfinder.com/data/icons/user-interface-131/32/close-512.png"
alt=""
/>
<ul class="mobile-nav-links">
<li class="features-mobile">Features
<ul class="features-mobile-dropdown">
<li>Todo List</li>
<li>Calenders</li>
<li>Reminders</li>
<li>Planning</li>
</ul>
</li>
<li class="company-mobile">Company</li>
<li>Careers</li>
<li>About</li>
</ul>
<div class="login-register-mobile-container">
<span class="login">Login</span>
<span class="register">Register</span>
</div>
</div>
</nav>
<div class="overlay"></div>
</header>

You forgot the return statement.
function displayTypeCheck(element, displayValue) {
return element.style.display === displayValue;
}
Otherwise the function will always return undefined which is a falsey value.

Within the displayTypeCheck function, you aren't returning the boolean result of the conditions.
Without the return statement, it is returning void
function displayTypeCheck(element, displayValue) {
return element.style.display === displayValue;
}

Related

Changing background color doesn't work well

I am trying to change the background color of my webpage using a hamburger menu. There are 4 color options on my hamburger menu. I managed to get a change on the background when clicking on the color of my choice. But that change only happens once. When I clicked another color and come back to click that same color from earlier on, it doesn't respond. The color seems to change only once, and not more than that.
The repository to my GitHub code is here: https://github.com/tand100b/Winc_Academy
const changeColorButton1 = document.getElementById("color1");
changeColorButton1.addEventListener("click", function() {
changeClassRedBackground();
});
const changeColorButton2 = document.getElementById("color2");
changeColorButton2.addEventListener("click", function() {
changeClassOrangeBackground();
});
const changeColorButton3 = document.getElementById("color3");
changeColorButton3.addEventListener("click", function() {
changeClassPurpleBackground();
});
const changeColorButton4 = document.getElementById("color4");
changeColorButton4.addEventListener("click", function() {
changeClassGreenBackground();
});
const changeClassRedBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("red-background");
}
const changeClassOrangeBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("orange-background");
};
const changeClassPurpleBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("purple-background");
};
const changeClassGreenBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("green-background");
};
body {
background-color: pink;
}
.red-background {
background-color: red;
}
.orange-background {
background-color: orange;
}
.purple-background {
background-color: purple;
}
.green-background {
background-color: green;
}
.btn-toggle-nav {
width: 60px;
height: 20%;
background-color: #f98f39;
background-image: url("https://i.stack.imgur.com/tniUv.png");
background-repeat: no-repeat;
background-size: 60%;
background-position: center;
cursor: pointer;
}
.btn-toggle-nav:hover {
opacity: 0.5;
}
.navbar ul {
padding-top: 15px;
/* visibility: hidden; */
}
.navbar ul li {
line-height: 60px;
list-style: none;
background-color: white;
width: 300px;
padding-top: 0px;
padding-top: 0px;
}
.navbar ul li a {
display: block;
height: 60px;
padding: 0 10px;
text-decoration: none;
font-family: arial;
font-size: 16px;
}
.navbar {
background-color: red;
width: 50px;
padding: 0 5px;
height: calc(100vh-60px);
z-index: 1000;
}
.list {
margin-top: 0px;
}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<div class="btn-toggle-nav"></div>
<aside class="navbar">
<ul class="list">
<li><a id="color1" href="#">Red</a></li>
<li><a id="color2" href="#">Orange</a></li>
<li><a id="color3" href="#">Purple</a></li>
<li><a id="color4" href="#">Green</a></li>
</ul>
</aside>
Can someone please look at my code and suggest what I can do?
Firstly, I suggest declaring variable bodyElement only once at the top of the file because each time it would be the same body element:
const bodyElement = document.body
Next, we create function that will check if body has any style classes in its classList. If it's not empty (length more than one) we remove all classes, and do nothing otherwise:
const isBodyHasStyle = () => bodyElement.classList.length ? bodyElement.classList = '' : null
Then, on each button click we going to call our new function:
changeColorButton1.addEventListener("click", function() {
isBodyHasStyle()
changeClassRedBackground();
});
Do the same with other buttons.
You need to make sure that you don't have multiple classes conflicting with each other, also try to DRY your code, here is an alternative I came up with:
const changeColor = (e) => {
const bodyElement = document.querySelector('body');
const colorIdMap = {
"color1": "red-background",
"color2": "orange-background",
"color3": "purple-background",
"color4": "green-background"
}
bodyElement.className = colorIdMap[e.target.id];
}
const btns = document.querySelectorAll('.list li');
btns.forEach(btn => btn.addEventListener('click', changeColor))
An easier way to accomplish this is by setting a data attribute on the background, based on the selected color. Just add a color data value to each of the menu items and set the body background to that color.
const toggleMenu = (event) => {
event.target.closest('.navbar').classList.toggle('open');
};
const changeColor = (event) => {
document.body.dataset.background = event.target.dataset.color;
toggleMenu(event); /* do not call ~ to stay open */
};
document.querySelector('.btn-toggle-nav')
.addEventListener('click', toggleMenu)
document.querySelectorAll('.color-picker')
.forEach(e => e.addEventListener('click', changeColor));
/* CSS reset */
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
body { display: flex; background-color: #222; }
ul { list-style-type: none; margin: 0; }
body[data-background="red"] { background-color: red }
body[data-background="orange"] { background-color: orange }
body[data-background="purple"] { background-color: purple }
body[data-background="green"] { background-color: green }
body[data-background="default"] { /* Do not set the background-color */ }
a[data-color="red"] { color: red; }
a[data-color="orange"] { color: orange; }
a[data-color="purple"] { color: purple; }
a[data-color="green"] { color: green; }
a[data-color="default"] { color: #222; }
.list {
position: absolute;
display: none; /* hide menu (default) */
flex-direction: column;
gap: 0.5em;
padding: 0.5em;
width: 6em;
left: 2em;
background: #444;
}
.list li a { text-decoration: none; font-weight: bold; }
.list li a:hover { text-decoration: underline; }
.navbar {
position: relative;
width: 2em;
background-color: #444;
}
.navbar.open .list {
display: flex; /* show menu */
}
.btn-toggle-nav {
width: 2em;
height: 2em;
background-image: url("https://i.stack.imgur.com/tniUv.png");
background-repeat: no-repeat;
background-size: 60%;
background-position: center;
cursor: pointer;
}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<aside class="navbar">
<div class="btn-toggle-nav"></div>
<ul class="list">
<li><a class="color-picker" href="#" data-color="red">Red</a></li>
<li><a class="color-picker" href="#" data-color="orange">Orange</a></li>
<li><a class="color-picker" href="#" data-color="purple">Purple</a></li>
<li><a class="color-picker" href="#" data-color="green">Green</a></li>
<li><a class="color-picker" href="#" data-color="default">Default</a></li>
</ul>
</aside>

How to remove div re-positioning when zoom up? (shrink the browser)

I've made a simple slider that responses the mouseenter event.
The algorithm is when if the user moves its mouse pointer one of Appear menu contents, a div called .slate goes down.
My problem is in Chrome or Opera, when the user zoomed up by using CTRL + Mouse Wheel Up, the .slate is going to spills a bit and goes back up smoothly while Firefox doesn't:
I'm looking for a solution to remove this unwanted re-positioning except not using transition.
I've tried to give the transition more dynamically to resolve the problem. Add the transition when mouse entered to the Appear, remove it when mouse entered to Disappear.
But this one didn't work with an another new issue. The transition is going to ignore when I wag the mouse like this:
Are there any ways to resolve this problem?
CodePen: Original Code / Attempt 2
Snippet (Original):
'use strict';
class Slate {
constructor(header) {
this.header = document.querySelector(header);
this.slate = document.querySelector('.slate');
this.menu = this.header.querySelector('.menu');
this.contents = this.menu.querySelectorAll('.contents');
this.addEvent();
}
addEvent() {
this.contents.forEach((cur, idx) => {
cur.addEventListener('mouseenter', (e) => this.expand(e, idx));
})
}
expand(e, index) {
let lesser = (index < 2),
ternary = {
toggle: (lesser) ? this.slate.classList.add('toggle') : this.slate.classList.remove('toggle')
};
}
}
const proSlate = new Slate('header');
* {
margin: 0;
padding: 0;
font-family: Helvetica;
}
div, section, header {
position: relative;
}
ul, li {
list-style-type: none;
}
header, .slate {
width: 800px;
}
header {
height: 100px;
line-height: 100px;
background-color: rgba(69, 255, 0, .4);
}
.slate {
height: 400px;
line-height: 400px;
text-align: center;
color: white;
background-color: steelblue;
top: -25rem;
transition: top 500ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
z-index: -1;
font-size: 4rem;
}
.menu {
width: 100%;
display: flex;
}
.contents {
margin: 0 20px;
}
.toggle {
top: 0;
}
<header>
<ul class="menu">
<li class="contents">Appear</li>
<li class="contents">Appear</li>
<li class="contents">Disapper</li>
<li class="contents">Disapper</li>
</ul>
</header>
<div class="slate">
CONTEXT OF SLATE
</div>
Instead of using top, go for transform
'use strict';
class Slate {
constructor(header) {
this.header = document.querySelector(header);
this.slate = document.querySelector('.slate');
this.menu = this.header.querySelector('.menu');
this.contents = this.menu.querySelectorAll('.contents');
this.addEvent();
}
addEvent() {
this.contents.forEach((cur, idx) => {
cur.addEventListener('mouseenter', (e) => this.expand(e, idx));
})
}
expand(e, index) {
let lesser = (index < 2),
ternary = {
toggle: (lesser) ? this.slate.classList.add('toggle') : this.slate.classList.remove('toggle')
};
}
}
const proSlate = new Slate('header');
* {
margin: 0;
padding: 0;
font-family: Helvetica;
}
div,
section,
header {
position: relative;
}
ul,
li {
list-style-type: none;
}
header,
.slate {
width: 800px;
}
header {
height: 100px;
line-height: 100px;
background-color: rgba(69, 255, 0, .4);
}
.slate {
height: 400px;
line-height: 400px;
text-align: center;
color: white;
background-color: steelblue;
transform: translateY(-100%);
transition: transform 500ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
z-index: -1;
font-size: 4rem;
}
.menu {
width: 100%;
display: flex;
}
.contents {
margin: 0 20px;
}
.toggle {
transform: translateY(0);
}
<header>
<ul class="menu">
<li class="contents">Appear</li>
<li class="contents">Appear</li>
<li class="contents">Disapper</li>
<li class="contents">Disapper</li>
</ul>
</header>
<div class="slate">
CONTEXT OF SLATE
</div>

Onclick Console Message Not Firing (javascript)

I'm building a simple flexbox navigation, when the screen size is below 980px a mobile version of the menu shows.
I'm building the javascript to do this - does anyone know why my console.log message won't show when the mobile version of the menu is clicked?
It's driving me around the twist.
You have to reduce the window below 980px to see what i mean.
https://codepen.io/emilychews/pen/eezYox?editors=1111
var mobileMenuButton = document.querySelector('#mobile-menu')
var mobileMenuItems = document.querySelector('#nav-menu')
// TOGGLE MOBILE MENU
var mobileMenu = false
if (mobileMenu === false) {
function showMobileMenu() {
mobileMenuButton.onclick(function() {
console.log("clicked");
})
mobileMenu = true
}
}
* {
padding: 0;
margin: 0;
}
p {
color: white;
}
header {
width: 100%;
}
#main-nav {
width: inherit;
height: 100px;
background: red;
display: flex;
justify-content: space-between;
box-sizing: border-box;
padding: 10px 5% 10px 5%;
align-items: center;
}
#logo-wrapper {
width: 150px;
height: 75px;
background-color: grey;
}
#nav-menu {
display: flex;
margin-left: auto;
}
#main-nav ul li {
list-style-type: none;
padding: 5px 10px;
background: pink;
margin: 0 5px;
}
#mobile-menu {
display: none;
}
#media only screen and (max-width: 980px) {
#mobile-menu {
display: block;
background: blue;
padding: 5px 10px;
box-sizing: border-box;
cursor: pointer;
z-index: 99;
}
#main-nav ul {
display: none;
}
}
<header>
<nav id="main-nav">
<div id="logo-wrapper"></div>
<ul id="nav-menu">
<li class="menu-item menu-item-1"><a>Home</a></li>
<li class="menu-item menu-item-2"><a>About</a></li>
<li class="menu-item menu-item-3"><a>Contact</a></li>
</ul>
<div id="mobile-menu"><a>Menu</a></div>
</nav>
</header>
Well there are few problems, You never call showMobileMenufunction, so event is never binded to that element. onclick is not a function. I believe You want something like:
var mobileMenuButton = document.querySelector('#mobile-menu')
var mobileMenuItems = document.querySelector('#nav-menu')
// TOGGLE MOBILE MENU
var mobileMenu = false
mobileMenuButton.addEventListener('click', function() {
toggleMobileMenu();
})
function toggleMobileMenu() {
if (mobileMenu === false) {
console.log("clicked");
mobileMenu = true
} else {
console.log("not clicked");
mobileMenu = false
}
}

Text slider in JS doesn't slide properly

I'm trying to write my first text slider in JS, which seemed super easy at first, but it bevahes very stange.
When the 'previous' button is clicked it works fine but ommits the last <li> item, when the 'next' button is clicked all of the <li>s become an empty class="" and that's all, it's doesn't slide to the next item.
Here's my code:
const slider = document.querySelector('.text-slider');
const sliderItems = slider.querySelectorAll('li');
const sliderNav = slider.querySelector('.slider-nav');
function changeSlide(e) {
// if the next button is clicked the direction is true
// if the prev button is clicked the direction is false
const direction = e.target.classList.contains('nav-next') ? true : false;
const itemsInTotal = sliderItems.length;
for(let i = 0; i < itemsInTotal; i++) {
// if the item is active
if(sliderItems[i].classList.contains('active')) {
//delete the active class
sliderItems[i].classList.remove('active');
//if the NEXT button was clicked
if(direction) {
//if it's the last slide
if(i === itemsInTotal-1) {
sliderItems[0].classList.add('active');
}
else {
sliderItems[i+1].classList.add('active');
}
// if the PREV button was clicked
} else {
//if it's the first element
if(i === 0) {
sliderItems[itemsInTotal-1].classList.add('active');
} else {
sliderItems[i-1].classList.add('active');
}
}
}
};
}
sliderNav.addEventListener('click', changeSlide);
.hero {
background-color: #252525;
min-height: 100vh;
position: relative;
}
.hero ul {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center; }
.hero ul li {
display: none;
color: #fff;
text-align: center;
font-family: "Frank Ruhl Libre", serif;
font-size: 2em; }
.hero ul li span {
color: #f5989d;
text-transform: uppercase;
font-family: "Josefin Sans", sans-serif;
font-size: 1.3em;
font-weight: 700;
display: block; }
.hero ul li.active {
display: block; }
.hero .slider-nav a {
border:1px solid red;
position: absolute;
content: ' ';
width: 30px;
height: 30px;
background: url("img/arrow-r.png");
background-size: contain;
position: absolute;
top: calc( 50% - 15px );
z-index: 10; }
.hero .slider-nav a:hover {
cursor: pointer; }
.hero .slider-nav a.nav-prev {
transform: rotate(180deg);
left: 7%; }
.hero .slider-nav a.nav-next {
right: 7%; }
<section class="hero">
<div class="text-slider">
<div class="slider-nav">
<a class="slider-nav nav-prev"></a>
<a class="slider-nav nav-next"></a>
</div>
<ul>
<li class="active">I like take photos <span>in the woods</span></li>
<li>I like observing <span>people and their emotions</span></li>
<li>I always take <span>the best of life</span></li>
<li>I always take <span>the best of life 2</span></li>
<li>I always take <span>the best of life 3</span></li>
</ul>
</div>
</section>
I will appreciate any help.
const slider = document.querySelector('.text-slider');
const sliderItems = slider.querySelectorAll('li');
const sliderNav = slider.querySelector('.slider-nav');
let counter = 0;
function changeSlide(e) {
// if the next button is clicked the direction is true
// if the prev button is clicked the direction is false
const direction = e.target.classList.contains('nav-next') ? true : false;
const itemsInTotal = sliderItems.length;
for(let i = 0; i < itemsInTotal; i++) {
// if the item is active
if(sliderItems[i].classList.contains('active')) {
//delete the active class
sliderItems[i].classList.remove('active');
//if the NEXT button was clicked
if(direction) {
//if it's the last slide
if(i === itemsInTotal-1) {
sliderItems[0].classList.add('active');
}
else {
sliderItems[i+1].classList.add('active');
break;
}
// if the PREV button was clicked
} else {
//if it's the first element
if(i === 0) {
sliderItems[itemsInTotal-1].classList.add('active');
break;
} else {
sliderItems[i-1].classList.add('active');
}
}
}
};
}
sliderNav.addEventListener('click', changeSlide);
.hero {
background-color: #252525;
min-height: 100vh;
position: relative;
}
.hero ul {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center; }
.hero ul li {
display: none;
color: #fff;
text-align: center;
font-family: "Frank Ruhl Libre", serif;
font-size: 2em; }
.hero ul li span {
color: #f5989d;
text-transform: uppercase;
font-family: "Josefin Sans", sans-serif;
font-size: 1.3em;
font-weight: 700;
display: block; }
.hero ul li.active {
display: block; }
.hero .slider-nav a {
border:1px solid red;
position: absolute;
content: ' ';
width: 30px;
height: 30px;
background: url("img/arrow-r.png");
background-size: contain;
position: absolute;
top: calc( 50% - 15px );
z-index: 10; }
.hero .slider-nav a:hover {
cursor: pointer; }
.hero .slider-nav a.nav-prev {
transform: rotate(180deg);
left: 7%; }
.hero .slider-nav a.nav-next {
right: 7%; }
<section class="hero">
<div class="text-slider">
<div class="slider-nav">
<a class="slider-nav nav-prev"></a>
<a class="slider-nav nav-next"></a>
</div>
<ul>
<li class="active">I like take photos <span>in the woods</span></li>
<li>I like observing <span>people and their emotions</span></li>
<li>I always take <span>the best of life</span></li>
<li>I always take <span>the best of life 2</span></li>
<li>I always take <span>the best of life 3</span></li>
</ul>
</div>
</section>
Okay, I added 2 break in the loop to stop the iteration after applying the class on the next element.
In fact, you have a problem with your previous button too because the state "Best of life 3" is never displayed.
I propose you to use a while loop instead a for, because you change always all "li" instead of changing only the concerned 2 (old active and new active).
I think, this will work :
changeSlide(e: any) {
// if the next button is clicked the direction is true
// if the prev button is clicked the direction is false
const direction = e.target.classList.contains('nav-next') ? true : false;
const itemsInTotal = this.sliderItems.length;
let isChangeDone = false;
let i = 0;
while(!isChangeDone && i < itemsInTotal) {
// if the item is active
if(this.sliderItems[i].classList.contains('active')) {
//delete the active class
this.sliderItems[i].classList.remove('active');
//if the NEXT button was clicked
if(direction) {
//if it's the last slide
if(i === itemsInTotal-1) {
this.sliderItems[0].classList.add('active');
isChangeDone = true;
}
else {
this.sliderItems[i+1].classList.add('active');
isChangeDone = true;
}
// if the PREV button was clicked
} else {
//if it's the first element
if(i === 0) {
this.sliderItems[itemsInTotal-1].classList.add('active');
isChangeDone = true;
} else {
this.sliderItems[i-1].classList.add('active');
isChangeDone = true;
}
}
}
i++;
};
}
Let me know.

Translating jQuery to Vanilla JS issue

I was watching a tutorial that used jQuery and wanted to turn it into JS, but my code is broken - was hoping someone could help me with this:
Tutorial JS:
$(function() {
var btn = $('button');
var progressBar = $('.progressbar');
btn.click(function() {
progressBar.find('li.active').next().addClass('active');
})
})
Taken from URL:http://www.kodhus.com/kodity/codify/kod/mGXAtb
Here is my failed attempt at rewriting the jQuery using JavaScript DOM:
var btn1 = document.getElementsByTagName('BUTTON');
var progBar = document.getElementsByClassName('progressbar');
function clickMe1() {
var elm = progBar.querySelectorAll("li");
var emlClass = elm.querySelector(".active");
return emlClass.nextElementSibling.addClass('active');
}
btn1.addEventListener("click", clickMe1, false);
where did I go wrong?
Working fiddle.
Your code will work after several changes check the notes below :
You've missed addClass() there it's a jQuery function, for vanilla JS use .classList.add() instead:
return emlClass.nextElementSibling.classList.add("active");
querySelectorAll(); will return a list of nodes you have to loop through them and add class, use :
var emlClass = progBar.querySelectorAll("li.active");
Instead of :
var elm = progBar.querySelectorAll("li");
var emlClass = elm.querySelector(".active");
Then loop and add active class:
for(var i=0;i<emlClass.length;i++){
emlClass[i].nextElementSibling.classList.add("active");
}
getElementsByTagName() and getElementsByClassName() will also returns a list of nodes with given name, you have to specify which one you want to pick (selecting the first in my example) :
var btn1 = document.getElementsByTagName('BUTTON')[0];
var progBar = document.getElementsByClassName('progressbar')[0];
Hope this helps.
var btn1 = document.getElementsByTagName('BUTTON')[0];
var progBar = document.getElementsByClassName('progressbar')[0];
function clickMe1() {
var emlClass = progBar.querySelectorAll("li.active");
for(var i=0;i<emlClass.length;i++){
emlClass[i].nextElementSibling.classList.add("active");
}
}
btn1.addEventListener("click", clickMe1, false);
.container {
width: 100%;
}
.progressbar {
counter-reset: step;
margin: 0;
margin-top: 50px;
padding: 0;
}
.progressbar li {
list-style-type: none;
float: left;
width: 33.33%;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid #ddd;
display: block;
text-align: center;
margin: 0 auto 10px auto;
border-radius: 50%;
background-color: white;
}
.progressbar li:after {
content: '';
position: absolute;
width: 100%;
height: 2px;
background-color: #ddd;
top: 15px;
left: -50%;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progressbar li.active {
color: green;
}
.progressbar li.active:before {
border-color: green;
}
.progressbar li.active + li:after {
background-color: green;
}
button {
position: relative;
border: none;
padding: 10px 20px;
font-size: 16px;
border-radius: 2px;
left: 50%;
margin-top: 30px;
transform: translate(-50%);
cursor: pointer;
outline: none;
}
button:hover {
opacity: 0.8;
}
<div class="container">
<ul class="progressbar">
<li class="active">Step 1</li>
<li>Step 2</li>
<li>Step 3</li>
</ul>
</div>
<button>Next step</button>
.querySelectorAll("li") will return an array (or an array-like object) with one or more <li> tags. So you need to either:
loop through every <li> in that list and do the rest,
or just take the first item from that list if you don't want to worry about there being more than one li in the page,
or use .querySelector (not .querySelectorAll) to just take the first <li> for you.
MDN

Categories