Is there a way to hide absolute div with JS? - javascript

I have this .endGame div which I wanna hide and then show again when I need it. So I created .endGameDisplay to hide it but it doesn't work that way and I don't know why.
It only hides when display: none; is in .endGame
In java script I want it to be hidden on page opening so i have sth like this:
const endGame = document.querySelector('.endGame');
endGameOff();
//end game on func
function endGameOn() {
endGame.classList.remove('.endGameDisplay');
}
//end game off func
function endGameOff() {
endGame.classList.add('.endGameDisplay');
}
I also tried to change classlist.add to .remove to check if I wasn't mistaken but still nothing.
My HTML:
<div class="endGame">
<h1>You</h1>
<h2 class="wonORlost">text</h2>
<h3>Do you want to restar game or go back to the menu?</h3>
<div class="btns">
<div class="restart">Restart</div>
<div class="exit">Exit</div>
</div>
</div>
My CSS:
.endGame {
position: absolute;
z-index: 1;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
background: $primary-color;
color: $white-color;
border-radius: 25px;
text-align: center;
box-shadow: 0 0 15px #333;
.h1 {
font-weight: $font-bold;
}
.h2 {
font-weight: $font-bold;
color: lighten($bot-color, 15%);
}
.h3 {
font-weight: $font-normal;
}
.btns {
display: grid;
justify-content: center;
justify-items: center;
.restart {
background: $green-color;
cursor: pointer;
#include transition-ease;
&:hover {
background: darken($green-color, 10%);
#include transition-ease;
}
}
.exit {
background: $red-color;
cursor: pointer;
#include transition-ease;
&:hover {
background: darken($red-color, 10%);
#include transition-ease;
}
}
}
&.endGameDisplay {
display: none;
}
}

Remove the period (.) when adding a class. .endGameDisplay should be endGameDisplay:
const endGame = document.querySelector('.endGame');
endGameOff();
//end game on func
function endGameOn() {
endGame.classList.remove('endGameDisplay');
}
//end game off func
function endGameOff() {
endGame.classList.add('endGameDisplay');
}
.endGameDisplay {
display: none;
}
<div class="endGame">
<h1>You</h1>
<h2 class="wonORlost">text</h2>
<h3>Do you want to restar game or go back to the menu?</h3>
<div class="btns">
<div class="restart">Restart</div>
<div class="exit">Exit</div>
</div>
</div>

Related

How do i refer the className when having a nested scss ? nextjs reactjs

I have a navbar with a hamburger button and i want to change the style (the bar color and the hamburger button style) on tap. I mention that i've tried using &:active, &.activeBar on the scss file.
For some reason the background color doesn t change and the hamburger button doesn't turn into an X
This is my SCSS file:
.topbar {
width: 100%;
background-color: $secondaryColor;
color: $mainColor;
height: 70px;
position: fixed;
top: 0;
z-index: 3;
transition: all 1s ease;
overflow: hidden;
.wrapper {
padding: 10px 30px;
display: flex;
align-items: center;
justify-content: space-between;
}
.left {
display: flex;
align-items: center;
margin: 10;
.itemContainer {
display: flex;
align-items: center;
.icon {
font-size: 36px;
margin-right: 5px;
&:hover {
color: blue;
}
}
span {
font-size: 15px;
font-weight: 700;
}
}
.logo {
font-size: 40px;
font-weight: 700;
text-decoration: none;
color: inherit;
margin-right: 40px;
}
}
.right {
.hamburger {
width: 32px;
height: 25px;
display: flex;
flex-direction: column;
justify-content: space-between;
span {
width: 100%;
height: 3px;
background-color: $mainColor;
transform-origin: left;
transition: all 0.5s ease;
}
}
}
&.activeBar {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
}
And this is where i try to change the classname in my js file:
import React from 'react';
import styles from './topbar.module.scss';
import { Facebook } from '#material-ui/icons';
const Topbar = ({ open, toggle }) => {
function menuToggled() {
toggle(!open);
console.log('menuToggled', open);
}
return (
<div className={`${styles.topbar} ${open ? 'active' : ''}`}>
<div className={styles.wrapper}>
<div className={styles.left}>
<a href='#slider' className={styles.logo}>
Muntenia cu gust
</a>
<div className={styles.itemContainer}>
<Facebook
className={styles.icon}
onClick={() => window.open('https://stackoverflow.com/')}
/>
</div>
</div>
<div className={styles.right}>
<div className={styles.hamburger} onClick={menuToggled}>
<span className={styles.line1}></span>
<span className={styles.line2}></span>
<span className={styles.line3}></span>
</div>
</div>
</div>
</div>
);
};
export default Topbar;
In your code, you're adding active as a class in the "global" scope. By default with css-modules, all classes are output in "local" scope. So your .topbar class, after compilation, would look something like: .Topbar_topbar__abc12 ("abc12" would be a hash).
So, the .active class is also being compiled to local scope, looking something like: .Topbar_active_def34
In your markup, you're toggling the .active class as a string rather than as styles.active. So, on output, you're expecting your "active" class to be .Topbar_topbar__abc12.active when in actuality, your stylesheet is declaring .Topbar_topbar_abc12.Topbar_active_def32 as the "active" class.
By declaring .active as being in the global scope, the output would then be as expected. Try adding the :global flag to your stylesheet:
...
&:global(.active) {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
...
use classnames package (https://www.npmjs.com/package/classnames) to combine classes that are on the same element, the rest is handled the same as in vanilla html/css/js
In your code you use active it also should come from styles and be combined using:
classnames('styles.ElementClassName', active && styles.active)
Adding the active selector on the regular .hamburger class should trigger on touch. Also the classname in you scss is activeBar but in your react app is only active.
&.clicked {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
If you want to change the topBar also then you'll need to change your TopBar component a bit
import React, { useState } from 'react';
import styles from './topbar.module.scss';
import { Facebook } from '#material-ui/icons';
const Topbar = ({ open, toggle }) => {
const [isClicked, setIsClicked] = useState(false);
function menuToggled() {
toggle(!open);
console.log('menuToggled', open);
}
return (
<div className={`${styles.topbar} ${open ? 'active' : ''} ${ isClicked && ' clicked'}`}>
<div className={styles.wrapper}>
<div className={styles.left}>
<a href='#slider' className={styles.logo}>
Muntenia cu gust
</a>
<div className={styles.itemContainer}>
<Facebook
className={styles.icon}
onClick={() => window.open('https://stackoverflow.com/')}
/>
</div>
</div>
<div className={styles.right}>
<div className={styles.hamburger} onClick={menuToggled} onTouchStart={(e) => setIsClicked(true)}>
<span className={styles.line1}></span>
<span className={styles.line2}></span>
<span className={styles.line3}></span>
</div>
</div>
</div>
</div>
);
};

Each card does not open and close as expected when dynamically created with JavaScript

"use strict";
const openModal = document.querySelector('[data-create]');
const exitModal = document.querySelector('[data-close]');
const saveBtn = document.querySelector('#save');
openModal.addEventListener('click', showModal);
exitModal.addEventListener('click', closeModal);
saveBtn.addEventListener('click', saveCard);
/*
Detects if text has been inputed. If not, an error is shown
if yes the createFlashCard and closed modal function are called.
*/
function saveCard() {
let questionArea = document.querySelector('#question');
let answerArea = document.querySelector('#answer');
let showAlert = document.querySelector('.show-error-message');
if (questionArea = null || questionArea.value == '') {
if (answerArea = null || answerArea.value == '') {
showAlert.classList.remove("hide-error");
}
setTimeout(() => {
showAlert.classList.add("hide-error");
}, 3000);
} else {
closeModal();
createFlashCard();
}
}
/*
Removes the is-hidden css class to open modal
*/
function showModal(e) {
let modal = document.querySelector('.modal-design');
modal.classList.remove("is-hidden");
}
/*
Adds the is-hidden css class to close modal
*/
function closeModal() {
let modal = document.querySelector('.modal-design');
modal.classList.add('is-hidden');
}
/*
Creates a flash card using input string values.
Then renders a card using the .innerHTML property.
Each card rendered will be clickable to show the answer.
*/
function createFlashCard() {
let questionText = document.querySelector('.question-text').value;
let answerText = document.querySelector('.answer-text').value;
let cardSection = document.querySelector('.card-container');
let createArticle = document.createElement('article');
createArticle.className += "card";
createArticle.innerHTML = `
<div class="card-question-button">
<h4 id="title">${questionText}</h4>
<button id="show">></button>
</div>
<div id="answer-card">
<p id="answer-card-p">${answerText}</p>
</div>`;
cardSection.appendChild(createArticle);
openCloseCards();
}
function openCloseCards() {
let buttons = document.querySelectorAll('.card-question-button');
buttons.forEach(function (btn) {
btn.addEventListener('click', function (e) {
let questions = e.currentTarget.parentElement;
questions.classList.toggle("show-text");
})
})
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
line-height: 1.5;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
/*
variables
*/
:root {
--primary-color:#5dcbd8;
--secondary-color: hsl(186, 100%, 94%);
--third-color: #F6F6F8;
--fourth-color: #fff;
--button-border: none;
--error-color: hsl(0deg 58% 70%);
--shadow: 0px 2px 3px 0 hsla(0 , 0%, 0%, 0.2);
}
header {
padding: 15px;
color: var(--third-color);
height: 100px;
background-color: var(--primary-color);
}
/**
Prompt question card
*/
.prompt-question {
display: flex;
padding: 15px;
align-items: center;
justify-content: space-around;
}
#create {
border: var(--button-border);
border-radius: 5px;
background-color: var(--secondary-color);
height: 60px;
width: 70px;
font-size: 25px;
transition: .3s ease-in-out;
}
#create:hover {
cursor: pointer;
background-color: #b5f0f7;
}
/*
Modal Design
*/
.modal-placement{
display: flex;
justify-content: center;
}
.modal-design {
width: 600px;
padding: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: #F6F6F8;
box-shadow:var(--shadow);
border-radius: 4px;
margin: 30px;
}
.is-hidden {
visibility: hidden;
opacity: 1;
}
.erase-modal-c {
display: flex;
justify-content: flex-end;
}
#erase {
background-color:var(--error-color);
display: flex;
justify-content: center;
border: none;
padding: 5px;
height: 25px;
width: 25px;
}
#close {
margin-top: -8px;
margin-left: 3px;
font-size: 20px;
transform: rotate(45deg);
}
#erase:hover {
cursor: pointer;
}
h3 {
padding-top: 15px;
}
/**
Textarea design
*/
#question, #answer {
height: 90px;
}
textarea {
font-size: 15px;
padding: 4px;
resize: vertical;
}
#save {
border: var(--button-border);
margin-top: 25px;
height: 45px;
font-size: 15px;
background-color:var(--primary-color);
color: var(--third-color);
}
#save:hover {
cursor: pointer;
background-color: #90d8e0;
}
.show-error-message {
background-color: var(--error-color);
color: var(--fourth-color);
margin-top: 15px;
padding: 10px;
text-align: center;
}
.hide-error {
visibility: hidden;
opacity: 0;
}
/*
Card container
*/
.card-container {
display: grid;
background-color: var(--third-color);
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
margin-top: 40px;
}
#title {
margin-left: 10px;
}
.card {
display: flex;
margin: 20px;
flex-direction: column;
align-items: center;
background-color:var(--fourth-color);
padding: 7px;
justify-content: space-between;
box-shadow:var(--shadow);
border-radius: 5px;
transition: .3s ease-in-out;
z-index: 1000;
}
.card-question-button {
display: flex;
justify-content: space-between;
padding: 5px;
width: 100%;
}
.card-question-button:hover {
cursor: pointer;
}
/*
Answer card
*/
#answer-card {
display: none;
border-top: 1px solid rgba(0, 0, 0, 0.2);
padding: 15px;
text-align: left;
}
#answer-card-p {
text-align: left;
}
.show-text #answer-card {
display: block;
}
#show {
border: none;
background-color: var(--fourth-color);
font-size: 20px;
transition: .2s ease-in-out;
}
#show:hover {
cursor:pointer;
transform: translateX(-2px);
}
/* Media Queries */
#media screen and (max-width: 800px) {
.prompt-question {
box-shadow:var(--shadow);
border-radius: 4px;
margin: 20px;
}
.card-container {
grid-template-columns: 1fr;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<header>
<h1>Flash Cards +</h1>
</header>
<article class="prompt-question">
<button id="create" data-create>+</button>
<p class="info">
Create a new card
</p>
</article>
<article class="modal-placement">
<section class="modal-design is-hidden">
<div class="erase-modal-c">
<button id="erase" data-close>
<p id="close">+</p>
</button>
</div>
<h3>Question</h3>
<textarea class="question-text textA" id="question"></textarea>
</div>
<h3>Answer</h3>
<textarea class="answer-text textA" id="answer"></textarea>
<button id="save">Save</button>
<div class="show-error-message hide-error">Please Submit Values</div>
</section>
</article>
<section class="card-container">
</section>
<script src="js/script.js"></script>
</html>
This is a flashcard project I am building. I am fairly new to programming and was looking for help on this particular bug that I cannot wrap my head around. Included in the gist is the css, html, and javascript code. Any tips on code structure is also appreciated.
Question:
When I dynamically create cards using JavaScript I want to show open and close behavior for each of them. The first card created does open and close as expected. However, the following cards do not. For example, one stays open while the other one closes.
I would like each card to open and close independently when clicked after dynamically being created. It seems the behavior is depending on the previous card.
When you call createFlashCard() The html that is generated:
<div class="card-question-button">
<h4 id="title">${questionText}</h4>
<button id="show">></button>
</div>
<div id="answer-card">
<p id="answer-card-p">${answerText}</p>
</div>
These elements will have the same ID's used more than once in a page when they should be unique. Add a unique identifier or remove the id attribute if its not needed. For example:
let cardCount=0;
function createFlashCard() {
cardCount++;
let questionText = document.querySelector('.question-text').value;
let answerText = document.querySelector('.answer-text').value;
let cardSection = document.querySelector('.card-container');
let createArticle = document.createElement('article');
createArticle.className += "card";
let title="title"+ cardCount;
let buttonID="show"+cardCount;
...
<button id=${buttonID}>
...
}
When you are executing your openCloseCards function, you are creating multiple event listeners based on the number of items in buttons.
I'd recommend adding the event listener in your createFlashCard function and removing the function definition of openCloseCards and it's call.
With this change the code seems to working as it should.
function createFlashCard() {
let questionText = document.querySelector('.question-text').value;
let answerText = document.querySelector('.answer-text').value;
let cardSection = document.querySelector('.card-container');
let createArticle = document.createElement('article');
createArticle.className += "card";
createArticle.innerHTML = `
<div class="card-question-button">
<h4 id="title">${questionText}</h4>
<button id="show">></button>
</div>
<div id="answer-card">
<p id="answer-card-p">${answerText}</p>
</div>`;
cardSection.appendChild(createArticle);
createArticle.addEventListener('click', function(e) {
let questions = e.target.parentElement;
questions.classList.toggle("show-text");
console.log(questions.classList)
})
}

Add smooth transition when changing an element's display using JavaScript

I've added a search bar in the header that is set to display: none by default and I used js to make it appear on a button click via assigning a .show class which contains display: block !important to the search bar element (#search). It's working fine but my only problem is the rough transition from display: none to block, so I've been looking into ways to make this transition smooth and most of the answers I found were using jQuery, which I don't really want to do since I'm still in the learning phase of js, so if there's a way I can do this using vanilla js, please help me with it.
Here's my code https://jsfiddle.net/5jxLq9ck/
In CSS line 38, I add the .show utility class
.show {
display: block !important;
}
And I'm assuming I'll have to edit something in here (js) to get the desired effect:
function showSearch(e) {
e.preventDefault;
if (
e.target.classList.contains("show-btn") ||
e.target.classList.contains("fas")
) {
const searchBar = document.querySelector("#search");
searchBar.classList.add("show");
}
}
Additional question: is my use of e.preventDefault correct here? The functionality didn't work until I used it.
Thanks a lot in advance.
Here is an updated snippet, I've changed the input width for the animation. You can make it even more smooth by set the input height.
const searchDiv = document.querySelector("#search-div");
// ADD EVENT LISTENERS
searchDiv.addEventListener("click", showSearch);
// FUNCTION: SHOW SEARCH BAR ON BUTTON CLICK
function showSearch(e) {
e.preventDefault;
if (
e.target.classList.contains("show-btn") ||
e.target.classList.contains("fas")
) {
const searchBar = document.querySelector("#search");
searchBar.classList.add("show");
}
}
/* GENERAL */
:root {
--light-color: #ccc;
--lighter-color: #f4f4f4;
--dark-color: #333;
--darker-color: #222;
--brand-color: #ff4;
--danger: #f44;
--danger-dark: #c00;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: var(--dark-color);
color: var(--light-color);
font-family: "Trebuchet MS";
}
ul li {
list-style: none;
}
button,
input {
outline: none;
}
/* UTILITY */
.highlight {
color: var(--brand-color);
}
.show {
width: 300px !important;
border: black 2px solid;
padding: 0.6rem 1rem;
}
/* HEADER */
header {
background: var(--darker-color);
display: flex;
flex-direction: row;
align-items: center;
text-align: center;
justify-content: space-between;
padding: 1.4rem 6rem;
width: 100%;
}
#logo {
font-size: 2.4rem;
font-weight: 200;
}
#search-div {
width: auto;
height: auto;
display: flex;
gap: 0.4rem;
}
.show-btn {
padding: 0.6rem 0.7rem;
background: var(--light-color);
border-radius: 5px;
border: none;
transition: ease-in 300ms;
font-size: 1.2rem;
cursor: pointer;
height: 100%;
margin-top: 2px;
}
.show-btn:hover {
background: var(--brand-color);
transition: ease-in 300ms;
}
#search {
width: 0;
background: var(--lighter-color);
color: var(--darker-color);
height: 100%;
font-size: 1.2rem;
border-radius: 2px;
transition: ease-in 300ms;
border: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Contact List</title>
<link rel="stylesheet" href="css/style.css">
<script src="https://kit.fontawesome.com/3ad7573e76.js" crossorigin="anonymous"></script>
</head>
<body>
<header>
<div id="logo-div">
<h1 id="logo">
<span class="highlight"><i class="fas fa-user-friends"></i></span> My<span
class="highlight">Contact</span>List
</h1>
</div>
<div id="search-div">
<button class="show-btn"><i class="fas fa-search"></i></button>
<input id="search" type="text" placeholder="Search contacts...">
</div>
</header>
<script src="js/main.js"></script>
</body>
</html>
You can make the transition from no display to block display smooth by playing with the opacity property so that when the element is given the "show" class it animates from an opacity of 0 to an opacity of 1 like so.
function showSearch(e) {
e.preventDefault;
if (
e.target.classList.contains("show-btn") ||
e.target.classList.contains("fas")
) {
const searchBar = document.querySelector("#search");
searchBar.classList.add("show");
}
}
document.getElementById("show").addEventListener("click", e => {
showSearch(e);
});
#keyframes smooth {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.show {
animation: smooth 1s ease;
display: block !important;
}
.none {
display: none;
}
<div class="none" id="search">Example</div>
<button class="show-btn fas" id="show">Show</button>

Creating 2 buttons that reveal content from 2 different direction

I want to create 2 buttons can when clicked will reveal their respective content from 2 different directions.
Example:
When a user click on smt, the content will open from the left.
When a user click on mi, the content will open from the right.
So far, I managed to do the smt part only as I don't know how to make the "mi" part work.
Below is my code:
Style:
<style>
.overlay {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 60;
left: 0;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #818181;
display: block;
transition: 0.3s;
}
.overlay a:hover, .overlay a:focus {
color: #f1f1f1;
}
.overlay .closebtn {
position: absolute;
top: 60px;
right: 45px;
font-size: 60px;
}
#media screen and (max-height: 650px) {
.overlay a {
font-size: 20px
}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
</style>
SMT button:
<div id="myNav" class="overlay">
×
<div class="overlay-content">Smt</div>
</div>
<span style="font-size:30px;cursor:pointer; position:absolute; top:680px; left:300px;" onclick="openNav()">smt</span>
JavaScript:
<script>
function openNav() {
document.getElementById( "myNav" ).style.width = "100%";
}
function closeNav() {
document.getElementById( "myNav" ).style.width = "0%";
}
</script>
How can I re-use the same code for the second button?
I think you are looking for this.. May be this could hep you
I use jquery-ui, function slide to achieve desire effect
Using single content
$('#loginPanel').click(function(){
if ($('#userNav').is(':hidden')) {
$('#userNav').show('slide',{direction:'left'},1000);
} else {
$('#userNav').hide('slide',{direction:'left'},1000);
}
});
$('#loginPanel1').click(function(){
if ($('#userNav').is(':hidden')) {
$('#userNav').show('slide',{direction:'right'},1000);
} else {
$('#userNav').hide('slide',{direction:'right'},1000);
}
});
a {
color: #000;
cursor:pointer;
display:block;
}
#userNav{
width: 200px;
height: 200px;
display: none;
background: #ff0000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<button id="loginPanel">left-to-right</button>
<button id="loginPanel1">right-to-left</button>
<div id="userNav">User Area</div>
Using separate content (i use flex to make both content show inline you can just remove class main-content to show them on separate line as block)
$('#loginPanel').click(function(){
if ($('#userNav').is(':hidden')) {
$('#userNav').show('slide',{direction:'left'},1000);
} else {
$('#userNav').hide('slide',{direction:'left'},1000);
}
});
$('#loginPanel1').click(function(){
if ($('#userNav1').is(':hidden')) {
$('#userNav1').show('slide',{direction:'right'},1000);
} else {
$('#userNav1').hide('slide',{direction:'right'},1000);
}
});
a {
color: #000;
cursor:pointer;
display:block;
}
.area{
width: 200px;
height: 200px;
display: none;
background: #ff0000;
}
.main-content {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<button id="loginPanel">left-to-right</button>
<button id="loginPanel1">right-to-left</button>
<div class="main-content">
<div class="area" id="userNav">User Area 1</div>
<div class="area" id="userNav1">User Area 2</div>
</div>
You can pass the Id to the function like this:
onclick="openNav("myNav1")"
And if you need to hide element, You can use: display: "none"
<script>
function openNav(id) {
document.getElementById(id).style.display = "block";
}
function closeNav(id) {
document.getElementById(id).style.display = "none";
}
</script>
Just need to do this for the code:
Add "2" to "openNav", "myNav2", "closeNav2"
< script>
function openNav2() {
document.getElementById( "myNav2" ).style.width = "100%";
}
function closeNav2() {
document.getElementById( "myNav2" ).style.width = "0%";
}
</script>
Same for the button code, add "2" to "myNav", "openNav", "closeNav"
<div id="myNav" class="overlay">
×
<div class="overlay-content">MI</div>
</div>
<span style="font-size:30px;cursor:pointer; position:absolute; top:680px;
left:300px;" onclick="openNav()">MI</span>

jQuery/JavaScript if statement for two toggles

I have two toggles (toggle-1 and toggle-2) with different contents in a header. I would like to prevent the user to have both toggles active simultaneously (otherwise they overlap).
In the code below I tried to use if statements to hide one of the toggles if the other is already opened but it does not work.
Ideally, what I would like to happen is that if toggle-1 is active and the user clicks on toggle-2, then toggle-1 would come back to its original state and toggle-2 would be now active. The same the other way around.
I am not familiar with JavaScript yet and I'd really appreciate if you could tell me what I have done wrong and how it should be done to have my ideal result
Here's the link to my CodePen if you find it easier:
https://codepen.io/fergos2/pen/NWWxgEp
var myToggle
var oneToggle = $(document).ready(function() {
$('.toggle-1').click(function() {
$('.toggle-1').toggleClass('active')
$('.toggle-1-content').toggleClass('active')
})
})
var twoToggle = $(document).ready(function() {
$('.toggle-2').click(function() {
$('.toggle-2').toggleClass('active')
$('.toggle-2-content').toggleClass('active')
})
})
if (myToggle == oneToggle) {
$(document).ready(function() {
$('toggle-2-content').hide();
})
} else if (myToggle == twoToggle) {
$('toggle-1-content').hide();
}
.container {
width: 100%;
height: 1000px;
margin: 0 auto;
background-color: #eee;
}
.wrapper {
background-color: pink;
position: relative;
display: flex;
align-items: center;
}
.toggle-1,
.toggle-2 {
display: block;
width: 20px;
height: 20px;
float: left;
cursor: pointer;
color: white;
text-align: center;
background-color: green;
margin: 10px;
}
.toggle-1.active,
.toggle-2.active {
background-color: red;
}
.toggle-1-content,
.toggle-2-content {
display: none;
}
.toggle-1-content.active,
.toggle-2-content.active {
display: block;
background-color: white;
border: 1px solid black;
position: absolute;
top: 40px;
}
.toggle-1-content.active {
left: 0;
}
.toggle-2-content.active {
left: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="wrapper">
<div class="toggle-1">1</div>
<div class="toggle-1-content">
<p>Some content 1</p>
</div>
<div class="toggle-2">2</div>
<div class="toggle-2-content">
<p>Some content 2</p>
</div>
</div>
</div>
Several issues.
Please study the code below
too many $(document.ready... and no need to store the result of such a statement
Using a data-attribute and a common class, shortens the code a lot. DRY Don't repeat yourself
I simplified the content containers CSS too
$(function() { // on page load
$('.toggle').on("click", function() { // any of the toggles
const $wrapper = $(this).closest(".wrapper");
const id = $(this).data("id");
$(this).toggleClass('active'); // toggle clicked div
const show = $(this).is(".active"); // is it active after we toggled?
$wrapper
.find(".toggle") // find all toggles
.not(this) // exclude the one we clicked
.removeClass("active"); // remove class
$wrapper.find(".content").hide(); // hide any content divs
$("#" + id).toggle(show); // show the one belonging to the clicked toggle
})
})
.container {
width: 100%;
height: 1000px;
margin: 0 auto;
background-color: #eee;
}
.wrapper {
background-color: pink;
position: relative;
display: flex;
align-items: center;
}
.toggle {
display: block;
width: 20px;
height: 20px;
float: left;
cursor: pointer;
color: white;
text-align: center;
background-color: green;
margin: 10px;
}
.active {
background-color: red;
}
.content {
display: none;
background-color: white;
border: 1px solid black;
position: absolute;
top: 40px;
}
#div1 {
left: 0;
}
#div2 {
left: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="wrapper">
<div class="toggle" data-id="div1">1</div>
<div id="div1" class="content">
<p>Some content 1</p>
</div>
<div class="toggle" data-id="div2">2</div>
<div id="div2" class="content">
<p>Some content 2</p>
</div>
</div>
</div>
Working code:
$(document).ready(function() {
$('.toggle-1').click(function() {
if ($('.toggle-2').hasClass('active')) {
// remove toggle-2 active classes
$('.toggle-2').removeClass('active');
$('.toggle-2-content').removeClass('active');
}
$('.toggle-1').toggleClass('active');
$('.toggle-1-content').toggleClass('active');
});
$('.toggle-2').click(function() {
if ($('.toggle-1').hasClass('active')) {
// remove toggle-1 active classes
$('.toggle-1').removeClass('active');
$('.toggle-1-content').removeClass('active');
}
$('.toggle-2').toggleClass('active');
$('.toggle-2-content').toggleClass('active');
});
});
Here is the link to my working version.
A few things to keep in mind:
You don't need to call $(document).ready() multiple times. There's just no reason to call it multiple times on a single page as the event is only fired once.
You need to keep track of state somehow; hence the if ($('el').hasClass('classname')) syntax. Once you handle that properly, it's easy to ensure that each element is 'reset' to its original state when the other is clicked.
Hope that helps!
toggleClass accepts a second boolean parameter that forces the type of toggle, on or off. More than that you can also target multiple elements with a single jQuery call, so use that to your advantage since the classes applied have the same name.
So you could simplify your code to
$(document).ready(function() {
$('.toggle-1').click(function() {
$('.toggle-1, .toggle-1-content').toggleClass('active');
$('.toggle-2, .toggle-2-content').toggleClass('active', false)
})
$('.toggle-2').click(function() {
$('.toggle-2, .toggle-2-content').toggleClass('active');
$('.toggle-1, .toggle-1-content').toggleClass('active', false)
})
})
.container {
width: 100%;
height: 1000px;
margin: 0 auto;
background-color: #eee;
}
.wrapper {
background-color: pink;
position: relative;
display: flex;
align-items: center;
}
.toggle-1,
.toggle-2 {
display: block;
width: 20px;
height: 20px;
float: left;
cursor: pointer;
color: white;
text-align: center;
background-color: green;
margin: 10px;
}
.toggle-1.active,
.toggle-2.active {
background-color: red;
}
.toggle-1-content,
.toggle-2-content {
display: none;
}
.toggle-1-content.active,
.toggle-2-content.active {
display: block;
background-color: white;
border: 1px solid black;
position: absolute;
top: 40px;
}
.toggle-1-content.active {
left: 0;
}
.toggle-2-content.active {
left: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="wrapper">
<div class="toggle-1">1</div>
<div class="toggle-1-content">
<p>Some content 1</p>
</div>
<div class="toggle-2">2</div>
<div class="toggle-2-content">
<p>Some content 2</p>
</div>
</div>
</div>
You can use the method "removeClass" to remove the active class from the other toggle
var oneToggle = $(document).ready(function() {
$(".toggle-1").click(function() {
$(".toggle-1").toggleClass("active")
$(".toggle-1-content").toggleClass("active")
$(".toggle-2").removeClass("active")
$(".toggle-2-content").removeClass("active")
})
})
var twoToggle = $(document).ready(function() {
$(".toggle-2").click(function() {
$(".toggle-1").removeClass("active")
$(".toggle-1-content").removeClass("active")
$(".toggle-2").toggleClass("active")
$(".toggle-2-content").toggleClass("active")
})
})

Categories

Resources