(function ($){
const SECOND=1;
const MINUTE=60 * SECOND;
const HOUR=60 * MINUTE;
const DAY=24 * HOUR;
const WEEK=7 * DAY;
const DEFAULT_OPTIONS={
format: 'full', // 'full', 'short', 'minimal'
onTick: null,
onComplete: null,
autoStart: true
};
function calculateTimeUnits(distance){
return {
weeks: Math.floor(distance / WEEK),
days: Math.floor((distance % WEEK) / DAY),
hours: Math.floor((distance % DAY) / HOUR),
minutes: Math.floor((distance % HOUR) / MINUTE),
seconds: Math.floor(distance % MINUTE)
};}
function calculateRepeatingTarget(repeatType){
const now=new Date();
let target;
if(repeatType==='daily'){
target=new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
}else if(repeatType==='weekly'){
const daysUntilMonday=(8 - now.getDay()) % 7;
target=new Date(now.getFullYear(), now.getMonth(), now.getDate() + daysUntilMonday);
}
target.setHours(0, 0, 0, 0);
return Math.floor((target - now) / 1000);
}
function padNumber(num){
return num < 10 ? '0' + num:num.toString();
}
function generateTimeUnit(unit, value, text, showDivider, hidden){
showDivider=showDivider||false;
hidden=hidden||false;
return [
'<span class="' + unit + ' timer ' + (hidden ? 'hidden':'') + '">',
'    <span class="digits">' + value + '</span>',
'    <span class="text">' + text + '</span>',
showDivider ? '    <span class="divider">:</span>':'',
'</span>'
].join('\n');
}
function generateTimerHTML(units, texts, format){
var parts=[];
var weeks=units.weeks;
var days=units.days;
var hours=units.hours;
var minutes=units.minutes;
var seconds=units.seconds;
if(format==='minimal'){
if(weeks > 0) return generateTimeUnit('weeks', weeks, texts.weeks);
if(days > 0) return generateTimeUnit('days', days, texts.days);
if(hours > 0) return generateTimeUnit('hours', hours, texts.hours);
if(minutes > 0) return generateTimeUnit('minutes', minutes, texts.minutes);
return generateTimeUnit('seconds', seconds, texts.seconds);
}
if(format==='short'){
if(weeks > 0) parts.push(generateTimeUnit('weeks', weeks, texts.weeks, true));
if(days > 0) parts.push(generateTimeUnit('days', days, texts.days, true));
parts.push(generateTimeUnit('hours', padNumber(hours), texts.hours, true));
parts.push(generateTimeUnit('minutes', padNumber(minutes), texts.minutes, true));
parts.push(generateTimeUnit('seconds', padNumber(seconds), texts.seconds));
return parts.join('');
}
parts=[
generateTimeUnit('weeks', weeks, texts.weeks, true, weeks===0),
generateTimeUnit('days', days, texts.days, true, days===0),
generateTimeUnit('hours', padNumber(hours), texts.hours, true),
generateTimeUnit('minutes', padNumber(minutes), texts.minutes, true),
generateTimeUnit('seconds', padNumber(seconds), texts.seconds)
];
return parts.join('');
}
$.fn.shopwell_countdown=function (customOptions){
customOptions=customOptions||{};
var options=$.extend({}, DEFAULT_OPTIONS, customOptions);
return this.each(function (){
var $element=$(this);
var remainingTime=$element.data('expire');
var texts=$element.data('text');
var repeatType=$element.data('repeat');
var isPaused=false;
var countdown;
if(repeatType&&(repeatType==='daily'||repeatType==='weekly')){
remainingTime=calculateRepeatingTarget(repeatType);
}
if(typeof remainingTime!=='number'||remainingTime < 0){
console.error('Invalid countdown time provided');
return;
}
if(!texts||typeof texts!=='object'){
console.error('Invalid or missing translation texts');
return;
}
function updateClock(distance){
if(distance < 0){
if(repeatType){
remainingTime=calculateRepeatingTarget(repeatType);
return true;
}
if(options.onComplete) options.onComplete.call($element);
return false;
}
var units=calculateTimeUnits(distance);
$element.html(generateTimerHTML(units, texts, options.format));
if(options.onTick) options.onTick.call($element, units);
return true;
}
function startCountdown(){
isPaused=false;
updateClock(remainingTime);
countdown=setInterval(function(){
if(!isPaused){
remainingTime--;
if(!updateClock(remainingTime)){
clearInterval(countdown);
}}
}, 1000);
}
$element.countdown={
pause: function(){
isPaused=true;
},
resume: function(){
isPaused=false;
},
restart: function(newTime){
clearInterval(countdown);
if(repeatType){
remainingTime=calculateRepeatingTarget(repeatType);
}else{
remainingTime=typeof newTime==='number' ? newTime:$element.data('expire');
}
startCountdown();
},
destroy: function(){
clearInterval(countdown);
$element.html('');
delete $element.countdown;
}};
if(options.autoStart){
startCountdown();
}});
};
$(function (){
$('.shopwell-countdown').shopwell_countdown();
$(document.body).on('shopwell_countdown', function(e, $el){
$el.shopwell_countdown();
});
});
})(jQuery);