Countdown timer for reveal.js / html slides - javascript

I want to integrate a countdown timer on specific slides in my reveal.js deck.
To achieve this, I used code from this codepen example and integrated this into my slideshow. It works nicely for the first instance of the timer, but does not appear when I try to add the timer to a second slide.
// the js code for the timer (source: https://codepen.io/geoffgraham/pen/yLywVbW)
// Credit: Mateusz Rybczonec
const FULL_DASH_ARRAY = 283;
const WARNING_THRESHOLD = 10;
const ALERT_THRESHOLD = 5;
const COLOR_CODES = {
info: {
color: "green"
},
warning: {
color: "orange",
threshold: WARNING_THRESHOLD
},
alert: {
color: "red",
threshold: ALERT_THRESHOLD
}
};
const TIME_LIMIT = 20;
let timePassed = 0;
let timeLeft = TIME_LIMIT;
let timerInterval = null;
let remainingPathColor = COLOR_CODES.info.color;
document.getElementById("app").innerHTML = `
<div class="base-timer">
<svg class="base-timer__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g class="base-timer__circle">
<circle class="base-timer__path-elapsed" cx="50" cy="50" r="45"></circle>
<path
id="base-timer-path-remaining"
stroke-dasharray="283"
class="base-timer__path-remaining ${remainingPathColor}"
d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"
></path>
</g>
</svg>
<span id="base-timer-label" class="base-timer__label">${formatTime(
timeLeft
)}</span>
</div>
`;
startTimer();
function onTimesUp() {
clearInterval(timerInterval);
}
function startTimer() {
timerInterval = setInterval(() => {
timePassed = timePassed += 1;
timeLeft = TIME_LIMIT - timePassed;
document.getElementById("base-timer-label").innerHTML = formatTime(
timeLeft
);
setCircleDasharray();
setRemainingPathColor(timeLeft);
if (timeLeft === 0) {
onTimesUp();
}
}, 1000);
}
function formatTime(time) {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
if (seconds < 10) {
seconds = `0${seconds}`;
}
return `${minutes}:${seconds}`;
}
function setRemainingPathColor(timeLeft) {
const {
alert,
warning,
info
} = COLOR_CODES;
if (timeLeft <= alert.threshold) {
document
.getElementById("base-timer-path-remaining")
.classList.remove(warning.color);
document
.getElementById("base-timer-path-remaining")
.classList.add(alert.color);
} else if (timeLeft <= warning.threshold) {
document
.getElementById("base-timer-path-remaining")
.classList.remove(info.color);
document
.getElementById("base-timer-path-remaining")
.classList.add(warning.color);
}
}
function calculateTimeFraction() {
const rawTimeFraction = timeLeft / TIME_LIMIT;
return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction);
}
function setCircleDasharray() {
const circleDasharray = `${(
calculateTimeFraction() * FULL_DASH_ARRAY
).toFixed(0)} 283`;
document
.getElementById("base-timer-path-remaining")
.setAttribute("stroke-dasharray", circleDasharray);
}
// this code is to initialize the slideshow
Reveal.initialize({
hash: true,
});
/* all css is for the timer*/
body {
font-family: sans-serif;
display: grid;
height: 100vh;
place-items: center;
}
.base-timer {
position: relative;
width: 300px;
height: 300px;
}
.base-timer__svg {
transform: scaleX(-1);
}
.base-timer__circle {
fill: none;
stroke: none;
}
.base-timer__path-elapsed {
stroke-width: 7px;
stroke: grey;
}
.base-timer__path-remaining {
stroke-width: 7px;
stroke-linecap: round;
transform: rotate(90deg);
transform-origin: center;
transition: 1s linear all;
fill-rule: nonzero;
stroke: currentColor;
}
.base-timer__path-remaining.green {
color: rgb(65, 184, 131);
}
.base-timer__path-remaining.orange {
color: orange;
}
.base-timer__path-remaining.red {
color: red;
}
.base-timer__label {
position: absolute;
width: 300px;
height: 300px;
top: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.6.0/js/reveal.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.6.0/css/reveal.min.css" rel="stylesheet" />
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>reveal.js</title>
<link rel="stylesheet" href="plugin/highlight/monokai.css">
</head>
<body>
<div class="reveal">
<div class="slides">
<section>the timer appears here<br>
<div id="app"></div>
</section>
<section>but does not appear here<br>
<div id="app"></div>
</section>
</div>
</div>
</body>
</html>
I'm not very versed with Javascript.. can anybody tell me what I can do to get the second instance of the timer working?

The reveal-countdown plugin already provides this feature, no need to build it on your own! You can install it by downloading the repo and adding it to plugins/countdown or via npm

Related

svg path, that has property stroke-dashoffset and svg "fill" on page scroll in wordpress

I ve been trying to find how to achieve svg path, that has property stroke-dashoffset and svg "fill" on page scroll,its been done on this website: https://asaro.co.uk/
$(document).on('scroll', function(e){
var d = d || parseInt($('.c-line.c-line--fill-2').css('stroke-dashoffset'));
var lastScrollTop = 0;
st = $(this).scrollTop();
if(st < lastScrollTop) {
if( d <= 1800){
d += $(this).scrollTop() / 20;
}
}
else {
if( d >= 0){
d -= $(this).scrollTop() / 20;
}
}
lastScrollTop = st;
$('.c-line.c-line--fill-2').css('stroke-dashoffset', d );
});
body {
background: #000;
height:1000px;
}
.c-line-wrap {
position: absolute;
}
.c-line-wrap svg {
height: 100%;
width: 100%;
}
.c-line {
fill: none;
stroke-miterlimit: 10;
}
.c-line--fill-1 {
stroke: #404150;
}
.c-line--fill-2 {
stroke: #fff;
}
.c-line--dashed {
stroke: #131424;
stroke-dasharray: 5 5;
stroke-width: 4;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<div class="cont">
<svg viewBox="0 0 1327.78 2952.52" preserveAspectRatio="none">
<path class="c-line c-line--fill c-line--fill-1" d="M.11.49s415.15,96,291.15,576-132,896,340,1284,732,472,692,1092" vector-effect="non-scaling-stroke"></path>
<path class="c-line c-line--fill c-line--fill-2 js-line--fill" d="M.11.49s415.15,96,291.15,576-132,896,340,1284,732,472,692,1092" vector-effect="non-scaling-stroke" style="stroke-dashoffset: 1800; stroke-dasharray: 1879.02px, 1889.02px;"></path>
<path class="c-line c-line--dashed" d="M.11.49s415.15,96,291.15,576-132,896,340,1284,732,472,692,1092" vector-effect="non-scaling-stroke"></path>
</svg>
</div>
Something like this, but remember, this is AS IS and this is only to understand to question starter how it probably can work:
MAGIC FIDDLE

How to calculate remaining time in custom html5 audio player with JavaScript?

I found a good custom HTML5 audio player and successfully redesigned it for my needs. Everything about it is ok, except it didn't show "remaining" time (how much time actually left to track end).
I want to add a calculation of time left without changing the original script, Is it possible?
[
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60),
seconds_int = length - minutes * 60,
seconds_str = seconds_int.toString(),
seconds = seconds_str.substr(0, 2),
time = minutes + ':' + seconds
return time;
}
function calculateCurrentValue(currentTime) {
var current_hour = parseInt(currentTime / 3600) % 24,
current_minute = parseInt(currentTime / 60) % 60,
current_seconds_long = currentTime % 60,
current_seconds = current_seconds_long.toFixed(),
current_time = (current_minute < 10 ? "0" + current_minute : current_minute) + ":" + (current_seconds < 10 ? "0" + current_seconds : current_seconds);
return current_time;
}
CodePen (original player source code)
What you want is extremely easy, You don't have to change a lot of code but just need to add just two lines.
Inside the "initProgressBar()" function just add these two lines of code
//calculate the remaining time
var rem_time=length-current_time;
jQuery(".rem-time").html(calculateCurrentValue(rem_time));
//HTML to show the remaining time(add it to the HTML)
<small style="float: left; position: relative; left: 15px;" class="rem-time"></small>
the first line is just getting the total seconds, "length" and "current_time" was already available in the code so I am just using them, nothing new.
In the second line, I am converting the remaining time to a readable format, again using an already available function "calculateCurrentValue()" and setting an HTML element with remaining time.
At last the HTML element in which the remaining time will be shown.
You can also take a look at this CodePen which I have done for a better understanding.
Adding Full code here to make sure it is available always
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60),
seconds_int = length - minutes * 60,
seconds_str = seconds_int.toString(),
seconds = seconds_str.substr(0, 2),
time = minutes + ':' + seconds
return time;
}
function calculateCurrentValue(currentTime) {
var current_hour = parseInt(currentTime / 3600) % 24,
current_minute = parseInt(currentTime / 60) % 60,
current_seconds_long = currentTime % 60,
current_seconds = current_seconds_long.toFixed(),
current_time = (current_minute < 10 ? "0" + current_minute : current_minute) + ":" + (current_seconds < 10 ? "0" + current_seconds : current_seconds);
return current_time;
}
var prevcurrentime=0;
function initProgressBar() {
var player = document.getElementById('player');
var length = player.duration
var current_time = player.currentTime;
// calculate total length of value
var totalLength = calculateTotalValue(length)
jQuery(".end-time").html(totalLength);
// calculate current value time
var currentTime = calculateCurrentValue(current_time);
jQuery(".start-time").html(currentTime);
//checking if the current time is bigger than the previous or else there will be sync different between remaining and current
if(currentTime>prevcurrentime){
//calculate the remaining time
var rem_time=length-current_time;
jQuery(".rem-time").html(calculateCurrentValue(rem_time));
}
//setting the previouscurrent time to this current time
prevcurrentime=currentTime;
//progress bar calculation
var progressbar = document.getElementById('seekObj');
progressbar.value = (player.currentTime / player.duration);
progressbar.addEventListener("click", seek);
if (player.currentTime == player.duration) {
$('#play-btn').removeClass('pause');
}
function seek(evt) {
var percent = evt.offsetX / this.offsetWidth;
player.currentTime = percent * player.duration;
progressbar.value = percent / 100;
}
};
function initPlayers(num) {
// pass num in if there are multiple audio players e.g 'player' + i
for (var i = 0; i < num; i++) {
(function() {
// Variables
// ----------------------------------------------------------
// audio embed object
var playerContainer = document.getElementById('player-container'),
player = document.getElementById('player'),
isPlaying = false,
playBtn = document.getElementById('play-btn');
// Controls Listeners
// ----------------------------------------------------------
if (playBtn != null) {
playBtn.addEventListener('click', function() {
togglePlay()
});
}
// Controls & Sounds Methods
// ----------------------------------------------------------
function togglePlay() {
if (player.paused === false) {
player.pause();
isPlaying = false;
$('#play-btn').removeClass('pause');
} else {
player.play();
$('#play-btn').addClass('pause');
isPlaying = true;
}
}
}());
}
}
initPlayers(jQuery('#player-container').length);
html {
height: 100%;
display: table;
margin: auto;
}
body {
height: 100%;
display: table-cell;
vertical-align: middle;
background: yellow;
}
.audio-player {
background: white;
border: 1px solid #dfdfdf;
width: 50vw;
text-align: center;
display: flex;
flex-flow: row;
margin: 4rem 0 4rem 0;
}
.audio-player .album-image {
min-height: 100px;
width: 110px;
background-size: cover;
}
.audio-player .player-controls {
align-items: center;
justify-content: center;
margin-top: 2.5rem;
flex: 3;
}
.audio-player .player-controls progress {
width: 90%;
}
.audio-player .player-controls progress[value] {
-webkit-appearance: none;
appearance: none;
background-color: white;
color: blue;
height: 5px;
}
.audio-player .player-controls progress[value]::-webkit-progress-bar {
background-color: white;
border-radius: 2px;
border: 1px solid #dfdfdf;
color: blue;
}
.audio-player .player-controls progress::-webkit-progress-value {
background-color: blue;
}
.audio-player .player-controls p {
font-size: 1.6rem;
}
.audio-player #play-btn {
background-image: url("http://www.lukeduncan.me/images/play-button.png");
background-size: cover;
width: 75px;
height: 75px;
margin: 2rem 0 2rem 2rem;
}
.audio-player #play-btn.pause {
background-image: url("http://www.lukeduncan.me/images/pause-button.png");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="audio-player">
<div id="play-btn"></div>
<div class="audio-wrapper" id="player-container" href="javascript:;">
<audio id="player" ontimeupdate="initProgressBar()">
<source src="http://www.lukeduncan.me/oslo.mp3" type="audio/mp3">
</audio>
</div>
<div class="player-controls scrubber">
<p>Oslo <small>by</small> Holy Esque</p>
<span id="seekObjContainer">
<progress id="seekObj" value="0" max="1"></progress>
</span>
<br>
<small style="float: left; position: relative; left: 15px;" class="start-time"></small><br/>
<small style="float: left; position: relative; left: 15px;" class="rem-time"></small>
<small style="float: right; position: relative; right: 20px;" class="end-time"></small>
</div>
<div class="album-image" style="background-image: url('https://artwork-cdn.7static.com/static/img/sleeveart/00/051/614/0005161476_350.jpg')"></div>
</div>

why the button will only change the object properties after the input is manually changed?

Attached is full code of the application.
The problem is that the buttons of the session length section will only change the CLOCK.session properties and the #countdown span if the session length input is changed first. What is strange is that this code worked before I started to do CSS styling to the page, but no it doesn't (and there should't be any connection).
Thank you for the help!`
const canvas = document.querySelector('#timer-circle');
const context = canvas.getContext('2d');
const CLOCK = {
timerInit: function() {
context.beginPath();
context.strokeStyle = "#527A71";
context.lineWidth = 2;
context.arc(120, 120, 118, 0, 2 * Math.PI);
context.stroke();
},
drawStep: function() {
context.beginPath();
context.lineWidth = 4;
context.fillStyle = "#505000";
context.arc(120, 120, 115, Math.PI / 2 - Math.PI * CLOCK.whichSession().timeStep, Math.PI / 2 + Math.PI * CLOCK.whichSession().timeStep);
context.stroke();
context.fill();
document.querySelector('#countdown').innerText = Math.floor(CLOCK.whichSession().timeZero / 60).toString() + ':' + (CLOCK.whichSession().timeZero % 60).toString();
},
initCount: function(total) {
total *= 60
if(CLOCK.sessionSwitch) {
CLOCK.session.timeZero = total;
let localTimeZero = total;
CLOCK.session.timeStep = (total - localTimeZero) / total;
}
else if(!CLOCK.sessionSwitch) {
CLOCK.breakProp.timeZero = total;
let localTimeZero = total;
CLOCK.breakProp.timeStep = (total - localTimeZero) / total;
}
},
clockDisplay: function(total, zero) {
document.querySelector('#countdown').innerText = total.toString() + ':00';
},
timerReset: function() {
context.clearRect(0, 0, canvas.width, canvas.height);
//INITIALIZING FUNCTIONS AND BUTTONS
},
whichSession: function() {
return CLOCK.sessionSwitch ? CLOCK.session : CLOCK.breakProp;
},
timerCount: function() {
if(CLOCK.whichSession().timeStep <= 1) {
CLOCK.drawStep();
CLOCK.whichSession().timeZero--;
CLOCK.whichSession().timeStep = (60 * CLOCK.whichSession().timeTotal - CLOCK.whichSession().timeZero) / (60 * CLOCK.whichSession().timeTotal);
}
else if(CLOCK.whichSession().timeStep >= 1) {
if(CLOCK.sessionSwitch) {
// INITIALIZING BREAK COUNT
CLOCK.sessionSwitch = false;
document.querySelector('#label').innerText = 'Break!';
CLOCK.timerReset();
CLOCK.timerInit();
CLOCK.initCount(CLOCK.breakProp.timeTotal);
}
else if(!CLOCK.sessionSwitch) {
// INITIALIZING SESSION COUNT
CLOCK.sessionSwitch = true;
document.querySelector('#label').innerText = 'Session';
CLOCK.timerReset();
CLOCK.timerInit();
CLOCK.initCount(CLOCK.session.timeTotal);
}
//reset the circle
//switch the countdown to the correct time
CLOCK.drawStep();
CLOCK.whichSession().timeZero--;
CLOCK.whichSession().timeStep = (60 * CLOCK.whichSession().timeTotal - CLOCK.whichSession().timeZero) / (60 * CLOCK.whichSession().timeTotal);
}
},
timerSwitch: false,
sessionSwitch: true,
session: {
timeTotal: undefined,
timeZero: undefined,
timeStep: undefined
},
breakProp: {
timeTotal: undefined,
timeZero: undefined,
timeStep: undefined
},
timerInterval: undefined,
};
$(document).ready(function() {
CLOCK.timerInit()
CLOCK.clockDisplay(document.querySelector('#session-length input').value);
CLOCK.session.timeTotal = Number(document.querySelector('#session-length input').value)
CLOCK.breakProp.timeTotal = Number(document.querySelector('#break-length input').value)
$('button.increase').click(function() {
if($(this)['0'].nextElementSibling.value >= 1 && $(this)['0'].nextElementSibling.value < 99) {
if(this.parentNode.id == 'session-length') {
$(this)['0'].nextElementSibling.value++;
CLOCK.session.timeTotal++;
CLOCK.clockDisplay($(this)[0].nextElementSibling.value);
}
else if(this.parentNode.id = 'break-length') {
$(this)['0'].nextElementSibling.value++;
CLOCK.breakProp.timeTotal++;
}
}
});
$('button.decrease').click(function() {
if($(this)['0'].previousElementSibling.value > 1 && $(this)['0'].previousElementSibling.value <= 99) {
$(this)['0'].previousElementSibling.value--;
if(this.parentNode.id == 'session-length') {
CLOCK.session.timeTotal--;
CLOCK.clockDisplay($(this)[0].previousElementSibling.value);
}
else if(this.parentNode.id = 'break-length') {
CLOCK.breakProp.timeTotal--;
}
}
});
$('input').on('keyup', function() {
if(this.parentNode.id = 'session-length') {
CLOCK.session.timeTotal = Number(this.value);
CLOCK.clockDisplay(this.value);
}
else if(this.parentNode.id = 'break-length') {
CLOCK.breakProp.timeTotal = Number(this.value);
}
});
$('#timer-count').on('click', function() {
if(!CLOCK.timerSwitch) {
CLOCK.initCount(CLOCK.session.timeTotal);
CLOCK.timerInterval = setInterval(CLOCK.timerCount, 1000);
CLOCK.timerSwitch = true;
$('button, input').prop('disabled', true);
}
else if(CLOCK.timerSwitch) {
clearInterval(CLOCK.timerInterval);
CLOCK.timerSwitch = false;
CLOCK.sessionSwitch = true;
CLOCK.clockDisplay(CLOCK.session.timeTotal, )
CLOCK.timerReset();
CLOCK.timerInit();
$('button, input').prop('disabled', false);
}
});
});
body {
background: rgb(0, 0, 0);
background: -moz-linear-gradient(-45deg, rgba(0, 0, 0, 1) 0%, rgba(38, 36, 0, 1) 51%, rgba(81, 66, 0, 1) 100%);
background: -webkit-linear-gradient(-45deg, rgba(0, 0, 0, 1) 0%, rgba(38, 36, 0, 1) 51%, rgba(81, 66, 0, 1) 100%);
background: linear-gradient(135deg, rgba(0, 0, 0, 1) 0%, rgba(38, 36, 0, 1) 51%, rgba(81, 66, 0, 1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#514200', GradientType=1);
background-repeat: no-repeat;
background-attachment: fixed;
color: white;
}
#clock-container {
margin: 100px 20% 0 35%;
color: white;
}
input {
width: 65px;
background-color: transparent;
color: inherit;
border: solid 7px green;
border-radius: 20px;
text-align: center;
font-weight: 700;
font-size: 2em;
}
.input {
display: inline-block;
margin-right: 10%;
}
.clock-form {
display: flex;
padding: 0 5%;
}
.decrease {
margin-left: 0px;
}
#animation {
margin-top: 50px;
margin-left: 7%;
}
#timer-count {
position: absolute;
text-align: center;
width: 240px;
height: 240px;
z-index: 2;
padding: 80px 20px;
font-size: 25px;
font-weight: 600;
}
#timer-circle {
position: absolute;
z-index: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Alon's Pomodoro Clock</title>
<!-- =========JQUERY -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- ==============>BOOTSTRAP -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<!-- ============>FONT -->
<link href="https://fonts.googleapis.com/css?family=Gochi+Hand" rel="stylesheet">
<!-- ================>STYLESHEET -->
<link rel="stylesheet" href="stylesheet.css">
</head>
<body>
<div id="clock-container">
<h1>Alon's Pomodoro Clock</h1>
<div id="session-length" class="input">
<h3>Session Length</h3>
<div class="clock-form">
<button class="increase">+</button>
<input type="text" maxlength="2" value="25" />
<button class="decrease">-</button>
</div>
</div>
<div id="break-length" class="input">
<h3>Break Length</h3>
<div class="clock-form">
<button class="increase">+</button>
<input type="text" maxlength="2" value="5" />
<button class="decrease">-</button>
</div>
</div>
<div id="animation">
<canvas id="timer-circle" width="240" height="240">
</canvas>
<div id="timer-count">
<span id="label">Session</span>
<span id="countdown">01:00</span>
</div>
</div>
</div>
<script src="javascript.js"></script>
</body>
</html>
`
SOLVED!
problem was that I added a div with class .clock-form while editing the css, therefore $(this)['0'].parentNode.id refered to .clock-form instead of either session-input or break-input. though I still haven't figured out why the buttons worked after inserting a value to the inputs manually.

Disable multiple clicks that accumulate interval points

I am building a timer that has a pause and resume function. I found out the user can set multiple intervals when the timer is clicked more than once.
How can I prevent users from setting multiple intervals?
I tried inserting ($('.clock)).off("click") once the interval has set, but then couldn't figure out how to resume it. I thought I could do a statement pause = true, but not sure how I can use it in my code.
let currentMins = 10
let currentCount = 10*60
let pause = true
$(document).ready(function(){
// --- SET TIME --- //
$('select').on('change', function(){
const timePair = {
pappardelle : 7,
penne : 10,
farfalle : 11,
bucatini : 8,
angelhair : 4,
gnocchi : 1,
orecchiette : 10,
justboiledeggs : 11
}
const selected = this.value
for(let keys in timePair){
let toPrint = ''
if(selected.split(' ').join('').toLowerCase() == keys){
toPrint = timePair[keys]
$('#mins').html(toPrint)
$('.clock').html(toPrint+':00')
currentMins = toPrint
currentCount = timePair[keys]*60
console.log('current counts on set: ',currentCount)
}
}
})
// --- UPDATE CLOCK --- //
//basic increment and decrement setting
$('.decrement').click(function(){
if((currentMins)>1){
currentMins-=1
currentCount-=60
$('#mins').html(currentMins)
$('.clock').html(currentMins + ':00')
console.log("current mins and count in decrement :", currentMins, currentCount)
}
})
$('.increment').click(function(){
if(currentMins<100){
currentMins+=1
currentCount += 60
$('#mins').html(currentMins)
$('.clock').html(currentMins + ':00')
console.log("current mins and count in increment :", currentMins, currentCount)
}
})
$('.clock').click(function(){
console.log("current currentCount in the starting clock div :", currentCount)
//interval setting
const interval = window.setInterval(function(){
if(currentCount == 0){
pause=true
$('.clock').html('Buon appetito!')
} else {
console.log("current currentCount in the else clause in clock div :", currentCount)
pause = false
currentCount --
let minuites = Math.floor(currentCount / 60)
let seconds = currentCount - minuites * 60
$('.clock').html(minuites + ':' + ('0' + seconds).slice(-2))
}
$('.pause').click(function(){
pause = true;
clearInterval(interval)
})
}, 1000)
$('select').on('change', function(){
pause = true;
clearInterval(interval)
})
})
})//end jquery
You can do that with a flag variable:
let started = false
and a conditional return statement:
if (started && !pause) {
return;
} else {
started = true;
}
All it does is when the clock is clicked, it checks to see if started is true. If it is, then the timer has already been enabled, so it just returns out of the function (unless it's paused). If the value of started is false, then the timer begins and the flag variable is set to true.
See this working example:
let currentMins = 10
let currentCount = 10 * 60
let pause = true
let started = false
$(document).ready(function() {
// --- SET TIME --- //
$('select').on('change', function() {
const timePair = {
pappardelle: 7,
penne: 10,
farfalle: 11,
bucatini: 8,
angelhair: 4,
gnocchi: 1,
orecchiette: 10,
justboiledeggs: 11
}
const selected = this.value
for (let keys in timePair) {
let toPrint = ''
if (selected.split(' ').join('').toLowerCase() == keys) {
toPrint = timePair[keys]
$('#mins').html(toPrint)
$('.clock').html(toPrint + ':00')
currentMins = toPrint
currentCount = timePair[keys] * 60
console.log('current counts on set: ', currentCount)
}
}
if (selected.indexOf('Seamless') != -1) {
window.open('http://seamless.com', '_blank')
}
})
// --- UPDATE CLOCK --- //
//basic increment and decrement setting
$('.decrement').click(function() {
if ((currentMins) > 1) {
currentMins -= 1
currentCount -= 60
$('#mins').html(currentMins)
$('.clock').html(currentMins + ':00')
console.log("current mins and count in decrement :", currentMins, currentCount)
}
})
$('.increment').click(function() {
if (currentMins < 100) {
currentMins += 1
currentCount += 60
$('#mins').html(currentMins)
$('.clock').html(currentMins + ':00')
console.log("current mins and count in increment :", currentMins, currentCount)
}
})
$('.clock').click(function() {
if (started && !pause) {
return;
} else {
started = true;
}
console.log("current currentCount in the starting clock div :", currentCount)
//interval setting
const interval = window.setInterval(function() {
if (currentCount == 0) {
pause = true
$('.clock').html('Buon appetito!')
} else {
console.log("current currentCount in the else clause in clock div :", currentCount)
pause = false
currentCount--
let minuites = Math.floor(currentCount / 60)
let seconds = currentCount - minuites * 60
$('.clock').html(minuites + ':' + ('0' + seconds).slice(-2))
}
$('.pause').click(function() {
pause = true;
clearInterval(interval)
})
}, 1000)
$('select').on('change', function() {
pause = true;
clearInterval(interval)
})
})
}) //end jquery
body {
margin: 50px;
font-family: 'Cormorant Garamond', serif;
color: tomato;
}
main {
justify-content: center;
}
h1 {
font-size: 40px;
text-align: center;
}
.grid {
display: grid;
grid-gap: 10px;
grid-template-columns: [col1-start] 130px [col2-start] 130px [col3-start] 140px [col3-end];
grid-template-rows: [row1-start] 120px [row2-start] 120px [row2-end];
background-color: #fff;
color: tomato;
justify-content: center;
}
.box {
color: tomato;
padding: 30px;
font-size: 150%;
border: 1px solid tomato;
}
.food {
grid-column: col1-start / col3-start;
grid-row: row1-start;
}
.clock {
grid-column: col3-start;
grid-row: row1-start / row2-end;
display: flex;
justify-content: center;
align-items: center;
}
.clock:hover {
color: #ffd700;
font-size: 25px;
cursor: pointer;
}
.settimer {
grid-column: col1-start;
grid-row: row2-start;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
align-content: stretch;
}
.settimer div {
margin: 5px;
}
#mins {
align-items: center;
font-size: 20px;
}
.icon {
font-size: 15px;
}
.icon:hover {
color: #ffd700;
cursor: pointer;
font-size: 18px;
}
.pause {
grid-column: col2-start;
grid-row: row2-start;
font-size: 20px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
align-content: stretch;
}
.pause:hover {
color: #ffd700;
cursor: pointer;
}
<!DOCTYPE html>
<html>
<head>
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="pomodoro.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Cormorant+Garamond:400,700" rel="stylesheet">
<script src="pomodorooo.js"></script>
<title>Pomodoro Clock</title>
</head>
<body>
<main>
<h1>Pomodoro clock</h1>
<div class="grid">
<div class="box food">Set the timer for
<select id="pasta">
<option id="0">I meant, pasta</option>
<option id="1">Pappardelle</option>
<option id="2">Penne</option>
<option id="3">Farfalle</option>
<option id="4">Bucatini</option>
<option id="5">Angel Hair</option>
<option id="6">Gnocchi</option>
<option id="7">Orecchiette</option>
<option id="8">Just boiled eggs</option>
<option id="9">Take me to Seamless already</option>
</select>
<!-- deleted form -->
</div>
<!-- a click box that has various food options, default set for each food -->
<div class="box clock">Start</div>
<!-- a blank circle. will be filled red-->
<div class="box settimer">
<div class="decrement icon"><i class="fas fa-caret-left"></i></div>
<div id="mins">Ready</div>
<!-- deleted span -->
<div class="increment icon"><i class="fas fa-caret-right"></i></div>
</div>
<!-- timer set. increment and decrement enabled -->
<div class="box pause">Pause</div>
<!-- break set. increment and decrement enabled -->
</div>
</main>
<br /><br /><br /><br /><br /><br />
</body>
</html>

Draw a circle within svg countdown

I have made an example countdown using svg but i need a clock face which would be just a dark circle which is being filled with the colour of the countdown which i made.
Here is the code i got:
var time = 1800;
var initialOffset = '440';
var i = 1
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h3').text(secondsToTime(1800-i).m.toString()+" min " +secondsToTime(1800-i).s.toString()+" sek");
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
function secondsToTime(secs)
{
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
var obj = {
"m": minutes,
"s": seconds
};
return obj;
}
.item {
position: relative;
float: left;
}
.item h3 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item html">
<h3>0</h3>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="15" stroke="blue" fill="none"/>
</g>
</svg>
</div>
This is the result i am looking for (dark clock face) and countdown filling it out:
One of my tries to accomplish what i want was adding a new css class named "circle" but it does not seem to show up when i add it to <circle id="circle" class="circle circle_animation" r="69.85699" cy="81" cx="81" stroke-width="15" stroke="blue" fill="none"/>.
var time = 1800;
var initialOffset = '440';
var i = 1
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h3').text(secondsToTime(1800-i).m.toString()+" min " +secondsToTime(1800-i).s.toString()+" sek");
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
function secondsToTime(secs)
{
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
var obj = {
"m": minutes,
"s": seconds
};
return obj;
}
.item {
position: relative;
float: left;
}
.item h3 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle {
border: 15px solid #03002e;
height: 125px;
border-radius:50%;
width: 125px;
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item html">
<h3>30 min 00 sek</h3>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle circle_animation" r="69.85699" cy="81" cx="81" stroke-width="15" stroke="blue" fill="none"/>
</g>
</svg>
</div>
Just add another circle to your svg area before the current circle and make sure it doesn't have the same class the one you are animating. <circle id="circle" r="69.85699" cy="81" cx="81" stroke-width="15" stroke="#1F2837" fill="none"/>
You can see a demo on jsbin

Categories

Resources