I want to show a pop up for three days, no more than three times a day. How could I achieve that?
HTML modal pop-up
<div id="popup1" class="modal fade" role="dialog" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content homeaz_popup">
<div class="modal-body">
<div class="banner_bg">
<a class="popup-banner" href="/landing.html">
<img class="banner_img" src="https://homeaz.vn/templates/themes/images/popupgheda.gif" alt="">
</a>
</div>
</div>
</div>
</div>
Here is a start, using js-cookie and JavaScript Date object.
jsFiddle link
Basically it:
gets client time
checks if first ever visit to the site
if first visit, it sets a final expiration datetime cookie 3 days from now
and also sets expired cookie to false
it not first visit, it checks if client time is greater than final expiration cookie time
if it is, it removes all cookies and sets expired cookie to true
if it's not, it checks for morning, afternoon and night cookies depending on the hour of the day
if it is the first visit at a particular part of the day, it will show a popup
and also change greeting text depending on time of day, eg:
Not very elegant or concise, but hopefully demonstrated well enough for you to make something.
When testing, if you want to view all cookies that have been set, you can use:
Cookies.get();
and to remove cookies, you can use:
Cookies.remove("cookie_name_here");
morning, afternoon and night are defined as:
0400 to 1200
1200 to 1700
1700 to 0400
but you can change them as you like.
javascript
// get current time of client
var client_time_now = new Date();
var client_time_now_hour = client_time_now.getHours();
console.log("client_time_now: " + client_time_now);
console.log("client_time_now_hour: " + client_time_now_hour);
// see if client has already visited the site
var final_expiry_date_time = Cookies.get("final_expiry_date_time");
// if first visit
if (final_expiry_date_time === undefined) {
console.log("this is your first visit");
// set the expiry date 3 days from now
// see: https://stackoverflow.com/a/56728401
var final_expiry_date_time_value = new Date(Date.now() + (3600 * 1000 * 72));
// to test expiry works, uncomment below
// var final_expiry_date_time_value = new Date();
console.log("final_expiry_date_time_value: " + final_expiry_date_time_value);
Cookies.set("final_expiry_date_time", final_expiry_date_time_value);
var expired = "false";
Cookies.set("expired", expired);
}
// if not first visit, check if 3 days has elapsed since first visit
else {
console.log("this is not your first visit");
// is current datetime greater than expiry datetime
// see: https://stackoverflow.com/a/493018
var expired = client_time_now.getTime() > new Date(Cookies.get("final_expiry_date_time")).getTime();
// for consistency, cookies are stored as strings
expired = expired.toString();
console.log("expired: " + expired);
// if expired, remove cookies and set expired to true
if (expired === "true") {
Cookies.set("expired", "true");
Cookies.remove("morning");
Cookies.remove("afternoon");
Cookies.remove("night");
} else {
Cookies.set("expired", "false");
}
}
if (expired === "false") {
// see if visits have been completed during these times
var already_visited_morning = Cookies.get("morning");
var already_visited_afternoon = Cookies.get("afternoon");
var already_visited_night = Cookies.get("night");
// morning handling - 4am to 12pm
if (client_time_now_hour > 3 && client_time_now_hour <= 11) {
var day_segment = "morning";
if (already_visited_morning === "true") {
console.log("you've already visited this morning");
} else {
Cookies.set("morning", "true");
// show your popup
$("#modal_bg").show();
// adjust greeting text depending on time of day
$("#greeting").text("good morning");
}
}
// afternoon handling - 12pm to 5pm
else if (client_time_now_hour > 11 && client_time_now_hour <= 16) {
var day_segment = "afternoon";
if (already_visited_afternoon === "true") {
console.log("you've already visited this afternoon");
} else {
Cookies.set("afternoon", "true");
// show your popup
$("#modal_bg").show();
// adjust greeting text depending on time of day
$("#greeting").text("good afternoon");
}
}
// night handling - 5pm to 4am
else if (client_time_now_hour > 16 && client_time_now_hour <= 23 || client_time_now_hour >= 0 && client_time_now_hour <= 3) {
var day_segment = "night";
if (already_visited_night === "true") {
console.log("you've already visited this night");
} else {
Cookies.set("night", "true");
// show your popup
$("#modal_bg").show();
// adjust greeting text depending on time of day
$("#greeting").text("good evening");
}
}
console.log("it's " + day_segment);
console.log("all cookies: ");
console.log(JSON.stringify(Cookies.get(), null, 4));
}
// hide the modal on clicking close button
$(document).on("click", ".close_button", function() {
$("#modal_bg").hide();
});
html
<div id="modal_bg">
<div class="modal_content">
<img src="http://lorempixel.com/400/200/abstract/">
<div id="greeting"></div>
<div class="close_button">X</div>
</div>
</div>
<p>
here is some content.
</p>
css
#modal_bg {
display: none;
background: rgba(0, 0, 0, 0.8);
height: 100%;
width: 100%;
position: absolute;
}
.modal_content {
margin-left: auto;
margin-right: auto;
margin-top: 50px;
width: 400px;
position: relative;
padding: 20px;
background: #fff;
}
.close_button {
background: #dcdcdc;
position: absolute;
top: 0px;
right: 0px;
padding: 10px 20px;
font-family: arial;
font-weight: bold;
}
.close_button:hover {
cursor: pointer;
}
#greeting {
background: #fff;
position: absolute;
bottom: 40px;
padding: 2px 10px;
font-family: arial;
margin-left: 10px;
right: 40px;
}
Related
I have an open and closed indicator (Thanks to those who helped me!) that shows I am open from 8:00 AM to 10:00 PM and from 10:00 PM to 8:00 AM I am closed, but it shows this even on a weekend when I am not open. Can you help me make the Javascript say I am closed when it is a weekend and on a holiday like December 24-25? Below will be my current code. Thanks!
Javascript:
var messageElement = document.getElementById("message");
var circleElement = document.getElementById("circle");
const refreshStatus = () => {
// Set the current time
let currentDate = new Date().getHours();
// If the time is between 8 am and 10 pm
if (currentDate >= 8 && currentDate <= 21) {
// Update text and add classes
messageElement.innerHTML = "We are open until 10 PM";
circleElement.className = 'open-circle';
messageElement.className = 'open-p';
} else {
// 21 pm to 8 am
messageElement.innerHTML = "We are closed until 8 AM";
circleElement.className = 'closed-circle';
messageElement.className = 'closed-p';
}
}
// run when starting
refreshStatus();
// updates every 8 seconds
setInterval(refreshStatus, 8000);
CSS:
/* Start indicator CSS */
.open-circle {
position: relative;
top: 23rem;
height: 1.5625rem;
width: 1.5625rem;
background-color: #00BF13;
border-radius: 50%;
display: inline-block;
}
.open-p {
position: relative;
top: 23rem;
color: #00BF13;
font-weight: bold;
display: inline-block;
width: 8rem;
}
.closed-circle {
position: relative;
top: 23rem;
height: 1.5625rem;
width: 1.5625rem;
background-color: #ea001d;
border-radius: 50%;
display: inline-block;
}
.closed-p {
position: relative;
top: 23rem;
color: #ea001d;
font-weight: bold;
display: inline-block;
width: 8rem;
}
/* End indicator CSS */
HTML:
<!-- Start status indicator -->
<div id="circle"></div>
<p id="message">We are open until 10 PM</p>
<script src="js/open-closed-indicator.js"></script>
<!-- End status indicator -->
You can achieve this using getDate() method for the Christmas period and use getDay() to check if it's a weekend.
Days in JS are 0 = sunday and 6 = Saturday. Refer to the comments in each line for more info.
For Christmas period dates you need to check whether it's the 11 months which is December and the date is 24 or 25th December.
To show different closed messages I am using JS ternary operator which helps to write less code and get the same results.
Live working demo.
var messageElement = document.getElementById("message");
var circleElement = document.getElementById("circle");
const refreshStatus = () => {
// Get dates/time/hours
let today = new Date(); //today date
let currentTime = today.getHours(); //get hours
let areWeekends = (today.getDay() == 6 || today.getDay() == 0) //get weekends
let santaDays = (today.getMonth() == 11 && (today.getDate() == 24 || today.getDate() == 25)) //get christmas dates
//Show available if this matches
if (currentTime >= 8 && currentTime <= 21 && !areWeekends && !santaDays) {
// Update text and add classes
messageElement.innerHTML = "We are open until 10 PM";
circleElement.className = 'open-circle';
messageElement.className = 'open-p';
} else {
//change text based on weekend / christmas or not - Using ternary operator Javascript
messageElement.innerHTML = `We are closed ${areWeekends ? ' - weekend' : santaDays ? 'Christmas' : 'until 8am'}`;
circleElement.className = 'closed-circle';
messageElement.className = 'closed-p';
}
}
// run when starting
refreshStatus();
// updates every 8 seconds
setInterval(refreshStatus, 8000);
/* Start indicator CSS */
.open-circle {
position: relative;
top: 23rem;
height: 1.5625rem;
width: 1.5625rem;
background-color: #00BF13;
border-radius: 50%;
display: inline-block;
}
.open-p {
position: relative;
top: 23rem;
color: #00BF13;
font-weight: bold;
display: inline-block;
width: 8rem;
}
.closed-circle {
position: relative;
top: 23rem;
height: 1.5625rem;
width: 1.5625rem;
background-color: #ea001d;
border-radius: 50%;
display: inline-block;
}
.closed-p {
position: relative;
top: 23rem;
color: #ea001d;
font-weight: bold;
display: inline-block;
width: 8rem;
}
/* End indicator CSS */
<!-- Start status indicator -->
<div id="circle"></div>
<p id="message">We are open until 10 PM</p>
<!-- //<script src="js/open-closed-indicator.js"></script>
-->
<!-- End status indicator -->
try this
// set your holidays
const holidays = [
{'2022-12-25' : 'christmas'},
{'2022-01-29' : 'testHoliday'},
]
const refreshStatus = () => {
// added code
let date = new Date();
let dayOfWeek = date.getDay(); // 6: saturday, 0: sunday
let today = date.getFullYear() + '-' + String(date.getMonth()+1).padStart(2, '0') + '-' + date.getDate(); // 2022-01-29
let isHoliday = holidays.filter(h => h[today]).length > 0 || dayOfWeek == 6 || dayOfWeek == 9;
//
// Set the current time
let currentDate = date.getHours();
// If the time is between 8 am and 10 pm
if (currentDate >= 8 && currentDate <= 21 && !isHoliday) {
// Update text and add classes
messageElement.innerHTML = "We are open until 10 PM";
circleElement.className = "open-circle";
messageElement.className = "open-p";
} else {
// 21 pm to 8 am
messageElement.innerHTML = "We are closed until 8 AM";
circleElement.className = "closed-circle";
messageElement.className = "closed-p";
}
};
I want to add a timer to the page where it starts on page load.
Where it goes up in milliseconds.
Then stops when the mouse is clicked on the button.
How would I create a code example of that?
That is all I am trying to do in the code.
Add a timer that starts on page load.
Goes up in milliseconds.
Then stops when the button is clicked.
I want to be able to see the numbers going up.
https://jsfiddle.net/xvkwmndq/
// Counter
var enterDate = new Date();
function secondsSinceEnter()
{
return (new Date() - enterDate) / 1000;
}
// Usage example
document.querySelector('button').onclick = function() {
var sec = secondsSinceEnter();
if (sec < 10)
this.innerText = sec + " seconds";
else
this.innerText = 'You are here like for eternity';
};
.play {
-webkit-appearance: none;
appearance: none;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
width: 90px;
height: 90px;
border-radius: 50%;
cursor: pointer;
border: 9px solid blue;
background: transparent;
filter: drop-shadow(3px 3px 3px #000000b3);
}
<button class="play" type="button" aria-label="Open"></button>
Related to the jsfiddle in your comment:
Don't use this to access the button. Instead, just use document.querySelector:
document.querySelector('button').onclick = function() {
var sec = secondsSinceEnter();
if (sec < 10)
document.querySelector('button').innerText = sec + " seconds";
else
document.querySelector('button').innerText = 'You are here like for eternity';
}
Then, you're just adding the time when the button is clicked. Additionally, you should call it every 0ms (every 'tick') using setInterval. So that you don't have to write the function twice, you could define it as a seperate function. Finally, remove the interval when the button is clicked.
Full script:
// Interval
var interval;
// Counter
var enterDate = new Date();
function secondsSinceEnter()
{
return (new Date() - enterDate) / 1000;
}
// Event function
function evtFct()
{
var sec = secondsSinceEnter().toFixed(3);
if (sec < 10)
document.querySelector('button').innerText = sec + " seconds";
else
document.querySelector('button').innerText = 'You are here like for eternity';
}
// Add interval to keep the current time uptodate
interval = setInterval(evtFct, 0); // Call evtFct every tick
// Usage example
document.querySelector('button').onclick = function()
{
evtFct();
clearInterval(interval); // Disable interval
}
I want to change background image during particular part of day using JavaScript. So, i want from 6:00 to 20:00 daytime pic and from 20-06 night time pic. I am learning JS last couple of months so i m quite new to this.I created clock also.
I tried last days by Google it, still nothing, no solution. Please help.
My html :
<div class="banner">
<div class="image-day" id="img-day"></div>
<div class="image-night" id="img-night"></div>
</div>
CSS:
.banner {
min-height: 100vh;
position: relative;
display: grid;
place-items: center;
text-align: center;
}
.image-day {
position: absolute;
background: url(../images/bluesky.jpg)no-repeat center center/cover;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.image-night {
position: absolute;
background: url(../images/nightime.jpg)no-repeat center center/cover;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
JS clock :
setInterval(displayClock, 500)
function displayClock() {
var time = new Date();
var hrs = time.getHours();
var min = time.getMinutes();
var sec = time.getSeconds();
if (hrs > 12) {
hrs = hrs + 0;
}
if (hrs == 0) {
hrs = 12;
}
if(hrs < 10) {
hrs = '0' + hrs;
}
if (min < 10) {
min = '0' + min;
}
if (sec < 10) {
sec = '0' + sec;
}
document.getElementById('clock').innerHTML = hrs + ':' + min + ':' + sec;
}
You can change css properties of a dom element by using the style property like :
<DOM element>.style.<css property> = <value>
In your case to change the background image you may use something like this :
document.querySelector(".banner").style.backgroundImage="url('../images/nightime.jpg')"
Since the display clock method is already running every 5 seconds you may add the following to check if hour is greater than 6 and less than 20
if(time.getHours()>=6&&time.getHours()<20)
{
document.querySelector(".banner").style.backgroundImage="url('../images/bluesky.jpg')";
}else{
document.querySelector(".banner").style.backgroundImage="url('../images/nightime.jpg')"
}
Find a demo in this bin : demo . Open the demo and try changing your system time
I have run into a little issue with a timer clock I was building. All went well but in short this is what it does:
user gets to set the time he/she wants to study or do any activity for
user presses start
the start button changes to a "stop" button
the timer counts down from the time chosen by the user
once the timer hits 0 the clock with stop and button changes back to "start" and everything is reset to 0:00
Note
Once the user taps the start button or the start button the device will vibrate if capable to notify the user.
The Issue
The problem I have is that when the clock is running and the user presses the "Stop Study" button, then the clock stops, yes thats good but when he/she presses the button again (which now should be a "start" button because its essentially paused), then the clock takes the time that was given and starts the clock over from that time the user gave and not continue until 0:00.
I have check out a few articles and I have used variables and switched between the Boolean state and checked if the clock is running or not.
isRunning = !isRunning
I have seen a few say that I should use:
clearInterval(name);
This doesn't work because I dont want to clear the state of the clock or maybe I am doing it wrong.
Code
The link to a fiddle can be found here: https://jsfiddle.net/ToreanJoel/c75vLf8b/
HTML
<br/>
<div class="timer" id="startingTimer">
<p class="title" id="state">Break</p>
<p id="time">00:00</p><span ng-style="{'height':fillHeight, 'background':fillColor }" class="fill" style="height: 0.933333%; background: rgb(153, 204, 0);"></span>
</div>
<br/>
<div class="session" id="toggleSessionStart">
<div class="timer control startingTimercontroller" id="startingTimercontroller">
<p class="title controlTitle" id="StartTimer">Start Study</p>
</div>
<!--<div class="timer control startingPauseTimercontroller" id="startingPauseTimercontroller">
<p class="title controlTitle" id="StartPauseTimer">Start Break</p>
</div>--></div>
<br/>
<header>
<div class="session">
<div class="sessionCtrl">
<p>session length</p>
<input type="number" class="time" id="valueTimerSession" value="10">
</div>
<!--<div class="breakCtrl">
<p>break length</p>
<input type="number" class="time" id="valueTimerBreak" value="5">
</div>--></div>
</header>
CSS
body {
background: #333333;
color: #fff;
}
#time {
font-size: 90px;
position: relative;
top: -40px;
}
#media (max-width: 500px) {
#time {
font-size: 90px;
position: relative;
top: -80px;
}
}
.plus {
background-color: #333333;
color: #fff;
border: none;
cursor: pointer;
font-size: 2em;
outline: none;
}
.time {
font-size: 2.5em;
padding-left: 10px;
padding-right: 10px;
width: 100%;
}
.minus {
background-color: #333333;
color: #fff;
border: none;
cursor: pointer;
font-size: 2em;
outline: none;
}
header {
display: flex;
justify-content: center;
text-align: center;
margin: 0 auto;
color: #fff;
text-transform: uppercase;
padding: 20px;
}
.session .breakCtrl, .session .sessionCtrl {
display: inline;
padding-left: 30px;
padding-right: 30px;
}
.session {
font-size: .8em;
display: flex;
}
.timer {
margin: 0 auto;
text-align: center;
width: 300px;
height: 300px;
font-size: 4em;
border: 2px solid #99CC00;
border-radius: 50%;
cursor: pointer;
position: relative;
z-index: 20;
overflow: hidden;
}
.control {
margin: 0 auto;
text-align: center;
width: 120px;
height: 120px;
font-size: 4em;
border: 2px solid #99CC00;
border-radius: 50%;
cursor: pointer;
position: relative;
z-index: 20;
overflow: hidden;
font-family: sans-serif;
}
.startingTimercontroller {
background: #37B703 !important;
border: 2px solid #fff;
}
.startingPauseTimercontroller {
background: #B70000 !important;
border: 2px solid #fff;
}
.title {
margin: 45px;
margin-bottom: -30px;
}
.controlTitle {
font-size: 28px;
position: relative;
top: 25px;
margin: 0;
}
.heading {
text-align: center;
font-size: 50px;
text-transform: uppercase;
font-family: sans-serif;
}
JS
//event Listener
var clickStart = document.getElementById("toggleSessionStart");
//pauseing the clock
var clockRunning = false;
var clicked = false;
//getting the user value ammount to study and break for
var valueTimerSession = parseInt(document.getElementById('valueTimerSession').value);
function pomodoro(studyTime) {
this.studyTime = studyTime;
this.seconds = 59;
this.timerDOM = document.getElementById("time");
this.state = document.getElementById("state");
this.toggleSessionStart = document.getElementById('toggleSessionStart');
}
pomodoro.prototype.startStudyTicker = function () {
var thisStudyTicker = this;
var seconds = this.seconds - 1;
var DOM = this.timerDOM;
var minutes = this.studyTime - 1;
var loopingSeconds = seconds;
var state = this.state;
var toggleSessionStart = this.toggleSessionStart;
if (clicked && clockRunning) {
console.log('We are runnung');
window.ticker = setInterval(function () {
//save the minutes to global variable
window.minSaved = minutes;
window.secSaved = loopingSeconds;
console.log("The time saved is " + window.minSaved + ":" + window.secSaved);
console.log(minutes + ":" + loopingSeconds);
var tick = loopingSeconds--;
if (loopingSeconds >= 0) {
tick;
DOM.innerHTML = minutes.toString() + ":" + (loopingSeconds < 10 ? '0' + loopingSeconds.toString() : loopingSeconds.toString());
} else {
if (minutes > 0) {
minutes--;
loopingSeconds = seconds;
tick;
DOM.innerHTML = minutes.toString() + ":" + (loopingSeconds < 10 ? '0' + loopingSeconds.toString() : loopingSeconds.toString());
}
if (minutes <= 0) {
//vibrate - Timer is Done
window.navigator.vibrate(300);
console.log('im finished');
clearInterval(ticker);
}
}
}, 1000);
} else {
if (!clicked && !clockRunning) {
clearInterval(ticker);
}
}
}
pomodoro.prototype.stopStudyTicker = function () {
var thisStudyTickerStop = this;
console.log('We are paused');
clearInterval(ticker);
thisStudyTickerStop.startStudyTicker();
}
//get the session title
var sessionTitle = document.getElementById('state');
//the DOM toggle
function toggleDOM(chosenTime) {
if (clicked && clockRunning) {
//started the session - the Title
sessionTitle.innerHTML = "Session";
clickStart.innerHTML =
'<div class="timer control startingPauseTimercontroller" id="startingPauseTimercontroller"><p class="title controlTitle" id="StartTimer">Stop Study</p></div>';
//vibrate
window.navigator.vibrate(300);
//prototype execution
var startStudy = new pomodoro(chosenTime);
startStudy.startStudyTicker();
} else {
sessionTitle.innerHTML = "Break";
clickStart.innerHTML =
'<div class="timer control startingTimercontroller" id="startingTimercontroller"><p class="title controlTitle" id="StartTimer">Start Study</p></div>';
//vibrate
window.navigator.vibrate([100, 100, 100]);
//prototype execution
var stopStudy = new pomodoro();
stopStudy.stopStudyTicker();
}
}
clickStart.addEventListener('click', function () {
//user clicked and the clock starts
clicked = !clicked;
clockRunning = !clockRunning;
//valueTimerBreak = parseInt(document.getElementById('valueTimerBreak').value);
valueTimerSession = parseInt(document.getElementById('valueTimerSession').value);
//the Toggle
toggleDOM(valueTimerSession);
});
I was looking at a few things on stack overflow but nothing really seemed to help as im not trying to use multiple buttons to pause or play but use one that toggles its states and the markup and the layout can be seen on jsFiddle (https://jsfiddle.net/ToreanJoel/c75vLf8b/).
I'm using Prototypal Pattern and I'm not use to it yet but I will be going over everything again just to refactor the code anyway to get use to it.
Thanks in advance
I didn't really understood your code but I made my own, basically if you click on a button and the seconds aren't stored in a variable - store them, else just continue looping. I think you'll understand my code, just replace your javascript with my.
var clickStart = document.getElementById("toggleSessionStart");
var pomodoro = function() {
this.inProgress = false;
this.studyTime = null;
this.timerInstance = null;
this.timerDOM = document.getElementById("time");
this.stateElement = document.getElementById("state");
this.toggleSessionStart = document.getElementById('toggleSessionStart');
}
pomodoro.prototype = {
start: function() {
var parent = this;
if(this.studyTime === null) this.studyTime = parseInt(document.getElementById('valueTimerSession').value, 10) * 60;
this.timerInstance = setInterval(function() {
parent.studyTime--;
if(parent.studyTime < 1) parent.destroy();
else parent.updateTime();
}, 1000);
return this;
},
pause: function() {
clearInterval(this.timerInstance);
this.timerInstance = null;
return this;
},
destroy: function() {
this.pause();
this.studyTime = null;
this.toogleState(false);
this.timerDOM.innerHTML = '00:00';
return this;
},
updateTime: function() {
var totalSec = this.studyTime,
minutes = Math.floor(totalSec / 60),
seconds = totalSec % 60;
this.timerDOM.innerHTML = (minutes < 10 ? "0" + minutes : minutes) + ":" + (seconds < 10 ? "0" + seconds : seconds);
return this;
},
toogleState: function(state) {
this.inProgress = (typeof state !== 'undefined') ? state : !this.inProgress;
if(this.inProgress) {
this.stateElement.innerHTML = "Session";
clickStart.innerHTML = '<div class="timer control startingPauseTimercontroller" id="startingPauseTimercontroller"><p class="title controlTitle" id="StartTimer">Stop Study</p></div>';
this.start();
}
else {
this.stateElement.innerHTML = "Break";
clickStart.innerHTML = '<div class="timer control startingTimercontroller" id="startingTimercontroller"><p class="title controlTitle" id="StartTimer">Start Study</p></div>';
this.pause();
}
window.navigator.vibrate(300);
return this;
}
};
var pomodoroInstance = new pomodoro();
clickStart.addEventListener('click', function () {
pomodoroInstance.toogleState();
});
BTW. there is one problem, you can't stop the timer manually so if user wants to set different time he will have to reload the page. You can add a little button which will trigger destroy() method.
I'd rather implement the logic for the clock in a separate class, after all a clock doesn't need anything but a time, our api will consist on methods to start/stop/pause the timer
The gui then creates a clock instance, whenever you click the start/stop button we just need to call the magic clock methods that control the timer, note that the clock doesn't have a method to render itself, it'd be better to have another class like ClockGUI that has an inner instance of Clock, this new class would just call methods of the Clock instance to update the timer and also update the gui
function Clock (time) {
this.timeLeft = time
this.paused = false
}
Clock.prototype.start = function () {
this.raf = requestAnimationFrame(
this._loop.bind(this)
)
}
Clock.prototype.stop = function () {
cancelRequestAnimationFrame(this.raf)
}
Clock.prototype.togglePause = function () {
this.paused = !this.paused
}
Clock.prototype._update = function (t) {
if (!this.paused) {
this.timeLeft -= t
if (this.timeLeft <= 0) {
this.stop()
}
}
}
Clock.prototype._loop = function () {
this.raf = requestAnimationFrame(this._loop.bind(this))
var now = Date.now()
var delta = now - (this.prev || now)
this._update(delta)
this.prev = now
}
// game
var timeLeft = document.querySelector('#time-left')
var input = document.querySelector('input')
var button = document.querySelector('button')
var started = false
var clock
button.addEventListener('click', function () {
button.innerText = button.innerText === 'start' ? 'pause' : 'start'
if (!started) {
started = true
clock = new Clock(input.value * 1000 * 60)
clock.start()
input.disabled = true
return
}
// toggle the state of the clock
clock.togglePause()
})
function render () {
requestAnimationFrame(render)
// render only if a clock was created
if (clock) {
var time = Math.floor(clock.timeLeft / 1000)
var minutes = Math.floor(time / 60)
var seconds = time % 60
var ms = clock.timeLeft % 1000
timeLeft.innerHTML = minutes + ':' + seconds + ':' + ms
}
}
requestAnimationFrame(render)
<div>
Time left: <span id="time-left"></span>
</div>
<button> start </button>
<input type="number" value="10">
As you've seen the clock is not controlled by setInterval but by requestAnimationFrame, the problem of having a fixed 1000 ms interval is the pause behavior you want:
pause: just call clearInterval
start: compute how much time is left that isn't part of a second e.g. timeLeft % 1000, set a timeout on that much time left and then call set interval again
You could use setInterval with a small frequency like 10ms, however it's not guaranteed that the function will be called with exactly 10ms but as close as 10ms therefore you still need to compute the time elapsed between two calls of the setInterval function, in the example above this is done on Clock.prototype._loop
In FullCalendar JQuery plugin, when I set calEvent.allDay = false; in eventReceive function and switch to agendaDay view, if I try to move events around they disappear. If I remove the setting to all Day completely, then when I go to agendaDay View the events are placed in the allDay event section. I can move them wherever I want then, without a problem, but I wanted to set the times internally before I switched to agendaDay view. Anyone know a way around this? Not sure how to do code here (I am a newbie), so will include it here:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<link href='fullcalendar.css' rel='stylesheet' />
<link href='fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='lib/moment.min.js'></script>
<script src='lib/jquery.min.js'></script>
<script src='lib/jquery-ui.custom.min.js'></script>
<script src='fullcalendar.min.js'></script>
<script>
$(document).ready(function() {
var screenLimit = 12;
var scenes = ["FADE IN",
"LATER THAT DAY",
"THE NEXT DAY",
"TWO OR THREE DAYS LATER",
"THE NEXT DAY",
"LATER THAT DAY",
"TWO OR THREE DAYS LATER",
"ONE OR TWO DAYS LATER",
"THE NEXT DAY",
"LATER THAT DAY",
"ONE OR TWO DAYS LATER",
"TWO OR THREE DAYS LATER"];
var fakeresponse = '["FADE IN","LATER THAT DAY","THE NEXT DAY","TWO OR THREE DAYS LATER","THE NEXT DAY","LATER THAT DAY","TWO OR THREE DAYS LATER","ONE OR TWO DAYS LATER","THE NEXT DAY","LATER THAT DAY","ONE OR TWO DAYS LATER","TWO OR THREE DAYS LATER"]';
var obj = JSON.parse(fakeresponse);
if (obj == null) {
var listlength = scenes.length;
if (listlength < screenLimit) {
for(i=0;i<listlength;i++) {
var lstid = "Sc" + (i+1);
document.getElementById(lstid).innerHTML = scenes[i];
}
for(i=listlength;i<screenLimit;i++) {
var lstid1 = "Sc" + (i+1);
document.getElementById(lstid1).style.display = "none";
}
} else {
for(i=0;i<scenes.length;i++) {
if (screenLimit > i) {
var lstid = "Sc"+(i+1);
document.getElementById(lstid).innerHTML = scenes[i];
}
}
}
} else {
var listlength = obj.length;
if (listlength < screenLimit) {
for(i=0;i<listlength;i++) {
var lstid = "Sc" + (i+1);
document.getElementById(lstid).innerHTML = obj[i];
}
for(i=listlength;i<screenLimit;i++) {
var lstid1 = "Sc" + (i+1);
document.getElementById(lstid1).style.display = "none";
}
} else {
for(i=0;i<obj.length;i++) {
if (screenLimit > i) {
var lstid = "Sc"+(i+1);
document.getElementById(lstid).innerHTML = obj[i];
}
}
}
}
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events .fc-event').each(function() {
// store data so the calendar knows to render an event upon drop
$(this).data('event', {
title: $.trim($(this).text()), // use the element's text as the event title
stick: true // maintain when user navigates (see docs on the renderEvent method)
});
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
var currDate;
$('#calendar').fullCalendar({
header: {
left: 'prevYear,prev',
center: 'title',
right: 'next,nextYear agendaDay month'
},
buttonText: {
agendaDay: 'Action Scheduler',
month: 'Scene Scheduler'
},
editable: true,
fixedWeekCount: false,
slotDuration: '00:05:00',
defaultTimedEventDuration: '00:15:00',
scrollTime: '09:00:00',
droppable: true, // this allows things to be dropped onto the calendar
drop: function() {
$(this).remove();
},
eventReceive: function(calEvent) {
currDate = $.fullCalendar.moment(calEvent.start.format()); // Create a clone of the dropped date
// calEvent.allDay = false;
// calEvent.overlap = false;
var sdate = $.fullCalendar.moment(calEvent.start.format()); // Create a clone of the dropped date
sdate.stripTime(); // The time should already be stripped but lets do a sanity check.
sdate.time('09:00:00'); // Set a default start time.
calEvent.start = sdate;
var edate = $.fullCalendar.moment(calEvent.start.format()); // Create a clone of the dropped date
edate.stripTime(); // The time should already be stripped but lets do a sanity check.
edate.time('09:30:00'); // Set a default start time.
calEvent.end = edate;
$('#calendar').fullCalendar('clientEvents', function(event) {
if (calEvent.start.format() == event.start.format() && calEvent.title != event.title) {
calEvent.start = edate;
var nedate = $.fullCalendar.moment(calEvent.start.format()); // Create a clone of dropped date
nedate.stripTime(); // The time should already be stripped but lets do a sanity check.
nedate.time('10:00:00'); // Set a default start time.
calEvent.end = nedate;
}
});
$('#calendar').fullCalendar('rerenderEvents' );
},
viewRender: function(view,element) {
if (view.name == "agendaDay") {
$('#calendar').fullCalendar('gotoDate', currDate);
}
}
});
});
</script>
<style>
body {
margin-top: 20px;
text-align: center;
font-size: 14px;
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
}
#wrap {
width: 950px;
margin: 0 auto;
}
#external-events {
float: left;
width: 150px;
padding: 0 10px;
border: 1px solid #ccc;
background: #eee;
text-align: left;
}
#external-events h4 {
font-size: 18px;
margin-top: 0;
padding-top: 1em;
}
#external-events h5 {
font-size: 16px;
margin-top: 0;
}
#external-events .fc-event {
margin: 10px 0;
cursor: pointer;
}
#external-events p {
margin: 1.5em 0;
font-size: 11px;
color: #666;
}
#external-events p input {
margin: 0;
vertical-align: middle;
}
#calendar {
float: right;
width: 700px;
}
</style>
</head>
<body>
<div id='wrap'>
<div id='external-events'>
<h4>Story Navigator</h4>
<h5>Byte Me!</h5>
<div class='fc-event' id='Sc1'>Sc 1 - FADE IN</div>
<div class='fc-event' id='Sc2'>Sc 2 - LATER THAT DAY</div>
<div class='fc-event' id='Sc3'>Sc 3 - THE NEXT DAY</div>
<div class='fc-event' id='Sc4'>Sc 4 - TWO OR THREE DAYS LATER</div>
<div class='fc-event' id='Sc5'>Sc 5 - THE NEXT DAY</div>
<div class='fc-event' id='Sc6'>Sc 6 - LATER THAT DAY</div>
<div class='fc-event' id='Sc7'>Sc 7 - TWO OR THREE DAYS LATER</div>
<div class='fc-event' id='Sc8'>Sc 8 - ONE OR TWO DAYS LATER</div>
<div class='fc-event' id='Sc9'>Sc 9 - THE NEXT DAY</div>
<div class='fc-event' id='Sc10'>Sc 10 - LATER THAT DAY</div>
<div class='fc-event' id='Sc11'>Sc 11 - ONE OR TWO DAYS LATER</div>
<div class='fc-event' id='Sc12'>Sc 12 - TWO OR THREE DAYS LATER</div>
</div>
<div id='calendar'></div>
<div style='clear:both'></div>
</div>
</body>
</html>
It seems that FullCalendar is not happy with me setting an end time for the events I drag and drop as I drop them. It works fine if I just set a start time and let defaultTimedEventDuration set the end for me. So code should be:
eventReceive: function(calEvent) {
calEvent.allDay = false;
currDate = $.fullCalendar.moment(calEvent.start.format()); // Create a clone of the dropped date
var sdate = $.fullCalendar.moment(calEvent.start.format()); // Create a clone of the dropped date
sdate.stripTime(); // The time should already be stripped but lets do a sanity check.
sdate.time('09:00:00'); // Set a default start time.
calEvent.start = sdate;
$('#calendar').fullCalendar('clientEvents', function(event) {
if (calEvent.start.format() == event.start.format() && calEvent.title != event.title) {
var edate = $.fullCalendar.moment(calEvent.start.format()); // Create a clone of the dropped date
edate.stripTime(); // The time should already be stripped but lets do a sanity check.
edate.time('09:05:00'); // Set a default start time.
calEvent.start = edate;
}
});
$('#calendar').fullCalendar('rerenderEvents' );
},
Thanks.