Been struggling hours now to find a solution for this.
I´m kinda new to JS so this is kinda tricky for me.
Was hoping someone here maybe had a bit of time to give me a solution.
Thanks.
If you click on the question mark (top right) it starts my animation to show the slider, and when you click the X it starts an animation to hide the slider.
I would like this to happen infinite. So when X has been clicked and the slider goes in, you can just click on the question mark and the slider pops up again, and so forth.
let press = document.getElementById("questionClick");
let show = document.getElementById("show");
let showOpt = document.getElementById("showSecond")
let hide = document.getElementById("exit");
let arrow = document.getElementById("nextArrow");
let info = document.getElementsByClassName("info");
show.classList.remove("info");
press.addEventListener("click", function () {
show.classList.add("info");
arrow.style.opacity = "0"
exit.style.opacity = "0"
setTimeout(function() {
exit.style.opacity = "100"
}, (400));
setTimeout(function() {
arrow.style.opacity = "100"
}, (1300));
});
hide.addEventListener("click", function () {
showOpt.style.width = "0em"
show.classList.add("infoExit");
hide.style.opacity = "40%"
setTimeout(function() {
arrow.style.opacity = "0"
}, (00));
setTimeout(function() {
exit.style.opacity = "0"
}, (800));
});
arrow.addEventListener("click", function() {
showOpt.style.width = "15em"
showOpt.style.height = "668px"
showOpt.style.padding = "1em"
});
const resultEl = document.getElementById('result');
const lengthEl = document.getElementById('length');
const uppercaseEl = document.getElementById('uppercase');
const lowercaseEl = document.getElementById('lowercase');
const numbersEl = document.getElementById('numbers');
const symbolsEl = document.getElementById('symbols');
const generateEl = document.getElementById('generate');
const clipboard = document.getElementById('clipboard');
const randomFunc = {
lower: getRandomLower,
upper: getRandomUpper,
number: getRandomNumber,
symbol: getRandomSymbol
}
clipboard.addEventListener('click', () => {
const textarea = document.createElement('textarea');
const password = resultEl.innerText;
if(!password) { return; }
textarea.value = password;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
textarea.remove();
alert('Password copied to clipboard');
});
generate.addEventListener('click', () => {
const length = +lengthEl.value;
const hasLower = lowercaseEl.checked;
const hasUpper = uppercaseEl.checked;
const hasNumber = numbersEl.checked;
const hasSymbol = symbolsEl.checked;
resultEl.innerText = generatePassword(hasLower, hasUpper, hasNumber, hasSymbol, length);
});
function generatePassword(lower, upper, number, symbol, length) {
let generatedPassword = '';
const typesCount = lower + upper + number + symbol;
const typesArr = [{lower}, {upper}, {number}, {symbol}].filter(item => Object.values(item)[0]);
// Doesn't have a selected type
if(typesCount === 0) {
return '';
}
// create a loop
for(let i=0; i<length; i+=typesCount) {
typesArr.forEach(type => {
const funcName = Object.keys(type)[0];
generatedPassword += randomFunc[funcName]();
});
}
const finalPassword = generatedPassword.slice(0, length);
return finalPassword;
}
/* Generating random lower case characters */
function getRandomLower() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 97);
}
/* Generating random upper case characters */
function getRandomUpper() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 65);
}
/* Generating random numbers */
function getRandomNumber() {
return +String.fromCharCode(Math.floor(Math.random() * 10) + 48);
}
/* Generating random symbols */
function getRandomSymbol() {
const symbols = '!##$%^&*(){}[]=<>/,.'
return symbols[Math.floor(Math.random() * symbols.length)];
}
.info {
animation: popup 1.6s;
animation-fill-mode:forwards;
}
#keyframes popup {
0% {
white-space: nowrap;
height: 4em;
width: 0em;
padding: 0.5em 1em 1em;
opacity: 0;
bottom: 13.9em; left: 9.7em;
color: rgba(0, 0, 0, 0);
}
40%, 50% {
width: 14em;
white-space: nowrap;
color: rgba(0, 0, 0, 0.555);
height: 4em;
padding: 0.5em 1em 1em;
opacity: 100;
bottom: 14em; left: 16.5em
}
60% {
white-space: normal;
}
90%, 100% {
height: 668px ;
width: 14em;
opacity: 100;
white-space: normal;
bottom: 0; left: 16.5em
}
}
.infoExit {
animation: popin 1.6s;
}
#exit {
padding: .3em .3em 0 0;
color: var(--clr-i-dim);
}
#exit:hover{
color: var(--clr-minibtn-inactive);
}
#keyframes popin {
0% {
height: 668px ;
width: 14em;
white-space: normal;
bottom: 0; left: 16.7em;
opacity: 100;
}
40%, 50% {
width: 14em;
white-space: nowrap;
height: 4em;
padding: 0.5em 1em 1em;
opacity: 100;
bottom: 14em; left: 16.5em;
}
50% {
white-space: nowrap;
color: rgba(0, 0, 0, 0.555);
}
80%, 100% {
white-space: nowrap;
height: 4em;
width: 0em;
padding: 0.5em 0em 1em;
opacity: 0;
bottom: 13.9em; left: 9.7em;
color: rgba(0, 0, 0, 0);
}
}
#infohead {
font-size: var(--fs-large);
font-weight: var(--fw-primary);
margin: 0.7em 0 0;
}
#show {
padding: 1em;
opacity: 0;
height: 668px ; width: 12em;
color: var(--txtclr-accent);
cursor: pointer;
font-size: var(--fs-info);
background: linear-gradient(45deg, #83b7da , #958bbb);
position: relative; left: 15.7em ; bottom: 0em; right: 0;
overflow: hidden;
border-radius: 0 .5em .5em 0;
}
#import url(https://fonts.googleapis.com/css?family=Montserrat);
#import url("https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700");
:root {
--ff-primary: 'Source Sans Pro', sans-serif;
--ff-accent: "Roboto", sans-serif;
--ff-option: "Open Sans", sans-serif;
--ff-number: 'Lato', sans-serif;
--fw-primary: 600;
--fw-accent: 400;
--fs-nomal: 1.2rem;
--fs-info: 1.3em;
--fs-large: 1.5rem;
--clr-primary: #50a3a2;
--clr-accent: #23235bdc;
--clr-white: rgba(255, 255, 255, 0.8);
--clr-btn: #530dc5;
--clr-btn-hover: #7031d4;
--clr-minibtn-hover: #4e694f;
--clr-minibtn-inactive: #943f3f;
--clr-shadow: 0px 5px 13px rgba(0, 0, 0, 0.993);
--clr-bg-primary: #4f65dd;
--clr-bg-accent: #aaa4a4 ;
--clr-i-dim: rgba(28, 28, 31, 0.637);
--txtclr-primary: rgba(255, 255, 255, 0.897);
--txtclr-accent: #212121 ;
}
* {
box-sizing: border-box;
}
html {
}
body {
background: var(--clr-primary);
color: var(--txtclr-primary);
font-family: var(--ff-primary);
display: flex; flex-direction: column;
align-items: center; justify-content: center;
min-height: 100vh;
background: -webkit-linear-gradient(top left, var(--clr-bg-primary) 0%, #ffffff 100%);
background: -moz-linear-gradient(top left, var(--clr-bg-primary) 0%, #ffffff 100%);
background: -o-linear-gradient(top left, var(--clr-bg-primary) 0%, #ffffff 100%);
background: linear-gradient(to bottom right, var(--clr-bg-primary) 0%, var(--clr-bg-accent) 100%);
}
h2 {
text-align: center;
margin: .2em 0 .8em;
}
h3 {
background: var(--clr-white);
color: var(--txtclr-accent);
font-family: var(--ff-option);
font-weight: var(--fw-accent);
line-height: 2rem;
}
label {
font-weight: var(--fw-primary);
font-family: var(--ff-option);
}
li {
margin: 1.8em 0;
list-style: none;
}
input {
cursor: pointer;
font-family: var(--ff-primary);
}
.container {
background: var(--clr-accent);
box-shadow: var(--clr-shadow);
position: absolute;
padding: 2em;
width:min(500px, 25em);
height: 668px;
}
.setting {
display: flex; justify-content: space-between; align-items: center;
}
.result-container {
background-color: rgba(168, 162, 162, 0.4);
display: flex; justify-content: flex-start; align-items: center;
position: relative;
font-size: var(--fs-nomal); letter-spacing: .14rem;
padding: 1em .6em; margin: 0 0 0.3em;
height: 2.6em;
}
.result-container #result {
word-wrap: break-word;
}
.result-container .btn {
font-size: 2rem;
position: absolute; top: 0.15em; right: 0.15em;
height: 1.3em; width: 1.3em;
}
.btn {
background: var(--clr-btn);
color: var(--txtclr-primary);
cursor: pointer;
border: none;
font-size: var(--fs-nomal);
padding: .6em;
}
.btn-large {
display: block;
width: 100%; height: 3.5em;
transition: .6s; overflow: hidden;
margin-top: 1.5em; border-radius: 4px;
transform: translateX(0%) translateY(0%);
}
#length {
height: 2.5em; width: 12em;
margin: 2em 0 1.7em; padding: 0 1em;
outline: 0;
color: var(--clr-bg-accent);
border: 0; border-radius: 5px;
outline: none;
cursor: pointer;
}
/* ICONS */
#questionClick, #exit, #exitOpt {
position: absolute; top: 0.3em; right: 0.3em;
}
#exit, #nextArrow {
transition: .2s; opacity: 0;
z-index: 999;
}
#nextArrow, #nextArrowOpt{
position: absolute; bottom: .4em; right: .4em;
}
#nextArrowOpt {
opacity: 100;
}
.far {
position: relative; bottom: 0.55em; right: 0.25em;
}
/* ICONS */
#keyframes jump {
0% {
top: 0.3em;
}
50% {
top: 0.32em;
}
100% {
top: 0.3em;
}
}
#showSecond {
position: absolute; left: 15.7em ; bottom: 0em; right: 0;
background: linear-gradient(45deg, #9fc4dd , #7d62dd);
opacity: 100;
white-space: normal;
height: 0px ; width: 0em;
cursor: pointer;
font-size: var(--fs-nomal); line-height: 1.5em;
position: relative; left: 19.2em ; bottom: 34.1em; right: 0;
overflow: hidden;
border-radius: 0 .5em .5em 0 ;
transition: 1s;
}
/* btn-large Effect */
button.btn-large:focus {
outline: 0;
}
button.btn-large:before {
content: '';
background: var(--clr-btn);
opacity: .5; filter: blur(30px);
transform: translateX(-100px) skewX(-15deg);
}
button.btn-large:after {
content: '';
display: block; position: absolute;
background: rgba(255, 255, 255, 0.2);
width: 30px; height: 100%;
left: 45px; top: 0;
opacity: 0; filter: blur(5px);
transform: translateX(-100px) skewX(-15deg);
}
button.btn-large:hover {
background: var(--clr-btn-hover);
}
button.btn-large:hover:before {
transform: translateX(300px) skewX(-15deg);
opacity: 0.6;
transition: .7s; }
button.btn-large:hover:after {
transform: translateX(300px) skewX(-15deg);
opacity: 1;
transition: .7s;
} /* btn-large Effect */
/* Mini button Effect */
.styled-checkbox {
position: absolute;
opacity: 100;
}
.styled-checkbox + label {
position: relative;
cursor: pointer;
padding: 0;
transition: 0.5s; }
.styled-checkbox + label:before {
content: '';
display: inline-block; vertical-align: text-top;
width: 20px; height: 20px;
background: var(--clr-minibtn-inactive); }
.styled-checkbox:hover + label:before {
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.342);
}
.styled-checkbox:focus + label:before {
box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.12); }
.styled-checkbox:checked + label:before {
background: var(--clr-minibtn-hover); }
.styled-checkbox:disabled + label {
color: #b8b8b8;
cursor: auto; }
.styled-checkbox:disabled + label:before {
box-shadow: none;
background: #ddd; }
.styled-checkbox:checked + label:after {
content: '';
position: absolute; left: 5px; top: 9px;
width: 2px; height: 2px;
background: white; box-shadow: 2px 0 0 white,
4px 0 0 white,
4px -2px 0 white,
4px -4px 0 white,
4px -6px 0 white,
4px -8px 0 white;
transform: rotate(45deg); }
/* Mini button Effect */
.range {
-webkit-appearance: none;
background: none;
}
.range::-webkit-slider-runnable-track {
background-color: #d7dbdd;
height: 6px;
border-radius: 3px;
border: 1px solid transparent;
}
.range::-ms-tooltip { display: none; /* display and visibility only */ }
.range::-webkit-slider-thumb {
-webkit-appearance: none;
border-radius: 100%;
background-color: #6574CF;
height: 18px;
width: 18px;
margin-top: -7px;
}
output {
min-width: 1em;
font-family: var(--ff-number);
font-size: 16px;
border-radius: 3px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="CS.css">
<script src="https://kit.fontawesome.com/79efab5353.js" crossorigin="anonymous"></script>
<script src="CS.js" defer></script>
<title>Document</title>
</head>
<body>
<div>
<h3 class="info" class="infoExit" id="show" class="show">
<span style = "">
<i id="exit" class="fas fa-times"></i>
</span>
<p id="infohead">Did you know?</p>
<br>
<br>
<b>6.850.000</b> passwords are getting hacked each day?
<br>
<br>
That is <b>158</b> each second!
<br>
<br>
Stop that from being you.
<br>
<br>
Let us help you make a strong password.
<span>
<i id="nextArrow" class="fas fa-chevron-circle-right"></i>
</span>
</h3>
</div>
<div class="container">
<h2>Password Generator</h2>
<div class="result-container">
<span id="result"></span>
<button class="btn" id="clipboard">
<section style = "font-size: 0.6em;">
<i class="far fa-clipboard"></i>
</section>
</button>
</div>
<span style = "font-size: 2em; color: rgb(209, 204, 214)">
<i id="questionClick" class="fas fa-question-circle"></i>
</span>
<div class="settings">
<div class="setting">
<label>Password length</label>
<input type="range" class="range" id="length" min='4' max='20' value='20' onmousemove="rangevalue1.value=value" />
<output id="rangevalue1"></output>
</div>
<div class="setting">
<label>Include uppercase letters</label>
<li>
<input class="styled-checkbox" id="uppercase" type="checkbox" value="value2" checked>
<label for="uppercase"></label>
</li>
</div>
<div class="setting">
<label>Include lowercase letters</label>
<li>
<input class="styled-checkbox" id="lowercase" type="checkbox" value="value2" checked>
<label for="lowercase"></label>
</li>
</div>
<div class="setting">
<label>Include numbers</label>
<li>
<input class="styled-checkbox" id="numbers" type="checkbox" value="value2" checked>
<label for="numbers"></label>
</li>
</div>
<div class="setting">
<label for="styled-checkbox-2">Include symbols</label>
<li>
<input class="styled-checkbox" id="symbols" type="checkbox" value="value2" checked>
<label for="symbols"></label>
</li>
</div>
</div>
<button class="btn btn-large" id="generate">
Generate password
</button>
<h3 id="showSecond">
<span style = "">
<i id="exitOpt" class="fas fa-times"></i>
</span>
<p id="infohead">What is a safe password?</p>
<br>
<br>
<b>7 characters</b> is normally the <b>minimum</b> length of a password with mixed symbols. <br><br>But it is highly recomended to use much more.
<br>
<br>
<b>The best possible password contains of 12 or more characters, mixed with symbols, numbers. lower & uppercase characters.</b>
<span>
<i id="nextArrowOpt" class="fas fa-chevron-circle-right"></i>
</span>
</h3>
</div>
</body>
</html>
Try using these function as below. Have updated the bare minimum.
press.addEventListener("click", function () {
show.classList.add("info");
show.classList.remove("infoExit");
arrow.style.opacity = "0"
exit.style.opacity = "0"
setTimeout(function() {
exit.style.opacity = "100"
}, (400));
setTimeout(function() {
arrow.style.opacity = "100"
}, (1300));
});
hide.addEventListener("click", function () {
setTimeout(function() {
show.classList.remove("info");
},1600);
showOpt.style.width = "0em"
hide.style.opacity = "40%"
show.classList.add("infoExit");
setTimeout(function() {
arrow.style.opacity = "0"
}, (00));
setTimeout(function() {
exit.style.opacity = "0"
}, (800));
});
I think your problem is your infoExit class that you don't remove after closing an idea would be to use maybe a toggle variable
//remove show.classList.remove("info");
let togglePress = false;
press.addEventListener("click", function () {
show.classList.remove("infoExit");
if (!togglePress) {
show.classList.add("info");
arrow.style.opacity = "0";
exit.style.opacity = "0";
setTimeout(function () {
exit.style.opacity = "100";
}, 400);
setTimeout(function () {
arrow.style.opacity = "100";
}, 1300);
togglePress = true;
}
})
hide.addEventListener("click", function () {
show.classList.remove("info");
if (togglePress) {
showOpt.style.width = "0em";
show.classList.add("infoExit");
hide.style.opacity = "40%";
setTimeout(function () {
arrow.style.opacity = "0";
}, 00);
setTimeout(function () {
exit.style.opacity = "0";
}, 800);
togglePress = false;
}
});
also you have several class attributes on your component which is not necessary
<h3 id="show">
<span id="exit">
<i class="fas fa-times"></i>
</span>
<p id="infohead">Did you know?</p>
<br />
<br />
<b>6.850.000</b> passwords are getting hacked each day?
<br />
<br />
That is <b>158</b> each second!
<br />
<br />
Stop that from being you.
<br />
<br />
Let us help you make a strong password.
<span>
<i id="nextArrow" class="fas fa-chevron-circle-right"></i>
</span>
</h3>
Related
What's going on and what should be going on
I built a 3 d carousel popup. There are 3 slides; each slide must show a paragraph if it's "selected".
The z-index for the "selected" one always equals 1, the one on the right equals 0 and the one on the left equals -1.
I tried to add and remove visibility from the paragraphs if the z-index for the slide = 1. But unfortunately,your text it only works when I open the page because that's when the z-index is being checked I guess.
I would like to fade in the paragraphing that belongs to the slide every time it's "selected".
(I know my code for this might be 100% wrong.)
What I think should work...
I think I might need some sort of a swipe event listener but I'm not sure and I don't know how to do one of those.
HTML
`
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://kit.fontawesome.com/661fc68da9.js" crossorigin="anonymous"></script>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" />
<!-- Link Swiper's CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper/swiper-bundle.min.css" />
<script src="https://kit.fontawesome.com/661fc68da9.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/swiper/swiper-bundle.min.js"></script>
</head>
<body>
<button onclick="Size()"></button>
<div class="sizeGuidance">
<form data-multi-step2>
<div class="whatGuideD" data-step2>
<br>
<h1>The Size Guide</h1>
<div class="swiper mySwiper">
<div class="swiper-wrapper">
<div id="sw1" class="swiper-slide">
<span style="--i:1;"><button type="button" class="pickGuideD" ><i class="fa-solid fa-ruler fa-3x" style=" display: flex; flex-wrap: wrap;justify-content: center; margin-bottom: 20px; margin-top: 15px; " ></i>Quick Guide</button></span>
</div>
<div id="sw2" class="swiper-slide">
<span style="--i:2;"><button type="button" class="pickGuideD" ><i class="fa-solid fa-bullseye fa-2x" style=" display: flex; flex-wrap: wrap;justify-content: center; margin-bottom: 20px; margin-top: 15px" ></i>Super Guide</button></span>
</div>
<div id="sw3" class="swiper-slide">
<span style="--i:3;"><button type="button" class="pickGuideD" ><i class="fa-solid fa-square-poll-horizontal fa-2x" style=" display: flex; flex-wrap: wrap;justify-content: center; margin-bottom: 20px; margin-top: 15px" ></i>Size Chart</button></span>
</div>
</div>
<div class="swiper-pagination"></div>
<p id="d1" class="d1">Get to know your size in less than 1 minute. <br> - no measuring bands required.</p>
<p id="d2" class="d1">Get a more accurate size recommendation. <br> - no measuring bands required.</p>
<p id="d3" class="d1">You already know your measurments? <br> here is the size guide.</p>
</div>
</div>
</form>
<form data-multi-step2M>
<div class="whatGuideM" data-step2M>
<br>
<h1>The Size Guide</h1>
<br>
<div class="swiper mySwiper">
<div class="swiper-wrapper">
<div class="swiper-slide">
<span style="--i:1;"><button type="button" class="pickGuideM" ><i class="fa-solid fa-ruler fa-3x" style=" display: flex; flex-wrap: wrap;justify-content: center; margin-bottom: 20px; margin-top: 15px; " ></i>Quick Guide</button></span>
</div>
<div class="swiper-slide">
<span style="--i:2;"><button type="button" class="pickGuideM" ><i class="fa-solid fa-bullseye fa-3x" style=" display: flex; flex-wrap: wrap;justify-content: center; margin-bottom: 20px; margin-top: 15px" ></i>Super Guide</button></span>
</div>
<div class="swiper-slide">
<span style="--i:3;"><button type="button" class="pickGuideM" ><i class="fa-solid fa-square-poll-horizontal fa-3x" style=" display: flex; flex-wrap: wrap;justify-content: center; margin-bottom: 20px; margin-top: 15px" ></i>Size Chart</button></span>
</div>
</div>
<div class="swiper-pagination"></div>
<p id="d1" ></p>
</div>
</div>
</form>
</div>
</body>
</html>
`
CSS
`
<style>
.d1 {
visibility: hidden;
opacity: 0;
transition: 0.5s ease-in-out;
position: absolute;
}
.d1.showDisc1{
visibility: visible;
opacity: 1;
transition: 0.5s ease-in-out;
}
.d2 {
visibility: hidden;
opacity: 0;
transition: 0.5s ease-in-out;
position: absolute;
}
.d2.showDisc2{
visibility: visible;
opacity: 1;
transition: 0.5s ease-in-out;
}
.d3 {
visibility: hidden;
opacity: 0;
transition: 0.5s ease-in-out;
position: absolute;
}
.d3.showDisc3{
visibility: visible;
opacity: 1;
transition: 0.5s ease-in-out;
}
</style>
<style>
#import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap');
</style>
<style>
/*only desktop*/
.whatGuideD {
display: none;
}
#media only screen and (min-width: 900px) {
.whatGuideD {display: block;
}
.whatGuideM {display: none;
}
}
</style>
<!-- Demo styles -->
<style>
html {
height: -webkit-fill-available;
}
body {
position: relative;
height: 100%;
}
body {
background: #eee;
font-size: 14px;
color: #000;
margin: 0;
padding: 0;
width: 100%;
height: 100vh;
height: -webkit-fill-available;
}
.swiper {
width: 100%;
padding-top: 0;
padding-bottom: 50px;
padding-left: 0;
padding-right: 0;
}
.swiper-slide {
background-position: center;
background-size: cover;
width: 60%;
max-width: 500px;
height: 75vh;
max-height: 500px;
border-radius: 15px;
background: rgb(238, 235, 241);
box-shadow: 10px 10px 10px -1px rgba(10, 99, 169, 0.16),
-10px -10px 10px -1px rgba(255, 255, 255, 0.70);
-webkit-box-reflect: below 1px linear-gradient(transparent, transparent, #fff6)
}
.swiper-slide button {
display: block;
width: 100%;
max-width: 500px;
}
h1 {
text-align: center;
Font-family: 'Bebas Neue', cursive;
font-size: 5vw;
margin: 0;
}
.pickGuideD {
Font-family: 'Bebas Neue', cursive;
text-transform: uppercase;
font-size: 48px;
font-weight: 500;
height: 100%;
background: rgb(238, 235, 241);
cursor: pointer;
border-radius: 10px;
color: rgb(0, 0, 0);
border: none;
text-align: center;
}
.pickGuideD:hover {
box-shadow: inset 10px 10px 10px -1px rgba(10, 99, 169, 0.16),
inset -10px -10px 10px -1px rgba(255, 255, 255, 0.70);
}
</style>
<style>
.pickGuideM {
Font-family: 'Bebas Neue', cursive;
text-transform: uppercase;
font-size: 24px;
font-weight: 500;
height: 100%;
background: rgb(238, 235, 241);
cursor: pointer;
border-radius: 10px;
color: rgb(0, 0, 0);
border: none;
text-align: center;
}
.pickGuideM:hover {
box-shadow: inset 10px 10px 10px -1px rgba(10, 99, 169, 0.16),
inset -10px -10px 10px -1px rgba(255, 255, 255, 0.70);
}
.close-button1D {
background-color: rgb(238, 235, 241);
color: rgb(0, 0, 0);
cursor: pointer;
font-size: 30px;
float: right;
margin-right: 40px;
border: 0;
}
::-webkit-scrollbar {
display: none;
}
</style>
<style>
.whatGuideD {
width: 100%;
height:100vh;
background: rgb(238, 235, 241);
text-align: center;
color: rgb(15, 15, 15);
visibility: hidden;
opacity: 0;
transition: 0.5s ease-in-out;
z-index: 3;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
}
.whatGuideD.active2{
visibility: visible;
opacity: 1;
position: fixed;
z-index: 4;
overflow-y: scroll;
transform: translate(-50%, -50%) scale(1);
}
.whatGuideM {
width: 100%;
height:100vh;
background: rgb(238, 235, 241);
text-align: center;
color: rgb(15, 15, 15);
visibility: hidden;
opacity: 0;
transition: 0.5s ease-in-out;
z-index: 3;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
}
.whatGuideM.active2M{
visibility: visible;
opacity: 1;
position: fixed;
z-index: 4;
overflow-y: hidden;
transform: translate(-50%, -50%) scale(1);
}
</style>
`
JS
`
<script>
var disc1 = document.querySelector("[showdiscrip1]")
function showdisc1() {
disc1.classList.add("disc");
}
function removedisc1() {
disc1.classList.remove("disc")
}
var disc2 = document.querySelector("[showdiscrip2]")
function showdisc2() {
disc2.classList.add("disc");
}
function removedisc2() {
disc2.classList.remove("disc")
}
var disc3 = document.querySelector("[showdiscrip3]")
function showdisc3() {
disc3.classList.add("disc");
}
function removedisc3() {
disc3.classList.remove("disc")
}
const mulitStepForm2 = document.querySelector("[data-multi-step2]")
const formSteps2 = [...mulitStepForm2.querySelectorAll("[data-step2]")]
let currentStep2 = formSteps2.findIndex(step2 => {
return step2.classList.contains("active2")
})
if (currentStep2 < 0) {
function SizeD() {
currentStep2 = 0
formSteps2[currentStep2].classList.add("active2")
showCurrentStep2();
window.scrollTo(0, 20);
}
}
mulitStepForm2.addEventListener("click", j => {
if (j.target.matches("[data-next]")) {
currentStep2++
} else if (j.target.matches("[data-closeguide]")) {
currentStep2 = -1
}
showCurrentStep2()
})
function showCurrentStep2() {
formSteps2.forEach((step2, index) => {
step2.classList.toggle("active2", index ===
currentStep2)
})
}
const mulitStepForm2M = document.querySelector("[data-multi-step2M]")
const formSteps2M = [...mulitStepForm2M.querySelectorAll("[data-step2M]")]
let currentStep2M = formSteps2M.findIndex(step2M => {
return step2M.classList.contains("active2M")
})
if (currentStep2M < 0) {
function SizeM() {
currentStep2M = 0
formSteps2M[currentStep2M].classList.add("active2M")
showCurrentStep2M();
window.scrollTo(0, 0);
}
}
mulitStepForm2M.addEventListener("click", j => {
if (j.target.matches("[data-nextM]")) {
currentStep2M++
} else if (j.target.matches("[data-closeguideM]")) {
currentStep2M = -1
}
showCurrentStep2M()
})
function showCurrentStep2M() {
formSteps2M.forEach((step2M, index) => {
step2M.classList.toggle("active2M", index ===
currentStep2M)
})
}
function Size() {
SizeD();
SizeM();
}
var swiper = new Swiper(".mySwiper", {
effect: "coverflow",
grabCursor: true,
centeredSlides: true,
slidesPerView: "auto",
coverflowEffect: {
rotate: 50,
stretch: 0,
depth: 500,
modifier: 1,
slideShadows: true,
},
pagination: {
el: ".swiper-pagination",
},
});
</script>
<script>
const sw1 = document.getElementById("sw1");
const sw2 = document.getElementById("sw2");
const sw3 = document.getElementById("sw3");
const sw1CS = window.getComputedStyle(sw1);
const sw2CS = window.getComputedStyle(sw2);
const sw3CS = window.getComputedStyle(sw3);
console.log(sw1CS.zIndex)
console.log(sw2CS.zIndex)
console.log(sw3CS.zIndex)
if (sw1CS.zIndex == 1) {
document.getElementById("d1").classList.add("showDisc1")
document.getElementById("d2").classList.remove("showDisc2")
}
if (sw2CS.zIndex == 1) {
document.getElementById("d2").classList.add("showDisc2")
document.getElementById("d1").classList.remove("showDisc1")
document.getElementById("d3").classList.remove("showDisc3")
}
if (sw3CS.zIndex == 1) {
document.getElementById("d3").classList.add("showDisc3")
document.getElementById("d2").classList.remove("showDisc2")
}
</script>
`
I want to style the bottom line in the dropdown so that when I clicked it was the same color as the input, i.e. to focus on that color, but I read that focus doesn't work with a div, there were other options, but they don't work for me, also I want my dropdowns and inputs to have this animation in the bottom line on hover: https://jsfiddle.net/andrewphoenix228/v1spzha5/3/
/*******************************************************************************
* Initialize the amount for the first currency
*******************************************************************************/
function initializeAmount() {
document.getElementById('amount-one').addEventListener('input', refreshAmount);
}
/*******************************************************************************
* Initialize the Swap trigger already existing in DOM
*******************************************************************************/
function initializeSwap() {
swap.addEventListener('click', () => {
const [selectOne, selectTwo] = document.querySelectorAll('.custom-select');
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const [valueOne, valueTwo] = [selectOne, selectTwo].map(
select => select.querySelector('.custom-select__option--select').dataset.value
);
//--------------------------------------------------------------------------
// Dirty trick to avoid problems when swapping currencies on the 2 DDs
// by finding the currencies not chosen by the two dropdowns
// and first selecting a third currency on the first dropdown
// before doing the actual swap
//--------------------------------------------------------------------------
const availableCurrencies = [];
const chosenCurrencies = [valueOne, valueTwo];
selectOne.querySelectorAll('.custom-select__list .custom-select__option-name').forEach((option)=>{
availableCurrencies.push( option.innerText );
});
const notChosenCurrencies = availableCurrencies.filter(chosen => !chosenCurrencies.includes(chosen));
amountOne.value = amountTwo.value
selectOne.querySelector(`[data-value="${notChosenCurrencies[0]}"]`).click();
selectTwo.querySelector(`[data-value="${valueOne}"]`).click();
selectOne.querySelector(`[data-value="${valueTwo}"]`).click();
refreshConversionRatesAndAmount();
});
}
/*******************************************************************************
* Initialize the Currency Dropdowns already defined in the DOM
*******************************************************************************/
function initializeCurrencyDropdowns() {
//given the array of all .custom-select
[...document.querySelectorAll(".custom-select")]
//map()
.map(select => {
//inits dropdown options
let selected = select.querySelector(".custom-select__option--select");
if (selected) {
select.dataset.value = selected.dataset.value;
const placeholder = select.querySelector(".custom-select__placeholder");
placeholder.innerHTML = "";
const pho = selected.cloneNode(true);
pho.classList.remove("custom-select__option--select");
placeholder.appendChild(pho);
}
//adds click event listener to the list of options
select.querySelector(".custom-select__list").addEventListener("click", e => {
//--------------------------------------------------------------------------
// Logic to hide from the other DD the selected currency in this DD
//--------------------------------------------------------------------------
//fetches information about the currently selected dropdown
const thisDD = e.target.closest('.custom-select');
const currencyCurrentlySelected = e.target.closest('.custom-select__option').dataset.value;
//fetches information about the other dropdown
const otherDD_id = ((thisDD.id == 'curr-one' ? 'curr-two' : 'curr-one'));
const otherDD = document.getElementById(otherDD_id);
//removes the displaynone class to all the options in the other dropdown
otherDD.querySelectorAll('.custom-select__option').forEach((option)=>{
option.classList.remove('display-none');
});
//adds the class displaynone to the currently selected currency in the second dropdown
otherDD.querySelector(`.custom-select__option[data-value="${currencyCurrentlySelected}"]`)
.classList.add('display-none');
//--------------------------------------------------------------------------
let target = e.target.closest(".custom-select__option");
if (target) {
let parent = target.closest(".custom-select");
parent
.querySelector(".custom-select__option--select")
.classList.remove("custom-select__option--select");
target.classList.add("custom-select__option--select");
let selected = parent.querySelector(".custom-select__option--select");
parent.dataset.value = selected.dataset.value;
const placeholder = parent.querySelector(".custom-select__placeholder");
placeholder.innerHTML = "";
const pho = selected.cloneNode(true);
pho.classList.remove("custom-select__option--select");
placeholder.appendChild(pho);
target.closest(".custom-select").classList.remove("custom-select--drop");
}
//--------------------------------------------------------------------------
refreshConversionRatesAndAmount();
});
//adds click event listener to the placeholder
select.querySelector(".custom-select__placeholder").addEventListener("click", e => {
let target = e.target.closest(".custom-select__placeholder");
if (target) {
target.closest(".custom-select").classList.toggle("custom-select--drop");
}
});
});
}
/*******************************************************************************
* Refresh the conversion rates and converted amount (and metadata)
* displayed in the respective labels
*******************************************************************************/
async function refreshConversionRatesAndAmount() {
const rates = await fetchConversionRates();
const currencyOne = getSelectedCurrencyOne();
const currencyTwo = getSelectedCurrencyTwo();
const rateOne = rates[currencyOne];
const rateTwo = rates[currencyTwo];
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const rateLabel = document.getElementById('rate');
const ratio = (1 * rateOne.rate / rateTwo.rate).toFixed(4);
rateLabel.innerText = `1 ${currencyOne} = ${ratio} ${currencyTwo}`;
amountTwo.ratio = ratio;
const newAmount = (amountOne.value * amountTwo.ratio).toFixed(2);
amountTwo.value = (amountOne.value !== '') ? newAmount : '';
}
/*******************************************************************************
* Refresh the amount only
*******************************************************************************/
function refreshAmount() {
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const newAmount = (amountOne.value * amountTwo.ratio).toFixed(2);
amountTwo.value = (amountOne.value !== '') ? newAmount : '';
}
/*******************************************************************************
* Fetch and return the conversion rates from a static url
*******************************************************************************/
async function fetchConversionRates() {
const url = 'https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json';
const response = await fetch(url);
const data = await response.json();
data.unshift({
"txt": "Українська гривня",
"rate": 1,
"cc": "UAH"
});
const ratesMapped = Object.assign({}, ...data.map((rate) => ({[rate.cc]: rate})));
return ratesMapped;
}
/*******************************************************************************
* Returns the Currency code selected on the first currency dropdown
*******************************************************************************/
function getSelectedCurrencyOne() {
const curr_oneDD = document.querySelector('#curr-one.custom-select');
return curr_oneDD.textContent.trim().slice(0, 3);
}
/*******************************************************************************
* Returns the Currency code selected on the second currency dropdown
*******************************************************************************/
function getSelectedCurrencyTwo() {
const curr_twoDD = document.querySelector('#curr-two.custom-select');
return curr_twoDD.textContent.trim().slice(0, 3);
}
initializeAmount();
initializeSwap();
initializeCurrencyDropdowns();
refreshConversionRatesAndAmount();
body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 100vh;
margin: 0;
}
.custom-select {
display: block;
width: 150px;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
z-index: 1;
margin-bottom: 8.7px;
}
.custom-select:hover {
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
}
.custom-select__list {
display: block;
border-radius: 5px;
background-color: #fff;
padding: 5px 0;
box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.15);
position: absolute;
z-index: 999;
left: 0;
top: calc(100% + 12px);
opacity: 0;
pointer-events: none;
transform: translateY(10px);
transition-property: transform, opacity;
transition-timing-function: ease-out;
transition-duration: 0.3s;
box-sizing: border-box;
}
.custom-select--drop .custom-select__list {
transform: translateY(0);
opacity: 1;
pointer-events: all;
}
.custom-select--drop .custom-select__placeholder::after {
transform: translateY(-80%) rotateX(360deg);
}
.custom-select__option {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0.5em 1.5em;
box-sizing: border-box;
cursor: pointer;
z-index: 0;
}
.custom-select__option-icon {
display: block;
flex-shrink: 0;
border-radius: 5px;
overflow: hidden;
margin-right: 10px;
}
.custom-select__option-icon img {
display: block;
width: 18px;
height: 15px;
max-height: 100%;
-o-object-fit: cover;
object-fit: cover;
margin: 0;
}
.custom-select__option-name {
display: block;
width: 100%;
text-transform: uppercase;
margin-right: 10px;
}
.custom-select__option-symbol {
display: block;
font-weight: bold;
}
.custom-select__option--select .custom-select__option-name {
color: #8dc641;
}
.custom-select__placeholder {
display: block;
width: 100%;
}
.custom-select__placeholder::after {
content: '';
display: block;
width: 0;
height: 0;
border: 6px solid transparent;
border-top-width: 6px;
border-bottom: 6px solid #616161;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-30%) rotateX(180deg);
transition-property: transform;
transition-timing-function: ease-out;
transition-duration: 0.3s;
}
.custom-select__option {
padding-right: calc(1.5em + 10px);
position: relative;
}
.custom-select {
display:inline-block;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
}
.custom-select:after {
display:block;
content: '';
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
position: relative;
bottom: -2px;
}
.custom-select:hover:after { transform: scaleX(1);
}
.custom-select:focus {
border-bottom: 2px solid #8dc641;
}
/* .custom-select__placeholder .custom-select__option::before,
.custom-select__placeholder .custom-select__option::after{
content: '';
position: absolute; bottom: -2px;
width: 0;
height: 2px;
background-color: #8dc641;
transition: width .3s ease;
}
.custom-select__placeholder .custom-select__option::before {
left: 50%;
}
.custom-select__placeholder .custom-select__option::after {
right: 50%;
}
.custom-select--drop .custom-select__placeholder .custom-select__option::before,
.custom-select--drop .custom-select__placeholder .custom-select__option::after {
width: 50%;
}
.custom-select__option:hover {
background-color: transparent;
} */
/* .container {
border: solid 2px #212121;
border-radius: 10px;
background-color: white;
box-sizing: border-box;
-webkit-box-sizing: border-box;
} */
.header {
display: flex;
align-items: center;
}
.indent-right {
display: flex;
width: 24px;
height: 24px;
background-image: url("https://cdn.privat24.ua/icons/file/ServiceCurrency.svg");
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
margin-right: 10px !important;
}
.btn {
display: inline-flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
position: relative;
width: 57px;
height: 44px;
font-size: 16px;
line-height: 1.5;
font-family: 'Open Sans', sans-serif;
font-weight: 600;
padding: 8px 16px;
border-radius: 4px;
transition-duration: 450ms;
transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
word-break: normal;
color: rgba(0, 0, 0, 0.54);
background: rgb(255, 255, 255);
box-shadow: rgb(0 0 0 / 12%) 0px 2px 4px 0px, rgb(0 0 0 / 12%) 0px 0px 4px 0px;
white-space: nowrap;
border-style: none;
border-width: 0px;
border-color: rgb(255, 255, 255);
margin: 0px;
cursor: pointer;
}
.btn:hover {
background-color: #F5F5F5;
box-shadow: 1px 1px 3px 3px #E0E0E0;
}
.swap-rate-container .btn-arrows {
transform: rotate(90deg);
opacity: 0.54;
transition: opacity 450ms cubic-bezier(0.23, 1, 0.32, 1);
position: absolute;
z-index: 0;
font-family: 'Open Sans', sans-serif;
}
.currency {
padding: 40px 0;
display: flex;
align-items: center;
justify-content: space-between;
}
input::placeholder {
font-family: 'Open Sans', sans-serif;
font-size: 16px;
}
.currency input {
background: transparent;
font-size: 16px;
line-height: 1.5;
text-align: right;
font-weight: 400;
color: rgba(0, 0, 0, 0.87);
border-style: none;
border-width: 0px;
border-radius: 0px;
background: transparent;
box-shadow: none;
outline: none;
width: 65%;
font-family: 'Open Sans', sans-serif;
background: transparent;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
margin-left: 15px
}
.currency input:hover {
display: block;
line-height: 1.5;
font-family: "Open Sans", sans-serif;
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
}
.currency input:focus {
border-bottom: 2px solid #8dc641;
border-bottom-color: transparent;
}
.select-placeholder {
background: rgb(255, 255, 255);
color: rgba(0, 0, 0, 0.38);
}
.swap-rate-container {
display: flex;
align-items: center;
justify-content: space-between;
}
.rate {
color: black;
font-size: 15px;
padding: 0 10px;
background: #E0E0E0;
line-height: var(--tl-small);
padding: 8px;
font-family: 'Open Sans', sans-serif;
border-radius: 2px;
}
input::-webkit-inner-spin-button {
display: none !important;
}
.input-container {
position: relative;
width: 65%;
margin-left: 15px;
bottom: -1px;
}
.input-container input {
width: 100%;
margin-left: 0;
}
.input-container input:focus {
border-bottom: 2px solid #8dc641;
}
.input-box:hover + .input-border {
transform: scaleX(1);
}
.input-border {
display: block;
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
position: absolute; bottom: 0; left: 0;
width: 102%;
}
#media (maz-width: 600px) {
.currency input {
width: 200px;
}
}
.display-none {
display: none;
}
/* for dropdown css*/
/* for input border css */
/* .input-container {
position: relative;
width: 65%;
margin-left: 15px;
}
.input-container input {
width: 100%;
margin-left: 0;
}
.input-border {
position: absolute; bottom: 0; left: 0;
width: 100%;
height: 2px;
}
.input-border::before,
.input-border::after{
content: '';
position: absolute; top: 0;
width: 0;
height: 100%;
background-color: #8dc641;
transition: width .3s ease;
}
.input-border::before {
left: 50%;
}
.input-border::after {
right: 50%;
}
.input-container input:focus + .input-border::before,
.input-container input:focus + .input-border::after {
width: 50%;
} */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Currency Converter</title>
<link rel="shortcut icon" href="currencies-icon-10.jpg" type="image/x-icon">
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="header">
<div class="indent-right"></div>
<b>Конвертор валют</b>
</div>
<div class="currency">
<div class="custom-select" id="curr-one">
<div class="custom-select__placeholder"></div>
<div class="custom-select__list">
<div class="custom-select__option" data-value="EUR">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/EU.svg">
</div>
<div class="custom-select__option-name">EUR</div>
<div class="custom-select__option-symbol">€</div>
</div>
<div class="custom-select__option custom-select__option--select" data-value="USD">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/US.svg">
</div>
<div class="custom-select__option-name">USD</div>
<div class="custom-select__option-symbol">$</div>
</div>
<div class="custom-select__option" data-value="GBP">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/GB.svg">
</div>
<div class="custom-select__option-name">GBP</div>
<div class="custom-select__option-symbol">£</div>
</div>
<div class="custom-select__option display-none" data-value="UAH">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/UA.svg" />
</div>
<div class="custom-select__option-name">UAH</div>
<div class="custom-select__option-symbol">₴</div>
</div>
</div>
</div>
<div class="input-container">
<input type="number" id="amount-one" class="input-box" placeholder="200.00" />
<span class="input-border"></span>
</div>
</div>
<div class="swap-rate-container">
<button class="btn" id="swap">
<div class="btn-arrows">
<div style="display: flex;">
<svg
height="24px" width="24px" version="1.1"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd" stroke="none" stroke-width="1">
<path d="M0 0h24v24H0z"></path>
<path
d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"
fill="#000"
fill-rule="nonzero"></path>
</g>
</svg>
</div>
</div>
</button>
<div class="rate" id="rate"></div>
</div>
<div class="currency">
<div class="custom-select" id="curr-two">
<div class="custom-select__placeholder"></div>
<div class="custom-select__list">
<div class="custom-select__option custom-select__option--select" data-value="UAH">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/UA.svg" />
</div>
<div class="custom-select__option-name">UAH</div>
<div class="custom-select__option-symbol">₴</div>
</div>
<div class="custom-select__option" data-value="GBP">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/GB.svg">
</div>
<div class="custom-select__option-name">GBP</div>
<div class="custom-select__option-symbol">£</div>
</div>
<div class="custom-select__option" data-value="EUR">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/EU.svg">
</div>
<div class="custom-select__option-name">EUR</div>
<div class="custom-select__option-symbol">€</div>
</div>
<div class="custom-select__option display-none" data-value="USD">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/US.svg">
</div>
<div class="custom-select__option-name">USD</div>
<div class="custom-select__option-symbol">$</div>
</div>
</div>
</div>
<div class="input-container">
<input type="number" id="amount-two" class="input-box" placeholder="200.00" />
<span class="input-border"></span>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
i have shared code hover effect on Input & dropdown. please check
/*******************************************************************************
* Initialize the amount for the first currency
*******************************************************************************/
function initializeAmount() {
document.getElementById('amount-one').addEventListener('input', refreshAmount);
}
/*******************************************************************************
* Initialize the Swap trigger already existing in DOM
*******************************************************************************/
function initializeSwap() {
swap.addEventListener('click', () => {
const [selectOne, selectTwo] = document.querySelectorAll('.custom-select');
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const [valueOne, valueTwo] = [selectOne, selectTwo].map(
select => select.querySelector('.custom-select__option--select').dataset.value
);
//--------------------------------------------------------------------------
// Dirty trick to avoid problems when swapping currencies on the 2 DDs
// by finding the currencies not chosen by the two dropdowns
// and first selecting a third currency on the first dropdown
// before doing the actual swap
//--------------------------------------------------------------------------
const availableCurrencies = [];
const chosenCurrencies = [valueOne, valueTwo];
selectOne.querySelectorAll('.custom-select__list .custom-select__option-name').forEach((option)=>{
availableCurrencies.push( option.innerText );
});
const notChosenCurrencies = availableCurrencies.filter(chosen => !chosenCurrencies.includes(chosen));
amountOne.value = amountTwo.value
selectOne.querySelector(`[data-value="${notChosenCurrencies[0]}"]`).click();
selectTwo.querySelector(`[data-value="${valueOne}"]`).click();
selectOne.querySelector(`[data-value="${valueTwo}"]`).click();
refreshConversionRatesAndAmount();
});
}
/*******************************************************************************
* Initialize the Currency Dropdowns already defined in the DOM
*******************************************************************************/
function initializeCurrencyDropdowns() {
//given the array of all .custom-select
[...document.querySelectorAll(".custom-select")]
//map()
.map(select => {
//inits dropdown options
let selected = select.querySelector(".custom-select__option--select");
if (selected) {
select.dataset.value = selected.dataset.value;
const placeholder = select.querySelector(".custom-select__placeholder");
placeholder.innerHTML = "";
const pho = selected.cloneNode(true);
pho.classList.remove("custom-select__option--select");
placeholder.appendChild(pho);
}
//adds click event listener to the list of options
select.querySelector(".custom-select__list").addEventListener("click", e => {
//--------------------------------------------------------------------------
// Logic to hide from the other DD the selected currency in this DD
//--------------------------------------------------------------------------
//fetches information about the currently selected dropdown
const thisDD = e.target.closest('.custom-select');
const currencyCurrentlySelected = e.target.closest('.custom-select__option').dataset.value;
//fetches information about the other dropdown
const otherDD_id = ((thisDD.id == 'curr-one' ? 'curr-two' : 'curr-one'));
const otherDD = document.getElementById(otherDD_id);
//removes the displaynone class to all the options in the other dropdown
otherDD.querySelectorAll('.custom-select__option').forEach((option)=>{
option.classList.remove('display-none');
});
//adds the class displaynone to the currently selected currency in the second dropdown
otherDD.querySelector(`.custom-select__option[data-value="${currencyCurrentlySelected}"]`)
.classList.add('display-none');
//--------------------------------------------------------------------------
let target = e.target.closest(".custom-select__option");
if (target) {
let parent = target.closest(".custom-select");
parent
.querySelector(".custom-select__option--select")
.classList.remove("custom-select__option--select");
target.classList.add("custom-select__option--select");
let selected = parent.querySelector(".custom-select__option--select");
parent.dataset.value = selected.dataset.value;
const placeholder = parent.querySelector(".custom-select__placeholder");
placeholder.innerHTML = "";
const pho = selected.cloneNode(true);
pho.classList.remove("custom-select__option--select");
placeholder.appendChild(pho);
target.closest(".custom-select").classList.remove("custom-select--drop");
}
//--------------------------------------------------------------------------
refreshConversionRatesAndAmount();
});
//adds click event listener to the placeholder
select.querySelector(".custom-select__placeholder").addEventListener("click", e => {
let target = e.target.closest(".custom-select__placeholder");
if (target) {
target.closest(".custom-select").classList.toggle("custom-select--drop");
}
});
});
}
/*******************************************************************************
* Refresh the conversion rates and converted amount (and metadata)
* displayed in the respective labels
*******************************************************************************/
async function refreshConversionRatesAndAmount() {
const rates = await fetchConversionRates();
const currencyOne = getSelectedCurrencyOne();
const currencyTwo = getSelectedCurrencyTwo();
const rateOne = rates[currencyOne];
const rateTwo = rates[currencyTwo];
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const rateLabel = document.getElementById('rate');
const ratio = (1 * rateOne.rate / rateTwo.rate).toFixed(4);
rateLabel.innerText = `1 ${currencyOne} = ${ratio} ${currencyTwo}`;
amountTwo.ratio = ratio;
const newAmount = (amountOne.value * amountTwo.ratio).toFixed(2);
amountTwo.value = (amountOne.value !== '') ? newAmount : '';
}
/*******************************************************************************
* Refresh the amount only
*******************************************************************************/
function refreshAmount() {
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const newAmount = (amountOne.value * amountTwo.ratio).toFixed(2);
amountTwo.value = (amountOne.value !== '') ? newAmount : '';
}
/*******************************************************************************
* Fetch and return the conversion rates from a static url
*******************************************************************************/
async function fetchConversionRates() {
const url = 'https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json';
const response = await fetch(url);
const data = await response.json();
data.unshift({
"txt": "Українська гривня",
"rate": 1,
"cc": "UAH"
});
const ratesMapped = Object.assign({}, ...data.map((rate) => ({[rate.cc]: rate})));
return ratesMapped;
}
/*******************************************************************************
* Returns the Currency code selected on the first currency dropdown
*******************************************************************************/
function getSelectedCurrencyOne() {
const curr_oneDD = document.querySelector('#curr-one.custom-select');
return curr_oneDD.textContent.trim().slice(0, 3);
}
/*******************************************************************************
* Returns the Currency code selected on the second currency dropdown
*******************************************************************************/
function getSelectedCurrencyTwo() {
const curr_twoDD = document.querySelector('#curr-two.custom-select');
return curr_twoDD.textContent.trim().slice(0, 3);
}
initializeAmount();
initializeSwap();
initializeCurrencyDropdowns();
refreshConversionRatesAndAmount();
body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 100vh;
margin: 0;
}
.custom-select {
display: block;
width: 150px;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
z-index: 1;
margin-bottom: 8.7px;
}
/* .custom-select:hover {
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
} */
.custom-select__list {
display: block;
border-radius: 5px;
background-color: #fff;
padding: 5px 0;
box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.15);
position: absolute;
z-index: 999;
left: 0;
top: calc(100% + 12px);
opacity: 0;
pointer-events: none;
transform: translateY(10px);
transition-property: transform, opacity;
transition-timing-function: ease-out;
transition-duration: 0.3s;
box-sizing: border-box;
}
.custom-select--drop .custom-select__list {
transform: translateY(0);
opacity: 1;
pointer-events: all;
}
.custom-select--drop .custom-select__placeholder::after {
transform: translateY(-80%) rotateX(360deg);
}
.custom-select__option {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0.5em 1.5em;
box-sizing: border-box;
cursor: pointer;
z-index: 0;
}
.custom-select__option-icon {
display: block;
flex-shrink: 0;
border-radius: 5px;
overflow: hidden;
margin-right: 10px;
}
.custom-select__option-icon img {
display: block;
width: 18px;
height: 15px;
max-height: 100%;
-o-object-fit: cover;
object-fit: cover;
margin: 0;
}
.custom-select__option-name {
display: block;
width: 100%;
text-transform: uppercase;
margin-right: 10px;
}
.custom-select__option-symbol {
display: block;
font-weight: bold;
}
.custom-select__option--select .custom-select__option-name {
color: #8dc641;
}
.custom-select__placeholder {
display: block;
width: 100%;
}
.custom-select__placeholder::after {
content: '';
display: block;
width: 0;
height: 0;
border: 6px solid transparent;
border-top-width: 6px;
border-bottom: 6px solid #616161;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-30%) rotateX(180deg);
transition-property: transform;
transition-timing-function: ease-out;
transition-duration: 0.3s;
}
.custom-select__option {
padding-right: calc(1.5em + 10px);
position: relative;
}
.custom-select {
display:inline-block;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
}
.custom-select:after {
display:block;
content: '';
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
position: relative;
bottom: -2px;
}
.custom-select:hover:after { transform: scaleX(1);
}
.custom-select:focus {
border-bottom: 2px solid #8dc641;
}
.header {
display: flex;
align-items: center;
}
.indent-right {
display: flex;
width: 24px;
height: 24px;
background-image: url("https://cdn.privat24.ua/icons/file/ServiceCurrency.svg");
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
margin-right: 10px !important;
}
.btn {
display: inline-flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
position: relative;
width: 57px;
height: 44px;
font-size: 16px;
line-height: 1.5;
font-family: 'Open Sans', sans-serif;
font-weight: 600;
padding: 8px 16px;
border-radius: 4px;
transition-duration: 450ms;
transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
word-break: normal;
color: rgba(0, 0, 0, 0.54);
background: rgb(255, 255, 255);
box-shadow: rgb(0 0 0 / 12%) 0px 2px 4px 0px, rgb(0 0 0 / 12%) 0px 0px 4px 0px;
white-space: nowrap;
border-style: none;
border-width: 0px;
border-color: rgb(255, 255, 255);
margin: 0px;
cursor: pointer;
}
.btn:hover {
background-color: #F5F5F5;
box-shadow: 1px 1px 3px 3px #E0E0E0;
}
.swap-rate-container .btn-arrows {
transform: rotate(90deg);
opacity: 0.54;
transition: opacity 450ms cubic-bezier(0.23, 1, 0.32, 1);
position: absolute;
z-index: 0;
font-family: 'Open Sans', sans-serif;
}
.currency {
padding: 40px 0;
display: flex;
align-items: center;
justify-content: space-between;
}
input::placeholder {
font-family: 'Open Sans', sans-serif;
font-size: 16px;
}
.currency input {
background: transparent;
font-size: 16px;
line-height: 1.5;
text-align: right;
font-weight: 400;
color: rgba(0, 0, 0, 0.87);
border-style: none;
border-width: 0px;
border-radius: 0px;
background: transparent;
box-shadow: none;
outline: none;
width: 65%;
font-family: 'Open Sans', sans-serif;
background: transparent;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
margin-left: 15px
}
.currency input:hover {
display: block;
line-height: 1.5;
font-family: "Open Sans", sans-serif;
/* border-bottom: 2px solid rgba(0, 0, 0, 0.54); */
}
.currency input:focus {
border-bottom: 2px solid #8dc641;
border-bottom-color: transparent;
}
.select-placeholder {
background: rgb(255, 255, 255);
color: rgba(0, 0, 0, 0.38);
}
.swap-rate-container {
display: flex;
align-items: center;
justify-content: space-between;
}
.rate {
color: black;
font-size: 15px;
padding: 0 10px;
background: #E0E0E0;
line-height: var(--tl-small);
padding: 8px;
font-family: 'Open Sans', sans-serif;
border-radius: 2px;
}
input::-webkit-inner-spin-button {
display: none !important;
}
.input-container {
position: relative;
width: 65%;
margin-left: 15px;
bottom: -1px;
}
.input-container input {
width: 100%;
margin-left: 0;
}
.input-box:hover + .input-border ,
.input-box:focus + .input-border ,
.input-box:active + .input-border {
transform: scaleX(1);
}
.input-border {
display: block;
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
position: absolute; bottom: 0; left: 0;
width: 102%;
}
#media (maz-width: 600px) {
.currency input {
width: 200px;
}
}
.display-none {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Currency Converter</title>
<link rel="shortcut icon" href="currencies-icon-10.jpg" type="image/x-icon">
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="header">
<div class="indent-right"></div>
<b>Конвертор валют</b>
</div>
<div class="currency">
<div class="custom-select" id="curr-one">
<div class="custom-select__placeholder"></div>
<div class="custom-select__list">
<div class="custom-select__option" data-value="EUR">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/EU.svg">
</div>
<div class="custom-select__option-name">EUR</div>
<div class="custom-select__option-symbol">€</div>
</div>
<div class="custom-select__option custom-select__option--select" data-value="USD">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/US.svg">
</div>
<div class="custom-select__option-name">USD</div>
<div class="custom-select__option-symbol">$</div>
</div>
<div class="custom-select__option" data-value="GBP">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/GB.svg">
</div>
<div class="custom-select__option-name">GBP</div>
<div class="custom-select__option-symbol">£</div>
</div>
<div class="custom-select__option display-none" data-value="UAH">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/UA.svg" />
</div>
<div class="custom-select__option-name">UAH</div>
<div class="custom-select__option-symbol">₴</div>
</div>
</div>
</div>
<div class="input-container">
<input type="number" id="amount-one" class="input-box" placeholder="200.00" />
<span class="input-border"></span>
</div>
</div>
<div class="swap-rate-container">
<button class="btn" id="swap">
<div class="btn-arrows">
<div style="display: flex;">
<svg
height="24px" width="24px" version="1.1"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd" stroke="none" stroke-width="1">
<path d="M0 0h24v24H0z"></path>
<path
d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"
fill="#000"
fill-rule="nonzero"></path>
</g>
</svg>
</div>
</div>
</button>
<div class="rate" id="rate"></div>
</div>
<div class="currency">
<div class="custom-select" id="curr-two">
<div class="custom-select__placeholder"></div>
<div class="custom-select__list">
<div class="custom-select__option custom-select__option--select" data-value="UAH">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/UA.svg" />
</div>
<div class="custom-select__option-name">UAH</div>
<div class="custom-select__option-symbol">₴</div>
</div>
<div class="custom-select__option" data-value="GBP">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/GB.svg">
</div>
<div class="custom-select__option-name">GBP</div>
<div class="custom-select__option-symbol">£</div>
</div>
<div class="custom-select__option" data-value="EUR">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/EU.svg">
</div>
<div class="custom-select__option-name">EUR</div>
<div class="custom-select__option-symbol">€</div>
</div>
<div class="custom-select__option display-none" data-value="USD">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/US.svg">
</div>
<div class="custom-select__option-name">USD</div>
<div class="custom-select__option-symbol">$</div>
</div>
</div>
</div>
<div class="input-container">
<input type="number" id="amount-two" class="input-box" placeholder="200.00" />
<span class="input-border"></span>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
I want to change the words to icons in the exchange rate, I mean, so that it is not 1 USD = 36.5686 UAH, but 1 $ = 36.5686 ₴ and so on. I tried to put custom-select__option-symbol instead of custom-select__option-name, but it either doesn't work or takes only the first two currency icons and doesn't change them when changing currencies
/*******************************************************************************
* Initialize the amount for the first currency
*******************************************************************************/
function initializeAmount() {
document.getElementById('amount-one').addEventListener('input', refreshAmount);
}
/*******************************************************************************
* Initialize the Swap trigger already existing in DOM
*******************************************************************************/
function initializeSwap() {
swap.addEventListener('click', () => {
const [selectOne, selectTwo] = document.querySelectorAll('.custom-select');
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const [valueOne, valueTwo] = [selectOne, selectTwo].map(
select => select.querySelector('.custom-select__option--select').dataset.value
);
//--------------------------------------------------------------------------
// Dirty trick to avoid problems when swapping currencies on the 2 DDs
// by finding the currencies not chosen by the two dropdowns
// and first selecting a third currency on the first dropdown
// before doing the actual swap
//--------------------------------------------------------------------------
const availableCurrencies = [];
const chosenCurrencies = [valueOne, valueTwo];
selectOne.querySelectorAll('.custom-select__list .custom-select__option-name').forEach((option)=>{
availableCurrencies.push( option.innerText );
});
const notChosenCurrencies = availableCurrencies.filter(chosen => !chosenCurrencies.includes(chosen));
amountOne.value = amountTwo.value
selectOne.querySelector(`[data-value="${notChosenCurrencies[0]}"]`).click();
selectTwo.querySelector(`[data-value="${valueOne}"]`).click();
selectOne.querySelector(`[data-value="${valueTwo}"]`).click();
refreshConversionRatesAndAmount();
});
}
/*******************************************************************************
* Initialize the Currency Dropdowns already defined in the DOM
*******************************************************************************/
function initializeCurrencyDropdowns() {
//given the array of all .custom-select
[...document.querySelectorAll(".custom-select")]
//map()
.map(select => {
//inits dropdown options
let selected = select.querySelector(".custom-select__option--select");
if (selected) {
select.dataset.value = selected.dataset.value;
const placeholder = select.querySelector(".custom-select__placeholder");
placeholder.innerHTML = "";
const pho = selected.cloneNode(true);
pho.classList.remove("custom-select__option--select");
placeholder.appendChild(pho);
}
//adds click event listener to the list of options
select.querySelector(".custom-select__list").addEventListener("click", e => {
//--------------------------------------------------------------------------
// Logic to hide from the other DD the selected currency in this DD
//--------------------------------------------------------------------------
//fetches information about the currently selected dropdown
const thisDD = e.target.closest('.custom-select');
const currencyCurrentlySelected = e.target.closest('.custom-select__option').dataset.value;
//fetches information about the other dropdown
const otherDD_id = ((thisDD.id == 'curr-one' ? 'curr-two' : 'curr-one'));
const otherDD = document.getElementById(otherDD_id);
//removes the displaynone class to all the options in the other dropdown
otherDD.querySelectorAll('.custom-select__option').forEach((option)=>{
option.classList.remove('display-none');
});
//adds the class displaynone to the currently selected currency in the second dropdown
otherDD.querySelector(`.custom-select__option[data-value="${currencyCurrentlySelected}"]`)
.classList.add('display-none');
//--------------------------------------------------------------------------
let target = e.target.closest(".custom-select__option");
if (target) {
let parent = target.closest(".custom-select");
parent
.querySelector(".custom-select__option--select")
.classList.remove("custom-select__option--select");
target.classList.add("custom-select__option--select");
let selected = parent.querySelector(".custom-select__option--select");
parent.dataset.value = selected.dataset.value;
const placeholder = parent.querySelector(".custom-select__placeholder");
placeholder.innerHTML = "";
const pho = selected.cloneNode(true);
pho.classList.remove("custom-select__option--select");
placeholder.appendChild(pho);
target.closest(".custom-select").classList.remove("custom-select--drop");
}
//--------------------------------------------------------------------------
refreshConversionRatesAndAmount();
});
//adds click event listener to the placeholder
select.querySelector(".custom-select__placeholder").addEventListener("click", e => {
let target = e.target.closest(".custom-select__placeholder");
if (target) {
target.closest(".custom-select").classList.toggle("custom-select--drop");
}
});
});
}
/*******************************************************************************
* Refresh the conversion rates and converted amount (and metadata)
* displayed in the respective labels
*******************************************************************************/
async function refreshConversionRatesAndAmount() {
const rates = await fetchConversionRates();
const currencyOne = getSelectedCurrencyOne();
const currencyTwo = getSelectedCurrencyTwo();
const rateOne = rates[currencyOne];
const rateTwo = rates[currencyTwo];
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const rateLabel = document.getElementById('rate');
const ratio = (1 * rateOne.rate / rateTwo.rate).toFixed(4);
rateLabel.innerText = `1 ${currencyOne} = ${ratio} ${currencyTwo}`;
amountTwo.ratio = ratio;
const newAmount = (amountOne.value * amountTwo.ratio).toFixed(2);
amountTwo.value = (amountOne.value !== '') ? newAmount : '';
}
/*******************************************************************************
* Refresh the amount only
*******************************************************************************/
function refreshAmount() {
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const newAmount = (amountOne.value * amountTwo.ratio).toFixed(2);
amountTwo.value = (amountOne.value !== '') ? newAmount : '';
}
/*******************************************************************************
* Fetch and return the conversion rates from a static url
*******************************************************************************/
async function fetchConversionRates() {
const url = 'https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json';
const response = await fetch(url);
const data = await response.json();
data.unshift({
"txt": "Українська гривня",
"rate": 1,
"cc": "UAH"
});
const ratesMapped = Object.assign({}, ...data.map((rate) => ({[rate.cc]: rate})));
return ratesMapped;
}
/*******************************************************************************
* Returns the Currency code selected on the first currency dropdown
*******************************************************************************/
function getSelectedCurrencyOne() {
const curr_oneDD = document.querySelector('#curr-one.custom-select');
return curr_oneDD.textContent.trim().slice(0, 3);
}
/*******************************************************************************
* Returns the Currency code selected on the second currency dropdown
*******************************************************************************/
function getSelectedCurrencyTwo() {
const curr_twoDD = document.querySelector('#curr-two.custom-select');
return curr_twoDD.textContent.trim().slice(0, 3);
}
initializeAmount();
initializeSwap();
initializeCurrencyDropdowns();
refreshConversionRatesAndAmount();
body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 100vh;
margin: 0;
}
.custom-select {
display: block;
width: 150px;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
z-index: 1;
margin-bottom: 8.7px;
}
.custom-select:hover {
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
}
.custom-select__list {
display: block;
border-radius: 5px;
background-color: #fff;
padding: 5px 0;
box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.15);
position: absolute;
z-index: 999;
left: 0;
top: calc(100% + 12px);
opacity: 0;
pointer-events: none;
transform: translateY(10px);
transition-property: transform, opacity;
transition-timing-function: ease-out;
transition-duration: 0.3s;
box-sizing: border-box;
}
.custom-select--drop .custom-select__list {
transform: translateY(0);
opacity: 1;
pointer-events: all;
}
.custom-select--drop .custom-select__placeholder::after {
transform: translateY(-80%) rotateX(360deg);
}
.custom-select__option {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0.5em 1.5em;
box-sizing: border-box;
cursor: pointer;
z-index: 0;
}
.custom-select__option-icon {
display: block;
flex-shrink: 0;
border-radius: 5px;
overflow: hidden;
margin-right: 10px;
}
.custom-select__option-icon img {
display: block;
width: 18px;
height: 15px;
max-height: 100%;
-o-object-fit: cover;
object-fit: cover;
margin: 0;
}
.custom-select__option-name {
display: block;
width: 100%;
text-transform: uppercase;
margin-right: 10px;
}
.custom-select__option-symbol {
display: block;
font-weight: bold;
}
.custom-select__option--select .custom-select__option-name {
color: #8dc641;
}
.custom-select__placeholder {
display: block;
width: 100%;
}
.custom-select__placeholder::after {
content: '';
display: block;
width: 0;
height: 0;
border: 6px solid transparent;
border-top-width: 6px;
border-bottom: 6px solid #616161;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-30%) rotateX(180deg);
transition-property: transform;
transition-timing-function: ease-out;
transition-duration: 0.3s;
}
.custom-select__option {
padding-right: calc(1.5em + 10px);
position: relative;
}
.custom-select {
display:inline-block;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
}
.custom-select:after {
display:block;
content: '';
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
position: relative;
bottom: -2px;
}
.custom-select:hover:after {
transform: scaleX(1);
}
.custom-select__placeholder .custom-select__option--select .custom-select__option-name:focus {
border-bottom: 2px solid #8dc641;
}
/* .custom-select__placeholder .custom-select__option::before,
.custom-select__placeholder .custom-select__option::after{
content: '';
position: absolute; bottom: -2px;
width: 0;
height: 2px;
background-color: #8dc641;
transition: width .3s ease;
}
.custom-select__placeholder .custom-select__option::before {
left: 50%;
}
.custom-select__placeholder .custom-select__option::after {
right: 50%;
}
.custom-select--drop .custom-select__placeholder .custom-select__option::before,
.custom-select--drop .custom-select__placeholder .custom-select__option::after {
width: 50%;
}
.custom-select__option:hover {
background-color: transparent;
} */
/* .container {
border: solid 2px #212121;
border-radius: 10px;
background-color: white;
box-sizing: border-box;
-webkit-box-sizing: border-box;
} */
.header {
display: flex;
align-items: center;
}
.indent-right {
display: flex;
width: 24px;
height: 24px;
background-image: url("https://cdn.privat24.ua/icons/file/ServiceCurrency.svg");
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
margin-right: 10px !important;
}
.btn {
display: inline-flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
position: relative;
width: 57px;
height: 44px;
font-size: 16px;
line-height: 1.5;
font-family: 'Open Sans', sans-serif;
font-weight: 600;
padding: 8px 16px;
border-radius: 4px;
transition-duration: 450ms;
transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
word-break: normal;
color: rgba(0, 0, 0, 0.54);
background: rgb(255, 255, 255);
box-shadow: rgb(0 0 0 / 12%) 0px 2px 4px 0px, rgb(0 0 0 / 12%) 0px 0px 4px 0px;
white-space: nowrap;
border-style: none;
border-width: 0px;
border-color: rgb(255, 255, 255);
margin: 0px;
cursor: pointer;
}
.btn:hover {
background-color: #F5F5F5;
box-shadow: 1px 1px 3px 3px #E0E0E0;
}
.swap-rate-container .btn-arrows {
transform: rotate(90deg);
opacity: 0.54;
transition: opacity 450ms cubic-bezier(0.23, 1, 0.32, 1);
position: absolute;
z-index: 0;
font-family: 'Open Sans', sans-serif;
}
.currency {
padding: 40px 0;
display: flex;
align-items: center;
justify-content: space-between;
}
input::placeholder {
font-family: 'Open Sans', sans-serif;
font-size: 16px;
}
.currency input {
background: transparent;
font-size: 16px;
line-height: 1.5;
text-align: right;
font-weight: 400;
color: rgba(0, 0, 0, 0.87);
border-style: none;
border-width: 0px;
border-radius: 0px;
background: transparent;
box-shadow: none;
outline: none;
width: 65%;
font-family: 'Open Sans', sans-serif;
background: transparent;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
margin-left: 15px
}
.currency input:hover {
display: block;
line-height: 1.5;
font-family: "Open Sans", sans-serif;
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
}
.currency input:focus {
border-bottom: 2px solid #8dc641;
border-bottom-color: transparent;
}
.select-placeholder {
background: rgb(255, 255, 255);
color: rgba(0, 0, 0, 0.38);
}
.swap-rate-container {
display: flex;
align-items: center;
justify-content: space-between;
}
.rate {
color: black;
font-size: 15px;
padding: 0 10px;
background: #E0E0E0;
line-height: var(--tl-small);
padding: 8px;
font-family: 'Open Sans', sans-serif;
border-radius: 2px;
}
input::-webkit-inner-spin-button {
display: none !important;
}
.input-container {
position: relative;
width: 65%;
margin-left: 15px;
bottom: -1px;
}
.input-container input {
width: 100%;
margin-left: 0;
}
.input-container input:focus {
border-bottom: 2px solid #8dc641;
}
.input-box:hover + .input-border {
transform: scaleX(1);
}
.input-border {
display: block;
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
position: absolute; bottom: 0; left: 0;
width: 102%;
}
#media (maz-width: 600px) {
.currency input {
width: 200px;
}
}
.display-none {
display: none;
}
/* for dropdown css*/
/* for input border css */
/* .input-container {
position: relative;
width: 65%;
margin-left: 15px;
}
.input-container input {
width: 100%;
margin-left: 0;
}
.input-border {
position: absolute; bottom: 0; left: 0;
width: 100%;
height: 2px;
}
.input-border::before,
.input-border::after{
content: '';
position: absolute; top: 0;
width: 0;
height: 100%;
background-color: #8dc641;
transition: width .3s ease;
}
.input-border::before {
left: 50%;
}
.input-border::after {
right: 50%;
}
.input-container input:focus + .input-border::before,
.input-container input:focus + .input-border::after {
width: 50%;
} */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Currency Converter</title>
<link rel="shortcut icon" href="currencies-icon-10.jpg" type="image/x-icon">
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="header">
<div class="indent-right"></div>
<b>Конвертор валют</b>
</div>
<div class="currency">
<div class="custom-select" id="curr-one">
<div class="custom-select__placeholder"></div>
<div class="custom-select__list">
<div class="custom-select__option" data-value="EUR">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/EU.svg">
</div>
<div class="custom-select__option-name">EUR</div>
<div class="custom-select__option-symbol">€</div>
</div>
<div class="custom-select__option custom-select__option--select" data-value="USD">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/US.svg">
</div>
<div class="custom-select__option-name">USD</div>
<div class="custom-select__option-symbol">$</div>
</div>
<div class="custom-select__option" data-value="GBP">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/GB.svg">
</div>
<div class="custom-select__option-name">GBP</div>
<div class="custom-select__option-symbol">£</div>
</div>
<div class="custom-select__option display-none" data-value="UAH">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/UA.svg" />
</div>
<div class="custom-select__option-name">UAH</div>
<div class="custom-select__option-symbol">₴</div>
</div>
</div>
</div>
<div class="input-container">
<input type="number" id="amount-one" class="input-box" placeholder="200.00" />
<span class="input-border"></span>
</div>
</div>
<div class="swap-rate-container">
<button class="btn" id="swap">
<div class="btn-arrows">
<div style="display: flex;">
<svg
height="24px" width="24px" version="1.1"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd" stroke="none" stroke-width="1">
<path d="M0 0h24v24H0z"></path>
<path
d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"
fill="#000"
fill-rule="nonzero"></path>
</g>
</svg>
</div>
</div>
</button>
<div class="rate" id="rate"></div>
</div>
<div class="currency">
<div class="custom-select" id="curr-two">
<div class="custom-select__placeholder"></div>
<div class="custom-select__list">
<div class="custom-select__option custom-select__option--select" data-value="UAH">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/UA.svg" />
</div>
<div class="custom-select__option-name">UAH</div>
<div class="custom-select__option-symbol">₴</div>
</div>
<div class="custom-select__option" data-value="GBP">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/GB.svg">
</div>
<div class="custom-select__option-name">GBP</div>
<div class="custom-select__option-symbol">£</div>
</div>
<div class="custom-select__option" data-value="EUR">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/EU.svg">
</div>
<div class="custom-select__option-name">EUR</div>
<div class="custom-select__option-symbol">€</div>
</div>
<div class="custom-select__option display-none" data-value="USD">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/US.svg">
</div>
<div class="custom-select__option-name">USD</div>
<div class="custom-select__option-symbol">$</div>
</div>
</div>
</div>
<div class="input-container">
<input type="number" id="amount-two" class="input-box" placeholder="200.00" />
<span class="input-border"></span>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
This snippet replaces the code given in your comment with:
const ratio = (1 * rateOne.rate / rateTwo.rate).toFixed(4);
function symbol(str) {
switch (str) {
case 'EUR': return '€';
case 'USD': return '$';
case 'GBP': return '£';
case 'UAH': return '₴';
default: return '?';
}
}
rateLabel.innerText = symbol(`${currencyOne}`) + `1 = ` + symbol(`${currencyTwo}`) + `${ratio} `;
That is, instead of showing the string representing the currency, show its symbol before the amount.
/*******************************************************************************
* Initialize the amount for the first currency
*******************************************************************************/
function initializeAmount() {
document.getElementById('amount-one').addEventListener('input', refreshAmount);
}
/*******************************************************************************
* Initialize the Swap trigger already existing in DOM
*******************************************************************************/
function initializeSwap() {
swap.addEventListener('click', () => {
const [selectOne, selectTwo] = document.querySelectorAll('.custom-select');
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const [valueOne, valueTwo] = [selectOne, selectTwo].map(
select => select.querySelector('.custom-select__option--select').dataset.value
);
//--------------------------------------------------------------------------
// Dirty trick to avoid problems when swapping currencies on the 2 DDs
// by finding the currencies not chosen by the two dropdowns
// and first selecting a third currency on the first dropdown
// before doing the actual swap
//--------------------------------------------------------------------------
const availableCurrencies = [];
const chosenCurrencies = [valueOne, valueTwo];
selectOne.querySelectorAll('.custom-select__list .custom-select__option-name').forEach((option) => {
availableCurrencies.push(option.innerText);
});
const notChosenCurrencies = availableCurrencies.filter(chosen => !chosenCurrencies.includes(chosen));
amountOne.value = amountTwo.value
selectOne.querySelector(`[data-value="${notChosenCurrencies[0]}"]`).click();
selectTwo.querySelector(`[data-value="${valueOne}"]`).click();
selectOne.querySelector(`[data-value="${valueTwo}"]`).click();
refreshConversionRatesAndAmount();
});
}
/*******************************************************************************
* Initialize the Currency Dropdowns already defined in the DOM
*******************************************************************************/
function initializeCurrencyDropdowns() {
//given the array of all .custom-select
[...document.querySelectorAll(".custom-select")]
//map()
.map(select => {
//inits dropdown options
let selected = select.querySelector(".custom-select__option--select");
if (selected) {
select.dataset.value = selected.dataset.value;
const placeholder = select.querySelector(".custom-select__placeholder");
placeholder.innerHTML = "";
const pho = selected.cloneNode(true);
pho.classList.remove("custom-select__option--select");
placeholder.appendChild(pho);
}
//adds click event listener to the list of options
select.querySelector(".custom-select__list").addEventListener("click", e => {
//--------------------------------------------------------------------------
// Logic to hide from the other DD the selected currency in this DD
//--------------------------------------------------------------------------
//fetches information about the currently selected dropdown
const thisDD = e.target.closest('.custom-select');
const currencyCurrentlySelected = e.target.closest('.custom-select__option').dataset.value;
//fetches information about the other dropdown
const otherDD_id = ((thisDD.id == 'curr-one' ? 'curr-two' : 'curr-one'));
const otherDD = document.getElementById(otherDD_id);
//removes the displaynone class to all the options in the other dropdown
otherDD.querySelectorAll('.custom-select__option').forEach((option) => {
option.classList.remove('display-none');
});
//adds the class displaynone to the currently selected currency in the second dropdown
otherDD.querySelector(`.custom-select__option[data-value="${currencyCurrentlySelected}"]`)
.classList.add('display-none');
//--------------------------------------------------------------------------
let target = e.target.closest(".custom-select__option");
if (target) {
let parent = target.closest(".custom-select");
parent
.querySelector(".custom-select__option--select")
.classList.remove("custom-select__option--select");
target.classList.add("custom-select__option--select");
let selected = parent.querySelector(".custom-select__option--select");
parent.dataset.value = selected.dataset.value;
const placeholder = parent.querySelector(".custom-select__placeholder");
placeholder.innerHTML = "";
const pho = selected.cloneNode(true);
pho.classList.remove("custom-select__option--select");
placeholder.appendChild(pho);
target.closest(".custom-select").classList.remove("custom-select--drop");
}
//--------------------------------------------------------------------------
refreshConversionRatesAndAmount();
});
//adds click event listener to the placeholder
select.querySelector(".custom-select__placeholder").addEventListener("click", e => {
let target = e.target.closest(".custom-select__placeholder");
if (target) {
target.closest(".custom-select").classList.toggle("custom-select--drop");
}
});
});
}
/*******************************************************************************
* Refresh the conversion rates and converted amount (and metadata)
* displayed in the respective labels
*******************************************************************************/
async function refreshConversionRatesAndAmount() {
const rates = await fetchConversionRates();
const currencyOne = getSelectedCurrencyOne();
const currencyTwo = getSelectedCurrencyTwo();
const rateOne = rates[currencyOne];
const rateTwo = rates[currencyTwo];
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const rateLabel = document.getElementById('rate');
const ratio = (1 * rateOne.rate / rateTwo.rate).toFixed(4);
function symbol(str) {
switch (str) {
case 'EUR':
return '€';
case 'USD':
return '$';
case 'GBP':
return '£';
case 'UAH':
return '₴';
default:
return '?';
}
}
rateLabel.innerText = symbol(`${currencyOne}`) + `1 = ` + symbol(`${currencyTwo}`) + `${ratio} `;
amountTwo.ratio = ratio;
const newAmount = (amountOne.value * amountTwo.ratio).toFixed(2);
amountTwo.value = (amountOne.value !== '') ? newAmount : '';
}
/*******************************************************************************
* Refresh the amount only
*******************************************************************************/
function refreshAmount() {
const amountOne = document.getElementById('amount-one');
const amountTwo = document.getElementById('amount-two');
const newAmount = (amountOne.value * amountTwo.ratio).toFixed(2);
amountTwo.value = (amountOne.value !== '') ? newAmount : '';
}
/*******************************************************************************
* Fetch and return the conversion rates from a static url
*******************************************************************************/
async function fetchConversionRates() {
const url = 'https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json';
const response = await fetch(url);
const data = await response.json();
data.unshift({
"txt": "Українська гривня",
"rate": 1,
"cc": "UAH"
});
const ratesMapped = Object.assign({}, ...data.map((rate) => ({
[rate.cc]: rate
})));
return ratesMapped;
}
/*******************************************************************************
* Returns the Currency code selected on the first currency dropdown
*******************************************************************************/
function getSelectedCurrencyOne() {
const curr_oneDD = document.querySelector('#curr-one.custom-select');
return curr_oneDD.textContent.trim().slice(0, 3);
}
/*******************************************************************************
* Returns the Currency code selected on the second currency dropdown
*******************************************************************************/
function getSelectedCurrencyTwo() {
const curr_twoDD = document.querySelector('#curr-two.custom-select');
return curr_twoDD.textContent.trim().slice(0, 3);
}
initializeAmount();
initializeSwap();
initializeCurrencyDropdowns();
refreshConversionRatesAndAmount();
body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 100vh;
margin: 0;
}
.custom-select {
display: block;
width: 150px;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
z-index: 1;
margin-bottom: 8.7px;
}
.custom-select:hover {
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
}
.custom-select__list {
display: block;
border-radius: 5px;
background-color: #fff;
padding: 5px 0;
box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.15);
position: absolute;
z-index: 999;
left: 0;
top: calc(100% + 12px);
opacity: 0;
pointer-events: none;
transform: translateY(10px);
transition-property: transform, opacity;
transition-timing-function: ease-out;
transition-duration: 0.3s;
box-sizing: border-box;
}
.custom-select--drop .custom-select__list {
transform: translateY(0);
opacity: 1;
pointer-events: all;
}
.custom-select--drop .custom-select__placeholder::after {
transform: translateY(-80%) rotateX(360deg);
}
.custom-select__option {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0.5em 1.5em;
box-sizing: border-box;
cursor: pointer;
z-index: 0;
}
.custom-select__option-icon {
display: block;
flex-shrink: 0;
border-radius: 5px;
overflow: hidden;
margin-right: 10px;
}
.custom-select__option-icon img {
display: block;
width: 18px;
height: 15px;
max-height: 100%;
-o-object-fit: cover;
object-fit: cover;
margin: 0;
}
.custom-select__option-name {
display: block;
width: 100%;
text-transform: uppercase;
margin-right: 10px;
}
.custom-select__option-symbol {
display: block;
font-weight: bold;
}
.custom-select__option--select .custom-select__option-name {
color: #8dc641;
}
.custom-select__placeholder {
display: block;
width: 100%;
}
.custom-select__placeholder::after {
content: '';
display: block;
width: 0;
height: 0;
border: 6px solid transparent;
border-top-width: 6px;
border-bottom: 6px solid #616161;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-30%) rotateX(180deg);
transition-property: transform;
transition-timing-function: ease-out;
transition-duration: 0.3s;
}
.custom-select__option {
padding-right: calc(1.5em + 10px);
position: relative;
}
.custom-select {
display: inline-block;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
}
.custom-select:after {
display: block;
content: '';
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
position: relative;
bottom: -2px;
}
.custom-select:hover:after {
transform: scaleX(1);
}
.custom-select__placeholder .custom-select__option--select .custom-select__option-name:focus {
border-bottom: 2px solid #8dc641;
}
/* .custom-select__placeholder .custom-select__option::before,
.custom-select__placeholder .custom-select__option::after{
content: '';
position: absolute; bottom: -2px;
width: 0;
height: 2px;
background-color: #8dc641;
transition: width .3s ease;
}
.custom-select__placeholder .custom-select__option::before {
left: 50%;
}
.custom-select__placeholder .custom-select__option::after {
right: 50%;
}
.custom-select--drop .custom-select__placeholder .custom-select__option::before,
.custom-select--drop .custom-select__placeholder .custom-select__option::after {
width: 50%;
}
.custom-select__option:hover {
background-color: transparent;
} */
/* .container {
border: solid 2px #212121;
border-radius: 10px;
background-color: white;
box-sizing: border-box;
-webkit-box-sizing: border-box;
} */
.header {
display: flex;
align-items: center;
}
.indent-right {
display: flex;
width: 24px;
height: 24px;
background-image: url("https://cdn.privat24.ua/icons/file/ServiceCurrency.svg");
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
margin-right: 10px !important;
}
.btn {
display: inline-flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
position: relative;
width: 57px;
height: 44px;
font-size: 16px;
line-height: 1.5;
font-family: 'Open Sans', sans-serif;
font-weight: 600;
padding: 8px 16px;
border-radius: 4px;
transition-duration: 450ms;
transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
word-break: normal;
color: rgba(0, 0, 0, 0.54);
background: rgb(255, 255, 255);
box-shadow: rgb(0 0 0 / 12%) 0px 2px 4px 0px, rgb(0 0 0 / 12%) 0px 0px 4px 0px;
white-space: nowrap;
border-style: none;
border-width: 0px;
border-color: rgb(255, 255, 255);
margin: 0px;
cursor: pointer;
}
.btn:hover {
background-color: #F5F5F5;
box-shadow: 1px 1px 3px 3px #E0E0E0;
}
.swap-rate-container .btn-arrows {
transform: rotate(90deg);
opacity: 0.54;
transition: opacity 450ms cubic-bezier(0.23, 1, 0.32, 1);
position: absolute;
z-index: 0;
font-family: 'Open Sans', sans-serif;
}
.currency {
padding: 40px 0;
display: flex;
align-items: center;
justify-content: space-between;
}
input::placeholder {
font-family: 'Open Sans', sans-serif;
font-size: 16px;
}
.currency input {
background: transparent;
font-size: 16px;
line-height: 1.5;
text-align: right;
font-weight: 400;
color: rgba(0, 0, 0, 0.87);
border-style: none;
border-width: 0px;
border-radius: 0px;
background: transparent;
box-shadow: none;
outline: none;
width: 65%;
font-family: 'Open Sans', sans-serif;
background: transparent;
border-bottom: 2px solid rgba(0, 0, 0, 0.12);
margin-left: 15px
}
.currency input:hover {
display: block;
line-height: 1.5;
font-family: "Open Sans", sans-serif;
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
}
.currency input:focus {
border-bottom: 2px solid #8dc641;
border-bottom-color: transparent;
}
.select-placeholder {
background: rgb(255, 255, 255);
color: rgba(0, 0, 0, 0.38);
}
.swap-rate-container {
display: flex;
align-items: center;
justify-content: space-between;
}
.rate {
color: black;
font-size: 15px;
padding: 0 10px;
background: #E0E0E0;
line-height: var(--tl-small);
padding: 8px;
font-family: 'Open Sans', sans-serif;
border-radius: 2px;
}
input::-webkit-inner-spin-button {
display: none !important;
}
.input-container {
position: relative;
width: 65%;
margin-left: 15px;
bottom: -1px;
}
.input-container input {
width: 100%;
margin-left: 0;
}
.input-container input:focus {
border-bottom: 2px solid #8dc641;
}
.input-box:hover+.input-border {
transform: scaleX(1);
}
.input-border {
display: block;
border-bottom: 2px solid rgba(0, 0, 0, 0.54);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
position: absolute;
bottom: 0;
left: 0;
width: 102%;
}
#media (maz-width: 600px) {
.currency input {
width: 200px;
}
}
.display-none {
display: none;
}
/* for dropdown css*/
/* for input border css */
/* .input-container {
position: relative;
width: 65%;
margin-left: 15px;
}
.input-container input {
width: 100%;
margin-left: 0;
}
.input-border {
position: absolute; bottom: 0; left: 0;
width: 100%;
height: 2px;
}
.input-border::before,
.input-border::after{
content: '';
position: absolute; top: 0;
width: 0;
height: 100%;
background-color: #8dc641;
transition: width .3s ease;
}
.input-border::before {
left: 50%;
}
.input-border::after {
right: 50%;
}
.input-container input:focus + .input-border::before,
.input-container input:focus + .input-border::after {
width: 50%;
} */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Currency Converter</title>
<link rel="shortcut icon" href="currencies-icon-10.jpg" type="image/x-icon">
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="header">
<div class="indent-right"></div>
<b>Конвертор валют</b>
</div>
<div class="currency">
<div class="custom-select" id="curr-one">
<div class="custom-select__placeholder"></div>
<div class="custom-select__list">
<div class="custom-select__option" data-value="EUR">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/EU.svg">
</div>
<div class="custom-select__option-name">EUR</div>
<div class="custom-select__option-symbol">€</div>
</div>
<div class="custom-select__option custom-select__option--select" data-value="USD">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/US.svg">
</div>
<div class="custom-select__option-name">USD</div>
<div class="custom-select__option-symbol">$</div>
</div>
<div class="custom-select__option" data-value="GBP">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/GB.svg">
</div>
<div class="custom-select__option-name">GBP</div>
<div class="custom-select__option-symbol">£</div>
</div>
<div class="custom-select__option display-none" data-value="UAH">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/UA.svg" />
</div>
<div class="custom-select__option-name">UAH</div>
<div class="custom-select__option-symbol">₴</div>
</div>
</div>
</div>
<div class="input-container">
<input type="number" id="amount-one" class="input-box" placeholder="200.00" />
<span class="input-border"></span>
</div>
</div>
<div class="swap-rate-container">
<button class="btn" id="swap">
<div class="btn-arrows">
<div style="display: flex;">
<svg
height="24px" width="24px" version="1.1"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd" stroke="none" stroke-width="1">
<path d="M0 0h24v24H0z"></path>
<path
d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"
fill="#000"
fill-rule="nonzero"></path>
</g>
</svg>
</div>
</div>
</button>
<div class="rate" id="rate"></div>
</div>
<div class="currency">
<div class="custom-select" id="curr-two">
<div class="custom-select__placeholder"></div>
<div class="custom-select__list">
<div class="custom-select__option custom-select__option--select" data-value="UAH">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/UA.svg" />
</div>
<div class="custom-select__option-name">UAH</div>
<div class="custom-select__option-symbol">₴</div>
</div>
<div class="custom-select__option" data-value="GBP">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/GB.svg">
</div>
<div class="custom-select__option-name">GBP</div>
<div class="custom-select__option-symbol">£</div>
</div>
<div class="custom-select__option" data-value="EUR">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/EU.svg">
</div>
<div class="custom-select__option-name">EUR</div>
<div class="custom-select__option-symbol">€</div>
</div>
<div class="custom-select__option display-none" data-value="USD">
<div class="custom-select__option-icon">
<img src="https://cdn.privat24.ua/icons/file/US.svg">
</div>
<div class="custom-select__option-name">USD</div>
<div class="custom-select__option-symbol">$</div>
</div>
</div>
</div>
<div class="input-container">
<input type="number" id="amount-two" class="input-box" placeholder="200.00" />
<span class="input-border"></span>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Making a sliding button to switch website theme using a CSS variable and javascript. It is working properly except there is a small bug that I am unable to fix. If I reload the page is light theme, the functionality of the button is being reversed. The "On" state of the button turns on light mode and off state toggles dark mode. However, the initial configuration is entirely opposite.
As you can see in the executable code snippet below, I tried solving this using click() function. This problem arises only when the value of num is 0 and page is reloaded. So, I thought if I store a variable in localStorage as false and check its value at the beginning of the function and if its false, then click the button and dont execute function, if its not false, then execute normally.
But it is not working for some reason. Please check this code:
if (!localStorage.getItem('thisvarisgud4me')) {
localStorage.setItem("thisvarisgud4me", "1")
}
document.getElementById("btn").addEventListener("click", change);
var c = "true";
if (!localStorage.getItem("clickc"))
{
localStorage.setItem("clickc", c);
}
function change() {
if (localStorage.getItem("clickc") == "false") {
localStorage.setItem("clickc","true");
document.getElementById("btn").click();
}
else if (localStorage.getItem("clickc") == "true") {
if (localStorage.getItem('thisvarisgud4me') == '1') {
localStorage.setItem("thisvarisgud4me", '0')
} else {
localStorage.setItem("thisvarisgud4me", '1')
}
var num = Number(localStorage.getItem('thisvarisgud4me'));
let root = document.documentElement;
root.style.setProperty("--numvar", num);
console.log(num);
if (num == 0) {
window.addEventListener("beforeunload", function (event) {
console.log("The page is redirecting")
alert("Reload");
localStorage.setItem("clickc", "false");
// document.getElementById("btn").click();
// debugger;
});
}
}
}
var num = Number(localStorage.getItem('thisvarisgud4me'));
let root = document.documentElement;
root.style.setProperty("--numvar", num);
:root {
--numvar: 0;
}
html {
filter: invert(var(--numvar));
}
body {
background: #fff;
}
.outer-button {
display: inline-block;
height: 28px;
width: 28px;
position: relative;
margin: 0 3px;
}
.inner-button {
display: inline-block;
position: absolute;
width: 100%;
height: 100%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), inset 0px 0px 1px 2px white;
border-radius: 20px;
background: #f5f5f5;
}
span {
display: inline-block;
vertical-align: middle;
}
.status-text {
color: white;
text-transform: uppercase;
font-size: 11px;
font-family: Futura, sans-serif;
transition: all 0.2s ease;
}
.sliding-switch {
height: 28px;
width: 72px;
position: relative;
}
.outer-switch-box {
overflow: hidden;
height: 100%;
width: 100%;
display: inline-block;
border-radius: 20px;
position: relative;
box-shadow: inset 0 1px 3px 0px #818181, 0px 1px 2px 1px white;
transition: all 0.3s ease;
transition-delay: 65ms;
position: absolute;
z-index: 1;
}
.inner-switch-box {
position: relative;
width: 175px;
transition: all 0.3s ease;
}
/* .switch-checkbox:checked+.outer-switch-box .unchecked-text {
color: transparent;
}
.switch-checkbox:not(:checked)+.outer-switch-box .checked-text {
color: transparent;
} */
.switch-checkbox:checked+.outer-switch-box .inner-switch-box {
left: -27px;
/*OFF*/
}
.switch-checkbox:not(:checked)+.outer-switch-box .inner-switch-box {
left: 20px;
/*ON*/
}
.switch-checkbox:checked+.outer-switch-box {
/* background-image: linear-gradient(#b6d284, #b6d284); */
background: #492d7b;
/* background: #b6d284; */
}
.switch-checkbox:not(:checked)+.outer-switch-box {
/* background-image: linear-gradient(#cbcbcb, #dbdbdb); */
background: #dbdbdb;
}
[type="checkbox"] {
margin: 0;
padding: 0;
appearance: none;
width: 100%;
height: 100%;
border: 1px solid black;
position: absolute;
top: 0;
left: 0;
z-index: 100;
opacity: 0;
}
.unchecked-text {
color: black !important;
font-weight: 700;
}
.btn-heading {
color: black;
font-family: 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Open Sans', 'Helvetica Neue', 'sans-serif';
padding: .4vw 0;
}
body {
float: left;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<body>
<div class="btn-heading">Dark Mode</div>
<div class="sliding-switch">
<input type="checkbox" id="btn" class="switch-checkbox" />
<div class="outer-switch-box">
<div class="inner-switch-box">
<span class="status-text checked-text" id="textp1">on</span>
<span class="outer-button">
<span class="inner-button"></span>
</span>
<span class="status-text unchecked-text" id="textp2">off</span>
</div>
</div>
</div>
</body>
</html>
As you might have noticed, I also tried manipulating CSS pseudo class properties using JS. But that was a complete mess. Then, I thought of this approach and I was quite confident that it is correct but looks like I was wrong :(
Just adding a condition to setting "clickc" to "true" will probably do the trick. Here I've used a similar condition to that you've already used for the "thisvarisgud4me" key.
I took the opportunity to test out a utility I created that essentially implements the Storage API (that's what <script src="https://heretic-monkey.link/FauxStorage.js"></script> is in the HTML, and why all of your localStorage references now say localStore).
So if you decide to copy and paste this into your own code, just do a search and replace of localStore with localStorage.
if (!localStore.getItem('thisvarisgud4me')) {
localStore.setItem("thisvarisgud4me", "1")
}
document.getElementById("btn").addEventListener("click", change);
var c = "true";
if (!localStore.getItem("clickc")) {
localStore.setItem("clickc", c);
}
function change() {
if (localStore.getItem("clickc") == "false") {
document.getElementById("btn").click();
localStore.getItem("clickc") = "true";
} else if (localStore.getItem("clickc") == "true") {
if (localStore.getItem('thisvarisgud4me') == '1') {
localStore.setItem("thisvarisgud4me", '0')
} else {
localStore.setItem("thisvarisgud4me", '1')
}
var num = Number(localStore.getItem('thisvarisgud4me'));
let root = document.documentElement;
root.style.setProperty("--numvar", num);
console.log(num);
if (num == 0) {
window.addEventListener("beforeunload", function(event) {
console.log("The page is redirecting")
alert("Reload");
localStore.setItem("clickc", "false");
// document.getElementById("btn").click();
// debugger;
});
}
}
}
var num = Number(localStore.getItem('thisvarisgud4me'));
let root = document.documentElement;
root.style.setProperty("--numvar", num);
:root {
--numvar: 0;
}
html {
filter: invert(var(--numvar));
}
body {
background: #fff;
}
.outer-button {
display: inline-block;
height: 28px;
width: 28px;
position: relative;
margin: 0 3px;
}
.inner-button {
display: inline-block;
position: absolute;
width: 100%;
height: 100%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), inset 0px 0px 1px 2px white;
border-radius: 20px;
background: #f5f5f5;
}
span {
display: inline-block;
vertical-align: middle;
}
.status-text {
color: white;
text-transform: uppercase;
font-size: 11px;
font-family: Futura, sans-serif;
transition: all 0.2s ease;
}
.sliding-switch {
height: 28px;
width: 72px;
position: relative;
}
.outer-switch-box {
overflow: hidden;
height: 100%;
width: 100%;
display: inline-block;
border-radius: 20px;
position: relative;
box-shadow: inset 0 1px 3px 0px #818181, 0px 1px 2px 1px white;
transition: all 0.3s ease;
transition-delay: 65ms;
position: absolute;
z-index: 1;
}
.inner-switch-box {
position: relative;
width: 175px;
transition: all 0.3s ease;
}
/* .switch-checkbox:checked+.outer-switch-box .unchecked-text {
color: transparent;
}
.switch-checkbox:not(:checked)+.outer-switch-box .checked-text {
color: transparent;
} */
.switch-checkbox:checked+.outer-switch-box .inner-switch-box {
left: -27px;
/*OFF*/
}
.switch-checkbox:not(:checked)+.outer-switch-box .inner-switch-box {
left: 20px;
/*ON*/
}
.switch-checkbox:checked+.outer-switch-box {
/* background-image: linear-gradient(#b6d284, #b6d284); */
background: #492d7b;
/* background: #b6d284; */
}
.switch-checkbox:not(:checked)+.outer-switch-box {
/* background-image: linear-gradient(#cbcbcb, #dbdbdb); */
background: #dbdbdb;
}
[type="checkbox"] {
margin: 0;
padding: 0;
appearance: none;
width: 100%;
height: 100%;
border: 1px solid black;
position: absolute;
top: 0;
left: 0;
z-index: 100;
opacity: 0;
}
.unchecked-text {
color: black !important;
font-weight: 700;
}
.btn-heading {
color: black;
font-family: 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Open Sans', 'Helvetica Neue', 'sans-serif';
padding: .4vw 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://heretic-monkey.link/FauxStorage.js"></script>
</head>
<body>
<div class="btn-heading">Dark Mode</div>
<div class="sliding-switch">
<input type="checkbox" id="btn" class="switch-checkbox" />
<div class="outer-switch-box">
<div class="inner-switch-box">
<span class="status-text checked-text" id="textp1">on</span>
<span class="outer-button">
<span class="inner-button"></span>
</span>
<span class="status-text unchecked-text" id="textp2">off</span>
</div>
</div>
</div>
</body>
</html>
Here's how I would refactor it. This is more of an object-oriented way of doing things; it might not appeal to everyone and it certainly isn't meant to. It works for me and I'm the only one I need to make happy with it :).
class ThemeStore {
_darkModeKey = "thisvarisgud4me";
_darkMode = null;
get darkMode() {
if (this._darkMode === null) {
if (!localStore.getItem(this._darkModeKey)) {
localStore.setItem(this._darkModeKey, 0);
}
this._darkMode = JSON.parse(localStore.getItem(this._darkModeKey));
}
return this._darkMode;
}
set darkMode(value) {
this._darkMode = value;
}
persist() {
localStore.setItem("thisvarisgud4me", JSON.stringify(this.darkMode));
}
}
var themeStore = new ThemeStore();
document.getElementById("btn").addEventListener("click", change);
function change(e) {
themeStore.darkMode = e.target.checked ? 0 : 1;
let root = document.documentElement;
root.style.setProperty("--numvar", themeStore.darkMode);
console.log(themeStore.darkMode);
if (themeStore.darkMode === 0) {
window.addEventListener("beforeunload", function(event) {
console.log("The page is redirecting")
themeStore.persist();
});
}
}
document.getElementById("btn").dispatchEvent(new CustomEvent("change"));
:root {
--numvar: 0;
}
html {
filter: invert(var(--numvar));
}
body {
background: #fff;
}
.outer-button {
display: inline-block;
height: 28px;
width: 28px;
position: relative;
margin: 0 3px;
}
.inner-button {
display: inline-block;
position: absolute;
width: 100%;
height: 100%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), inset 0px 0px 1px 2px white;
border-radius: 20px;
background: #f5f5f5;
}
span {
display: inline-block;
vertical-align: middle;
}
.status-text {
color: white;
text-transform: uppercase;
font-size: 11px;
font-family: Futura, sans-serif;
transition: all 0.2s ease;
}
.sliding-switch {
height: 28px;
width: 72px;
position: relative;
}
.outer-switch-box {
overflow: hidden;
height: 100%;
width: 100%;
display: inline-block;
border-radius: 20px;
position: relative;
box-shadow: inset 0 1px 3px 0px #818181, 0px 1px 2px 1px white;
transition: all 0.3s ease;
transition-delay: 65ms;
position: absolute;
z-index: 1;
}
.inner-switch-box {
position: relative;
width: 175px;
transition: all 0.3s ease;
}
/* .switch-checkbox:checked+.outer-switch-box .unchecked-text {
color: transparent;
}
.switch-checkbox:not(:checked)+.outer-switch-box .checked-text {
color: transparent;
} */
.switch-checkbox:checked+.outer-switch-box .inner-switch-box {
left: -27px;
/*OFF*/
}
.switch-checkbox:not(:checked)+.outer-switch-box .inner-switch-box {
left: 20px;
/*ON*/
}
.switch-checkbox:checked+.outer-switch-box {
/* background-image: linear-gradient(#b6d284, #b6d284); */
background: #492d7b;
/* background: #b6d284; */
}
.switch-checkbox:not(:checked)+.outer-switch-box {
/* background-image: linear-gradient(#cbcbcb, #dbdbdb); */
background: #dbdbdb;
}
[type="checkbox"] {
margin: 0;
padding: 0;
appearance: none;
width: 100%;
height: 100%;
border: 1px solid black;
position: absolute;
top: 0;
left: 0;
z-index: 100;
opacity: 0;
}
.unchecked-text {
color: black !important;
font-weight: 700;
}
.btn-heading {
color: black;
font-family: 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Open Sans', 'Helvetica Neue', 'sans-serif';
padding: .4vw 0;
}
<script src="https://heretic-monkey.link/FauxStorage.js"></script>
<div class="btn-heading">Dark Mode</div>
<div class="sliding-switch">
<input type="checkbox" id="btn" class="switch-checkbox" />
<div class="outer-switch-box">
<div class="inner-switch-box">
<span class="status-text checked-text" id="textp1">on</span>
<span class="outer-button">
<span class="inner-button"></span>
</span>
<span class="status-text unchecked-text" id="textp2">off</span>
</div>
</div>
</div>
$(document).ready(function() {
var mx, my, anime = false;
var e_top = $('.panel-dock').css('top').split('px')[0]
var e_bottom = $('.panel-dock').css('height').split('px')[0]
e_top = parseFloat(e_top)
e_bottom = parseFloat(e_bottom)
$(document).mousemove(function(e) {
if (anime) {
return;
}
mx = parseFloat(e.clientX);
my = parseFloat(e.clientY);
console.log(my, e_top, e_bottom)
if (mx <= 80) {
//if (my >= e_top && my <= e_bottom) {
anime = true;
$('.panel-dock').animate({
left: 0,
}, 'fast', function() {
anime = false;
});
//}
} else if (mx > 80) {
//if (my < e_top && my > e_bottom) {
anime = true;
$('.panel-dock').animate({
left: -60,
}, 'slow', function() {
anime = false;
});
//}
}
});
});
.panel-menu,
.g-tip,
h4,
h5,
p {
font-family: 'Ubuntu', sans-serif;
font-size: 11pt;
}
.panel-dock {
position: fixed;
top: calc(10em - 20px);
margin: 0;
background: #333;
opacity: 0.9;
border-radius: 0 6px 6px 0;
width: 3em;
height: max-content;
padding: 0.5em;
z-index: 1;
color: white;
box-shadow: 8px 4px 20px rgba(0, 0, 0, 0.3);
float: left;
}
#media (max-height: 600px) {
.gadget-dock {
position: fixed;
top: calc(7em - 20px);
}
}
.panel-dock .panel-menu {
cursor: pointer;
width: 100%;
/* background: transparent; */
text-align: center;
z-index: 2;
padding: 2%;
letter-spacing: 0.06em;
margin-bottom: 10%;
margin-top: 10%;
border-radius: 3px;
}
.panel-dock .panel-menu:nth-child(n) {
border: 1px solid transparent;
border-top: 1px solid #585858;
border-bottom: 1px solid #585858;
}
.panel-dock .panel-menu:hover {
background: white;
}
.panel-dock .panel-icons {
background: -webkit-linear-gradient(250deg, #6da741 40%, #00a489 60%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
width: 30px;
height: 30px;
display: inline-block;
}
.panel-dock .g-icon {
max-width: auto;
max-height: 30px;
}
.panel-dock .g-icon i {
margin-top: 25%;
}
.panel-dock .g-tip {
position: absolute;
left: 55px;
color: #6da741;
line-height: 1.3;
min-height: 30px;
box-shadow: 2px 2px 6px #e0e0e0;
z-index: 1;
letter-spacing: 0.006em;
padding: 5% 5% 0 5%;
border: 2px solid #eee;
border-radius: 8%;
text-align: center;
width: 125px;
background: #fff
}
.panel-dock .g-tip h5 {
display: inline-block;
text-transform: none;
text-shadow: 2px 3px 3px #e0e0e0;
letter-spacing: 0.06em;
color: #6da741;
}
.panel-dock .g-tip:before {
content: '';
position: absolute;
top: 25%;
left: -13%;
border: 8px solid #fff;
border-left: 8px solid transparent;
border-bottom: 8px solid transparent;
border-top: 8px solid transparent;
}
.t1 {
position: absolute;
top: 15px;
}
.t2 {
position: absolute;
top: 50px;
}
.t3 {
position: absolute;
top: 85px;
}
.t4 {
position: absolute;
top: 120px;
}
.t1,
.t2,
.t3,
.t4 {
display: none;
}
.tgl {
left: -80px;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="panel-dock" id="g">
<div class="panel-menu">
<div class="panel-icons">
<span class="g-icon tg1"><i class="fa fa-th"></i></span>
</div>
<div class="g-tip t1">
<h5>Library</h5>
</div>
</div>
<div class="panel-menu">
<div class="panel-icons">
<span class="g-icon tg2"><i class="fa fa-plus"></i></span>
</div>
<div class="g-tip t2">
<h5>Create a post</h5>
</div>
</div>
<div class="panel-menu">
<div class="panel-icons">
<span class="g-icon tg3"><i class="fa fa-bookmark"></i></span>
</div>
<div class="g-tip t3">
<h5>Bookmarks</h5>
</div>
</div>
<div class="panel-menu">
<div class="panel-icons">
<span class="g-icon tg4"><i class="fa fa-heart"></i></span>
</div>
<div class="g-tip t4">
<h5>Favorites</h5>
</div>
</div>
</div>
Below code is working while I remove the condition if (my>=e_top && my<=e_bottom) and if (my<e_top && my>e_bottom). And, if mouse enters anywhere within mx <= 80 the panel is visible; otherwise, it slowly hides.
I want to show this panel if mouse is within 80px from left and between the start position of panel and it's height.
$(document).ready(function() {
var mx, my, anime = false;
var e_top = $('.panel').css('top').split('px')[0]
var e_bottom = $('.panel').css('bottom').split('px')[0]
$(document).mousemove(function(e) {
if (anime) {
return;
}
mx = e.clientX;
my = e.clientY;
// console.log(my, e_top, e_bottom)
if (mx<=80) {
if (my>=e_top && my<=e_bottom) {
anime = true;
$('.panel').animate({
left: '0',
}, 'fast', function () {
anime = false;
});
}
} else if (mx > 80) {
if (my<e_top && my>e_bottom) {
anime = true;
$('.panel').animate({
left: '-60',
}, 'slow', function () {
anime = false;
});
}
}
});
});
So, any solution?
You've got a couple problems here. First off, you're calculating the e_bottom wrong. You just looked at the height, but the bottom is the height plus the top, and you were trying to do it with strings, not numbers.
var e_top = parseFloat($('.panel-dock').css('top').split('px')[0])
var e_bottom = parseFloat($('.panel-dock').css('height').split('px')[0]) + e_top
And more importantly, your second commented out if statement: if (my < e_top && my > e_bottom) { could never return true, because it's impossible for my to be less than the top AND greater than the bottom. It needs to be an OR.
if (my < e_top || my > e_bottom) {
$(document).ready(function() {
var mx, my, anime = false;
var e_top = parseFloat($('.panel-dock').css('top').split('px')[0])
var e_bottom = parseFloat($('.panel-dock').css('height').split('px')[0]) + e_top
e_top = parseFloat(e_top)
e_bottom = parseFloat(e_bottom)
$(document).mousemove(function(e) {
if (anime) {
return;
}
mx = parseFloat(e.clientX);
my = parseFloat(e.clientY);
console.log(my, e_top, e_bottom)
if (mx <= 80) {
if (my >= e_top && my <= e_bottom) {
anime = true;
$('.panel-dock').animate({
left: 0,
}, 'fast', function() {
anime = false;
});
}
} else if (mx > 80) {
if (my < e_top || my > e_bottom) {
anime = true;
$('.panel-dock').animate({
left: -60,
}, 'slow', function() {
anime = false;
});
}
}
});
});
.panel-menu,
.g-tip,
h4,
h5,
p {
font-family: 'Ubuntu', sans-serif;
font-size: 11pt;
}
.panel-dock {
position: fixed;
top: calc(10em - 20px);
margin: 0;
background: #333;
opacity: 0.9;
border-radius: 0 6px 6px 0;
width: 3em;
height: max-content;
padding: 0.5em;
z-index: 1;
color: white;
box-shadow: 8px 4px 20px rgba(0, 0, 0, 0.3);
float: left;
}
#media (max-height: 600px) {
.gadget-dock {
position: fixed;
top: calc(7em - 20px);
}
}
.panel-dock .panel-menu {
cursor: pointer;
width: 100%;
/* background: transparent; */
text-align: center;
z-index: 2;
padding: 2%;
letter-spacing: 0.06em;
margin-bottom: 10%;
margin-top: 10%;
border-radius: 3px;
}
.panel-dock .panel-menu:nth-child(n) {
border: 1px solid transparent;
border-top: 1px solid #585858;
border-bottom: 1px solid #585858;
}
.panel-dock .panel-menu:hover {
background: white;
}
.panel-dock .panel-icons {
background: -webkit-linear-gradient(250deg, #6da741 40%, #00a489 60%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
width: 30px;
height: 30px;
display: inline-block;
}
.panel-dock .g-icon {
max-width: auto;
max-height: 30px;
}
.panel-dock .g-icon i {
margin-top: 25%;
}
.panel-dock .g-tip {
position: absolute;
left: 55px;
color: #6da741;
line-height: 1.3;
min-height: 30px;
box-shadow: 2px 2px 6px #e0e0e0;
z-index: 1;
letter-spacing: 0.006em;
padding: 5% 5% 0 5%;
border: 2px solid #eee;
border-radius: 8%;
text-align: center;
width: 125px;
background: #fff
}
.panel-dock .g-tip h5 {
display: inline-block;
text-transform: none;
text-shadow: 2px 3px 3px #e0e0e0;
letter-spacing: 0.06em;
color: #6da741;
}
.panel-dock .g-tip:before {
content: '';
position: absolute;
top: 25%;
left: -13%;
border: 8px solid #fff;
border-left: 8px solid transparent;
border-bottom: 8px solid transparent;
border-top: 8px solid transparent;
}
.t1 {
position: absolute;
top: 15px;
}
.t2 {
position: absolute;
top: 50px;
}
.t3 {
position: absolute;
top: 85px;
}
.t4 {
position: absolute;
top: 120px;
}
.t1,
.t2,
.t3,
.t4 {
display: none;
}
.tgl {
left: -80px;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="panel-dock" id="g">
<div class="panel-menu">
<div class="panel-icons">
<span class="g-icon tg1"><i class="fa fa-th"></i></span>
</div>
<div class="g-tip t1">
<h5>Library</h5>
</div>
</div>
<div class="panel-menu">
<div class="panel-icons">
<span class="g-icon tg2"><i class="fa fa-plus"></i></span>
</div>
<div class="g-tip t2">
<h5>Create a post</h5>
</div>
</div>
<div class="panel-menu">
<div class="panel-icons">
<span class="g-icon tg3"><i class="fa fa-bookmark"></i></span>
</div>
<div class="g-tip t3">
<h5>Bookmarks</h5>
</div>
</div>
<div class="panel-menu">
<div class="panel-icons">
<span class="g-icon tg4"><i class="fa fa-heart"></i></span>
</div>
<div class="g-tip t4">
<h5>Favorites</h5>
</div>
</div>
</div>