Last active
October 3, 2017 15:10
-
-
Save steven-prybylynskyi/a2e92f2cb7183ade043061a97ad10372 to your computer and use it in GitHub Desktop.
moment.js - show recurring remaining time (requires jQuery and Lodash)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="//cdn.jsdelivr.net/lodash/4/lodash.min.js"></script> | |
<script src="//code.jquery.com/jquery-2.2.4.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> | |
<div | |
id="countdownTimer" | |
data-end-date="01-01-2020" | |
data-end-time="13:00:00" | |
data-days-of-week="[1,2,3,4,5]" | |
data-exclude-dates="['31-12', '1-01']" | |
> | |
<span class="days"></span> day(s) | |
<span class="hours"></span>h | |
<span class="minutes"></span>min | |
<span class="seconds"></span>sec | |
time remains till next shipping | |
</div> | |
<style> | |
#countdownTimer { | |
display: none; | |
} | |
</style> | |
<!-- Show how much days and time left till next shipping day every Monday excluding holidays --> | |
<script>$(function() { | |
var $clock = $('#countdownTimer'); | |
var endDate = $clock.data('endDate') || '01-01-2020'; // dd:mm:yyyy | |
var endTime = $clock.data('endTime') || '13:00:00'; // hh:mm:ss | |
var excludeDates = (new Function('return ' + $clock.data('excludeDates')))() || []; | |
var daysOfWeek = $clock.data('daysOfWeek') || [1, 2, 3, 4, 5, 6, 7]; | |
showRemaining($clock, 'DD-MM-YYYY', endDate, endTime, daysOfWeek, excludeDates); | |
/** | |
* Show remaining days and time | |
* | |
* @param {jQuery} $clock Container for remaining days/time elements | |
* Should contain 4 elements with corresponding classes: | |
* days, hours, minutes and seconds | |
* | |
* @param {Object} dateFormat Localized date format, e.g. DD.MM.YYYY in Denmark | |
* @param {Object} endDate Last date of schedule | |
* @param {number} endTime Time in `HH:mm:ss` format | |
* @param {Array} daysOfWeek Days on which the event will happen | |
* @param {Array} excludeDates Dates to ignore | |
*/ | |
function showRemaining($clock, dateFormat, endDate, endTime, daysOfWeek, excludeDates) { | |
var currentTimeObj = moment(); | |
var eventTimeObj = getNextMatchingDate(daysOfWeek, currentTimeObj, endTime); | |
while (matchesDate(excludeDates, eventTimeObj, dateFormat)) { | |
currentTimeObj = currentTimeObj.add(1, 'day'); | |
eventTimeObj = getNextMatchingDate(daysOfWeek, currentTimeObj, endTime); | |
} | |
var endTimeObj = moment(endDate + ' ' + endTime, dateFormat + ' HH:mm:ss'); | |
var diffEndTime = endTimeObj.unix() - eventTimeObj.unix(); | |
// Check if current date/time have past the end date | |
if (diffEndTime < 0) { | |
return; | |
} | |
var diffTime = eventTimeObj.unix() - currentTimeObj.unix(); | |
var remaining = moment.duration(diffTime * 1000, 'milliseconds'); | |
var interval = 1000; | |
var $d = $clock.find('.days'); | |
var $h = $clock.find('.hours'); | |
var $m = $clock.find('.minutes'); | |
var $s = $clock.find('.seconds'); | |
// Show clock | |
setTimeout(function() { | |
$clock.show(); | |
}, interval); | |
setInterval(function() { | |
// Update remaining time | |
remaining = moment.duration(remaining.asMilliseconds() - interval, 'milliseconds'); | |
// Show how many hours, minutes and seconds are left | |
$d.text(remaining.days()); | |
$h.text(_.padStart(remaining.hours(), 2, '0')); | |
$m.text(_.padStart(remaining.minutes(), 2, '0')); | |
$s.text(_.padStart(remaining.seconds(), 2, '0')); | |
}, interval); | |
} | |
/** | |
* @param {Array} daysOfWeek | |
* @param {Object} currentTimeObj | |
* @param {string} endTime | |
* | |
* @return {Object} | |
*/ | |
function getNextMatchingDate(daysOfWeek, currentTimeObj, endTime) { | |
// Whether event time is in past related to current time | |
var isPastEventTime = (moment(endTime, 'HH:mm:ss').unix() - moment().unix() < 0); | |
var currentDayOfWeek = currentTimeObj.day(); | |
var matchingDayOfWeek = _.find(daysOfWeek, function(dayOfWeek) { | |
var diffDays = dayOfWeek - currentDayOfWeek; | |
if (diffDays > 0 || (diffDays === 0 && !isPastEventTime)) { | |
return dayOfWeek; | |
} | |
}); | |
matchingDayOfWeek = matchingDayOfWeek || _.min(daysOfWeek); | |
if (matchingDayOfWeek - currentDayOfWeek < 0) { | |
// Sunday + next week's clothest day | |
matchingDayOfWeek = 7 + _.min(daysOfWeek); | |
} | |
var eventTimeObj = moment(endTime, 'HH:mm:ss').day(matchingDayOfWeek); | |
return eventTimeObj; | |
} | |
/** | |
* Match date in dates array | |
* | |
* @param {string[]} dates | |
* @param {Object} dateMatchObj | |
* @param {string} dateFormat | |
*/ | |
function matchesDate(dates, dateMatchObj, dateFormat) { | |
return dates.some(function(dateNext) { | |
var dateNextObj = moment(dateNext, dateFormat); | |
return (dateNextObj.month() === dateMatchObj.month()) && (dateNextObj.date() === dateMatchObj.date()); | |
}); | |
} | |
});</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment