I'm working on a pop up modal and when I click a button I add a class changes the display property from 'none' to 'block'. It worked fine at first then I appended some HTML to the body via JS and since then it hasn't worked.
// Open modal
function openModal(clicked_id) {
var button = document.getElementById(clicked_id);
var modal = button.getAttribute("data-modal");
var modalElement = document.getElementById(modal);
document.body.innerHTML += "<div id='modal-backdrop' class='modal-backdrop'></div>";
var backdrop = document.getElementById("modal-backdrop");
backdrop.className += " modal-open";
modalElement.className += " modal-open";
// Close Same Modal Event Handlers
(function() {
document.getElementById("modal-close").onclick = function(e) {
closeModal(modalElement, backdrop);
}
document.getElementById("close").onclick = function(e) {
closeModal(modalElement, backdrop);
}
document.getElementById("modal-backdrop").onclick = function(e) {
closeModal(modalElement, backdrop);
}
})();
}
From debuggin I can see that element is being selected and the class name is added to the class list, but this isn't reflected on the computed HTML. I tried moving the line:
modalElement.className += " modal-open";
above the line:
document.body.innerHTML += "<div id='modal-backdrop' class='modal-backdrop'></div>";
But then the close functions stopped working. There's no errors in the console and the debugger runs the code as if it worked so I'm stumped. I have a code pen that shows everything bought together: http://codepen.io/WebDevelopWolf/pen/XMZdBg
Instead of using += (or string concatenation) for appending to the body, use document.createElement() and body.appendChild(element) to append the new element to the body. This small change will get your modal working again.
// Open modal
function openModal(clicked_id) {
var button = document.getElementById(clicked_id);
var modal = button.getAttribute("data-modal");
var modalElement = document.getElementById(modal);
var backdrop = document.createElement('div');
backdrop.id="modal-backdrop";
backdrop.classList.add("modal-backdrop");
document.body.appendChild(backdrop);
backdrop.classList.add("modal-open");
modalElement.classList.add("modal-open");
// Close Same Modal Event Handlers
(function() {
document.getElementById("modal-close").onclick = function(e) {
closeModal(modalElement, backdrop);
}
document.getElementById("close").onclick = function(e) {
closeModal(modalElement, backdrop);
}
backdrop.onclick = function(e) {
closeModal(modalElement, backdrop);
}
})();
}
// Close Modal
function closeModal(modalElement, backdrop) {
modalElement.className = modalElement.className.replace(/\bmodal-open\b/, '');
backdrop.className = backdrop.className.replace(/\bmodal-open\b/, '');
}
#import url('https://fonts.googleapis.com/css?family=Open+Sans');
body {
background: #0881a3;
font-family: 'Open Sans', sans-serif;
font-size: 14px;
color: #666;
position: relative;
overflow: hidden;
}
#heading {
text-align: center;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 1);
color: #e1e1e1;
text-transform: uppercase;
}
h3 {
text-transform: none;
text-shadow: 0px 0px 0px rgba(0, 0, 0, 1);
font-size: 13px;
}
#trigger {
width: 50%;
margin: 0 auto;
margin-top: 35px;
text-align: center;
}
.modal {
color: #1f4e5f;
background: #a4e5d9;
width: 40%;
margin: 50px auto;
border-radius: 5px;
text-align: left;
-webkit-box-shadow: 2px 2px 10px 0px rgba(0, 0, 0, 0.75);
-moz-box-shadow: 2px 2px 10px 0px rgba(0, 0, 0, 0.75);
box-shadow: 2px 2px 10px 0px rgba(0, 0, 0, 0.75);
z-index: 1050;
position: fixed;
top: 0;
right: 0;
left: 0;
transition: opacity .15s linear;
opacity: 0;
-webkit-transition: opacity .15s linear;
-o-transition: opacity .15s linear;
opacity: 1;
display: none;
}
small {
text-align: center;
color: #FFF;
}
.modal-body,
.modal-footer,
.modal-heading {
padding: 25px 20px;
}
.modal-heading {
border-bottom: 1px solid #c8f4de;
}
.modal-heading h2 {
margin: 0;
}
.modal-heading h2 i {
margin-right: 10px;
}
.modal-heading .close {
position: absolute;
right: 20px;
top: 17px;
font-size: 28px;
}
.modal-heading .close:hover {
cursor: pointer;
}
.modal-footer {
border-top: 1px solid #c8f4de;
position: relative;
bottom: 0;
}
.modal-footer button,
#trigger button {
width: 100%;
font-size: 16px;
padding: 10px;
display: block;
background-color: #649dad;
border: 1px solid transparent;
color: #ffffff;
font-weight: bold;
-webkit-border-radius: 3px;
border-radius: 3px;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
#trigger button {
width: auto;
margin: 0px auto;
}
.modal-footer button:hover,
#trigger button:hover {
background-color: #ffffff;
color: #009ac9;
border-color: #009ac9;
cursor: pointer;
}
.modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #000;
opacity: .5;
z-index: 0;
display: none;
}
.modal-open {
display: block;
}
<script src="https://use.fontawesome.com/f79e01ac29.js"></script>
<div id="heading">
<h1><i class="fa fa-paw"></i> Akela - The Pure JS Pop-up</h1>
<h3>A lightweight modal pop-up with no framework dependancy that's mobile friendly.</h3>
</div>
<!--Modal Trigger-->
<div id="trigger">
<button id="staticbtn" data-modal="static" onClick="openModal(this.id)" class="btn btn-info">Show Static Modal</button><br />
<small><i class="fa fa-star"></i> Made with the help of Font Awesome <i class="fa fa-star"></i></small>
</div>
<!--Static Modal-->
<div id="static" class="modal" tabindex="-1" role="dialog">
<div class="modal-content">
<div class="modal-heading">
<h2><i class="fa fa-paw"></i> Hello World</h2>
<div class="close"><i id="close" class="fa fa-close"></i></div>
</div>
<div class="modal-body">
I'm a pop up!
</div>
<div id="modalFooter" class="modal-footer">
<button id="modal-close" type="button" class="btn btn-info">Close</button>
</div>
</div>
</div>
Related
I am creating a settings portion on a website. I want the features chosen to be "saved" and kept when the page refreshes. I attempted this but it seems to just reset the form when I refresh the page. Another issue is when I click on the cancel button, the toggle buttons reset but the dropdown comes back blank instead of going back to the placeholder "select timezone". The issue most likely lies in my javascript code below. It's also throwing an error in stack overflow but works properly on my website (minus the issues described above). Any suggestions would be much appreciated!
// ---------- TOGGLE BTN ----------
const toggle = document.getElementsByClassName("toggle");
const labels = document.getElementsByClassName("labels");
for(let i=0; i < 2; i++) {
labels[i].innerHTML = "OFF";
toggle[i].addEventListener( "click", () => {
if(labels[i].innerHTML == "OFF") {
// console.log("button toggled");
labels[i].classList.add("on");
labels[i].innerHTML= "ON";
} else {
labels[i].classList.remove("on");
labels[i].innerHTML = "OFF";
}
});
}
// ---------- LOCAL STORAGE DATA ----------
const save = document.getElementById("save");
const cancel = document.getElementById("cancel");
const emailBtn = document.getElementById("togBtn");
const publicBtn = document.getElementById("togBtn2");
const zone = document.getElementById("timezone");
// emailBtn.value = data;
// publicBtn.value = data;
// zone.value = data;
const data = {
email: emailBtn.value,
privacy: publicBtn.value,
timezone: zone.value
}
var emailVal = localStorage.getItem("email");
var privacyVal = localStorage.getItem("privacy");
var zoneVal = localStorage.getItem("timezone");
save.addEventListener('click', () => {
localStorage.setItem("email", emailBtn.value);
localStorage.setItem("privacy", publicBtn.value);
localStorage.setItem("timezone", zone.value);
});
cancel.addEventListener('click', () => {
localStorage.clear();
for(let i=0; i < 2; i++) {
labels[i].innerHTML = "OFF";
labels[i].classList.remove("on");
}
emailBtn.checked = false;
publicBtn.checked =false;
zone.value = 'Select Timezone';
});
.settings {
padding-left: 15px;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.settings h3 {
flex-basis: 100%;
}
.button1,
.button2 {
flex-basis: 100%;
display: flex;
align-items:center;
}
label {
flex-basis: 90%;
}
input {
flex-basis: 10%;
}
.form-field {
flex-basis: 100%;
background-color: rgb(241, 240, 240);
border: 1px solid lightgrey;
color: grey;
border-radius: 5px;
padding: 10px;
margin: 0 15px 10px 0;
}
.settings-button {
display: flex;
justify-content: center;
}
button {
margin: 10px 15px 10px 0;
padding: 10px;
border: 1px solid lightgrey;
border-radius: 5px;
}
#save,
#cancel {
flex-basis: 50%;
}
#save {
background-color: #7477BF;
color: white;
}
#cancel {
background-color: darkgray;
color: white;
}
#timezone {
margin-top:25px;
}
/* toggle button */
.toggle {
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
position: relative;
outline: 0;
cursor: pointer;
margin: 10px 15px;
}
.toggle:after {
content: '';
width: 80px;
height: 28px;
display: inline-block;
background: rgba(196, 195, 195, 0.55);
border: 2px solid rgba(196, 195, 195, 0.55);
border-radius: 18px;
clear: both;
}
.toggle:before {
content: '';
width: 20px;
height: 20px;
display: block;
position: absolute;
top: 3px;
/* left: 0;
top: -3px; */
border: 2px solid rgba(196, 195, 195, 0.55);
border-radius: 50%;
background: rgb(255, 255, 255);
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6);
}
.toggle:checked:before {
left: 54px;
box-shadow: -1px 1px 3px rgba(0, 0, 0, 0.6);
}
.toggle:checked:after {
background: #7477BF;
}
.toggle,
.toggle:before,
.toggle:after,
.toggle:checked:before,
.toggle:checked:after {
transition: ease .4s;
-webkit-transition: ease .4s;
-moz-transition: ease .4s;
-o-transition: ease .4s;
}
.labels {
color: gray;
position: relative;
font-size: 15px;
transform: translate(-48px, -3px);
}
.on {
color: white;
transform: translate(-90px, -3px);
}
<section class="settings" id="settings">
<h3>Settings</h3>
<!-- custom CSS toggle code-->
<div class="button1">
<label for="togBtn">Send Email Notfications </label>
<input type="checkbox" class="toggle" id="togBtn">
<span class="labels"></span>
</div>
<div class="button2">
<label for="togBtn2">Set Profile to Public </label>
<input type="checkbox" class="toggle" id="togBtn2">
<span class="labels"></span>
</div>
<select class="form-field" id="timezone">
<option disabled selected>Select a Timezone</option>
<option>Eastern</option>
<option>Western</option>
<!-- more options -->
</select>
<div class="settings-button" >
<button class="button-primary" id="save">Save</button>
<button class="button-disabled" id="cancel">Cancel</button>
</div>
</section>
here a working example.
The problems with your code were that you were using emailBtn.value and publicBtn.value instead of emailBtn.checked and publicBtn.checked (they are checkbox so in order to get the correct value you have to read che checked property) and you were not loading the saved values on document load (the function inside window.addEventListener("load", ...) in my example.
Hope this helps you.
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>
I a problem doing a simple css opacity transition on the selector #loginForm > div:first-child h1 by simply adding the class .animated to that element using javascript. Although it is not working. Below is the code:
document.querySelector('#loginForm > div:nth-child(2)').style.display = 'none';
document.querySelector('#loginForm > div:first-child').style.display = 'block';
var verified_text = document.querySelector('#loginForm > div:first-child h1');
verified_text.classList.add('animated');
#loginForm {
position: relative;
padding: 40px;
background-color: #fcde84;
border-radius: 5px;
margin-top: 75px;
width: 462px;
}
#loginForm>div:first-child {
height: 380px;
border: 0;
filter: drop-shadow( 5px 8px 8px rgba(0, 0, 0, 0.1));
}
#loginForm>div:first-child div {
margin-top: 165px;
}
#loginForm>div div {
width: 150px;
height: 150px;
margin: 0 auto;
overflow: hidden;
}
#loginForm>div:first-child h1 {
font-family: 'Arial Rounded MT';
color: rgb(109, 204, 91);
text-align: center;
display: block;
transition: all 5s ease-out;
opacity: 0;
}
#loginForm>div:first-child h1.animated {
opacity: 1;
}
#loginForm h2 {
font-size: 34px;
text-transform: uppercase;
line-height: 24px;
color: #2f4e71;
letter-spacing: -2px;
font-weight: 700;
font-family: 'Montserrat', sans-serif;
}
#loginForm p {
font-size: 17px;
line-height: 40px;
color: #333850;
display: block;
margin: 0 0 10px;
font-weight: 700;
}
#loginForm>div:nth-child(2) div {
border-radius: 50%;
border: solid 2.5px #3A5E77;
}
#loginForm ul {
padding: 10px 15px 10px 30px;
background-color: #fc7f77;
color: white;
border-radius: 7.5px;
margin: 12px 0;
display: none;
}
#loginForm li {
text-align: center;
display: block;
font-size: 24px;
}
#loginForm label {
margin: 0 0 12px;
display: block;
font-size: 1.25em;
color: #217093;
font-weight: 700;
}
#loginForm input {
border-radius: 32.5px;
height: 65px;
width: 100%;
font-weight: 600;
font-size: 1.55em;
transition: box-shadow .2s linear, border-color .25s ease-out, background-color .2s ease-out;
}
#email,
#password {
margin: 0 0 24px;
padding: 0 1em 0;
background-color: #f3fafd;
border: solid 2px #217093;
}
#email:focus,
#password:focus {
outline: none;
box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);
border: solid 2px #4eb8dd;
}
#loginForm input[type="submit"] {
padding: .65em 1em 1em;
background-color: #4eb8dd;
color: #FFF;
}
#loginForm input[type="submit"]:hover {
background-color: #217093;
}
<form autocomplete="on" method="post" id="loginForm">
<div style="display: none;">
<div></div>
<h1>Verified</h1>
</div>
<div>
<h2>Join our community</h2>
<p>Login to get instant access to our video courses</p>
<div>SVG goes here</div>
<ul></ul>
<label for="email">Username</label>
<input type="text" id="email" name="username" form="loginForm" required autofocus/>
<label for="password">Password</label>
<input type="password" id="password" name="password" form="loginForm" required/>
<input type='submit' value="Login" name="login" form="loginForm">
</div>
</form>
video of the problem:
https://youtu.be/OGZWfBaG_aM
I want the word verified to fade in
Because the CSS and JavaScript load at virtually the same time as far as the Browser is concerned, a transition is not detected. Change that last line of JavaScript to something like:
setTimeout(()=>{
verified_text.classList.add('animated');
}, 100);
I stumbled on something similar on a React project. It was head-scratching at first but what #StackSlave mentioned above gave me a good hint about the issue I was having.
I had a parent component rendering a child component and I was trying to fade out the child component on a certain click event.
It wasn't working
I had the following setup at first:
const Parent = () =>{
const Child = () =>(
<Image
...
className={clsx(s.image, !showPoster && s.hidden)}
...
/>
)
return(
<>
...
<Child/>
...
</>)
}
I then modified above to the following and the CSS transition worked smoothly.
const Parent = () =>{
return(
<>
...
<Image
...
className={clsx(s.image, !showPoster && s.hidden)}
...
/>
...
</>)
}
styles
.image {
...
opacity: 1;
transition: all 0.2s ease-out !important;
}
.hidden {
opacity: 0;
}
I've got a function on a drop-down button which when scrolled past it, it changes position to fixed so that it's always visible. Although, my problem is when it changes to position:fixed, it's usually aligned to the right, but it changes position to the left. How can I make it so that it stays in place? I can't use any fixed "right" value, as I need this to work on mobile version as well(width of parent container varies). Check my jsFiddle https://jsfiddle.net/ramisrour/2asco9n1/6/
Also, the .dropContainer doesn't need height or width, I just set it there for the fiddle, so you can test with the scrolling.
<div class="dropContainer">
<div class="dropDwn">
<div class="dropToggle">Viktig informasjon! Les her <i class="bouncer"></i></div>
<div class="dropContentBox">
<div class="dropTxt">
Vær oppmerksom på at Huawei P40-serien og Mate Xs ikke har Google Mobile Services (GMS) installert (Du kan derfor ikke laste ned apper direkte fra Google Play Butikken). Istedenfor har den AppGallery, Huaweis egen offisielle appbutikk.
</br>Du kan bruke AppGallery til å lete etter, laste ned, håndtere og dele mobilapper.
</div>
</div>
<div class="acceptCta"><span class="acceptCtaTxt">Jeg har lest og forstått </span><i class="arroww"></i></div>
</div>
</div>
.dropContainer{
position: relative;
box-sizing: border-box;
}
.dropDwn {
font-family: inherit;
background-color: #fff;
color: #333;
border: solid 1px #333;
position: relative;
text-align: center;
display: block;
z-index: 9999;
cursor: pointer;
padding: 5px;
border-radius: 5px;
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.4);
transition: all 0.5s ease;
font-size: 16px;
width: 250px;
box-sizing: border-box;
height: 30px;
overflow: hidden;
float: right;
}
.dropDwn.open {
height: 280px;
width: 320px;
cursor: default;
background-color: #000E52;
color: #fff;
}
.dropTxt{
margin: 10px;
}
.bouncer {
position: relative;
border: solid #333;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transition: all 0.5s ease;
animation: bouncer 2s infinite;
}
.dropDwn.open .bouncer {
transform: rotate(225deg);
border-color: #fff;
}
.dropContentBox {
margin-top: 10px;
display: inline-block;
color: #fff;
transition: all 0.5s ease;
text-align: center;
}
.acceptCta {
display: block;
position: relative;
cursor: pointer;
text-align: center;
margin: 0 auto;
background-color: #7CBD2B;
color: #333;
height: 35px;
width: 220px;
font-size: 14px;
font-weight: 600;
padding: 10px 25px;
box-sizing: border-box;
border-radius: 3px;
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
transition: all 0.5s ease;
z-index: 10;
}
.acceptCta:hover {
background-color: #88D41B;
padding: 9px 24px;
}
.acceptCtaTxt {
display: inline-block;
float: left;
vertical-align: middle;
position: relative;
}
.arroww {
border: solid #333;
border-width: 0 3px 3px 0;
display: inline-block;
box-sizing: border-box;
padding: 3px;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
transition: all 0.5s ease;
}
.acceptCta:hover .arroww {
/*padding: 6px 2px;
transform: rotate(-315deg);*/
}
#keyframes bouncer {
0% {
bottom: 0px;
}
20% {
bottom: 7px;
}
40% {
bottom: 0px;
}
60% {
bottom: 7px;
}
80% {
bottom: 0px;
}
100% {
bottom: 0px;
}
}
// Open/close
$(document).ready(function() {
$('.dropToggle').click(function() {
$(this).parent().addClass("open");
});
setTimeout(function() {
$('.acceptCta').click(function() {
//This needed
var $this = $(this);
var $container = $('.dropDwn');
var $arrow = $('.arroww');
$arrow.css("transform", "rotate(-315deg)");
$arrow.css("padding", "6px 2px");
setTimeout(function() {
$this.parent().removeClass("open");
}, 600);
setTimeout(function() {
$container.css("opacity", "0");
$container.css("right", "-1000px");
}, 1100);
setTimeout(function() {
$container.css("display", "none");
}, 1600);
});
})
});
// Hide if src image is in viewport, otherwise show
$(document).ready(function() {
var topOfOthDiv = $("[alt='Guide for installasjon av apper']").offset().top;
$(window).scroll(function() {
if ($(window).scrollTop() > topOfOthDiv + 200) {
$(".dropDwn").css("right", "-1000px");
$(".dropDwn").css("opacity", "0");
} else {
$(".dropDwn").css("opacity", "1");
}
});
});
// Stick button when scrolling past it
$(document).ready(function() {
var topOfOthDiv2 = $('.dropDwn').offset().top;
var drop = $('.dropDwn');
$(window).scroll(function() {
if ($(window).scrollTop() > topOfOthDiv2 + 20) {
drop.css("position", "fixed");
} else {
drop.css("position", "relative");
}
});
});
It's the bottom jQuery function which makes it stick by scrolling.
you have to add right value when you apply fixed position. in simalr way you can add top value too.
Update below js and also the yo
if ($(window).scrollTop() > topOfOthDiv2 + 20) {
drop.css("position", "fixed");
drop.css("right", "10px");
} else {
drop.css("position", "relative");
drop.css("right", "0px");
}
I solved this by using flex. In case anybody needs help with this here's what I did:
Max-width: 1280px; on the container, because it never gets bigger than 1280px. Added display: flex; and justify-content: flex-end; so the child element would always sit at the end of the parent element, even in fixed position.
Also added some margin and top values to make the transition from absolute to fixed more smoothly, but that might differ for you as this suited my situation.
.dropContainer{
display: flex;
max-width: 1280px;
justify-content: flex-end;
position: relative;
box-sizing: border-box;
}
.dropDwn {
font-family: inherit;
background-color: #fff;
color: #333;
border: solid 1px #333;
position: absolute;
text-align: center;
display: block;
z-index: 9999;
cursor: pointer;
padding: 5px;
border-radius: 5px;
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.4);
transition: all 0.5s ease;
font-size: 16px;
width: 250px;
box-sizing: border-box;
height: 30px;
overflow: hidden;
float: right;
margin-right: 10px;
}
// Hide if src image is in viewport, show if not
$(document).ready(function() {
var topOfOthDiv2 = $('.dropDwn').offset().top;
var drop = $('.dropDwn');
var cont = $('.dropContainer');
$(window).scroll(function() {
if ($(window).scrollTop() > topOfOthDiv2 - 10) {
drop.css("position", "fixed");
drop.css("top", "10px");
} else {
drop.css("position", "absolute");
drop.css("top", "");
}
});
});
I am creating a sort-of popup menu that is specific to each .smallCatalogBlock div. The circle you see under the title is the trigger. The issue I am having is that if you click on the blue circle, both popup menus fadeIn, when it should only be that specific one.
The same applies to the popup title. It uses only the first .smallCatalogBlock information, opposed to the one clicked on.
Does anyone know how I can leave this in the dynamic setup I am going for, while populating the specific information for the one clicked on?
var catalogName = $('.smallCatalogBlock').data('fill-specs');
//Filling Circle
$('.catalogSmallCircle').html(
'<div class="catalogSmallCircleIn" data-catalog-name=' + catalogName + '><div class="total-center"><div class="circlePlus"></div></div></div><div class="catalogCircleExpand"><div class="catalogExpandClose">x</div><div class="total-center expandText"><span class="catalogName pdfSubHeader"></span><p class="dGw circleExpandText"></p><button class="catalogDownload downloadButton" name="Profile_Catalog" data-catalog-now="Profile Small Catalog Button" data-catalog-view-name="Profile Catalog">View</button><button class="catalogDownload requestButton" data-catalog-name="Profile Catalog">Request</button></div></div>'
)
//Circle Expand
$('.catalogSmallCircleIn').on('click', function() {
// old $('.catalogSmallCircle').addClass('rectangle').find('.catalogSmallCircleIn').hide();
$(this).closest('.catalogSmallCircle').addClass('rectangle').find('.catalogSmallCircleIn').hide();
// old $('.catalogCircleExpand').fadeIn(100).addClass('rectangle');
//$(this).closest('.catalogCircleExpand').fadeIn(100).addClass('rectangle');
$('.catalogCircleExpand').fadeIn(100).addClass('rectangle');
//Getting Catalog Name
let catalogChoice = $(this).data('catalog-name');
$('.catalogName').html(catalogChoice);
event.stopPropagation();
});
//Close Circle
$('.catalogExpandClose').on('click', function(event) {
$('.catalogSmallCircle').removeClass('rectangle').find('.catalogSmallCircleIn').fadeIn();
$('.catalogCircleExpand').hide().removeClass('rectangle');
});
.smallCatalogWrap {
width: 100%;
height: auto;
margin: 60px 0;
}
.smallCatalogBlock {
width: 25%;
height: auto;
display: inline-block;
vertical-align: top;
margin: 20px auto;
text-decoration: none;
}
.smallCatalogTitle {
font-family: 'Nunito', sans-serif;
color: #4d4d4d;
font-size: 1.3rem;
text-align: center;
display: block;
font-weight: 400;
}
.smallCatalogButtonWrap {
margin-top: 15px;
width: 100%;
position: relative;
}
.catalogSmallCircle {
background: #225DB8;
width: 70px;
height: 70px;
position: absolute;
margin: 10px auto;
left: 90%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
border-radius: 100%;
box-shadow: 0 0 20px rgba(0, 0, 0, .9);
border: 2px solid #FFF;
webkit-transition: all 1s;
transition: all 1s;
cursor: pointer;
}
.catalogSmallCircle.rectangle {
border-radius: 0;
border: 2px solid #094765;
background: linear-gradient(to bottom right, #225DB8, #4174C2);
width: 400px;
min-height: 200px;
webkit-transition: all 1s;
transition: all 1s;
transform: translate(-45%, -45%);
-webkit-transform: translate(-45%, -45%);
z-index: 1;
cursor: auto;
}
.catalogSmallCircleIn {
width: 100%;
height: 100%;
position: relative;
}
.circlePlus {
background-size: 30px 30px;
width: 30px;
height: 30px;
display: block;
margin: 0 auto;
z-index: 1;
}
.catalogCircleExpand {
height: 0;
display: none;
opacity: 0;
webkit-transition: all .5s;
transition: all .5s;
}
.catalogCircleExpand.rectangle {
opacity: 1;
height: auto;
webkit-transition: all .5s;
transition: all .5s;
transition-delay: .4s;
-webkit-transition-delay: .4s;
padding: 10px 0;
}
.expandText .catalogDownload {
font-size: 1.1rem;
padding: .7em 1.1em;
}
.expandText .pdfSubHeader {
font-size: 1.1rem;
}
.catalogExpandClose {
color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="smallCatalogWrap">
<div class="smallCatalogBlock" data-fill-specs="Catalog">
<span class="smallCatalogTitle">Catalog</span>
<div class="smallCatalogButtonWrap">
<div class="catalogSmallCircle"></div>
</div>
</div>
<div class="smallCatalogBlock" data-fill-specs="Technology">
<span class="smallCatalogTitle">Technology</span>
<div class="smallCatalogButtonWrap">
<div class="catalogSmallCircle"></div>
</div>
</div>
</div>
You have to loop over the smallCatalogBlocks and build them individually, otherwise they will all have the same catalog name. And then in your event handlers, you have to make all your selectors be contextual lookups.
I ran the modified code, and it appears to be building the circles correctly, however for some reason the text is not showing up on them, even though the text is there if you inspect the element. Didn't figure that part out, but this should show you at least how to do the contextual logic and the looping to build the elements.
$('.smallCatalogBlock').each(function(index, catalogBlock){
var catalogName = $(catalogBlock).data('fill-specs');
console.log(catalogName);
//Filling Circle
$('.catalogSmallCircle', catalogBlock).html(
'<div class="catalogSmallCircleIn" data-catalog-name='+ catalogName +'><div class="total-center"><div class="circlePlus"></div></div></div><div class="catalogCircleExpand"><div class="catalogExpandClose">x</div><div class="total-center expandText"><span class="catalogName pdfSubHeader"></span><p class="dGw circleExpandText"></p><button class="catalogDownload downloadButton" name="Profile_Catalog" data-catalog-now="Profile Small Catalog Button" data-catalog-view-name="Profile Catalog">View</button><button class="catalogDownload requestButton" data-catalog-name="Profile Catalog">Request</button></div></div>'
)
});
//Circle Expand
$('.catalogSmallCircleIn').on('click', function(event) {
var $smallCircle = $(this).closest('.catalogSmallCircle');
$smallCircle
.addClass('rectangle')
.find('.catalogSmallCircleIn')
.hide();
$smallCircle
.find('.catalogCircleExpand')
.fadeIn(100)
.addClass('rectangle');
//Getting Catalog Name
let catalogChoice = $(this).data('catalog-name');
console.log(catalogChoice);
$smallCircle.find('.catalogName').html(catalogChoice);
event.stopPropagation();
});
//Close Circle
$('.catalogExpandClose').on('click', function(event) {
var $smallCircle = $(this).closest('.catalogSmallCircle');
$smallCircle
.removeClass('rectangle')
.find('.catalogSmallCircleIn')
.fadeIn();
$smallCircle
.find('.catalogCircleExpand')
.hide()
.removeClass('rectangle');
});
.smallCatalogWrap {
width: 100%;
height: auto;
margin: 60px 0;
}
.smallCatalogBlock {
width: 25%;
height: auto;
display: inline-block;
vertical-align: top;
margin: 20px auto;
text-decoration: none;
}
.smallCatalogTitle {
font-family: 'Nunito', sans-serif;
color: #4d4d4d;
font-size: 1.3rem;
text-align: center;
display: block;
font-weight: 400;
}
.smallCatalogButtonWrap {
margin-top: 15px;
width: 100%;
position: relative;
}
.catalogSmallCircle {
background: #225DB8;
width: 70px;
height: 70px;
position: absolute;
margin: 10px auto;
left: 90%;
-webkit-transform: translateX(-50%);transform: translateX(-50%);
border-radius: 100%;
box-shadow: 0 0 20px rgba(0,0,0,.9);
border: 2px solid #FFF;
webkit-transition: all 1s;transition: all 1s;
cursor: pointer;
}
.catalogSmallCircle.rectangle {
border-radius: 0;
border: 2px solid #094765;
background: linear-gradient(to bottom right,#225DB8,#4174C2);
width: 400px;
min-height: 200px;
webkit-transition: all 1s; transition: all 1s;transform: translate(-45%, -45%);-webkit-transform: translate(-45%, -45%);
z-index: 1;
cursor: auto;
}
.catalogSmallCircleIn {
width: 100%;
height: 100%;
position: relative;
}
.circlePlus {
background-size: 30px 30px;
width: 30px;
height: 30px;
display: block;
margin: 0 auto;
z-index: 1;
}
.catalogCircleExpand {
height: 0;
display: none;
opacity: 0;
webkit-transition: all .5s;
transition: all .5s;
}
.catalogCircleExpand.rectangle {
opacity: 1;
height: auto;
webkit-transition: all .5s;
transition: all .5s;
transition-delay: .4s;
-webkit-transition-delay: .4s;
padding: 10px 0;
}
.expandText .catalogDownload {
font-size: 1.1rem;
padding: .7em 1.1em;
}
.expandText .pdfSubHeader {
font-size: 1.1rem;
}
.catalogExpandClose {
color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="smallCatalogWrap">
<div class="smallCatalogBlock" data-fill-specs="Catalog">
<span class="smallCatalogTitle">Catalog</span>
<div class="smallCatalogButtonWrap">
<div class="catalogSmallCircle"></div>
</div>
</div><div class="smallCatalogBlock" data-fill-specs="Technology">
<span class="smallCatalogTitle">Technology</span>
<div class="smallCatalogButtonWrap">
<div class="catalogSmallCircle"></div>
</div>
</div>
</div>