Countdown timer widget

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-04-2018 03:40 AM
Hi,
I'm looking for a countdown timer widget for the Service Portal. I have found some code online made for html/javascript/css, but am having trouble with encorporating it into a Portal widget.
HTML:
<div>
<h1>Countdown Clock</h1>
<div id="clockdiv">
<div>
<span class="days"></span>
<div class="smalltext">Days</div>
</div>
<div>
<span class="hours"></span>
<div class="smalltext">Hours</div>
</div>
<div>
<span class="minutes"></span>
<div class="smalltext">Minutes</div>
</div>
<div>
<span class="seconds"></span>
<div class="smalltext">Seconds</div>
</div>
</div>
</div>
CSS:
body{
text-align: center;
background: #00ECB9;
font-family: sans-serif;
font-weight: 100;
}
h1{
color: #396;
font-weight: 100;
font-size: 40px;
margin: 40px 0px 20px;
}
#clockdiv{
font-family: sans-serif;
color: #fff;
display: inline-block;
font-weight: 100;
text-align: center;
font-size: 30px;
}
#clockdiv > div{
padding: 10px;
border-radius: 3px;
background: #00BF96;
display: inline-block;
}
#clockdiv div > span{
padding: 15px;
border-radius: 3px;
background: #00816A;
display: inline-block;
}
.smalltext{
padding-top: 5px;
font-size: 16px;
}
Server Script/javascript
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
var deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
initializeClock('clockdiv', deadline);
Currently it's failing due to the "document" reference in the javascript line 17 as far as I understand from my error messages.
Optimally, I would like to be able to input the "due date" (where the countdown reaches 0) in Instance Options, but this did not seem intuitive as there is no date variable in the option builder.
So, my question is: does anybody have a countdown timer code they would be willing to share? Or can anybody help me find out what I need to make this work with existing code?
- Labels:
-
Service Portal Development

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-04-2018 04:44 AM
In order for this code to work, you can put the entire code in the template and using the below template :
<div>
<script>
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
var deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
initializeClock('clockdiv', deadline);
</script>
<h1>Countdown Clock</h1>
<div id="clockdiv">
<div>
<span class="days"></span>
<div class="smalltext">Days</div>
</div>
<div>
<span class="hours"></span>
<div class="smalltext">Hours</div>
</div>
<div>
<span class="minutes"></span>
<div class="smalltext">Minutes</div>
</div>
<div>
<span class="seconds"></span>
<div class="smalltext">Seconds</div>
</div>
</div>
</div>

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-13-2018 02:09 PM
Thanks, I managed to get this to work, and made a few edits.
<div>
<div>
<script>
function getTimeRemaining(endtime) {
var dnow = new Date();
//var dnow = data.nows;
//var z = "Europe/Paris"
//var dnow = new moment().tz(z);
var t = Date.parse(endtime) - Date.parse(dnow);
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
deadline = '2018-06-21 07:00:00';
//var deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
initializeClock('clockdiv', deadline);
</script>
<a ng-href="?id=kb_article&sys_id=1fc4627a1c62d3489c4646981559e915">
<div id="clockdiv">
<divv>
Welcome back in
</divv>
<div class="days"></div>
<div class="smalltext">Days</div>
<div class="hours"></div>
<div class="smalltext">Hours</div>
<div class="minutes"></div>
<div class="smalltext">Minutes</div>
<div class="seconds"></div>
<div class="smalltext">Seconds</div>
<!--div>
<span class="days"></span>
<div class="smalltext">Days</div>
</div>
<div>
<span class="hours"></span>
<div class="smalltext">Hours</div>
</div>
<div>
<span class="minutes"></span>
<div class="smalltext">Minutes</div>
</div>
<div>
<span class="seconds"></span>
<div class="smalltext">Seconds</div>
</div-->
</div>
</a>
</div>
</div>
However a new problem arose: This works brilliantly in Chrome and Firefox, but fails in Internet Explorer (11), and instead displays "NaN Days, NaN hours etcetc.
As the countdown is on the front page of the end-user portal, getting everyone to migrate to Chrome is not an option.
Hoping someone will be able to help with a quick fix. If I don't find any other solution by tomorrow I will have to find a workaround by replacing the countdown with just the target date for IE users. Would appreciate tips on how to do that easily as well.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-04-2018 06:20 AM
Hi,
Please find attached the widget xml, you can import and use it.
About the usage of dynamic variable as options. You can call this widget as below
HTML
<div>
<sp-widget widget="data.countDownWidget"></sp-widget>
</div>
Server side code
(function() {
var deadLine;
var gr = new GlideRecord('table');
if(gr.get('sys_id_of_record/logic'))
deadLine= gr.due_date.dateNumericValue(); // use dateNumericValue() to get time in millisecond
var countDownWidgetOptions = {"deadLine": deadLine};
data.countDownWidget = $sp.getWidget('countdown', countDownWidgetOptions);
})();
This way, you could use this widget multiple times just by passing deaLine value which is nothing but the value of due_date(any date field) in millisecond. I have attached a working screenshot 🙂