I've created easy game. I added two circular progressBar in setTimeout, but still doesn't work as i expect. I wanna to these bars goes from 0 to 100% and finish. Unfortunately second of them is 2 times quicker than first. If I try add only one bar, there's not problem. I add my program on GH, there I selected the most important lines. I'm sorry for my english, I'm not native :/
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://fonts.googleapis.com/css?family=Kalam&display=swap" rel="stylesheet">
<link rel="stylesheet" href="font/flaticon.css">
<link rel="stylesheet" href="style.css">
<title>ColorGame</title>
</head>
<body>
<div class="main-layer">
<h1 class="title">Remember this color! </h1>
<div class="square draw-square">
<!-- <div class="my-progress-bar"></div> -->
</div>
<div class="button-box">
<button class="button drawButton">Draw Color</button>
<button class="button listButton">Your scores</button>
</div>
</div>
<div class="check-layer">
<div class="square player-square">
<!-- <div class="my-progress-bar"></div> -->
</div>
<div class="input-box">
<input type="range" class="redInput" value="0" min="0" max="255">
<input type="range" class="greenInput" value="0" min="0" max="255">
<input type="range" class="blueInput" value="0" min="0" max="255">
</div>
</div>
<div class="end-layer">
<div class="result-text"></div>
<div class="compare-box">
<div class="draw-square square-modifier"></div>
<div class="player-square square-modifier"></div>
</div>
<i class="flaticon-close cross"></i>
</div>
<div class="list-layer">
<h1 class="list-title">Scores</h1>
<i class="flaticon-close"></i>
</div>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js"></script>
<script src="plugin.js"></script>
<script src="index.js"></script>
</body>
</html>
SCSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Kalam', cursive;
}
#mixin flex {
display: flex;
justify-content: center;
align-items: center;
}
:root {
--drawRed: 0;
--drawGreen: 0;
--drawBlue: 0;
--checkRed: 0;
--checkGreen: 0;
--checkBlue: 0;
}
$lightRed: rgb(192, 0, 0);
$mediumRed: rgb(80, 1, 1);
$darkRed: rgb(37, 0, 0);
$lightGreen: rgb(25, 146, 21);
$mediumGreen: rgb(11, 61, 9);
$darkGreen: rgb(3, 17, 2);
$lightBlue: rgb(16, 61, 185);
$mediumBlue: rgb(5, 21, 63);
$darkBlue: rgb(2, 8, 24);
body {
height: 100vh;
}
// main-layer
.main-layer {
#include flex();
position: absolute;
justify-content: space-evenly;
flex-direction: column;
background-color: #171717;
color: white;
width: 100%;
height: 100%;
padding: .5em;
}
.title, .description {
font-size: 1.5rem;
text-shadow: .05em .05em .01em black;
}
.square {
border: .1rem solid white;
width: 30vw;
height: 30vw;
border-radius: 1em;
}
.draw-square {
#include flex();
background-color: rgb(var(--drawRed), var(--drawGreen), var(--drawBlue));
}
.my-progress-bar {
position: relative;
}
.progress-percentage {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 2rem;
font-weight: bold;
color: rgba(0,0,0, .1)
}
.button-box {
#include flex();
width: 100%;
}
.button {
width: 7rem;
height: 2.2rem;
background-color: rgb(223, 70, 0);
color: white;
font-weight: bold;
font-size: 1rem;
border: none;
border-radius: .5em;
margin: 0 .5em;
text-shadow: .07em .07em .05em black;
box-shadow:
inset -.1em -.1em .2em .05em rgb(95, 30, 0),
.03em .03em .01em .01em rgb(12, 4, 0);
transition: 1s;
&:hover {
background-color: rgb(95, 30, 0);
box-shadow:
inset -.1em -.1em .2em .05em rgb(27, 9, 0),
.03em .03em .01em .01em rgb(12, 4, 0);
}
}
// check-layer
.check-layer {
position: absolute;
display: none;
justify-content: space-evenly;
align-items: center;
width: 100%;
height: 100%;
background-color: #171717;
}
.player-square {
#include flex();
background-color: rgb(var(--checkRed), var(--checkGreen), var(--checkBlue));
}
.input-box {
display: flex;
justify-content: space-evenly;
flex-direction: column;
width: 30vw;
height: 50vw;
}
input {
// position: relative;
width: 100%;
height: 1rem;
-webkit-appearance: none;
background: rgba(0,0,0,0.8);
outline: none;
border-radius: 1rem;
}
input::-webkit-slider-thumb {
-webkit-appearance: none;
width: .1rem;
height: .1rem;
border-radius: 50%;
}
.redInput::-webkit-slider-thumb {
box-shadow: 0 0 0 .3rem $lightRed;
border: .5rem solid $darkRed;
}
.greenInput::-webkit-slider-thumb {
box-shadow: 0 0 0 .3rem $lightGreen;
border: .5rem solid $darkGreen;
}
.blueInput::-webkit-slider-thumb {
box-shadow: 0 0 0 .3rem $lightBlue;
border: .5rem solid $darkBlue;
}
.redInput {
background-color: $mediumRed;
box-shadow: .1em 0 .3em .1em $darkRed;
}
.greenInput {
background-color: $mediumGreen;
box-shadow: .1em 0 .3em .1em $darkGreen;
}
.blueInput {
background-color: $mediumBlue;
box-shadow: .1em 0 .3em .1em $darkBlue;
}
// end-layer
.end-layer {
position: relative;
display: none;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: #171717;
}
.compare-box {
display: flex;
}
.square-modifier {
height: 100vh;
width: 50vw;
}
.result-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 5em;
font-weight: bold;
color: white;
text-shadow: .02em .02em .03em black;
}
.flaticon-close::before {
position: absolute;
top: .3em;
right: .3em;
color: white;
text-shadow: .04em .04em .02em black;
font-size: 2em;
margin: 0;
}
// list
.list-layer {
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
padding: 1em 0;
overflow-y: scroll;
}
.list-title {
#include flex();
font-size: 4em;
color: rgb(223, 70, 0);
}
.score {
font-size: 2em;
color: white;
}
#media (min-width: 768px) {
html {
font-size: 1.5rem;
}
.square {
width: 25vw;
height: 25vw;
}
}
#media (min-width: 1024px) {
html {
font-size: 2.5rem;
}
.square {
width: 35vw;
height: 35vw;
}
}
#media (min-width: 1366px) {
html {
font-size: 3rem;
}
.square {
width: 40vw;
height: 40vw;
}
}
#media (min-width: 1500px) {
html {
font-size: 3rem;
}
.square {
width: 30vw;
height: 30vw;
}
}
#media (orientation:portrait) {
// main-layer
.main-layer {
justify-content: space-around;
}
.title {
font-size: 2rem;
text-align: center;
}
.button {
width: 70vw;
height: 2.5rem;
margin: .5em 0;
}
.square {
width: 90vw;
height: 90vw;
}
.button-box {
flex-direction: column;
}
// check-layer
.check-layer {
justify-content: space-evenly;
flex-direction: column;
}
.input-box {
justify-content: space-between;
width: 80%;
height: 50vw;
}
// end-layer
.compare-box {
flex-direction: column;
}
.square-modifier {
height: 50vh;
width: 100vw;
}
}
#media (orientation:portrait) and (min-width: 375px) {
html {
font-size: 1.5rem;
}
}
#media (orientation:portrait) and (min-width: 768px) {
html {
font-size: 1.7rem;
}
.input-box {
height: 25vw;
}
}
JavaScript
const checkDuration = 7000;
const fadeDuration = 1000;
const progressBar = [];
const score = [];
let squareSize;
let currentPercent;
let scoreCounter = 0;
// wylosowane kolory na samym początku
let drawRed = 0;
let drawGreen = 0;
let drawBlue = 0;
// kolory ustawione przez player'a
let checkRed = 0;
let checkGreen = 0;
let checkBlue = 0;
// timeoutsy
let firstTimeOut = 0;
let secondTimeOut = 0;
function addScore() {
score[scoreCounter] = $('<div>').addClass('score').text((scoreCounter+1) + ". " + currentPercent);
$('.list-layer').append(score[scoreCounter]);
}
function randNumber(min, max) {
return Math.round(Math.random()*max + min);
}
function setCssVariable(cssVariable, currentValue) {
document.documentElement.style.setProperty(cssVariable, currentValue);
// console.log(cssVariable+", "+currentValue)
}
function updateValue(cssVariable, sliderClass) {
setCssVariable(cssVariable, parseInt($(sliderClass).val())); // ustawia zmienną css'ową na daną wartość slidera
setGlobalVariable(sliderClass)
}
function setGlobalVariable(sliderClass) {
if(sliderClass == '.redInput') {
checkRed = parseInt($(sliderClass).val());
}
else if(sliderClass == '.greenInput'){
checkGreen = parseInt($(sliderClass).val());
}
else {
checkBlue = parseInt($(sliderClass).val());
}
}
function setColor() { // <<< ----------------------------------- FIRST TIMEOUT
firstTimeOut = setTimeout(()=> {
checkLayer();
console.log("check-layer")
}, checkDuration)
}
function deleteProgressBar() {
$(progressBar[0]).remove();
$(progressBar[1]).remove();
}
function addProgressBar(numberBar, destination) {
progressBar[numberBar] = $('<div>').addClass('my-progress-bar');
$(destination).append(progressBar[numberBar]);
$(progressBar[numberBar]).circularProgress({
width: squareSize,
height: squareSize,
line_width:10,
color: "rgba(0, 0, 0, .25)",
starting_position: 0,
percent: 0
// counter_clockwise: false
}).circularProgress('animate', 100, checkDuration); // <<< --------------------- checkDuration
}
function fadeLayer(show, element, duration) {
if(show) {
$(element).css('display', 'flex').fadeIn(duration); // odkrywa się check-layer
} else {
$(element).css('display', 'none').fadeOut(duration); // odkrywa się check-layer
}
}
function checkLayer() {
// $(progressBar[0]).remove();
fadeLayer(true, '.check-layer', fadeDuration);
addProgressBar(1, '.check-layer .player-square');
secondTimeOut = setTimeout(()=>{ ///////////////////// <<< ------------------------------ SECOND TIMEOUT
compareColors();
addScore();
fadeLayer(true, '.end-layer', fadeDuration);
scoreCounter++;
}, checkDuration);
}
function compareColors() {
// algoryt I
// const redDeviation = drawRed-checkRed
// const greenDeviation = drawGreen-checkGreen;
// const blueDeviation = drawBlue-checkBlue;
// // const distance = Math.sqrt(Math.pow(redDeviation, 2) + Math.pow(greenDeviation, 2) + Math.pow(blueDeviation, 2))
// // const percent = Math.floor(100 - (distance/Math.sqrt(3*Math.pow(255, 2)))*100) +"%";
// const distance = Math.sqrt(redDeviation*redDeviation + greenDeviation*greenDeviation + blueDeviation*blueDeviation);
// console.log(distance)
// const percent = Math.floor(100 - (distance/442)*100) +"%"
// algorytm II
const rmean = (drawRed+checkRed)/2;
const r = drawRed-checkRed
const g = drawGreen-checkGreen;
const b = drawBlue-checkBlue;
const weightR = 2 + rmean/256;
const weightG = 4.0;
const weightB = 2 + (255-rmean)/256;
const d1 = Math.sqrt(weightR*r*r + weightG*g*g + weightB*b*b);
const maxColDist = 764.8339663572415;
const s1 = Math.round(((maxColDist-d1)/maxColDist)*100) + "%";
currentPercent = s1;
$('.result-text').text(s1);
}
function drawButton() {
$('.drawButton').click(()=> {
// dodaje progressBar
addProgressBar(0, '.main-layer .draw-square');
// zablokowanie przycisku
$('.drawButton').prop('disabled', true);
$('.listButton').prop('disabled', true);
// losuje liczby do rgb() w css'ie
drawRed = randNumber(0, 255);
drawGreen = randNumber(0, 255);
drawBlue = randNumber(0, 255);
// ustawia zmiennym wylosowaną wartość
setCssVariable('--drawRed', drawRed)
setCssVariable('--drawGreen', drawGreen)
setCssVariable('--drawBlue', drawBlue)
setColor(); // <<< -------------------------- ODPALA SIĘ TIMEOUT NR1
})
}
function sliders() {
$('.redInput').on('change mousemove touchmove', updateValue.bind(this, "--checkRed", '.redInput'));
$('.greenInput').on('change mousemove touchmove', updateValue.bind(this, "--checkGreen", '.greenInput'));
$('.blueInput').on('change mousemove touchmove', updateValue.bind(this, "--checkBlue", '.blueInput'));
}
function cross() {
$('.cross').click(() => {
restart();
})
}
function setDefaultSliderPosition() {
$('.redInput').val(0);
$('.greenInput').val(0);
$('.blueInput').val(0);
}
function restart() {
$('.drawButton').prop('disabled', false); // odblokowanie przycisku
$('.listButton').prop('disabled', false); // odblokowanie przycisku
fadeLayer(false, '.check-layer', 0);
fadeLayer(false, '.end-layer', 0);
setCssVariable('--drawRed', 0);
setCssVariable('--drawGreen', 0);
setCssVariable('--drawBlue', 0);
setCssVariable('--checkRed', 0);
setCssVariable('--checkGreen', 0);
setCssVariable('--checkBlue', 0);
setDefaultSliderPosition();
deleteProgressBar();
clearTimeout(secondTimeOut); // <<<------------------------- CLEAR TIMEOUTS
clearTimeout(firstTimeOut);
}
function list() {
$('.listButton, .list-layer .flaticon-close').click(() => {
$('.list-layer').slideToggle(1500, 'easeOutBounce');
});
}
function resize() {
$(window).on('resize', () => {
squareSize = $('.square').css("width");
});
}
$('.list-layer').fadeOut(0);
// funckje nasłuchujące
drawButton();
sliders();
cross();
list();
resize();
Related
So here is my code that i need help with
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style8.css" />
<title>Progress Steps</title>
</head>
<body>
<div class="container">
<div class="progress-container">
<div class="progress" id="progress"></div>
<div class="circle active">1</div>
<div class="circle">2</div>
<div class="circle">3</div>
<div class="circle">4</div>
</div>
<button class="btn" id="prev" disabled>Prev</button>
<button class="btn" id="next">Next</button>
</div>
<script src="script8.js"></script>
</body>
</html>
Here is the css
#import url('https://fonts.googleapis.com/css?family=Muli&display=swap');
:root {
--line-border-fill: #3498db;
--line-border-empty: #383838;
}
* {
box-sizing: border-box;
}
body {
background-color: #1f1f1f;
font-family: 'Muli', sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
margin: 0;
}
.container {
text-align: center;
}
.progress-container { //im trying to use this
display: flex;
justify-content: space-between;
position: relative;
margin-bottom: 30px;
max-width: 100%;
width: 350px;
}
.progress-container::before { //im trying to use this
content: '';
background-color: var(--line-border-empty);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 100%;
z-index: -1;
}
.progress { //im trying to use this
background-color: var(--line-border-fill);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 0%;
z-index: -1;
transition: 0.4s ease;
}
.circle {
background-color: #1f1f1f;
color:#e2e2e2;
border-radius: 50%;
height: 30px;
width: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid var(--line-border-empty);
transition: 0.4s ease;
}
.circle.active {
border-color: var(--line-border-fill);
}
.btn {
background-color: var(--line-border-fill);
color: #fff;
border: 0;
border-radius: 6px;
cursor: pointer;
font-family: inherit;
padding: 8px 30px;
margin: 5px;
font-size: 14px;
}
.btn:active {
transform: scale(0.98);
}
.btn:focus {
outline: 0;
}
.btn:disabled {
background-color: var(--line-border-empty);
cursor: not-allowed;
}
And here is the javascript. Im not really familiar with javascript. Kind of a newbie at it.
const progress = document.getElementById("progress");
const prev = document.getElementById("prev");
const next = document.getElementById("next");
const circles = document.querySelectorAll(".circle");
let currentActive = 1;
next.addEventListener("click", () => {
currentActive++;
if (currentActive > circles.length) {
currentActive = circles.length;
}
update();
});
prev.addEventListener("click", () => {
currentActive--;
if (currentActive < 1) {
currentActive = 1;
}
update();
});
function update() { //here is the part i need help with
}
const actives = document.querySelectorAll(".active");
progress.style.width =
((actives.length - 1) / (circles.length - 1)) * 100 + "%";
if (currentActive === 1) {
prev.disabled = true;
} else if (currentActive === circles.length) {
next.disabled = true;
} else {
prev.disabled = false;
next.disabled = false;
}
Im trying to write a function to update the html when the back or next button is pressed and i need to use the progress css class. I have no idea how to implement it.
You should be able to use the DOM control functions in JavaScript to fix your problem.
Send my answer. Sincerely
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Progress Steps</title>
</head>
<style>
#import url('https://fonts.googleapis.com/css?family=Muli&display=swap');
:root {
--line-border-fill: #3498db;
--line-border-empty: #383838;
}
* {
box-sizing: border-box;
}
body {
background-color: #1f1f1f;
font-family: 'Muli', sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
margin: 0;
}
.container {
text-align: center;
}
.progress-container {
display: flex;
justify-content: space-between;
position: relative;
margin-bottom: 30px;
max-width: 100%;
width: 350px;
}
.progress-container::before {
content: '';
background-color: var(--line-border-empty);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 100%;
z-index: -1;
}
.progress {
background-color: #3498db;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 0%;
z-index: -1;
transition: 0.4s ease;
}
.circle {
background-color: #1f1f1f;
color:#e2e2e2;
border-radius: 50%;
height: 30px;
width: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid var(--line-border-empty);
transition: 0.4s ease;
}
.circle.active {
border-color: #3498db;
}
.btn {
background-color: #3498db;
color: #fff;
border: 0;
border-radius: 6px;
cursor: pointer;
font-family: inherit;
padding: 8px 30px;
margin: 5px;
font-size: 14px;
}
.btn:active {
transform: scale(0.98);
}
.btn:focus {
outline: 0;
}
.btn:disabled {
background-color: var(--line-border-empty);
cursor: not-allowed;
}
</style>
<body>
<div class="container">
<div id="content" style="border: 1px solid black; margin: 0 auto; width: 300px; height: 100px; background-color: white;">
Content 1
</div>
<div class="progress-container">
<div class="progress" id="progress"></div>
<div class="circle active">1</div>
<div class="circle">2</div>
<div class="circle">3</div>
<div class="circle">4</div>
</div>
<button class="btn" id="prev" disabled>Prev</button>
<button class="btn" id="next">Next</button>
</div>
</body>
<script>
const progress = document.getElementById("progress");
const prev = document.getElementById("prev");
const next = document.getElementById("next");
const content = document.getElementById("content"); // added
const circles = document.querySelectorAll(".circle");
let currentActive = 1;
next.addEventListener("click", () => {
currentActive++;
if (currentActive > circles.length) {
currentActive = circles.length;
}
update(currentActive);
});
prev.addEventListener("click", () => {
currentActive--;
if (currentActive < 1) {
currentActive = 1;
}
update(currentActive);
});
function update(currentStep) {
//here is the part I fixed
let stepItems = document.getElementsByClassName("circle");
for (let i = 0; i < stepItems.length; i++) {
const stepItem = stepItems[i];
if (stepItem.textContent == currentStep) {
stepItem.classList.toggle("active");
}
}
prev.toggleAttribute("disabled", false);
next.toggleAttribute("disabled", false);
if (currentStep == 1) prev.setAttribute("disabled", true);
if (currentStep == 4) next.setAttribute("disabled", true);
content.innerText = "Content" + currentStep;
}
const actives = document.querySelectorAll(".active");
progress.style.width = ((actives.length - 1) / (circles.length - 1)) * 100 + "%";
if (currentActive === 1) {
prev.disabled = true;
} else if (currentActive === circles.length) {
next.disabled = true;
} else {
prev.disabled = false;
next.disabled = false;
}
</script>
</html>
I made this iPhone in HTML (Please do not pay attention to the spaghetti code, and it's in german, if it is necessary i can translate it with pleasure):
var time = document.getElementById("time");
var notification = document.getElementById("notification");
var notificationHeader = document.getElementById("notificationHeader");
var notificationDescription = document.getElementById("notificationDescription");
var verificationCode = Math.floor(1000 + Math.random() * 9000);
var input = document.getElementById("instagramNumberText");
var correctOrWrongCheck = document.getElementById("correctOrWrongCheck");
var verificationCodePTag = document.getElementById("verificationCode");
var instagram = document.getElementById("instagramApp");
var mail = document.getElementById("mailApp");
var createAccountButton = document.getElementById("createAccount");
var createAccountForm = document.getElementById("createAccountForm");
var verificationCodeInstagramPage = document.getElementById("verificationCodeInstagramPage");
var controlVerificationCodeButton = document.getElementById("controlVerificationCode");
var continueToInstagramAccountButton = document.getElementById("continueToInstagramAccount");
var verificationCodeEmailDescription = document.getElementById("verificationCodeEmailDescription");
var verificationCodeEmail = document.getElementById("verificationCodeEmail");
var erfolgreichAngemeldet = document.getElementById("erfolgreichAngemeldet");
var instagramAccount = document.getElementById("instagramAccount");
var instagramName = document.getElementById("instagramName");
var instagramNameInput = document.getElementById("instagramNameInput");
// Time
function checkTime(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
// add a zero in front of numbers<10
m = checkTime(m);
document.getElementById('time').innerHTML = h + ":" + m;
t = setTimeout(function() {
startTime()
}, 500);
}
startTime();
// Insta
function controlVerificationCode() {
if (input.value == verificationCode) {
correctOrWrongCheck.innerHTML = "Der Code war korrekt!";
continueToInstagramAccountButton.style.display = "block";
continueToInstagramAccountButton.style.margin = "5px auto";
controlVerificationCodeButton.style.display = "none";
} else if (input.value !== verificationCode) {
correctOrWrongCheck.innerHTML = "Der Code ist leider Falsch!";
continueToInstagramAccountButton.style.display = "none";
controlVerificationCodeButton.style.display = "block";
}
}
verificationCodeEmailDescription.innerHTML = "Ihr Bestätigunscode lautet: " + verificationCode;
// OPEN AND CLOSE APPS
function openVerificationCodeInstagramPage() {
createAccountForm.style.display = "none";
verificationCodeInstagramPage.style.display = "block"
verificationCodeEmail.style.display = "block";
instagramName.value = instagramNameInput.value;
notification.style.transform = "translate(-50%, -50%) scale(0)";
notificationDescription.innerHTML = "Ihr Bestätigunscode lautet: ...";
setTimeout(
function() {
notification.style.transform = "translate(-50%, -50%) scale(1)";
}, 1000);
setTimeout(
function() {
notification.style.transform = "translate(-50%, -50%) scale(0)";
}, 7000);
}
function continueToInstagramAccount() {
verificationCodeInstagramPage.style.display = "none";
instagramAccount.style.display = "flex";
erfolgreichAngemeldet.display = "none";
notificationDescription.innerHTML = "Erfolgreich bei Instagram angemeldet"
notification.style.transform = "translate(-50%, -50%) scale(0)";
erfolgreichAngemeldet.style.display = "block";
setTimeout(
function() {
notification.style.transform = "translate(-50%, -50%) scale(1)";
}, 1000);
setTimeout(
function() {
notification.style.transform = "translate(-50%, -50%) scale(0)";
}, 7000);
var counter = 0;
var followers = document.getElementById('followers');
setTimeout(function(){
var st = setInterval(function(){
followers.innerHTML = ++counter;
},100)
},100);
}
function closeNotification() {
notification.style.transform = "translate(-50%, -50%) scale(0)";
}
function openInstagram() {
instagram.style.transform = "scale(1)";
}
function openMail() {
mail.style.transform = "scale(1)";
}
function closeApp() {
instagram.style.transform = "scale(0)";
mail.style.transform = "scale(0)";
}
window.onload = function() {
document.getElementById("instagramNumberText").value = '';
}
* {
margin: 0;
padding: 0;
font-family: 'Roboto',sans-serif;
user-select: none;
}
input:focus, textarea:focus {
outline: 0;
}
#phone {
height: 600px;
width: 350px;
border-radius: 50px;
position: absolute;
top: 600px;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
border-top: 90px solid;
border-right: 15px solid;
border-left: 15px solid;
border-bottom: 90px solid;
background-image: url("https://ioshacker.com/wp-content/uploads/2019/06/iOS-13-wallpaper.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.app {
box-shadow: 0 0 9px -4px #000;
}
#topbar {
padding: 0.3em;
color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
height: 20px;
transform: translate(-4%,0) scale(0.9);
width: 370px;
}
#connection {
display: flex;
align-items: center;
width: 110px;
justify-content: space-around;
}
#battery {
display: flex;
align-items: center;
width: 110px;
justify-content: end;
}
#battery .bi-battery-full {
font-size: 23px;
margin-left: 5px;
}
#topbar .bi-wifi-2 {
font-size: 25px;
margin-top: -3px;
}
#time {
text-align: center;
}
#notification {
margin: 0;
position: absolute;
top: 365px;
left: 50%;
-ms-transform: translate(-50%, -50%) scale(0);
transform: translate(-50%, -50%) scale(0);
height: 85px;
width: 315px;
background: #EDEBED;
border-radius: 10px;
z-index: 10000;
transition: all 0.5s;
box-shadow: 0 0 10px -1px #525252;
padding: 0.5em 0 0.5em 1em;
display: flex;
flex-direction: column;
justify-content: center;
}
#notification h1 {
font-size: 23px;
}
#appsOne {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
#instagramIcon, #verificationCode, #mailIcon {
margin: 20px;
}
.app {
font-size: 40px;
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 10px;
transition: all 0.2s;
}
.app:hover {
cursor: pointer;
filter: brightness(90%);
}
.bi-instagram, .bi-envelope-fill {
width: 40px;
height: 40px;
color: #fff;
font-family: sans-serif;
}
/* Instagram */
#instagramIcon {
background: linear-gradient(45deg, #f09433 0%,#e6683c 25%,#dc2743 50%,#cc2366 75%,#bc1888 100%);
}
#instagramApp {
position: absolute;
top: 0;
left: 0;
background: #EAEAEA;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
transition: all 0.3s;
transform: scale(0);
z-index: 99999;
text-align: center;
}
.instagramHeader {
font-family: 'Handlee', cursive;
font-size: 35px;
}
.instagramSecondHeader {
font-size: 15px;
width: 260px;
margin: 1em 0;
}
#instagramNameInput, #instagramEmail, #instagramNumberText {
font-size: 15px;
padding: 0.5em;
border: 1px solid #D1D1D1;
margin: 0.5em 0 0.5em 0;
width: 220px;
}
.instagramButton {
width: 236px;
font-size: 15px;
padding: 0.5em;
background: #3296F0;
color: #fff;
border: none;
margin: 0.5em 0;
transition: all 0.2s;
}
.instagramButton:hover {
filter: brightness(80%);
cursor: pointer;
}
#verificationCodeInstagramPage {
display: none;
}
#continueToInstagramAccount {
display: none;
}
#instagramAccount {
display: none;
justify-content: flex-start;
height: 100%;
width: 100%;
background: #f7f7f7;
flex-direction: column;
align-items: center;
}
#instagramName {
font-size: 20px;
text-align: left;
width: 85%;
padding: 20px 20px 15px 10px;
border-bottom: 1px solid gray;
height: 20px;
border-right: none;
border-top: none;
border-left: none;
background: none;
}
#profilePicture {
font-size: 35px;
width: 80px;
height: 80px;
display: flex;
justify-content: center;
align-items: center;
background: #eae9e9;
border-radius: 100000px;
margin: 20px;
border: 1px solid #6f6e6e;
color: #6f6e6e;
}
#instagramPictureAndNumbers {
display: inherit;
width: 360px;
}
#numbers {
width: 225px;
height: 45px;
margin: 35px 0 0 0;
}
#userDescription {
width: 320px;
font-size: 13px;
border: none;
background: none;
resize: none;
}
.bi-table {
font-size: 25px;
border-bottom: 1px solid;
width: 90%;
margin-top: 0.5em;
}
#emptyImages {
color: #c7c7c7;
margin: 100px;
font-size: 14px;
}
/* Mail */
#mailIcon {
background: linear-gradient(0deg, #05ffff 0%, #3cabe6 30%, #2763dc 70%);
}
#mailApp {
position: absolute;
top: 0;
left: 0;
background: #f6f6f6;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
transition: all 0.3s;
transform: scale(0);
z-index: 99999;
text-align: center;
}
#mailHeader {
font-size: 25px;
padding: 20px;
background: #fff;
width: 88%;
z-index: 999;
}
#verificationCodeEmail {
display: none;
}
.email {
background: #fff;
width: 97%;
padding: 5px;
border-top: 1px solid #e6e6e6;
}
.emailHeader {
text-align: left;
margin: 10px;
font-size: 25px;
}
#verificationCodeEmailDescription, #erfolgreichAngemeldetDescription {
text-align: left;
margin: 10px;
}
#erfolgreichAngemeldet {
display: none;
}
/* Home Button */
#homeButton {
position: absolute;
height: 60px;
width: 60px;
background: transparent;
z-index: 9999;
bottom: -107px;
border-radius: 100000px;
left: 50%;
-ms-transform: translate(-50%, -50%) rotate(-10deg);
transform: translate(-50%, -50%) rotate(-10deg);
border: 1px outset;
cursor: pointer;
}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.4.1/font/bootstrap-icons.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght#100;300;400&display=swap" rel="stylesheet">
<div id="notification" onclick="closeNotification();">
<h1 id="notificationHeader"><b>Neue Email erhalten!</b></h1>
<p id="notificationDescription"></p>
</div>
<div id="phone">
<div id="topbar">
<div id="connection">
<i class="bi bi-bar-chart-fill"></i>
LIDL LTE
<i class="bi bi-wifi-2"></i>
</div>
<p id="time"></p>
<div id="battery">
98%
<i class="bi bi-battery-full"></i>
</div>
</div>
<div id="slider">
<div id="appsOne">
<!-- Instagram -->
<div id="instagramIcon" class="app" onclick="openInstagram();"><i class="bi bi-instagram"></i></div>
<div id="instagramApp">
<form id="createAccountForm" action="#" onsubmit="openVerificationCodeInstagramPage(); return false;">
<h1 class="instagramHeader">Instagram</h1>
<p>Erstelle einen Account</p>
<input type="text" id="instagramNameInput" placeholder="Name" maxlength="12" autocomplete="off" required>
<input type="email" id="instagramEmail" placeholder="E-Mail" autocomplete="off" required>
<button type="submit" id="createAccount" class="instagramButton">Erstellen</button>
</form>
<div id="verificationCodeInstagramPage">
<h1 class="instagramHeader">Bestätigen</h1>
<p class="instagramSecondHeader">Wir haben ihn einen Bestätigungscode per Email gesendet!</p>
<input type="text" id="instagramNumberText" maxlength="4" onkeypress="return /[0-9]/i.test(event.key)" placeholder="Bestätigungscode"><br>
<button onclick="controlVerificationCode();" id="controlVerificationCode" class="instagramButton">Bestätigen</button>
<button class="instagramButton" id="continueToInstagramAccount" onclick="continueToInstagramAccount()">Weiter</button>
<p id="correctOrWrongCheck"></p>
</div>
<div id="instagramAccount">
<input type="text" id="instagramName">
<div id="instagramPictureAndNumbers">
<div id="profilePicture"><i class="bi bi-person-fill"></i></div>
<table id="numbers">
<tr>
<th id="posts">0</th>
<th id="followers">1</th>
<th id="following">0</th>
</tr>
<tr>
<td>Posts</td>
<td>Followers</td>
<td>Following</td>
</tr>
</table>
</div>
<textarea id="userDescription" placeholder="Beschreibung..." rows="10"></textarea>
<i class="bi bi-table"></i>
<p id="emptyImages">No images found</p>
</div>
</div>
<div id="appsTwo">
Second App Page
</div>
</div>
<!-- Mail App -->
<div id="mailIcon" class="app" onclick="openMail();"><i class="bi bi-envelope-fill"></i></div>
<div id="mailApp">
<h1 id="mailHeader">E-Mails</h1>
<div class="email" id="erfolgreichAngemeldet">
<h1 class="emailHeader">Instagram</h1>
<p class="emailDescription" id="erfolgreichAngemeldetDescription">Erfolgreich angemeldet</p>
</div>
<div class="email" id="verificationCodeEmail">
<h1 class="emailHeader">Instagram</h1>
<p class="emailDescription" id="verificationCodeEmailDescription">Ihr Bestätigunscode lautet</p>
</div>
</div>
</div>
<div id="homeButton" onclick="closeApp();"></div>
To see the iPhone better you should click on Full-Page in the snippet.
My problem was that I have 2 divs: #appsOne and #appsTwo which are in the div #slider. On the home page of the iPhone you can see two apps (#appsOne) and a text (#appsTwo) in the middle. The apps (#appsOne) should stay where they are but the text (#appsTwo) should be made on a second page with a horizontal scroll snap. How could I do that?
And here's an image, how it looks like without the slider and the #appsTwo div:
CSS Scroll-snapping
We can seperate the two 'screen's by wrapping each in a div with class panel.
To make the slider scrollable, we have to apply white-space: nowrap to force it into a single line. To make scroll-snap work horizontally, set scroll-snap-type to x and make it mandatory (scroll-snap-type: x mandatory;). This means that:
The visual viewport of this scroll container will rest on a snap point if it isn't currently scrolled. That means it snaps on that point when the scroll action finished, if possible. If content is added, moved, deleted or resized the scroll offset will be adjusted to maintain the resting on that snap point.MDN
We also set overscroll-behavior-x to contain which makes sure that no scroll chaining occurs to neighboring scrolling areas, e.g. underlying elements will not scroll.
We then apply scroll-snap-align: center to .panel. To prevent the overflowing contents in the panels, we also apply white-space: initial.
Result:
https://jsfiddle.net/Spectric/j7br8h5a/
JS Scroll-snapping (mouse drag)
We can take it one step further by adding support for user drag to scroll.
For this, we don't actually need scroll-snap at all. We can do it with pure JS.
Add an event listener for mousedown that sets isDown to true. Record the last position of the mouse.
Add an event listener for mousemove that checks whether the user is currently dragging (isDown == true). If the user is, calculate the distance from the current mouse position and the last mouse position, increment the slider's scrollLeft by the difference, and set the last position to the current position.
Add an event listener for mouseup that sets isDown to false and checks whether the slider's current scrollLeft is bigger than half. If it is, we can use scrollIntoView() on one panel to smoothly scroll it into the viewport.
To prevent scrolling when an app is opened, we can store the status in a variable which we set it to true when one of the open app function is called and false when the closeApp function is called. In the mousemove listener we also check whether this variable is true.
Best viewed in full-page mode
var time = document.getElementById("time");
var notification = document.getElementById("notification");
var notificationHeader = document.getElementById("notificationHeader");
var notificationDescription = document.getElementById("notificationDescription");
var verificationCode = Math.floor(1000 + Math.random() * 9000);
var input = document.getElementById("instagramNumberText");
var correctOrWrongCheck = document.getElementById("correctOrWrongCheck");
var verificationCodePTag = document.getElementById("verificationCode");
var instagram = document.getElementById("instagramApp");
var mail = document.getElementById("mailApp");
var createAccountButton = document.getElementById("createAccount");
var createAccountForm = document.getElementById("createAccountForm");
var verificationCodeInstagramPage = document.getElementById("verificationCodeInstagramPage");
var controlVerificationCodeButton = document.getElementById("controlVerificationCode");
var continueToInstagramAccountButton = document.getElementById("continueToInstagramAccount");
var verificationCodeEmailDescription = document.getElementById("verificationCodeEmailDescription");
var verificationCodeEmail = document.getElementById("verificationCodeEmail");
var erfolgreichAngemeldet = document.getElementById("erfolgreichAngemeldet");
var instagramAccount = document.getElementById("instagramAccount");
var instagramName = document.getElementById("instagramName");
var instagramNameInput = document.getElementById("instagramNameInput");
// Time
function checkTime(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
// add a zero in front of numbers<10
m = checkTime(m);
document.getElementById('time').innerHTML = h + ":" + m;
t = setTimeout(function() {
startTime()
}, 500);
}
startTime();
// Insta
function controlVerificationCode() {
if (input.value == verificationCode) {
correctOrWrongCheck.innerHTML = "Der Code war korrekt!";
continueToInstagramAccountButton.style.display = "block";
continueToInstagramAccountButton.style.margin = "5px auto";
controlVerificationCodeButton.style.display = "none";
} else if (input.value !== verificationCode) {
correctOrWrongCheck.innerHTML = "Der Code ist leider Falsch!";
continueToInstagramAccountButton.style.display = "none";
controlVerificationCodeButton.style.display = "block";
}
}
verificationCodeEmailDescription.innerHTML = "Ihr Bestätigunscode lautet: " + verificationCode;
// OPEN AND CLOSE APPS
function openVerificationCodeInstagramPage() {
createAccountForm.style.display = "none";
verificationCodeInstagramPage.style.display = "block"
verificationCodeEmail.style.display = "block";
instagramName.value = instagramNameInput.value;
notification.style.transform = "translate(-50%, -50%) scale(0)";
notificationDescription.innerHTML = "Ihr Bestätigunscode lautet: ...";
setTimeout(
function() {
notification.style.transform = "translate(-50%, -50%) scale(1)";
}, 1000);
setTimeout(
function() {
notification.style.transform = "translate(-50%, -50%) scale(0)";
}, 7000);
}
function continueToInstagramAccount() {
verificationCodeInstagramPage.style.display = "none";
instagramAccount.style.display = "flex";
erfolgreichAngemeldet.display = "none";
notificationDescription.innerHTML = "Erfolgreich bei Instagram angemeldet"
notification.style.transform = "translate(-50%, -50%) scale(0)";
erfolgreichAngemeldet.style.display = "block";
setTimeout(
function() {
notification.style.transform = "translate(-50%, -50%) scale(1)";
}, 1000);
setTimeout(
function() {
notification.style.transform = "translate(-50%, -50%) scale(0)";
}, 7000);
var counter = 0;
var followers = document.getElementById('followers');
setTimeout(function() {
var st = setInterval(function() {
followers.innerHTML = ++counter;
}, 100)
}, 100);
}
function closeNotification() {
notification.style.transform = "translate(-50%, -50%) scale(0)";
}
var isAppOpened = false;
function openInstagram() {
isAppOpened = true;
instagram.style.transform = "scale(1)";
}
function openMail() {
isAppOpened = true;
mail.style.transform = "scale(1)";
}
function closeApp() {
isAppOpened = false;
instagram.style.transform = "scale(0)";
mail.style.transform = "scale(0)";
}
window.onload = function() {
document.getElementById("instagramNumberText").value = '';
}
const slider = document.getElementById("slider");
const panels = document.querySelectorAll('.panel');
var lastX = 0;
var isDown = false;
document.addEventListener("mousedown", function(e) {
lastX = e.pageX;
isDown = true;
})
document.addEventListener("mousemove", function(e) {
if (isDown && !isAppOpened) {
const curX = e.pageX;
const diff = lastX - curX;
slider.scrollLeft += diff;
lastX = curX;
}
})
document.addEventListener("mouseup", function() {
isDown = false;
slider.style.scrollBehavior = "smooth";
if (slider.scrollLeft > 175) {
panels[1].scrollIntoView();
} else {
panels[0].scrollIntoView();
}
slider.style.scrollBehavior = "unset";
})
* {
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
user-select: none;
}
input:focus,
textarea:focus {
outline: 0;
}
#phone {
height: 600px;
width: 350px;
border-radius: 50px;
position: absolute;
top: 600px;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
border-top: 90px solid;
border-right: 15px solid;
border-left: 15px solid;
border-bottom: 90px solid;
background-image: url("https://ioshacker.com/wp-content/uploads/2019/06/iOS-13-wallpaper.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.app {
box-shadow: 0 0 9px -4px #000;
}
#topbar {
padding: 0.3em;
color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
height: 20px;
transform: translate(-4%, 0) scale(0.9);
width: 370px;
}
#connection {
display: flex;
align-items: center;
width: 110px;
justify-content: space-around;
}
#battery {
display: flex;
align-items: center;
width: 110px;
justify-content: end;
}
#battery .bi-battery-full {
font-size: 23px;
margin-left: 5px;
}
#topbar .bi-wifi-2 {
font-size: 25px;
margin-top: -3px;
}
#time {
text-align: center;
}
#notification {
margin: 0;
position: absolute;
top: 365px;
left: 50%;
-ms-transform: translate(-50%, -50%) scale(0);
transform: translate(-50%, -50%) scale(0);
height: 85px;
width: 315px;
background: #EDEBED;
border-radius: 10px;
z-index: 10000;
transition: all 0.5s;
box-shadow: 0 0 10px -1px #525252;
padding: 0.5em 0 0.5em 1em;
display: flex;
flex-direction: column;
justify-content: center;
}
#notification h1 {
font-size: 23px;
}
#appsOne {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
#instagramIcon,
#verificationCode,
#mailIcon {
margin: 20px;
}
.app {
font-size: 40px;
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 10px;
transition: all 0.2s;
}
.app:hover {
cursor: pointer;
filter: brightness(90%);
}
.bi-instagram,
.bi-envelope-fill {
width: 40px;
height: 40px;
color: #fff;
font-family: sans-serif;
}
/* Instagram */
#instagramIcon {
background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%);
}
#instagramApp {
position: absolute;
top: 0;
left: 0;
background: #EAEAEA;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
transition: all 0.3s;
transform: scale(0);
z-index: 99999;
text-align: center;
}
.instagramHeader {
font-family: 'Handlee', cursive;
font-size: 35px;
}
.instagramSecondHeader {
font-size: 15px;
width: 260px;
margin: 1em 0;
}
#instagramNameInput,
#instagramEmail,
#instagramNumberText {
font-size: 15px;
padding: 0.5em;
border: 1px solid #D1D1D1;
margin: 0.5em 0 0.5em 0;
width: 220px;
}
.instagramButton {
width: 236px;
font-size: 15px;
padding: 0.5em;
background: #3296F0;
color: #fff;
border: none;
margin: 0.5em 0;
transition: all 0.2s;
}
.instagramButton:hover {
filter: brightness(80%);
cursor: pointer;
}
#verificationCodeInstagramPage {
display: none;
}
#continueToInstagramAccount {
display: none;
}
#instagramAccount {
display: none;
justify-content: flex-start;
height: 100%;
width: 100%;
background: #f7f7f7;
flex-direction: column;
align-items: center;
}
#instagramName {
font-size: 20px;
text-align: left;
width: 85%;
padding: 20px 20px 15px 10px;
border-bottom: 1px solid gray;
height: 20px;
border-right: none;
border-top: none;
border-left: none;
background: none;
}
#profilePicture {
font-size: 35px;
width: 80px;
height: 80px;
display: flex;
justify-content: center;
align-items: center;
background: #eae9e9;
border-radius: 100000px;
margin: 20px;
border: 1px solid #6f6e6e;
color: #6f6e6e;
}
#instagramPictureAndNumbers {
display: inherit;
width: 360px;
}
#numbers {
width: 225px;
height: 45px;
margin: 35px 0 0 0;
}
#userDescription {
width: 320px;
font-size: 13px;
border: none;
background: none;
resize: none;
}
.bi-table {
font-size: 25px;
border-bottom: 1px solid;
width: 90%;
margin-top: 0.5em;
}
#emptyImages {
color: #c7c7c7;
margin: 100px;
font-size: 14px;
}
/* Mail */
#mailIcon {
background: linear-gradient(0deg, #05ffff 0%, #3cabe6 30%, #2763dc 70%);
}
#mailApp {
position: absolute;
top: 0;
left: 0;
background: #f6f6f6;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
transition: all 0.3s;
transform: scale(0);
z-index: 99999;
text-align: center;
}
#mailHeader {
font-size: 25px;
padding: 20px;
background: #fff;
width: 88%;
z-index: 999;
}
#verificationCodeEmail {
display: none;
}
.email {
background: #fff;
width: 97%;
padding: 5px;
border-top: 1px solid #e6e6e6;
}
.emailHeader {
text-align: left;
margin: 10px;
font-size: 25px;
}
#verificationCodeEmailDescription,
#erfolgreichAngemeldetDescription {
text-align: left;
margin: 10px;
}
#erfolgreichAngemeldet {
display: none;
}
/* Home Button */
#homeButton {
position: absolute;
height: 60px;
width: 60px;
background: transparent;
z-index: 9999;
bottom: -107px;
border-radius: 100000px;
left: 50%;
-ms-transform: translate(-50%, -50%) rotate(-10deg);
transform: translate(-50%, -50%) rotate(-10deg);
border: 1px outset;
cursor: pointer;
}
#slider {
white-space: nowrap;
position: relative;
overflow-x: scroll;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
height: calc(100% - 30px);
}
.panel {
display: inline-block;
width: 350px;
white-space: initial;
}
#appsTwo {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.4.1/font/bootstrap-icons.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght#100;300;400&display=swap" rel="stylesheet">
</head>
<body>
<div id="notification" onclick="closeNotification();">
<h1 id="notificationHeader"><b>Neue Email erhalten!</b></h1>
<p id="notificationDescription"></p>
</div>
<div id="phone">
<div id="topbar">
<div id="connection">
<i class="bi bi-bar-chart-fill"></i> LIDL LTE
<i class="bi bi-wifi-2"></i>
</div>
<p id="time"></p>
<div id="battery">
98%
<i class="bi bi-battery-full"></i>
</div>
</div>
<div id="slider">
<div class="panel">
<div id="appsOne">
<!-- Instagram -->
<div id="instagramIcon" class="app" onclick="openInstagram();"><i class="bi bi-instagram"></i></div>
<div id="instagramApp">
<form id="createAccountForm" action="#" onsubmit="openVerificationCodeInstagramPage(); return false;">
<h1 class="instagramHeader">Instagram</h1>
<p>Erstelle einen Account</p>
<input type="text" id="instagramNameInput" placeholder="Name" maxlength="12" autocomplete="off" required>
<input type="email" id="instagramEmail" placeholder="E-Mail" autocomplete="off" required>
<button type="submit" id="createAccount" class="instagramButton">Erstellen</button>
</form>
<div id="verificationCodeInstagramPage">
<h1 class="instagramHeader">Bestätigen</h1>
<p class="instagramSecondHeader">Wir haben ihn einen Bestätigungscode per Email gesendet!
</p>
<input type="text" id="instagramNumberText" maxlength="4" onkeypress="return /[0-9]/i.test(event.key)" placeholder="Bestätigungscode"><br>
<button onclick="controlVerificationCode();" id="controlVerificationCode" class="instagramButton">Bestätigen</button>
<button class="instagramButton" id="continueToInstagramAccount" onclick="continueToInstagramAccount()">Weiter</button>
<p id="correctOrWrongCheck"></p>
</div>
<div id="instagramAccount">
<input type="text" id="instagramName">
<div id="instagramPictureAndNumbers">
<div id="profilePicture"><i class="bi bi-person-fill"></i></div>
<table id="numbers">
<tr>
<th id="posts">0</th>
<th id="followers">1</th>
<th id="following">0</th>
</tr>
<tr>
<td>Posts</td>
<td>Followers</td>
<td>Following</td>
</tr>
</table>
</div>
<textarea id="userDescription" placeholder="Beschreibung..." rows="10"></textarea>
<i class="bi bi-table"></i>
<p id="emptyImages">No images found</p>
</div>
</div>
<div id="mailIcon" class="app" onclick="openMail();"><i class="bi bi-envelope-fill"></i></div>
<div id="mailApp">
<h1 id="mailHeader">E-Mails</h1>
<div class="email" id="erfolgreichAngemeldet">
<h1 class="emailHeader">Instagram</h1>
<p class="emailDescription" id="erfolgreichAngemeldetDescription">Erfolgreich angemeldet</p>
</div>
<div class="email" id="verificationCodeEmail">
<h1 class="emailHeader">Instagram</h1>
<p class="emailDescription" id="verificationCodeEmailDescription">Ihr Bestätigunscode lautet
</p>
</div>
</div>
</div>
</div>
<div class="panel">
<div id="appsTwo">
<div>
Second App Page
</div>
</div>
</div>
</div>
<div id="homeButton" onclick="closeApp();"></div>
</div>
</body>
</html>
Result:
You can hide the horizontal scrollbar by applying overflow-x:hidden to #slider
I have a "piggy bank" project that saves and withdraws an amount of money passed through two different forms (Each modal is for one type of transaction), but when trying to withdraw, the values are empty as in the example:
{date: "", amount: "", type: "Retirada"}
When saving the values normally:
{date: "2021-02-27", amount: "1", type: "Depósito"}
I'm not able to find the error of not taking the values
Snipped Code:
const Modals = {
modalType: "",
openModals(type){
if(type == "Depósito") {
this.modalType = type;
document.querySelector('.modal1-overlay').classList.add('active')
} else {
document.querySelector('.modal2-overlay').classList.add('active')
this.modalType = type;
}
},
closeModals(type) {
if(type == "Depósito") {
document.querySelector('.modal1-overlay').classList.remove('active')
this.modalType = "";
} else {
document.querySelector('.modal2-overlay').classList.remove('active')
this.modalType = "";
}
},
openErrorModal(message) {
document.querySelector('.modalError-overlay').classList.add('active')
document.getElementById('errorMessage').innerHTML = message
},
closeErrorModal() {
document.querySelector('.modalError-overlay').classList.remove('active')
}
}
const Transaction = {
all: [],
add(transaction) {
Transaction.all.push(transaction)
App.reload()
},
totalBalance() {
let total = 0;
Transaction.all.forEach(transaction => {
if (transaction.type == "Retirada") {
total -= transaction.amount;
} else {
total += transaction.amount;
}
})
return total;
},
}
const DOM = {
transactionsContainer: document.querySelector('#data-table tbody'),
addTransaction(transaction, index) {
const tr = document.createElement('tr');
tr.innerHTML = this.innerHTMLTransaction(transaction);
this.transactionsContainer.appendChild(tr)
},
innerHTMLTransaction(transaction) {
const CSSclass = transaction.type === 'Retirada' ? "withdraw" : "income"
const amount = Utils.formatCurrency(transaction.amount, transaction.type)
const html = `
<tr>
<td class="${CSSclass}">${transaction.type}</td>
<td class="price-transaction">${amount}</td>
<td class="date">${transaction.date}</td>
<td></td>
</tr>
`;
return html;
},
updateBalance() {
document
.getElementById("totalCurrency")
.innerHTML = Utils.formatCurrency(Transaction.totalBalance())
},
clearTransactions() {
DOM.transactionsContainer.innerHTML = "";
}
}
const Utils = {
formatAmount(value) {
value = Number(value)*100
return value;
},
formatDate(date){
const splittedDate = date.split("-")
return `${splittedDate[2]}/${splittedDate[1]}/${splittedDate[0]}`
},
formatCurrency(value, type) {
if (type == "Retirada") {
value = String(value).replace(/\D/g, "");
value = Number(value) / 100
value = value.toLocaleString("pt-BR", {style: "currency", currency: "BRL"})
return "- " + value;
} else {
const signal = "";
value = String(value).replace(/\D/g, "");
value = Number(value) / 100
value = value.toLocaleString("pt-BR", {style: "currency", currency: "BRL"})
return value
}
}
}
const Form = {
amount: Modals.modalType == "Retirada" ? document.querySelector('input#amount2') : document.querySelector('input#amount'),
date: Modals.modalType == "Retirada" ? document.querySelector('input#date2') : document.querySelector('input#date'),
getValues() {
return {
date: this.date.value,
amount: this.amount.value,
type: Modals.modalType
}
},
validateField() {
const {date, amount, type} = Form.getValues()
if(date.trim() === "" || amount.trim() === "" || type.trim() === "") {
throw new Error("Por favor, preencha todos os campos!")
}
},
formatValues() {
let { date, amount, type} = Form.getValues()
amount = Utils.formatAmount(amount)
date = Utils.formatDate(date)
return {date, amount, type}
},
clearFieldsForm(){
Form.amount.value = "";
Form.date.value = "";
Modals.modalType = "";
},
submit(event) {
event.preventDefault()
try {
console.log(this.getValues())
// Form.validateField()
const transaction = Form.formatValues()
Transaction.add(transaction)
Modals.closeModals(Modals.modalType)
Form.clearFieldsForm();
} catch (error) {
Modals.openErrorModal(error.message)
}
}
}
const App = {
init() {
Transaction.all.forEach(transaction => {
DOM.addTransaction(transaction)
});
DOM.updateBalance()
},
reload() {
DOM.clearTransactions()
App.init()
}
}
App.init()
/* Global CSS */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Ubuntu', sans-serif;
}
:root {
--darkblue: #363f5f;
--green: rgb(0, 172, 0);
}
body {
background-color: rgb(241, 241, 241);
}
.sr-only {
position: absolute;
margin: 0;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
border-width: 0;
}
.container {
width: min(90vw, 800px);
margin: auto;
}
/* Header */
header {
background-color: green;
padding: 2rem 2rem 5rem 2rem;
text-align: center;
color: white;
}
/* Modal CSS */
.modal1-overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
}
.modal1-overlay.active {
opacity: 1;
visibility: visible;
}
.modal1 {
background:snow;
padding: 2.4rem;
position: relative;
display: flex;
flex-direction: column;
}
.modal2-overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
}
.modal2-overlay.active {
opacity: 1;
visibility: visible;
}
.modal2 {
background:snow;
border-radius: 2px;
padding: 2.4rem;
position: relative;
}
#form {
max-width: 500px;
}
#form h2 {
margin-top: 0;
}
.modalError-overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
}
.modalError-overlay.active {
opacity: 1;
transition: opacity .25s ease-in;
visibility: visible;
}
.modalErrorContainer {
background-color: white;
border-radius: 2px;
width: 70vh;
height: 16vh;
padding: 10px;
}
.modalErrorContainer h3 {
margin-bottom: 1.5rem;
}
input {
border: 1px solid rgba(0, 0, 0, 0.192);
border-radius: 0.2rem;
padding: 0.8rem;
width: 100%;
}
.input-group {
margin-top: 0.8rem;
}
.input-group small {
opacity: 0.4;
margin-left: 5px;
font-size: 10px;
}
.input-group.actions {
display: flex;
justify-content: space-between;
align-items: center;
}
.input-group.actions .button,
.input-group.actions button {
width: 48%;
margin: 0;
}
/* Main CSS */
#logo {
width: 40vh;
margin-left: -2vh;
}
#balance {
margin-top: -3rem;
color: white;
display: flex;
flex-wrap: wrap;
}
h2 {
font-weight: 400;
user-select: none;
padding-top: 10px;
padding-bottom: 6px;
}
h3 {
color: black;
}
.card {
display: flex;
flex-direction: column;
width: 100%;
background-color: white;
border-radius: 3px;
margin-right: 0;
padding: 5px 10px;
margin-bottom: 1.5rem;
box-shadow: 0px 1px 1px 0px rgba(59, 59, 59, 0.527);
}
.card h3 {
margin: 0;
margin-top: 5px;
font-size: 16px;
font-weight: 400;
user-select: none;
}
.card p {
margin-left: 1.5vw;
color: var(--darkblue);
margin-top: 0.5rem;
font-weight: 600;
font-size: 24px;
}
.card.total {
background: rgb(0, 190, 0);
margin-right: 0;
margin-left: 0;
}
.card.total p {
color: white;
}
.card.total h3 {
color: white;
}
.containerButtons {
display: flex;
justify-content: center;
}
.button {
text-decoration: none;
margin: 15px;
border: 1px solid;
padding: 1.5vh;
border-radius: 5px;
}
.button.save {
color: var(--green);
}
.button.withdraw {
color: red;
}
.button.ok {
color: white;
background-color: var(--green);
margin-left: 85%;
}
button {
width: 100%;
height: 50px;
background-color: var(--green);
color: white;
border: 0;
border-radius: 5px;
cursor: pointer;
font-weight: 400;
font-size: 16px;
}
button:hover {
box-shadow: 0px 0px 2px 1px green;
}
.button.cancel {
color: red;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
font-weight: 400;
}
#data-table {
border-spacing: 0 0.5rem;
color: black;
}
#data-table th {
background: white;
color: #646464;
width: 50%;
font-weight: normal;
padding: 1rem 2rem;
user-select: none;
text-align: left;
}
#data-table tbody tr{
opacity: 0.7;
}
#data-table tbody tr:hover{
opacity: 1;
}
#data-table td {
background-color: white;
padding: 1rem 2rem;
}
td.price-transaction {
color: var(--darkblue);
}
td.withdraw {
color: red;
}
td.income {
color: green;
}
td.date {
color: var(--darkblue);
}
td.moneyatbank {
color: var(--darkblue);
}
/* Responsive */
#media screen and (min-width: 800px) {
#balance {
flex-wrap: nowrap;
}
.card {
margin-right: 2.5vh;
}
.card.total {
margin-left: 2.5vh;
}
}
#media screen and (max-width: 800px) {
#data-table {
display: block;
width: 100%;
border-spacing: 0 0.5rem;
color: black;
overflow: scroll;
}
}
<header>
<img src="assets/logo.svg" alt="Logo BiggyBank" id="logo">
</header>
<main class="container">
<section id="balance">
<h2 class="sr-only">Balanço</h2>
<div class="card">
<h3>Meta</h3>
<p>R$ 2000,00</p>
</div>
<div class="card total">
<h3>Total</h3>
<p id="totalCurrency"></p>
</div>
</section>
<section id="transaction">
<h2 class="sr-only">Transações</h2>
<div class="containerButtons">
+ Guardar
- Retirar
</div>
<table id="data-table">
<thead>
<tr>
<th>Tipo</th>
<th>Valor</th>
<th>Data</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</section>
</main>
<footer>
<img src="assets/darkmode.svg" alt="Icone DarkMode">
<img src="assets/lightmode.svg" alt="Icone DarkMode">
</footer>
<div class="modal1-overlay">
<div class="modal1">
<div id="form">
<h2>Guardar Dinheiro</h2>
<form action="" onsubmit="Form.submit(event)" id="form1">
<div class="input-group">
<label class="sr-only" for="amount">Valor à ser guardado</label>
<input id="amount" name="amount" type="number" step="0.01" placeholder="Valor à ser guardado" />
<small class="helpText">Use a vírgula (,) para casas decimais</small>
</div>
<div class="input-group">
<label class="sr-only" for="date">Valor à ser guardado</label>
<input id="date" name="date" type="date" />
</div>
<div class="input-group actions">
Cancelar
<button>Guardar</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal2-overlay">
<div class="modal2">
<div id="form">
<h2>Retirar Dinheiro</h2>
<form action="" onsubmit="Form.submit(event)" id="form2">
<div class="input-group">
<label class="sr-only" for="amount2">Valor à ser guardado</label>
<input id="amount2" name="amount2" type="number" step="0.01" placeholder="Valor à ser guardado" />
<small class="helpText">Use a vírgula (,) para casas decimais</small>
</div>
<div class="input-group">
<label class="sr-only" for="date2">Valor à ser guardado</label>
<input id="date2" name="date2" type="date" />
</div>
<div class="input-group actions">
Cancelar
<button>Retirar</button>
</div>
</form>
</div>
</div>
</div>
<div class="modalError-overlay">
<div class="modalErrorContainer">
<h3 id="errorMessage"></h3>
OK
</div>
</div>
I hope you can help.
Trying to make my video full screen but unable to.
Used MDN specifications and their code in order to help me.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML Video Player</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="player">
<video class="player__video viewer" src="652333414.mp4"></video>
<div class="player__controls">
<div class="progress">
<div class="progress__filled"></div>
</div>
<button class="player__button toggle" title="Toggle Play">►</button>
<input type="range" name="volume" class="player__slider" min="0" max="1" step="0.05" value="1">
<input type="range" name="playbackRate" class="player__slider" min="0.5" max="2" step="0.1" value="1">
<button data-skip="-10" class="player__button">« 10s</button>
<button data-skip="25" class="player__button">25s »</button>
<button type="button" data-state="go-fullscreen" class = "fullscreen__button">Fullscreen</button>
</div>
</div>
<script src="scripts.js"></script>
</body>
</html>
CSS
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
display: flex;
background: #7A419B;
min-height: 100vh;
background: linear-gradient(135deg, #7c1599 0%,#921099 48%,#7e4ae8 100%);
background-size: cover;
align-items: center;
justify-content: center;
}
.player {
max-width: 750px;
border: 5px solid rgba(0,0,0,0.2);
box-shadow: 0 0 20px rgba(0,0,0,0.2);
position: relative;
font-size: 0;
overflow: hidden;
}
/* This css is only applied when fullscreen is active. */
.player:fullscreen {
max-width: none;
width: 100%;
}
.player:-webkit-full-screen {
max-width: none;
width: 100%;
}
.player__video {
width: 100%;
}
.player__button {
background: none;
border: 0;
line-height: 1;
color: white;
text-align: center;
outline: 0;
padding: 0;
cursor: pointer;
max-width: 50px;
}
.player__button:focus {
border-color: #ffc600;
}
.player__slider {
width: 10px;
height: 30px;
}
.player__controls {
display: flex;
position: absolute;
bottom: 0;
width: 100%;
transform: translateY(100%) translateY(-5px);
transition: all .3s;
flex-wrap: wrap;
background: rgba(0,0,0,0.1);
}
.player:hover .player__controls {
transform: translateY(0);
}
.player:hover .progress {
height: 15px;
}
.player__controls > * {
flex: 1;
}
.progress {
flex: 10;
position: relative;
display: flex;
flex-basis: 100%;
height: 5px;
transition: height 0.3s;
background: rgba(0,0,0,0.5);
cursor: ew-resize;
}
.progress__filled {
width: 50%;
background: #ffc600;
flex: 0;
flex-basis: 50%;
}
/* unholy css to style input type="range" */
input[type=range] {
-webkit-appearance: none;
background: transparent;
width: 100%;
margin: 0 5px;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8.4px;
cursor: pointer;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0);
background: rgba(255,255,255,0.8);
border-radius: 1.3px;
border: 0.2px solid rgba(1, 1, 1, 0);
}
input[type=range]::-webkit-slider-thumb {
height: 15px;
width: 15px;
border-radius: 50px;
background: #ffc600;
cursor: pointer;
-webkit-appearance: none;
margin-top: -3.5px;
box-shadow:0 0 2px rgba(0,0,0,0.2);
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #bada55;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8.4px;
cursor: pointer;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0);
background: #ffffff;
border-radius: 1.3px;
border: 0.2px solid rgba(1, 1, 1, 0);
}
input[type=range]::-moz-range-thumb {
box-shadow: 0 0 0 rgba(0, 0, 0, 0), 0 0 0 rgba(13, 13, 13, 0);
height: 15px;
width: 15px;
border-radius: 50px;
background: #ffc600;
cursor: pointer;
}
JAVASCRIPT
/* Get Our Elements */
const player = document.querySelector('.player');
const video = player.querySelector('.viewer');
const progress = player.querySelector('.progress');
const progressBar = player.querySelector('.progress__filled');
const toggle = player.querySelector('.toggle');
const skipButtons = player.querySelectorAll('[data-skip]');
const ranges = player.querySelectorAll('.player__slider');
const fullScreen = player.querySelector('.fullscreen__button');
/*Build our functions */
// Play and Pause video
function togglePlay(){
if (video.paused){
video.play();
} else {
video.pause();
}
}
// Update Buttons when pausing
function updateButton(){
const icon = this.paused ? '►' : '❚ ❚';
toggle.textContent = icon;
}
// Update
function skip (){
video.currentTime += parseFloat(this.dataset.skip);
}
function handleRangeUpdate(){
video[this.name] = this.value;
}
function handleProgress(){
const percent = (video.currentTime / video.duration) * 100;
progressBar. style.flexBasis = `${percent}%`;
}
function scrub(e){
const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
video.currentTime = scrubTime;
}
function makeItBigger(){
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
}
/* Hook up event listenrs*/
video.addEventListener('click', togglePlay);
video.addEventListener('play', updateButton);
video.addEventListener('pause', updateButton);
video.addEventListener('timeupdate', handleProgress);
toggle.addEventListener('click', togglePlay);
fullScreen.addEventListener('click', makeItBigger);
skipButtons.forEach(button => button.addEventListener('click', skip));
ranges.forEach(range => range.addEventListener('change', handleRangeUpdate));
let mousedown = false;
progress.addEventListener('click', scrub);
progress.addEventListener('mousemove', (e) => mousedown && scrub(e));
progress.addEventListener('mousedown', () => mousedown = true);
progress.addEventListener('mouseup', () => mousedown = false);
The fullscreen is applied to the full window instead rather than just my video. I can see function is working just probably is not the right one.
I would like my actual video (black background) to be in fullscreen instead.
May be this would help you
.player:fullscreen {
max-width: 100%;
min-width: 100%;
width: 100%;
height: 100vh;
max-height: 100%;
min-height: 100vh;
}
How I can make the game restart from the beginning by clicking start button except reloading the whole page?
The problem occurs because when user clicks Start playGame function is called, but the a previous instance of playGame function is still running. I even thought about to kill a previous instance of function but in JS it can not be implemented except using webworker.terminate().
Here's the code:
document.addEventListener("DOMContentLoaded", function() {
'use strict';
var checkOn = document.querySelector("input[type=checkbox]");
var gameCount = document.getElementsByClassName("innerCount")[0];
var startButton = document.getElementById("innerStart");
var strictButton = document.getElementById("strictButton");
var strictInd = document.getElementById("strictIndicator");
var strictMode = false;
var soundArray = document.getElementsByTagName("audio");
var buttons = document.querySelectorAll(".bigButton");
var buttonArray = [].slice.call(buttons, 0);
checkOn.addEventListener("change", function() {
if (checkOn.checked) {
gameCount.innerHTML = "--";
} else {
gameCount.innerHTML = "";
}
});
strictButton.addEventListener("click", function() {
if (checkOn.checked) {
strictMode = !strictMode;
strictMode ? strictInd.style.backgroundColor = "#FF0000" :
strictInd.style.backgroundColor = "#850000";
}
});
function getRandArray() {
var array = [];
for (var i = 0; i < 22; i++) {
array[i] = Math.floor(Math.random() * 4);
}
return array;
}
startButton.addEventListener("click", function() {
if (checkOn.checked) {
var level = 0;
var randIndexArr = getRandArray();
sleep(700).then(function() {
playGame(randIndexArr, level);
});
}
});
function sleep(time) {
return new Promise(resolve => {
setTimeout(resolve, time)
})
}
function checkButton(randIndexArr, counter) {
var indexButton = 0;
var checker = function checker(e) {
var clickedButtonId = e.target.dataset.sound;
lightenButton(clickedButtonId);
if (+(clickedButtonId) === randIndexArr[indexButton]) {
if (indexButton === counter) {
counter++;
for (let i = 0; i < 4; i++) {
buttonArray[i].removeEventListener("click", checker, false)
}
sleep(2000).then(function() {
playGame(randIndexArr, counter);
});
}
indexButton++;
} else {
gameCount.innerHTML = "--";
if (strictMode) {
indexButton = 0;
counter = 0;
} else {
indexButton = 0;
}
for (let i = 0; i < 4; i++) {
buttonArray[i].removeEventListener("click", checker, false)
}
sleep(2000).then(function() {
playGame(randIndexArr, counter);
});
}
};
for (var i = 0; i < 4; i++) {
buttonArray[i].addEventListener("click", checker, false)
}
}
function playGame(randIndexArr, counter) {
if (counter === 22) {
return;
}
//Show the level of the Game
gameCount.innerHTML = counter + 1;
//Light and play user's input then check if input is correct
randIndexArr.slice(0, counter + 1).reduce(function(promise, div, index) {
return promise.then(function() {
lightenButton(div);
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve();
}, 1000);
})
})
}, Promise.resolve()).then(function() {
checkButton(randIndexArr, counter);
});
}
function lightenButton(id) {
var lightColorsArr = ["liteGreen", "liteRed", "liteYell", "liteBlue"];
soundArray[id].play();
buttonArray[id].classList.add(lightColorsArr[id]);
sleep(500).then(function() {
buttonArray[id].classList.remove(lightColorsArr[id])
});
}
});
#font-face {
font-family: myDirector;
src: url('https://raw.githubusercontent.com/Y-Taras/FreeCodeCamp/master/Simon/fonts/myDirector-Bold.otf');
}
body {
background-color: #5f5f5f;
}
#outerCircle {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
width: 560px;
border: 2px dotted grey;
position: relative;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.bigButton {
height: 250px;
width: 250px;
border: solid #464646;
transition: all 1s;
-webkit-transition: all 1s;
-moz-transition: all 1s;
-o-transition: background-color 0.5s ease;
}
#greenButton {
background-color: rgb(9, 174, 37);
border-radius: 100% 0 0 0;
border-width: 20px 10px 10px 20px;
}
.liteGreen#greenButton {
background-color: #86f999;
}
#redButton {
background-color: rgb(174, 9, 15);
border-radius: 0 100% 0 0;
border-width: 20px 20px 10px 10px;
}
.liteRed#redButton {
background-color: #f9868a;
}
#yellowButton {
background-color: rgb(174, 174, 9);
border-radius: 0 0 0 100%;
border-width: 10px 10px 20px 20px;
}
.liteYell#yellowButton {
background-color: #f9f986;
}
#blueButton {
background-color: rgb(9, 37, 174);
border-radius: 0 0 100% 0;
border-width: 10px 20px 20px 10px;
}
.liteBlue#blueButton {
background-color: #8699f9;
}
div#innerCircle {
border: 15px solid #464646;
border-radius: 50%;
position: absolute;
top: 25%;
right: 25%;
background-color: #c4c7ce;
}
div.additionalBorder {
margin: 4px;
border-radius: 50%;
height: 242px;
width: 242px;
overflow: hidden;
}
p#tradeMark {
margin: auto;
height: 104px;
text-align: center;
font-size: 68px;
font-family: myDirector;
color: #c4c7ce;
background-color: black;
border-color: antiquewhite;
line-height: 162px;
}
span#reg {
font-size: 12px;
}
.partition {
height: 6px;
}
.buttons {
height: 128px;
border-radius: 0 0 128px 128px;
border: 2px solid black;
}
/* Start and Strict buttons*/
table {
margin-left: 5px;
}
td {
text-align: center;
width: auto;
padding: 2px 10px;
vertical-align: bottom;
}
div.innerCount {
width: 54px;
height: 40px;
background-color: #34000e;
color: crimson;
border-radius: 11px;
font-size: 28px;
line-height: 42px;
text-align: center;
font-family: 'Segment7Standard', italic;
}
button#innerStart {
width: 27px;
height: 27px;
border: 4px solid #404241;
border-radius: 50%;
background: #a50005;
box-shadow: 0 0 3px gray;
cursor: pointer;
}
div.strict {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
button#strictButton {
width: 27px;
height: 27px;
border: 4px solid #404241;
border-radius: 50%;
background: yellow;
box-shadow: 0 0 3px gray;
cursor: pointer;
}
div#strictIndicator {
width: 6px;
height: 6px;
margin-bottom: 2px;
background-color: #850000;
border-radius: 50%;
border: 1px solid #5f5f5f;
}
#switcher {
display: flex;
justify-content: center;
align-items: center;
}
.labels {
font-family: 'Roboto', sans-serif;
margin: 4px;
}
/* toggle switch */
.checkbox > input[type=checkbox] {
visibility: hidden;
}
.checkbox {
display: inline-block;
position: relative;
width: 60px;
height: 30px;
border: 2px solid #424242;
}
.checkbox > label {
position: absolute;
width: 30px;
height: 26px;
top: 2px;
right: 2px;
background-color: #a50005;
cursor: pointer;
}
.checkbox > input[type=checkbox]:checked + label {
right: 28px;
}
<div id="outerCircle">
<div class="bigButton" id="greenButton" data-sound="0">
<audio src="https://s3.amazonaws.com/freecodecamp/simonSound1.mp3"></audio>
</div>
<div class="bigButton" id="redButton" data-sound="1">
<audio src="https://s3.amazonaws.com/freecodecamp/simonSound2.mp3"></audio>
</div>
<div class="bigButton" id="yellowButton" data-sound="2">
<audio src="https://s3.amazonaws.com/freecodecamp/simonSound3.mp3"></audio>
</div>
<div class="bigButton" id="blueButton" data-sound="3">
<audio src="https://s3.amazonaws.com/freecodecamp/simonSound4.mp3"></audio>
</div>
<div id="innerCircle">
<div class="additionalBorder">
<p id="tradeMark">simon<span id="reg">®</span>
</p>
<div class="partition"></div>
<div class="buttons">
<table>
<tr class="firstRow">
<td>
<div class="innerCount"></div>
</td>
<td>
<button type="button" id="innerStart"></button>
</td>
<td>
<div class="strict">
<div id="strictIndicator"></div>
<button type="button" id="strictButton"></button>
</div>
</td>
</tr>
<tr class="labels">
<td>
<div id="countLabel">COUNT</div>
</td>
<td>
<div id="startLabel">START</div>
</td>
<td>
<div id="strictLabel">STRICT</div>
</td>
</tr>
</table>
<div id="switcher">
<span class="labels">ON</span>
<div class="checkbox">
<input id="checkMe" type="checkbox">
<label for="checkMe"></label>
</div>
<span class="labels">OFF</span>
</div>
</div>
</div>
</div>
</div>
I didn't dig super deep into your code, but it looks like the crux of it is you're using setTimeout(), and that timeout may still be running when you restart.
What you need to do is store the return value of setTimeout() which is actually an id you can then pass to clearTimeout(), which will stop that timeout.
So, on your sleep() function, store the id:
function sleep(time) {
return new Promise(resolve => {
this.timeoutId = setTimeout(resolve, time)
});
}
And when you go to restart your game:
// ...
if (this.timeoutId) {
clearTimeout(this.timeoutId);
this.timeoutId = null;
}
//...
And then also just make sure you don't have any other code that will get more than two timeouts running at the same time (or you'll lose one of the ids).