I want to display a progress bar based on a countdown of 7 minutes that is displayed in a div: <div id = "quiz-time-left"> 0:06:24 </ div>
I need if the page is reloaded don´t reset the progress bar. Would it be possible with CSS and a script that the bar represents what the timer displays?
I use this css progress bar:
#quiz-time-left {
width: 0;
height: 100%;
-webkit-animation: progreso 420s linear;
animation: progreso 420s linear;
color: #eb7260;
background: #eb7260;
}
#page-mod-quiz-summary #quiz-timer {
text-align: center;
display: none;
position: absolute;
left: -50px;
top: -50px;
}
#quiz-timer {
border: 2px solid #eb7260;
text-indent: -9999px;
display:block;
font-size: 0px;
height: 35px;
}
#-webkit-keyframes progreso {
0% {
width: 100%;;
}
100% {
width: 0;
}
}
#keyframes progreso {
0% {
width: 100%;
}
100% {
width: 0;
}
}
html
<div id="quiz-timer" role="timer" aria-atomic="true" aria-relevant="text" style="display: block;">Time left: <div id="quiz-time-left">0:06:41</div></div>
Thank you. Best regards.
What you can do is using localStorage to store the current state of the timer and each second decrease this number.
So when the page has finished loading, test if localStorage is undefined, if it is then set it to 420. If localStorage != undefined then resume the animation from the time stored in localStorage.
You could implement something like this:
Make sure you save time left in localStorage
window.onbeforeunload = function(timeLeft) {
localStorage.setItem('countDown', timeLeft);
}
When loading the page check if there is an item called countDown and resume countDown with the value:
if(localStorage['countDown'] {
resumeCountdown(localStorage.getItem('countDown');
}
Related
I'm new to the web development world and wanted to know if there is a way to disable background scrolling.
I've tried z-index for the pop-up to display above all the elements, but some background content was getting overlapped with the pop-up.
I'm not much familiar with JS but was not able to get any help.
Below please find my code
body {
height: 200vh;
}
.bg-noscroll {
}
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup {
transform: translateY(-60px);
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 30%;
position: relative;
transition: all 5s ease-in-out;
}
.popup .close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.content {
height: 250px;
}
.popup .content {
overflow-y: scroll;
}
#media screen and (max-width: 700px){
.popup{
width: 70%;
}
<body class="bg-noscroll bg-scroll">
<span><a class="popupBG-Disable" href="#popup">Full Recipe</a></span>
<div id="popup" class="overlay">
<div class="popup">
<h3>Foxtail Millet Porridge:</h3>
<a class="close" href="#">×</a>
<div class="content">
<span>Ingredients:<br>here are some things that you'd use to make this<br> isn't this amazing?<br>Yes, it is!<br>
this is getting loooooong<br>this will take me a while!<br>oh... yes it will<br>we're getting close<br>and we should be there <br>or not...<br>Im losing hope<br>and patience<br>with how long this is taking<br>I could really cry<br>
but we'll get there soon<br>safe and sound<br>free as pie<br>I dont know what I meant by that<br>
this is taking long mannnn<br>
</span>
Thank you for your help!
I have a live codepen with your original code so you can just copy and paste if you wish.
Using Jquery, we can enable and disable overflow using some simple code:
const modal = document.querySelector("#btn");
const body = document.querySelector("body");
const showModal = function (e) {
modal.classList.toggle("hidden");
if (!modal.classList.contains("hidden")) {
body.style.overflow = "hidden";
} else {
body.style.overflow = "hidden";
}
}; // just reversed for re-enabling scroll, as seen in the codepen
Currently, you have to make use of javascript and add or remove the scrollbar-properties or css-class using a hashchange event-listener for example:
window.addEventListener("hashchange", event => {
const newHash = new URL(event.newURL).hash,
el = document.getElementById(newHash.substr(1));
if (el && el.classList && el.classList.contains("overlay")) {
document.body.style.overflow = "hidden";
// or document.body.classList.add("bg-noscroll");
} else {
document.body.style.overflow = "";
// or document.body.classList.remove("bg-noscroll");
}
});
Starting from chromium 101 the support for the :has()-selector has been implemented (experimental flag only) and the current chromium 105 dev channel brings the :has()-selector enabled by default.
With the has()-selector it will be possible using:
body:has(.overlay:target) {
overflow: hidden;
}
Keep also mind, it may take some more time for other browsers to implement the has()-selector. Therefor the best would be to stick with the javascript method for a while.
What I'm trying to achieve here is that when I scroll on a particular div here .ball, it should scale up to 1.5.
but when I'm not scrolling on that ball div it should shrink down to it's original height and width.
Here I'm using window method to do this trick and as soon as I scroll ball scale up which isn't what I'm trying to do. What can I use instead of window method and is there any other approach to do achieve this?
const ball = document.querySelector('.ball');
window.addEventListener('scroll', ()=> {
if (scroll) {
ball.classList.add('active');
} else {
ball.classList.remove('active');
}
});
.ball {
height: 200px;
width: 200px;
border-radius: 100%;
background-color: orange;
}
.ball.active {
transform: scale(1.5);
position: fixed;
}
body {
height: 150vh;
}
<div class="ball"></div>
I would use a setTimeout function to remove the class after a short period after the scroll. Do not forget to clear the timeout otherwise it will lead to weird behaviour. (as suggested by Lakshya when I was answering to the question).
To make the ball smoothly transition, I would add a css transition as shown bellow.
const ball = document.querySelector('.ball');
const container = document.querySelector('.container')
let scrollTimeout;
container.addEventListener('scroll', ()=> {
ball.classList.add('active');
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(()=> ball.classList.remove('active'), 100);
});
.ball {
height: 200px;
width: 200px;
border-radius: 100%;
background-color: orange;
transition: transform 0.3s ease;
position: fixed;
top: 50px;
left: 50px;
}
.ball.active {
transform: scale(1.5);
}
.container{
width: 100%;
background: red;
overflow: scroll;
height: 500px;
}
.inside_container{
position: relative;
width: 100%;
height: 2000px;
}
<div class="container">
<div class="inside_container">
<div class="ball"></div>
</div>
</div>
One of the approaches could be delaying the removal of .active class on ball by 200ms such that each time you try to scroll again, the timer is cleared and a new one starts to do the same. A debounce approach in a nutshell.
const ball = document.querySelector('.ball');
let scrollTimeout;
window.addEventListener('scroll', ()=> {
ball.classList.add('active');
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(()=> ball.classList.remove('active'),200);
});
.ball {
height: 200px;
width: 200px;
border-radius: 100%;
background-color: orange;
}
.ball.active {
transform: scale(1.5);
position: fixed;
}
body {
height: 150vh;
}
<div class="ball"></div>
Hello StackOverFlowers!
I found this really awesome animation on jsfiddle.net and would really love to use it in my project.
I'f you follow the link the author, 'internoma', states that it can be used as a page transition if a little Ajax is added.
My question is: What Ajax code do I add in order to make this work?!
I'm extremely lost, any suggestions will be greatly appreciated.
If you happen to know how to make this working using Barba.js or smoothState.js that would be awesome also since those are to plugins I'd like to dive deeper in learning.
Thanks in advance!
Link: Material Design Ripple Transition
JavaScript:
$(document).ready(function() {var ripple_wrap = $('.ripple-wrap'),
rippler = $('.ripple'),
finish = false,
monitor = function(el) {
var computed = window.getComputedStyle(el, null),
borderwidth = parseFloat(computed.getPropertyValue('border-left-width'));
if (!finish && borderwidth >= 1500) {
el.style.WebkitAnimationPlayState = "paused";
el.style.animationPlayState = "paused";
swapContent();
}
if (finish) {
el.style.WebkitAnimationPlayState = "running";
el.style.animationPlayState = "running";
return;
} else {
window.requestAnimationFrame(function() {monitor(el)});
}
};
storedcontent = $('#content-2').html();
$('#content-2').remove();
rippler.bind("webkitAnimationEnd oAnimationEnd msAnimationEnd
mozAnimationEnd animationend", function(e){
ripple_wrap.removeClass('goripple');
});
$('body').on('click', 'a', function(e) {
rippler.css('left', e.clientX + 'px');
rippler.css('top', e.clientY + 'px');
e.preventDefault();
finish = false;
ripple_wrap.addClass('goripple');
window.requestAnimationFrame(function() {monitor(rippler[0])});
});
function swapContent() {
var newcontent = $('#content-area').html();
$('#content-area').html(storedcontent);
storedcontent = newcontent;
// do some Ajax, put it in the DOM and then set this to true
setTimeout(function() {
finish = true;
},10);
}
});
CSS
.ripple-wrap {
display: none;
overflow: hidden;
position: fixed;
font-size: 0;
z-index: 1000;
top: 0; left: 0; right: 0; bottom: 0;
}
#-webkit-keyframes RIPPLER {
0% { border-width: 0; }
40% {
height: 0;
width: 0;
border-width: 1500px;
margin-top: -1500px;
margin-left:-1500px;
border-color: #009688;
}
41% {
height: 0;
width: 0;
border-width: 1500px;
margin-top: -1500px;
margin-left:-1500px;
border-color: #009688;
}
100% {
border-width: 1500px;
height: 2000px;
width: 2000px;
margin-top: -2500px;
margin-left:-2500px;
border-color: #009688;
}
}
#keyframes RIPPLER {
0% { border-width: 0; }
40% {
height: 0;
width: 0;
order-width: 1500px;
margin-top: -1500px;
margin-left:-1500px;
border-color: #009688;
}
41% {
height: 0;
width: 0;
border-width: 1500px;
margin-top: -1500px;
margin-left:-1500px;
border-color: #009688;
}
100% {
border-width: 1500px;
height: 2000px;
width: 2000px;
margin-top: -2500px;
margin-left:-2500px;
border-color: #009688;
}
}
.ripple {
display: block;
height: 0;
width: 0;
border-width: 0px;
border-style: solid;
border-color: #00796b;
border-radius: 100%;
position: absolute;
top: 300px;
left: 300px;
-webkit-animation: none;
animation: none;
}
.ripple-wrap.goripple {
display: block;
}
.ripple-wrap.goripple .ripple {
-webkit-animation-name: RIPPLER;
-webkit-animation-duration: 1.5s;
-webkit-animation-fill-mode: forwards;
animation-name: RIPPLER;
animation-duration: 1.5s;
animation-fill-mode: forwards;
}
HTML
<div class="wrap" id="content-area">
<h1>Material Design Ripple Transition</h1>
<p>Just playing around to see if I can recreate the Material Design
ripple as a page transition in CSS. Click any link in
this block of text to load another set of text. The links don't go anywhere yet. They are just hooks to allow you to click somewhere</p>
<p>The style and animation is entirely CSS so it is smooth. JavaScript
is used to add classes at the right time. It also pauses to wait for the
content to be replaced, and calculates where to centre the hole. There
are two stages to the animation. When a link is clicked
the border-width grows very large.</p>
<p>That's enough reading on this slide. Click a link to
load the second slide</p>
</div>
<div id="content-2" style="display:none">
<h2>Slide Two</h2>
<p>This is the second slide. If you want you can <a href="#">go back to
the first slide</a>. The second part of the animation is increasing the
size of the element itself in order to create a hole.</p>
<p>This transition could be used for presentation slides. Using
pushState then this could be used as a transition between webpages.</p>
</div>
<div class="ripple-wrap"><div class="ripple"></div></div>
I'm trying to switch images in a div every few seconds
the current code works, but there are 2 things that I want to change and I need your help for that:
The div resizes to the current image displaying in it, I want it to always use the size of the bigger image
I want to fade between the images instead of just switching
Thanks for reading, I hope you can help me.
This is what I got so far:
var imgIndex = 0;
setInterval(function() {
images[imgIndex].style.display = "none";
imgIndex++;
if (imgIndex >= images.length) {
imgIndex = 0;
}
images[imgIndex].style.display = "block";
}, 5000);
.imageDisplay {
display: inline-block;
width: 100%;
background-Color: white;
color: black;
border-radius: 5%;
margin: 2px;
padding: 1px;
opacity: 0.5;
transition-duration: 0.5s;
}
.imageDisplay:hover {
opacity: 1;
}
.Image {
width: 99%;
height: auto;
margin: 1px;
padding: 1px;
border-radius: 5%;
cursor: pointer;
display: none;
}
<div class="imageDisplay">
<p>Description</p>
<img class="Image"></img>
<img class="Image"></img>
</div>
Firstly you could set the div to be equal to the size of the large image and then use:
object-fit: cover;
object-position:center;
As for switching you could use:
transition: opacity .3s linear;
Read here on how to exactly implement the transitions. My suggestion would be stacking them all up and fading them in one by one every few seconds.
https://www.w3schools.com/css/css3_transitions.asp
http://css3.bradshawenterprises.com/cfimg/
I've created a jQuery function that scrolls a DIV by decreasing the left-margin of the element. It works, but it's incredibly slow. It eats up 100% CPU in no time :s
$(".scroll").hover(
function () {
var scroll_offset = parseInt($('#content').css('margin-left'));
sliderInt = self.setInterval(function(){
$content.css({'margin-left':scroll_offset+'px'});
scroll_offset--;
},8);
},
function () {
clearInterval(sliderInt);
}
);
Obviously I am running this function every 8ms, which is asking a lot. I'm already cacheing my selectors, so I don't know what I can do to improve performance. Am I just going about it the wrong way?
function play () {
$('#ball').animate({left: '+=20'}, 100, 'linear', play);
}
function pause () {
$('#ball').stop();
}
$("#bar").hover( play, pause );
#bar {
margin-top: 20px;
background: #444;
height: 20px;
}
#bar:hover #ball {
background: lightgreen;
}
#ball {
position: relative;
left: 0;
width: 20px;
height: 20px;
background: red;
border-radius: 50%;
}
<div id="bar">
<div id="ball"></div>
</div>
<script src="//code.jquery.com/jquery-3.1.0.js"></script>
This is really simple without the setInterval or even setTimeout.
The only important thing is to know that .animate() accepts a function callback, ideal for our purpose to create loop a function. Make sure to use the linear easing instead of the default 'swing' to make our loop constant.
To stop our animations we can use stop() to prevent animation buildups.
Simply create 2 functions and use them in your hover method.
Using CSS3
and toggling play/pause classes using jQuery:
function play() {
$('#ball').addClass("play").removeClass("pause");
}
function pause() {
$('#ball').addClass("pause"); // don't remove .play here
}
$("#bar").hover(play, pause);
#bar {
margin-top: 20px;
background: #444;
height: 20px;
}
#bar:hover #ball {
background: lightgreen;
}
#ball {
position: relative;
left: 0;
width: 20px;
height: 20px;
background: red;
border-radius: 50%;
}
.play {
animation: ball-anim 5s infinite linear;
}
.pause {
animation-play-state: paused;
}
#keyframes ball-anim {
0% { left: 0; }
50% { left: calc(100% - 20px); }
100% { left: 0; }
}
<div id="bar">
<div id="ball"></div>
</div>
<script src="//code.jquery.com/jquery-3.1.0.js"></script>
.animate() is a good way to do it. Example:
$(".scroll").hover(function(){
$("#content").animate({
marginLeft: "100px",
}, 1500 );
});
Working DEMO
Read the documentation to get the idea how to use it.