I am using ngx-dropzone and it is all working fine except on hover on <ngx-dropzone-label> it start to flicker.
example video is availble in this Link. it seems dragleave event fired when hovering a child element.
<ngx-dropzone class="dropzone" #dropzonde (change)="onSelect($event)" [accept]="allExtentions" [multiple]="true">
<ngx-dropzone-label>
<img class="empty-mountain" src="assets/icons/empty states/mountain.svg" alt="">
<span class="input-label">test</span>
<button igxButton="outlined" class="secondary-button" igxRipple="white">browse</button>
<div class="dropping-box">
<img class="drag-drop-upload-icon" src="assets/icons/internet/cloud_download.svg" alt="">
<div class="drag-drop-upload-header-text">test 1</div>
<div class="drag-drop-upload-text">test 2</div>
</div>
</ngx-dropzone-label>
</ngx-dropzone>
.dropzone {
display: flex;
align-items: center;
height: 250px;
background: var(--white);
cursor: pointer;
color: var(--g-600-comet);
border: 2px dashed var(--g-500-granite);
border-radius: 5px;
font-size: var(--font-size-16);
justify-content: center;
ngx-dropzone-label {
margin: 0px !important;
display: flex;
flex-direction: column;
align-items: center;
}
}
.ngx-dz-hovered {
background-color: rgba(0, 65, 91, 0.7);
.input-label {
color: var(--w-100-snow)
}
.empty-mountain {
filter: var(--white-filter-icon);
}
.dropping-box {
display: block !important;
z-index: 0;
}
.drag-drop-upload-icon {
width: 95px;
height: 95px;
filter: var(--white-filter-icon);
}
.drag-drop-upload-text,
.drag-drop-upload-header-text {
line-height: 24px;
letter-spacing: 0.15px;
color: var(--white);
padding-top: 1px;
}
.drag-drop-upload-header-text {
font-size: var(--font-size-16);
font-family: var(--font-family-semi-bold);
}
.drag-drop-upload-text {
font-size: var(--font-size-14);
font-family: var(--font-family-regular);
}
.igx-button,
.input-label,
.empty-mountain {
display: none;
}
}
Any idea why it is flickring on child element of that element?
Related
I have tried looking around for this but can't seem to find a question to match my current problem. I am trying to build a mock ecommerce website to practice using React. I have a header component. I want this component to be 100% of the screen width, so that the elements inside this component shrink whenever the page shrinks. I have some global css that sets the height and width of the html and body to 100%:
html, body{
background-color: rgb(167, 72, 72);
height: 100%;
min-width: 100%;
}
I am currently facing two problems, neither of which I understand very well the causes of. When I set my header component (the outermost component) to have a width of 100%, the page shrinks correctly. But when I open up developer tools to check the responsiveness, something goes wrong so that the right side of my header is shrinking faster than the page header_shrink
I am able to fix this by setting the width of my header to "fit-content" instead of "100%". Here is what the header looks like when I shrink the page using developer tools.header_fixed But when I do it this way, the components inside of my header don't shrink correctly. For example, my search bar is supposed to decrease in width as I shrink the page, but when I use "fit-content", it just stays set to whatever size it is. search-bar-constant. When I have the width set to 100% instead of fit content, it looks the way it's supposed to search-bar-fixed.
Sorry for the long explanation, but this is the bulk of my problem. "Width: 100%" allows the items in my header component to shrink correctly, but not the component itself. And "width: fit-content" allows the outer header component to shrink correctly, but not the items inside of it.
Here is the JSX I have for reference:
import React from 'react'
import './Header.css'
import { BiSearchAlt2 as SearchIcon} from "react-icons/bi";
import {RiArrowDropDownLine as DropDownIcon} from "react-icons/ri";
import { CgProfile as Profile } from "react-icons/cg";
import { CgShoppingCart as Cart } from "react-icons/cg";
const Header = () => {
const texts = [
'ORDERS OF $5K SHIP FREE',
'FREE SHIPPING ON SELECT ITEMS: SHOP NOW',
'BUY A RIG AND YOUR ENTIRE ORDER SHIPS FREE'
];
let currentTextIndex = 0;
setInterval(() => {
const shippingDealsText = document.querySelector('.shipping-deals-text');
shippingDealsText.classList.add('out');
setTimeout(() => {
shippingDealsText.textContent = texts[currentTextIndex];
shippingDealsText.classList.remove('out');
currentTextIndex = (currentTextIndex + 1) % texts.length;
}, 1000);
}, 5000);
return (
<div className="header">
<div className="header-top">
<div className="top-logo">
<h5 className='small-logo'>LEVIATHAN</h5>
</div>
<div className="space"></div>
<div className="link-container">
<div className="link-wrap">
Gift Cards
</div>
<div className="link-wrap">
Contact Us
</div>
<div className="link-wrap">
Order Status
</div>
<div className="link-wrap">
Live Chat
</div>
</div>
</div>
<div className="header-middle">
<div className="middle-logo">
<h5 className='big-logo'>LEVIATHAN</h5>
</div>
<div className="search-container">
<div className="search-wrapper">
<input
type="text"
id="search-bar"
placeholder="Search"
className='search'
/>
<div className="search-icon-wrapper">
<SearchIcon className='search-icon'/>
</div>
</div>
</div>
<div className="shipping-deals-container">
<div className="button-container">
<div className="shipping-deals-button">
<span className="deals-text">DAILY SHIPPING DEALS </span>
</div>
</div>
<div className="text-container">
<div className="text-slideshow">
<p className="shipping-deals-text">BUY A RIG AND YOUR ENTIRE ORDER SHIPS FREE</p>
</div>
</div>
</div>
<div className="icons-right">
<Profile className='login-pic'/>
<span>Log In</span>
<Cart className='shopping-cart'/>
</div>
</div>
<div className="header-bottom">
<div className="nav-bar">
<ul className='navigation'>
<li className='menu-items'>
<a href="/" className='button drop-down red'>Shop <DropDownIcon className='drop-icon'/></a>
<a href="/" className='button'>Equipment for Crossfit</a>
<a href="/" className='button'>New Gear</a>
<a href="/" className='button'>Barbells</a>
<a href="/" className='button'>Plates</a>
<a href="/" className='button'>Rigs and Racks</a>
<a href="/" className='button'>Shoes</a>
<a href="/" className='button'>Apparel</a>
<a href="/" className='button'>3 Ships Free</a>
<a href="/" className='button'>Zeus</a>
<a href="/" className='button drop-down'>The Index</a>
</li>
</ul>
</div>
</div>
</div>
)
}
export default Header
Here is the styling I am currently applying:
.header {
min-width: 100%;
margin: 0;
padding: 0;
}
.header-top {
background-color: white;
display: flex;
height: 2.5rem;
width: 100%;
}
.top-logo {
position: relative;
margin-left: 3rem;
}
.space {
flex-grow: 1;
}
.small-logo {
padding-top: 0.5em;
position: relative;
font-size: larger;
color: rgb(133, 133, 133)
}
.link-container {
display: flex;
/*border: 1px solid red;*/
margin-right: 3rem;
}
.link-wrap {
/*border: 1px solid green;*/
font-size: 14px;
padding-left: 1rem;
padding-top: 0.75rem;
}
.link-wrap a {
text-decoration: none;
color:#666666;
cursor: pointer;
}
/* Large section of header, black background */
.header-middle {
background-color: black;
height: 7rem;
display: flex;
}
/* Big LEVIATHAN text */
.middle-logo {
/*border: 1px solid red;*/
position: relative;
margin-left: 3rem;
display: flex;
justify-content: center;
align-items: center;
cursor: co;
}
.big-logo {
font-size: 48px;
/*padding-top: 2rem;*/
position: relative;
color: white;
}
.big-logo:hover {
color: rgb(210, 0, 0);
}
.search-container {
position: relative;
width: 40%;
display: flex;
flex-basis: 60%;
margin-left: 3rem;
align-items: center;
justify-content: center;
}
/*This is what has the appearance of the search bar*/
.search-wrapper {
min-width:100%;
height: 35%;
position: relative;
background-color: white;
display: flex;
flex-basis: 50%;
}
.search-icon-wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 3rem;
}
.search-icon {
color: black;
font-size: 20px;
}
/*This is the actual search bar tucked inside*/
.search {
width: 100%;
height: 100%;
border: none;
outline: none;
margin-left: 1em;
font-size: 17px;
}
.search::placeholder {
color:rgb(94, 94, 94);
}
/* This holds onto both our daily shipping deals button */
/* and our text slideshow */
.shipping-deals-container{
width: 18em;
margin-left: 2.5em;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
/*border: 2px solid rgb(136, 77, 255);*/
}
.shipping-deals-button {
width: 65%;
height: 44%;
background-color: rgb(234, 2, 2);
position: relative;
display: flex;
justify-content: center;
align-items: center;
margin-top: 1.5em;
}
.button-container {
width: 100%;
height: 50%;
/*border: 2px solid magenta;*/
}
.deals-text {
color: white;
font-size: 12px;
position: relative;
text-align: center;
align-items: stretch;
width: 100%;
}
.text-container {
/*border: 2px solid rgb(20, 182, 11);*/
width: 100%;
height: 50%;
}
.text-slideshow {
color: white;
width: 100%;
height: 50%;
font-size: 12px;
}
.shipping-deals-text {
transition: opacity 1s;
opacity: 1;
font-size: 13px;
}
.out {
opacity: 0;
transition: opacity 1s;
}
.shipping-deals-text-red{
color: red;
}
.navigation {
display: flex;
align-items:flex-start;
height: 3rem;
}
.menu-items {
height: 100%;
margin-left: 1.5rem;
padding-right: 1.5rem;
display: flex;
align-items: flex-start;
flex: 1;
}
ul {
list-style-type: none;
background-color: #333333;
}
.button {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
text-decoration: none;
color: white;
text-transform: uppercase;
white-space: nowrap;
padding: 1em;
font-weight: bold;
}
.button:hover {
color:rgb(210, 0, 0)
}
.red {
background-color: rgb(210, 0, 0);
}
.red:hover {
color: white;
}
.drop-icon {
font-size: 25px;
}
.icons-right {
height: 50%;
margin-top: 2em;
min-width: 10%;
display: flex;
justify-content: center;
align-items: center;
margin-right: 1rem;
}
.login-pic {
color: white;
font-size: 20px;
}
.shopping-cart {
color: white;
font-size: 20px;
margin-left: 1rem;
}
.icons-right span {
color: white;
margin-left: 0.5em;
}
#media (max-width: 1025px) {
.shipping-deals-container {
display: none;
}
.header-top {
display: none;
}
.header-middle {
height: 50%;
}
.search-wrapper {
border: 2px solid white;
height: 2rem;
}
.icons-right {
margin-bottom: 2rem;
}
}
I have tried altering the width of my body, and html, but nothing seems to be giving me the solution I am looking for
With width: 100% on .header it shrinks the header the way you want it. That seems to be correct actually.
The element that prevents shrinking is <li class="menu-items"></li> because of display: flex;. Flexbox is by default not wrapping (flex-wrap: nowrap;).
Add flex-wrap. wrap; and you'll see everything will shrink with fit-content or width: 100%;
Hope this helps.
On another note: You shouldn't use <li> (List-Element) as the list. Thats what <ul> (Unsorted list) is for.
It should look more like this ->
<ul>
<li>
Shop
</li>
<li>
Equipment for Crossfit
</li>
<li>
New Gear
</li>
<!-- ... -->
</ul>
I'm not sure what's causing the form button to fire the event of turning the page theme back to white after the dark mode has been clicked and enabled.
Not sure if that may be confusing, but for example if you open the page it's automatically on the light mode theme, when you click "dark" to switch the theme to dark and then click the button "search" while the theme is in "dark", the page will switch back to "light". What am I doing wrong or missing out? Please advise. Also, how could I refractor this JS better and simpler?
Thanks!
HTML - left out the head part intentionally
<html lang="en" color-mode="light">
<body>
<header class="header-container">
<h1 class="title">devfinder</h1>
<div class="light-dark mode">
<span
class="theme-toggle-btn light-hidden light"
aria-label="light theme toggle button">
LIGHT
<img class="light-icon" src="assets/icon-sun.svg" alt="" />
</span>
<span
class="theme-toggle-btn dark-hidden"
aria-label="dark theme toggle button">
DARK
<img src="assets/icon-moon.svg" alt="" />
</span>
</div>
</header>
<main class="content-container">
<section>
<form autocomplete="off" class="form" id="search">
<input
type="text"
id="search"
placeholder="Search GitHub username…" />
<button class="btn">Search</button>
</form>
JS
const themeBtn = document.querySelectorAll(".theme-toggle-btn");
const toggle = function (e) {
if (e.currentTarget.classList.contains("light-hidden")) {
document.documentElement.setAttribute("color-mode", "light");
localStorage.setItem("color-mode", "light");
return;
}
document.documentElement.setAttribute("color-mode", "dark");
localStorage.setItem("color-mode", "dark");
};
themeBtn.forEach((btn) => {
btn.addEventListener("click", toggle);
});
CSS
:root {
--monoFont: 'Space Mono', monospace;
--accent-blue: #0079FF;
--error-red: #F74646;
--light-hover: #60ABFF;
}
:root[color-mode="light"] {
--primary-text-color:#697C9A;
--secondary-text-color: #4B6A9B;
--accent-color: #2B3442;
--background-color: #F6F8FF;
--container-background: #FEFEFE;
--font-color: #222731;
}
:root[color-mode="dark"] {
--primary-text-color: #FFFFFF;
--background-color: #141D2F;
--container-background: #1E2A47;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
:root[color-mode="light"] .light-hidden,
:root[color-mode="dark"] .dark-hidden {
display: none;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: var(--background-color);
height: 100vh;
margin: 0;
color: var(--primary-text-color);
font-family: var(--monoFont);
}
.header-container {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 2em;
}
.header-container, .content-container {
width: 100%;
max-width: 730px;
}
/* header title */
.title {
color: var(--font-color);
font-size: 1.63rem;
}
/* theme toggle btn */
.theme-toggle-btn {
background-color: var(--background-color);
border: none;
color: var(--primary-text-color);
font-size: .7rem;
font-weight: 700;
letter-spacing: 1.5px;
cursor: pointer;
}
.theme-toggle-btn img {
margin: 0 0 -0.45em 0.75em;
width: 20px;
height: 20px;
}
/* search form */
.form {
position: relative;
display: flex;
align-items: center;
height: 69px;
}
.form input {
background-color: var(--container-background);
border: none;
width: 100%;
padding-left: 1.5em;
margin-bottom: 2em;
color: var(--font-color);
font-size: 1.05rem;
font-family: inherit;
font-weight: 400;
border-radius: 10px;
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;;
}
.form input::placeholder {
color: var(--secondary-text-color);
}
.btn {
position: absolute;
top: 50%;
right: 10px;
transform: translateY(-80%);
width: 100%;
max-width: 106px;
height: 50px;
background-color: var(--accent-blue);
border: none;
color: #FFFFFF;
font-size: 1rem;
border-radius: 10px;
cursor: pointer;
}
.btn:hover {
background-color: var(--light-hover);
}
I think when you're clicking the "Search" button, it's refreshing the page and reloads the html template. Because you have "color-mode="light" within the html element, it will then load the page in light mode rather than dark mode.
I think the problem is: your not consuming the selection from localStorage. To persist the user selection, you should check the preference in localStorage when the page loads.
Just made a simple div slider with navigation arrows. The div slider works just fine, except, I want some sort of CSS styling to be applied to the arrows.
That is, when a user clicks the left or right arrow, up to the last item, apply CSS styling telling the user they've reached the end of the slider.
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
let container = document.getElementById('slider')
buttonLeft.addEventListener('click', function() {
container.scrollLeft -= 90
})
buttonRight.addEventListener('click', function() {
container.scrollLeft += 90
})
body {
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper {
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider {
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail {
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child) {
margin-right: 10px;
}
div.thumbnail:nth-child(1) {
background-color: darkturquoise;
}
div.thumbnail:nth-child(2) {
background-color: goldenrod;
}
div.thumbnail:nth-child(3) {
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4) {
background-color: powderblue;
}
div.thumbnail:nth-child(5) {
background-color: firebrick;
}
div.thumbnail:nth-child(6) {
background-color: sienna;
}
div.thumbnail:nth-child(7) {
background-color: bisque;
}
div.thumbnail:nth-child(8) {
background-color: navy;
}
div#slide_wrapper>button {
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper>button:hover {
cursor: pointer;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>
Simply check to see if you need to disable each button based on the position of the scroll. Then if there is a need to disable a button, add the disabled class to the button, otherwise remove it.
Future enhancements.
Remove the hardcoded 360 value for the scroll end. This should be calculated from the size of the carousel items and the width of the viewport.
Allow more than one carousel to work with the same code. This could be achieved by using a javascript class that would hold the elements inside an object, separate from other carousels.
See the demo:
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
let container = document.getElementById('slider')
let checkScroll = function() {
if (container.scrollLeft <= 0)
buttonLeft.classList.add("disabled");
else
buttonLeft.classList.remove("disabled");
if (container.scrollLeft >= 360)
buttonRight.classList.add("disabled");
else
buttonRight.classList.remove("disabled");
}
checkScroll();
buttonLeft.addEventListener('click', function() {
container.scrollLeft -= 90;
checkScroll();
})
buttonRight.addEventListener('click', function() {
container.scrollLeft += 90;
checkScroll();
})
body {
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper {
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider {
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail {
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child) {
margin-right: 10px;
}
div.thumbnail:nth-child(1) {
background-color: darkturquoise;
}
div.thumbnail:nth-child(2) {
background-color: goldenrod;
}
div.thumbnail:nth-child(3) {
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4) {
background-color: powderblue;
}
div.thumbnail:nth-child(5) {
background-color: firebrick;
}
div.thumbnail:nth-child(6) {
background-color: sienna;
}
div.thumbnail:nth-child(7) {
background-color: bisque;
}
div.thumbnail:nth-child(8) {
background-color: navy;
}
div#slide_wrapper>button {
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper>button:hover {
cursor: pointer;
}
.slide_arrow.disabled {
opacity: 0.2;
cursor: auto !important;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>
a simple solution to this is to actually create a css class that defines the style of arrows when there are no more items and then just add/remove class based on current index of items
I have this piece of code:
function dropdown() {
let dropdownText = document.querySelector(".dropdown-button");
let item = document.querySelector(".dropdown-items").getElementsByTagName("div")[0];
var aux = dropdownText.innerHTML;
dropdownText.innerHTML = item.innerHTML;
item.innerHTML = aux;
document.querySelector(".dropdown-items").style.display = "none";
}
.btn {
width: 150px;
height: 30px;
border-radius: 5px;
border: none;
box-shadow: 0 3px 1px 0 black;
text-align: center;
line-height: 30px;
color: black;
font-family: Consolas, monaco, monospace;
}
.dropdown {
margin: 0 50px 0 50px;
position: relative;
}
.dropdown-items {
display: none;
position: absolute;
}
.dropdown:hover .dropdown-button {
background: red;
}
.dropdown:hover .dropdown-items {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.dropdown-button {
background: orange;
font-size: 15px;
color: white;
}
.dropdown-button:hover {
cursor: pointer;
}
.dropdown-items div {
margin-top: 5px;
transform: scaleX(90%);
height: 20px;
line-height: 20px;
background: lightgray;
padding: 5px 0 5px 0;
text-align: center;
}
.dropdown-items div:hover {
cursor: pointer;
background: gray;
}
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn" onclick="dropdown();">Interrupt</div>
</div>
</div>
As you can see, I am trying to make a dropdown. I also want to make it so that when I click an option in the dropdown, the dropdown items stop showing as the option has been selected. That's why I added the line document.querySelector(".dropdown-items").style.display = "none"; in the JS file as I thought the .dropdown:hover .dropdown-items part of my CSS would change back the display of those elements to visible when hovering again, but when hovering again after the first click, the dropdown does not show anymore. Why is happening and how can I fix this?
Inline styles override any stylesheet styles, as they have maximum CSS specificity.
Instead of working with inline styles (el.style.display = "none"), work with a CSS class open that you toggle. Also don't make use of inline event listeners like onclick. Those are insecure and widely considered bad practice for a whole bunch of reasons. Use addEventListener instead.
// get all the dropdowns in a NodeList
const dropdowns = document.querySelectorAll('.dropdown');
// iterate over the list
for (const dropdown of dropdowns) {
// for each dropdown, add a mouseenter and mouseleave listener
dropdown.addEventListener('mouseenter', function(event) {
dropdown.classList.add('open');
});
dropdown.addEventListener('mouseleave', function(event) {
dropdown.classList.remove('open');
});
// Now add a click listener to each <div class="dropdown-items">
// that transfers the text and closes the dropdown
dropdown.querySelector('.dropdown-items').addEventListener(
'click',
function(event) {
this.previousElementSibling.textContent = this.textContent;
dropdown.classList.remove('open');
}
);
}
.btn {
width: 150px;
height: 30px;
border-radius: 5px;
border: none;
box-shadow: 0 3px 1px 0 black;
text-align: center;
line-height: 30px;
color: black;
font-family: Consolas, monaco, monospace;
}
.dropdown {
display: inline-block;
position: relative;
}
.dropdown-items {
display: none;
position: absolute;
}
.dropdown:hover .dropdown-button {
background: red;
}
.dropdown.open .dropdown-items {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.dropdown-button {
background: orange;
font-size: 15px;
color: white;
}
.dropdown-button:hover {
cursor: pointer;
}
.dropdown-items div {
margin-top: 5px;
transform: scaleX(90%);
height: 20px;
line-height: 20px;
background: lightgray;
padding: 5px 0 5px 0;
text-align: center;
}
.dropdown-items div:hover {
cursor: pointer;
background: gray;
}
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn">Interrupt</div>
</div>
</div>
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn">Whatever</div>
</div>
</div>
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn">Another one</div>
</div>
</div>
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn">Here we go</div>
</div>
</div>
I try to change the variable of passLength using 4 different buttons. This will affect the length of the string result of the function. The problem I'm noticing is that when I press for example the "24" button, then run the main function with the (now commented out) console log, passLength still logs as the default of 16. I believe this is because it was declared globally at the beginning, and my changes on button click are not taking place since they are happening locally within functions. Because when I console log within the buttonclick functions, it always puts out the value I need.
So my question is: How do I change this global passLength variable with button clicks?
let passLength = 16; //Default lngth of password. This will be changable later on
document.getElementById('btn8').addEventListener('click', function(){
let passLength = 8;
console.log(passLength)
return passLength;
});
document.getElementById('btn16').addEventListener('click', function(){
let passLength = 16;
console.log(passLength)
return passLength;
});
document.getElementById('btn20').addEventListener('click', function(){
let passLength = 20;
console.log(passLength)
return passLength;
});
document.getElementById('btn24').addEventListener('click', function(){
let passLength = 24;
console.log(passLength)
return passLength;
});
randomString(passLength)
function randomString(passLength){
//console.log(passLength)
var randomPassword = '';
var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=+?!$/><)(%&*'
for(var i, i = 0; i < passLength; i++){
randomPassword += characters.charAt(Math.floor(Math.random() * characters.length))
};
console.log(randomPassword)
return randomPassword;
};
document.getElementById('btn').addEventListener('click', function(){
document.getElementById('string').textContent = randomString(passLength);
});
HTML:
<div id="contentWrapper">
<div class="row">
<h2>Generate a Secure Password</h2>
</div>
<div class="row">
<div id="stringContainer">
<p id="string">Click the button to start!</p> <!--password inside-->
</div>
</div>
<div class="btnRow">
<div id="generateButton">
<button id="btn">Generate</button>
</div>
</div>
<div class="row">
<!--empty row-->
</div>
<div class="h3Row">
<h3>Select Number of Characters:</h3>
</div>
<div class="selectingRow">
<div class="selectorBtn">
<button id="btn8" class="slctBtn">8</button>
</div>
<div class="selectorBtn">
<button id="btn16" class="slctBtn">16</button>
</div>
<div class="selectorBtn">
<button id="btn20" class="slctBtn">20</button>
</div>
<div class="selectorBtn">
<button id="btn24" class="slctBtn">24</button>
</div>
</div>
</div>
CSS
html, body {
font-family: sans-serif;
height: 100%;
margin: 0;
padding: 0;
}
#contentWrapper {
display: flex;
flex-direction: column;
height: 100vh;
justify-content: center;
align-items: center;
background-color: rgb(177, 192, 177);
}
h2 {
padding: 0;
margin: 0;
display: flex;
justify-content: center;
}
.row {
display: flex;
justify-content: center;
align-items: center;
padding: 4px 0;
width: 100%;
min-height: 50px;
}
.btnRow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 35px;
}
.h3Row {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
max-height: 25px;
}
.selectingRow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 25px;
}
.slctBtn {
min-height: 20px;
min-width: 20px;
border-radius: 4px;
border: none;
color: rgb(0, 0, 0);
background-color: rgb(255, 168, 168);
transition: all 0.07s linear;
font-weight: bold;
margin-left: 5px;
margin-right: 5px;
}
.slctBtn:hover { /*give this an animation later, maybe a little shake*/
background-color: rgb(201, 99, 99);
}
.slctBtn:active { /*give this an animation too*/
background-color: rgb(201, 99, 99);
border: 2px solid black;
}
#generateButton {
display: flex;
justify-content: center;
align-items: center;
}
#btn {
min-height: 50px;
min-width: 110px;
border-radius: 4px;
border: none;
color: rgb(0, 0, 0);
font-weight: bold;
font-size: large;
background-color: rgb(255, 168, 168);
transition: all 0.07s linear;
}
#btn:hover { /*give this an animation later, maybe a little shake*/
background-color: rgb(201, 99, 99);
}
#btn:active { /*give this an animation too*/
background-color: rgb(201, 99, 99);
border: 2px solid black;
}
#stringContainer { /*Box*/
width: 300px;
height: 50px;
background-color: #636161;
color: #fff;
border-radius: 5px;
border: none;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
#string {
display: flex;
letter-spacing: 2.1px;
}
You are re-declaring passLength with let (block scope) within each event handler which creates new variables, rather than affecting the global one. Remove all the let declarations in each callback to affect the one Global.
let passLength = 16; //Default lngth of password. This will be changable later on
document.getElementById('btn8').addEventListener('click', function(){
passLength = 8;
console.log(passLength)
return passLength;
});
document.getElementById('btn16').addEventListener('click', function(){
passLength = 16;
console.log(passLength)
return passLength;
});
document.getElementById('btn20').addEventListener('click', function(){
passLength = 20;
console.log(passLength)
return passLength;
});
document.getElementById('btn24').addEventListener('click', function(){
passLength = 24;
console.log(passLength)
return passLength;
});
randomString(passLength)
function randomString(passLength){
//console.log(passLength)
var randomPassword = '';
var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=+?!$/><)(%&*'
for(var i, i = 0; i < passLength; i++){
randomPassword += characters.charAt(Math.floor(Math.random() * characters.length))
};
console.log(randomPassword)
return randomPassword;
};
document.getElementById('btn').addEventListener('click', function(){
document.getElementById('string').textContent = randomString(passLength);
});
html, body {
font-family: sans-serif;
height: 100%;
margin: 0;
padding: 0;
}
#contentWrapper {
display: flex;
flex-direction: column;
height: 100vh;
justify-content: center;
align-items: center;
background-color: rgb(177, 192, 177);
}
h2 {
padding: 0;
margin: 0;
display: flex;
justify-content: center;
}
.row {
display: flex;
justify-content: center;
align-items: center;
padding: 4px 0;
width: 100%;
min-height: 50px;
}
.btnRow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 35px;
}
.h3Row {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
max-height: 25px;
}
.selectingRow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 25px;
}
.slctBtn {
min-height: 20px;
min-width: 20px;
border-radius: 4px;
border: none;
color: rgb(0, 0, 0);
background-color: rgb(255, 168, 168);
transition: all 0.07s linear;
font-weight: bold;
margin-left: 5px;
margin-right: 5px;
}
.slctBtn:hover { /*give this an animation later, maybe a little shake*/
background-color: rgb(201, 99, 99);
}
.slctBtn:active { /*give this an animation too*/
background-color: rgb(201, 99, 99);
border: 2px solid black;
}
#generateButton {
display: flex;
justify-content: center;
align-items: center;
}
#btn {
min-height: 50px;
min-width: 110px;
border-radius: 4px;
border: none;
color: rgb(0, 0, 0);
font-weight: bold;
font-size: large;
background-color: rgb(255, 168, 168);
transition: all 0.07s linear;
}
#btn:hover { /*give this an animation later, maybe a little shake*/
background-color: rgb(201, 99, 99);
}
#btn:active { /*give this an animation too*/
background-color: rgb(201, 99, 99);
border: 2px solid black;
}
#stringContainer { /*Box*/
width: 300px;
height: 50px;
background-color: #636161;
color: #fff;
border-radius: 5px;
border: none;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
#string {
display: flex;
letter-spacing: 2.1px;
}
<div id="contentWrapper">
<div class="row">
<h2>Generate a Secure Password</h2>
</div>
<div class="row">
<div id="stringContainer">
<p id="string">Click the button to start!</p> <!--password inside-->
</div>
</div>
<div class="btnRow">
<div id="generateButton">
<button id="btn">Generate</button>
</div>
</div>
<div class="row">
<!--empty row-->
</div>
<div class="h3Row">
<h3>Select Number of Characters:</h3>
</div>
<div class="selectingRow">
<div class="selectorBtn">
<button id="btn8" class="slctBtn">8</button>
</div>
<div class="selectorBtn">
<button id="btn16" class="slctBtn">16</button>
</div>
<div class="selectorBtn">
<button id="btn20" class="slctBtn">20</button>
</div>
<div class="selectorBtn">
<button id="btn24" class="slctBtn">24</button>
</div>
</div>
</div>