mouseenter clearInterval() in vanila JS carousel - javascript

I have an infinity carousel with 3 slides. I was able to separate functions with help. I want the function slider to stop when I put my mouse on this slide, and when I take my mouse off, it will work again.
ClearInterval was used through addEventListner, but it did not work. ClearInterval (movement) also did not work within the movement function.
The last function I tested was this. What should I do to implement this function? clearInterval(slider) is not working
function slider() {
let slides = document.querySelectorAll(".slide"),
slider = document.querySelector(".slider"),
last = slider.lastElementChild,
first = slider.firstElementChild,
btn = document.querySelectorAll(".btn");
slider.insertBefore(last, first);
btn.forEach(btn => {
btn.addEventListener("click", movement);
});
setInterval(function () {
movement({
target: {
id: "next"
}
});
}, 8000);
function movement(e) {
slider = document.querySelector(".slider");
last = slider.lastElementChild;
first = slider.firstElementChild;
const activeSlide = document.querySelector(".active");
if (e.target.id === "next") {
slider.insertBefore(first, last.nextSibling);
activeSlide.classList.remove("active");
activeSlide.nextElementSibling.classList.add("active");
} else {
slider.insertBefore(last, first);
activeSlide.classList.remove("active");
activeSlide.previousElementSibling.classList.add("active");
}
}
}
slider();
let slides = document.querySelectorAll(".slide");
for (i = 0; i < slides.length; i++) {
slides[i].mouseenter(function () {
clearInterval(slider);
}).mouseleave(function () {
setInterval(function () {
movement({
target: {
id: "next"
}
});
}, 8000);
})
}
* {
margin: 0;
padding: 0;
}
.slider {
position: relative;
width: 100vw;
max-width: 100%;
height: 120px;
margin: auto;
overflow: hidden;
}
.slide {
width: 100%;
height: 300px;
position: absolute;
text-align: center;
-webkit-transition: 0.6s ease;
transition: 0.6s ease;
-webkit-transform: translate(-100%, 0);
transform: translate(-100%, 0);
}
.slide.active {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
.slide.active~.slide {
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
text-align: center;
}
.slide {
background: #222;
color: white;
padding: 30px;
}
button {
margin-top: 20px;
border: none;
border-radius: 0;
background: aliceblue;
color: #333;
padding: 10px;
cursor: pointer;
}
<div class="slider__wrapper">
<div class="slider">
<div class="slide active">
<h3>Slide One</h3>
<p>test</p>
</div>
<div class="slide">
<h3>Slide Two</h3>
<p>test</p>
</div>
<div class="slide">
<h3>Slide Three</h3>
<p>1234</p>
</div>
</div>
<button id="prev" class="btn">Prev</button>
<button id="next" class="btn">Next</button>
</div>

Below is the working fine as you expected.clearInterval function needs the value that is returned by setInterval, another problem is defining the "movement" function in parallel to the slider function so that it can be accessed from mouseleave event.
<!DOCTYPE html>
<html>
<style>
* {
margin: 0;
padding: 0;
}
.slider {
position: relative;
width: 100vw;
max-width: 100%;
height: 120px;
margin: auto;
overflow: hidden;
}
.slide {
width: 100%;
height: 300px;
position: absolute;
text-align: center;
-webkit-transition: 0.6s ease;
transition: 0.6s ease;
-webkit-transform: translate(-100%, 0);
transform: translate(-100%, 0);
}
.slide.active {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
.slide.active~.slide {
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
text-align: center;
}
.slide {
background: #222;
color: white;
padding: 30px;
}
button {
margin-top: 20px;
border: none;
border-radius: 0;
background: aliceblue;
color: #333;
padding: 10px;
cursor: pointer;
}
</style>
<body>
<div class="slider__wrapper">
<div class="slider">
<div class="slide active">
<h3>Slide One</h3>
<p>test</p>
</div>
<div class="slide">
<h3>Slide Two</h3>
<p>test</p>
</div>
<div class="slide">
<h3>Slide Three</h3>
<p>1234</p>
</div>
</div>
<button id="prev" class="btn">Prev</button>
<button id="next" class="btn">Next</button>
</div>
</body>
<script>
var sliderInterval = '';
function movement(e) {
slider = document.querySelector(".slider");
last = slider.lastElementChild;
first = slider.firstElementChild;
const activeSlide = document.querySelector(".active");
if (e.target.id === "next") {
slider.insertBefore(first, last.nextSibling);
activeSlide.classList.remove("active");
activeSlide.nextElementSibling.classList.add("active");
} else {
slider.insertBefore(last, first);
activeSlide.classList.remove("active");
activeSlide.previousElementSibling.classList.add("active");
}
}
function slider() {
let slides = document.querySelectorAll(".slide"),
slider = document.querySelector(".slider");
console.log("slider=========",slider);
let last = slider.lastElementChild,
first = slider.firstElementChild,
btn = document.querySelectorAll(".btn");
slider.insertBefore(last, first);
btn.forEach(btn => {
btn.addEventListener("click", movement);
});
sliderInterval = setInterval(function () {
movement({
target: {
id: "next"
}
});
}, 1000);
}
slider();
let slides = document.querySelectorAll(".slide");
for (i = 0; i < slides.length; i++) {
console.log("slides[i]=========",slides[i]);
slides[i].addEventListener('mouseenter', function(){
console.log("on mouseenter");
clearInterval(sliderInterval);
})
slides[i].addEventListener('mouseleave', function(){
sliderInterval = setInterval(function () {
movement({
target: {
id: "next"
}
});
}, 1000);
})
}
</script>
</html>

Related

css transition animation not working. how to I fix?

I want to add a transition animation while image is changing. But transition doesn't work. As if no transition animation has been added
How transition style does work in this case?
( If there is way to from left to right animation like image strip, it will be better than ease animation )
Js, Css, Html codes :
var slides = document.querySelectorAll('.slide');
var next = document.getElementById('next');
var back = document.getElementById('back');
let currentSlide = 0;
var manualNav = function(manual) {
slides.forEach((slide) => {
slide.classList.remove('active');
});
slides[manual].classList.add('active');
}
next.addEventListener('click', function() {
if (currentSlide != slides.length - 1) {
currentSlide++;
manualNav(currentSlide);
}
})
back.addEventListener('click', function() {
if (currentSlide != 0) {
currentSlide--;
manualNav(currentSlide);
}
})
var repeat = function(activeClass) {
let active = document.getElementsByClassName('active');
let i = 1;
var repeater = () => {
setTimeout(function() {
[...active].forEach((activeSlide) => {
activeSlide.classList.remove('active');
});
slides[i].classList.add('active');
i++;
if (slides.length == i) {
i = 0;
}
if (i >= slides.length) {
return;
}
repeater();
}, 10000);
}
repeater();
}
repeat();
.gallery {
width: 50%;
height: 340px;
display: flex;
align-items: center;
flex-direction: column;
}
.gallery .content {
position: relative;
width: 564px;
height: 297px;
}
.gallery .content .slide {
display: none;
transition: all 1s ease-in;
}
.gallery .content .slide img {
width: 100%;
height: 297px;
object-fit: cover;
}
.gallery .content .slide.active {
display: block;
}
.gallery .content .firstSvg {
position: absolute;
right: 80px;
bottom: 24px;
cursor: pointer;
height: 50px;
width: 50px;
background-color: orange;
}
.gallery .content .lastSvg {
cursor: pointer;
position: absolute;
right: 24px;
bottom: 24px;
height: 50px;
width: 50px;
background-color: wheat;
}
<div class="gallery" id="gallery">
<div class="content">
<div class="slide active">
<img src="https://i.picsum.photos/id/250/536/354.jpg?hmac=qb3khzryKWU1ECPob2_1mYZLumW5eJTLSmhJzi1VVSI" alt="gallery">
</div>
<div class="slide">
<img src="https://i.picsum.photos/id/868/536/354.jpg?hmac=ZcbB7ABIgl6LS5B1wxkzJ_dxJFgNmCsODUTfxM5GdRk" alt="gallery">
</div>
<div class="slide">
<img src="https://i.picsum.photos/id/441/536/354.jpg?hmac=qHaUqO3vqlz-C811TXJPtRw-FV4ciRCazlDZb1gdodg" alt="gallery">
</div>
<div class="firstSvg" id="back">back</div>
<div class="lastSvg" id="next">next</div>
</div>
</div>
var slides = document.querySelectorAll('.slide');
var next = document.getElementById('next');
var back = document.getElementById('back');
let currentSlide = 0;
var manualNav = function(manual) {
slides.forEach((slide) => {
slide.classList.remove('active');
});
slides[manual].classList.add('active');
}
next.addEventListener('click', function() {
if (currentSlide != slides.length - 1) {
currentSlide++;
manualNav(currentSlide);
}
})
back.addEventListener('click', function() {
if (currentSlide != 0) {
currentSlide--;
manualNav(currentSlide);
}
})
var repeat = function(activeClass) {
let active = document.getElementsByClassName('active');
let i = 1;
var repeater = () => {
setTimeout(function() {
[...active].forEach((activeSlide) => {
activeSlide.classList.remove('active');
});
slides[i].classList.add('active');
i++;
if (slides.length == i) {
i = 0;
}
if (i >= slides.length) {
return;
}
repeater();
}, 10000);
}
repeater();
}
repeat();
.gallery {
width: 50%;
height: 340px;
display: flex;
align-items: center;
flex-direction: column;
}
.gallery .content {
position: relative;
width: 564px;
height: 297px;
}
.gallery .content .slide {
height: 0;
width: 0;
opacity: 0;
transition: all 1s ease-in;
}
.gallery .content .slide img {
width: 100%;
height: 297px;
object-fit: cover;
}
.gallery .content .slide.active {
height: 100%;
width: 100%;
opacity: 1;
}
.gallery .content .firstSvg {
position: absolute;
right: 80px;
bottom: 24px;
cursor: pointer;
height: 50px;
width: 50px;
background-color: orange;
}
.gallery .content .lastSvg {
cursor: pointer;
position: absolute;
right: 24px;
bottom: 24px;
height: 50px;
width: 50px;
background-color: wheat;
}
<div class="gallery" id="gallery">
<div class="content">
<div class="slide active">
<img src="https://i.picsum.photos/id/250/536/354.jpg?hmac=qb3khzryKWU1ECPob2_1mYZLumW5eJTLSmhJzi1VVSI" alt="gallery">
</div>
<div class="slide">
<img src="https://i.picsum.photos/id/868/536/354.jpg?hmac=ZcbB7ABIgl6LS5B1wxkzJ_dxJFgNmCsODUTfxM5GdRk" alt="gallery">
</div>
<div class="slide">
<img src="https://i.picsum.photos/id/441/536/354.jpg?hmac=qHaUqO3vqlz-C811TXJPtRw-FV4ciRCazlDZb1gdodg" alt="gallery">
</div>
<div class="firstSvg" id="back">back</div>
<div class="lastSvg" id="next">next</div>
</div>
</div>
Animations don't work with display property
When you are trying to change display: none; to display:block when a silde is active, browser won't recognise this as a transition event hence nothing happens.
Instead you can try using the changes below to create a fade in animation
Changes
.gallery .content .slide {
height: 0;
width: 0;
opacity: 0;
transition: all 1s ease-in;
}
.gallery .content .slide.active {
height: 100%;
width: 100%;
opacity: 1;
}
Initially silde do not have height,width,opacity which makes them 'invisible'.
But when silde is set toactive the above 3 properties are changed and that triggers an animation which in this case is transition: all 1s ease-in;

How reverse animation css in js?

I have problem, I wanted reverse animation in JS, before the "animationToggler" class is deleted, I tried to add the code that is commented out, but this not working.
Codepen
const menuToggler = document.querySelector('.toggler .hamburger');
menuToggler.addEventListener('click', function() {
this.classList.toggle('animationToggler');
// if(this.classList.contains('animationToggler')){
// this.style.animationDirection = "reverse"
// }
setTimeout(() => {
this.classList.toggle('active');
}, 400)
});
.toggler {
display: flex;
align-items: center;
cursor: pointer;
}
.animationToggler {
animation: animationTogglerMenu .8s ease;
}
.toggler p {
margin: 0;
text-transform: uppercase;
font-size: 1.65rem;
margin: 0 0 0 10px;
}
.hamburger .line {
height: 4px;
width: 2.5em;
background: #000;
margin: .45em 0;
border-radius: 50px;
transition: .6s;
}
.active .one {
transform: rotate(45deg) translateY(15px);
}
.active .two {
background-color: transparent;
transition: none;
}
.active .three {
transform: rotate(-45deg) translateY(-15px);
}
#keyframes animationTogglerMenu {
100% {
transform: rotate(720deg);
}
}
<div class="toggler">
<div class="hamburger">
<div class="line one"></div>
<div class="line two"></div>
<div class="line three"></div>
</div>
<p>Menu</p>
</div>
I managed to do it myself, this is code in the JS
const menuToggler = document.querySelector('.toggler');
const menuTogglerHamburger = document.querySelector('.toggler .hamburger');
menuToggler.addEventListener('click', function(){
//checking if there is a class animationToggler
if(menuTogglerHamburger.classList.contains('animationToggler')){
//restart animation rotate
menuTogglerHamburger.classList.remove('animationToggler');
void menuTogglerHamburger.offsetWidth;
menuTogglerHamburger.classList.add('animationToggler');
}
menuTogglerHamburger.classList.add('animationToggler');
setTimeout(()=>{
//animation line on the cross
menuTogglerHamburger.classList.toggle('active');
}, 200)
});

Vanilla JS - Infinite Auto play Slider

I'm going to make a responsive slider that automatically plays.The code I had at first is this.
It's working properly.
However, I'm going to separate the code because it doesn't play automatically.
I tried to auto-play the slides through setInterval(slider,3000), but it didn't work properly.
Realizing that it is a problem caused by all the content in the 'function slider', I separated the button from the press to create two functions, but it did not work. I don't know what to do...
function slider() {
let slides = document.querySelectorAll(".slide"),
slider = document.querySelector(".slider"),
last = slider.lastElementChild,
first = slider.firstElementChild,
btn = document.querySelectorAll(".btn");
slider.insertBefore(last, first);
btn.forEach(btn => {
btn.addEventListener("click", movement);
});
function movement(e) {
slider = document.querySelector(".slider");
last = slider.lastElementChild;
first = slider.firstElementChild;
const activeSlide = document.querySelector(".active");
if (e.target.id === "next") {
slider.insertBefore(first, last.nextSibling);
activeSlide.classList.remove("active");
activeSlide.nextElementSibling.classList.add("active");
} else {
slider.insertBefore(last, first);
activeSlide.classList.remove("active");
activeSlide.previousElementSibling.classList.add("active");
}
}
}
slider();
* {
margin: 0;
padding: 0;
}
.slider {
position: relative;
width: 100vw;
max-width: 100%;
height: 300px;
margin: auto;
overflow: hidden;
}
.slide {
width: 100%;
height: 300px;
position: absolute;
text-align: center;
-webkit-transition: 0.6s ease;
transition: 0.6s ease;
-webkit-transform: translate(-100%, 0);
transform: translate(-100%, 0);
}
.slide.active {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
.slide.active ~ .slide {
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
text-align: center;
}
.slide {
background:#222;
color: white;
padding: 30px;
}
button {
margin-top: 20px;
border: none;
border-radius: 0;
background: aliceblue;
color: #333;
padding: 10px;
cursor: pointer;
}
<div class="slider__wrapper">
<div class="slider">
<div class="slide active">
<h3>Slide One</h3>
<p>test</p>
</div>
<div class="slide">
<h3>Slide Two</h3>
<p>test</p>
</div>
<div class="slide">
<h3>Slide Three</h3>
<p>1234</p>
</div>
</div>
<button id="prev" class="btn">Prev</button>
<button id="next" class="btn">Next</button>
</div>
Because you are using event inside movement() function to see which button was pressed, you can supply a "dummy" object with the direction instead:
function slider() {
let slides = document.querySelectorAll(".slide"),
slider = document.querySelector(".slider"),
last = slider.lastElementChild,
first = slider.firstElementChild,
btn = document.querySelectorAll(".btn");
slider.insertBefore(last, first);
btn.forEach(btn => {
btn.addEventListener("click", movement);
});
setInterval(function()
{
movement({target:{id:"next"}});
}, 3000);
function movement(e) {
slider = document.querySelector(".slider");
last = slider.lastElementChild;
first = slider.firstElementChild;
const activeSlide = document.querySelector(".active");
if (e.target.id === "next") {
slider.insertBefore(first, last.nextSibling);
activeSlide.classList.remove("active");
activeSlide.nextElementSibling.classList.add("active");
} else {
slider.insertBefore(last, first);
activeSlide.classList.remove("active");
activeSlide.previousElementSibling.classList.add("active");
}
}
}
slider();
* {
margin: 0;
padding: 0;
}
.slider {
position: relative;
width: 100vw;
max-width: 100%;
height: 300px;
margin: auto;
overflow: hidden;
}
.slide {
width: 100%;
height: 300px;
position: absolute;
text-align: center;
-webkit-transition: 0.6s ease;
transition: 0.6s ease;
-webkit-transform: translate(-100%, 0);
transform: translate(-100%, 0);
}
.slide.active {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
.slide.active~.slide {
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
text-align: center;
}
.slide {
background: #222;
color: white;
padding: 30px;
}
button {
margin-top: 20px;
border: none;
border-radius: 0;
background: aliceblue;
color: #333;
padding: 10px;
cursor: pointer;
}
<div class="slider__wrapper">
<div class="slider">
<div class="slide active">
<h3>Slide One</h3>
<p>test</p>
</div>
<div class="slide">
<h3>Slide Two</h3>
<p>test</p>
</div>
<div class="slide">
<h3>Slide Three</h3>
<p>1234</p>
</div>
</div>
<button id="prev" class="btn">Prev</button>
<button id="next" class="btn">Next</button>
</div>

Keep the 3D Cube of Images Continue to Transition at the Same Side

I have used this tutorial to create a cube of images that move as a slideshow.
https://webdevtrick.com/css-3d-cube-carousel/?unapproved=16788&moderation-hash=ec78aa2bd99b49552d07f0ec60049b18#comment-16788
see what is doing https://files.fm/u/s2ywz7my
I have managed this to be automatically moved using setInterval. When the cube reached the fourth image. It moved back to the first one.
jQuery file
<script>
/** Code By Webdevtrick ( https://webdevtrick.com ) **/
var $carousel = $('.carousel'),currentSlide, nextSlide;
setInterval( function ()
{
currentSlide = $carousel.attr('data-slide');
nextSlide = +currentSlide === 4 ? 1 : +currentSlide + 1;
$carousel.attr('data-slide', nextSlide);
}
, 2000);
</script>
I want the cube to continue sliding to the left and also as it is moving around itself.
By adding some CSS and modify in JS, you can loop this cube slider. But it's animating by changing data-slide value and apply CSS to rotate cube. It's not dynamic slider.
Here is working Demo
$(document).ready(function() {
var $carousel = $('.carousel'),
currentSlide, nextSlide;
$('.next').click(function() {
if(!$carousel.hasClass('sliding')){
currentSlide = $carousel.attr('data-slide');
nextSlide = +currentSlide === 5 ? 0 : +currentSlide + 1;
$carousel.attr('data-slide', nextSlide);
$carousel.addClass('sliding');
}
$carousel.on('transitionend', function(){
if(nextSlide == 5){
$carousel.css('transition', 'none');
$carousel.attr('data-slide', 1);
setTimeout(function(){
$carousel.removeAttr('style');
},10);
}
$carousel.removeClass('sliding');
});
});
$('.prev').click(function() {
if(!$carousel.hasClass('sliding')){
currentSlide = $carousel.attr('data-slide');
nextSlide = +currentSlide === 0 ? 5 : +currentSlide - 1;
$carousel.attr('data-slide', nextSlide);
$carousel.addClass('sliding');
}
$carousel.on('transitionend', function(){
if(nextSlide == 0){
$carousel.css('transition', 'none');
$carousel.attr('data-slide', 4);
setTimeout(function(){
$carousel.removeAttr('style');
},10);
}
$carousel.removeClass('sliding');
});
});
});
/** Code By Webdevtrick ( https://webdevtrick.com ) **/
*, *:before, *:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
}
body {
margin-top: 200px;
background: #333;
font-family: 'Staatliches', cursive;
font-size: 2em;
line-height: 1.5;
}
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding-bottom: 5em;
perspective: 100em;
}
.carousel {
position: relative;
width: 15em;
height: 15em;
margin: 0 auto;
transform-style: preserve-3d;
transition: transform 0.5s ease;
}
.carousel[data-slide="0"] {
transform: rotateY(90deg);
}
.carousel[data-slide="1"] {
transform: rotateY(0deg);
}
.carousel[data-slide="2"] {
transform: rotateY(-90deg);
}
.carousel[data-slide="3"] {
transform: rotateY(-180deg);
}
.carousel[data-slide="4"] {
transform: rotateY(-270deg);
}
.carousel[data-slide="5"] {
transform: rotateY(-360deg);
}
.slides {
position: absolute;
width: 15em;
height: 15em;
background: white;
}
.slides img {
width: 100%;
}
.back, .slides:nth-child(3) {
transform: translateZ(-7.5em) rotateY(180deg);
}
.right, .slides:nth-child(2) {
transform: rotateY(-270deg) translateX(7.5em);
transform-origin: top right;
}
.left, .slides:nth-child(4) {
transform: rotateY(270deg) translateX(-7.5em);
transform-origin: center left;
}
.front, .slides:nth-child(1) {
transform: translateZ(7.5em);
}
.next, .prev {
position: absolute;
top: 50%;
right: 0;
width: 6em;
margin-top: -2.5em;
border-radius: 3px;
background: #212121;
text-align: center;
line-height: 3;
letter-spacing: 5px;
color: white;
transform: translateY(-50%);
cursor: pointer;
}
.prev:hover {
background: #e60023;
}
.prev {
left: 0;
}
.next:hover {
background: #e60023;
}
.cf:before, .slides:before,
.cf:after,
.slides:after {
content: " ";
display: table;
}
.cf:after, .slides:after {
clear: both;
}
.cf, .slides {
*zoom: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="carousel" data-slide="1">
<div class="slides">
<img src="https://picsum.photos/700/700?random=1" />
</div>
<div class="slides">
<img src="https://picsum.photos/700/700?random=2" />
</div>
<div class="slides">
<img src="https://picsum.photos/700/700?random=3" />
</div>
<div class="slides">
<img src="https://picsum.photos/700/700?random=4" />
</div>
</div>
<div class="next">NEXT ⇨</div>
<div class="prev">⇦ PREV</div>
</div>
You can trigger next button in setInterval function to slide cube automatically. by adding.
setInterval( function () {
$('.next').trigger('click');
},2000);

How to traverse through text in a textbox?

I'm trying to make a typing speed test counter. The goal is to move the blinking cursor throughout the text only if the correct character is entered. I'm unable to understand how to move through the text. I shall then count the number of minutes taken and calculate wpm.
function timer() {
var seconds = 3;
var element = document.getElementById('timer');
var timerId = setInterval(countdown, 1000);
function countdown() {
if (seconds == -1) {
clearTimeout(timerId);
element.innerHTML = "Time Up";
var value = 1;
wpm();
} else {
element.innerHTML = "Time Left: " + seconds + " " + "seconds";
seconds--;
}
}
}
body {
font-family: monospace;
}
.title-of-page>h1 {
text-align: center;
font-family: monospace;
}
.title-of-page {
background-color: #414a4c;
color: #ced3db;
}
.jumbotron {
margin: 0;
}
.navigation-bar {
background-color: #46494f;
}
a {
color: green;
}
.nav>li>a:hover {
background-color: #878f9b;
}
.navbar-nav>li {
text-align: center;
float: none;
display: table-cell;
}
.navbar-nav {
display: table;
width: 100%;
margin: 0;
}
.navbar {
margin: 0;
padding: 0;
border-radius: 0;
}
.typing-field {
width: 60em;
height: 8em;
background-color: #7e7e7f;
opacity: 0.4;
margin-left: 15em;
margin-top: 5em;
border: 3px solid black;
padding: 0.8em;
}
#display-text {
color: white;
font-size: 2em;
}
.user-input {
font-size: 1em;
padding-left: 35em;
padding-top: 2em;
}
#timer {
padding-top: 4em;
padding-left: 10em;
font-size: 1.5em;
color: red;
}
.typed-cursor {
opacity: 1;
-webkit-animation: blink 0.7s infinite;
-moz-animation: blink 0.7s infinite;
animation: blink 0.7s infinite;
color: black;
}
#keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-webkit-keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-moz-keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<body>
<div class="jumbotron title-of-page container-fluid">
<h1>Typing Counter</h1>
</div>
<nav class="navbar navigation-bar container-fluid">
<div class="">
<ul class="nav navbar-nav">
<li>Home</li>
<li>Contest</li>
<li>About</li>
<li>Leaderboard</li>
</ul>
</div>
</nav>
<div>
<div id="timer">
<button type="button" class="btn" onclick="timer();">Start</button>
</div>
<div class="typing-field">
<p id="display-text"><span class="typed-cursor">T</span>his is to test your typing speed. So type like you'll never type again.</p>
</div>
<div class="user-input">
<input type="text" name="user-input-text-box" id="user-input" />
</div>
</div>
</body>
For javascript I tried to do something like this. It's mostly wrong. I'm still a beginner.
window.onload = function wpm() {
var text = document.getElementById('user-input').innerHTML;
var i=0;
document.getElementById('user-input').onkeyup = function() {
var letter = this.value;
if(letter==text[i])
{
letter.style.color="green";
i++;
}
}
}
Here is what I ended up with after playing a little with your code:
var display = document.getElementById('display-text');
var userInput = document.getElementById('user-input');
userInput.onkeyup = function() {
for (var i = 0; i < userInput.value.length; i++) { // Counts correct letters
if (display.innerText[i] != userInput.value[i])
break; // Exit loop if incorrect
}
display.innerHTML = '<span style="color: green;">' + display.innerText.substr(0, i) + '</span>' + '<span class="typed-cursor">' + display.innerText.substr(i, 1) + '</span>' + display.innerText.substr(i + 1);
}
body {
font-family: monospace;
}
.typing-field {
width: auto;
/* Modified for snippet */
height: auto;
/* Modified for snippet */
background-color: #7e7e7f;
opacity: 0.4;
margin-left: 0;
/* Modified for snippet */
margin-top: 0;
/* Modified for snippet */
border: 3px solid black;
padding: 0.8em;
}
#display-text {
color: white;
font-size: 2em;
}
.user-input {
font-size: 1em;
padding-left: 0;
/* Modified for snippet */
padding-top: 0;
/* Modified for snippet */
}
#timer {
padding-left: 0;
/* Modified for snippet */
padding-top: 0;
/* Modified for snippet */
font-size: 1.5em;
color: red;
}
.typed-cursor {
opacity: 1;
-webkit-animation: blink 0.7s infinite;
-moz-animation: blink 0.7s infinite;
animation: blink 0.7s infinite;
color: black;
}
#keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-webkit-keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-moz-keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<body>
<div>
<div id="timer">
<button type="button" class="btn" onclick="timer();">Start</button>
</div>
<div class="typing-field">
<p id="display-text"><span class="typed-cursor">T</span>his is to test your typing speed. So type like you'll never type again.</p>
</div>
<div class="user-inputs">
<input type="text" name="user-input-text-box" id="user-input" />
</div>
</div>
</body>
This code compares the displayed and the typed strings, highlights in green the correct letters and put the blinking cursor on the one to be typed.
I hope it helps. :)
If you want to track the letters typed and then turn them a different color, you can save the text string in a variable and queue through it dumping the typed letters into another array, then merge them together into the output field:
let textToType = "This is what I want you to type.";
const typedLetters = [];
document.getElementById('user-input').addEventListener("keypress", function(event) {
const key = event.which || event.keyCode;
const nextLetter = textToType[0].charCodeAt();
const outputTarget = document.getElementById("display-text");
const greenWrapper = document.createElement("span");
greenWrapper.classList.add("typed-cursor");
if (key === nextLetter) {
typedLetters.push(String.fromCharCode(nextLetter));
textToType = textToType.substr(1);
greenWrapper.textContent = typedLetters.join("");
outputTarget.textContent = textToType;
outputTarget.prepend(greenWrapper);
};
})
body {
font-family: monospace;
}
.title-of-page>h1 {
text-align: center;
font-family: monospace;
}
.title-of-page {
background-color: #414a4c;
color: #ced3db;
}
.jumbotron {
margin: 0;
}
.navigation-bar {
background-color: #46494f;
}
a {
color: green;
}
.nav>li>a:hover {
background-color: #878f9b;
}
.navbar-nav>li {
text-align: center;
float: none;
display: table-cell;
}
.navbar-nav {
display: table;
width: 100%;
margin: 0;
}
.navbar {
margin: 0;
padding: 0;
border-radius: 0;
}
.typing-field {
width: 60em;
height: 8em;
background-color: #7e7e7f;
opacity: 0.4;
margin-left: 15em;
margin-top: 5em;
border: 3px solid black;
padding: 0.8em;
}
#display-text {
color: white;
font-size: 2em;
}
.user-input {
font-size: 1em;
padding-left: 35em;
padding-top: 2em;
}
#timer {
padding-top: 4em;
padding-left: 10em;
font-size: 1.5em;
color: red;
}
.typed-cursor {
opacity: 1;
-webkit-animation: blink 0.7s infinite;
-moz-animation: blink 0.7s infinite;
animation: blink 0.7s infinite;
color: black;
}
#keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-webkit-keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-moz-keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<div class="jumbotron title-of-page container-fluid">
<h1>Typing Counter</h1>
</div>
<nav class="navbar navigation-bar container-fluid">
<div class="">
<ul class="nav navbar-nav">
<li>Home</li>
<li>Contest</li>
<li>About</li>
<li>Leaderboard</li>
</ul>
</div>
</nav>
<div>
<div id="timer">
<button type="button" class="btn" onclick="timer();">Start</button>
</div>
<div class="typing-field">
<p id="display-text">This is what I want you to type.
</div>
<div class="user-input">
<input type="text" name="user-input-text-box" id="user-input" />
</div>
</div>

Categories