Last active
October 31, 2016 08:36
-
-
Save primozcigler/e1d25fc56eedf501914c to your computer and use it in GitHub Desktop.
ProteusThemes support working hours widget. Made with moment.js
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
<html> | |
<head> | |
<title>support opening time</title> | |
<!-- deps: jquery, underscore.js, moment.js --> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.4.0/moment.min.js"></script> | |
<script> | |
jQuery( document ).ready( function ( $ ) { | |
/** | |
* Header widget for the official online/offline and opening hours | |
*/ | |
(function () { | |
var SupportStatus = function () { | |
/** | |
* Ultimate config object | |
* @type {Object} | |
*/ | |
this.config = { | |
workingDays: [1, 2, 3, 4, 5], // 0 = sun, 1 = mon ... 6 = sat | |
workingHours: { // 24h format | |
start: 8, | |
end: 15 | |
}, | |
tmpls: { | |
status: _.template( 'Our <strong>support staff</strong> is currently <span class="support-status-badge is-<%- status %>"><%- status %></span>.' ), | |
onlineAgain: _.template( 'We will be online again <strong><%- timeToOnline %></strong>.' ), | |
yourOurTime: _.template( 'Your time: <strong><%- yourTime %></strong> | Our time: <strong><%- ourTime %></strong>' ), | |
officialHour: _.template( 'Official hours: <strong><%- workingRange %></strong>.' ), | |
}, | |
}; | |
// set local pointer to moment() | |
this.moment = moment; | |
// alias | |
this.tmpls = this.config.tmpls; | |
/** | |
* Set times on init and moment objects for the working hours | |
*/ | |
this.updateTimes(); | |
return this; | |
}; | |
_.extend( SupportStatus.prototype, { | |
/** | |
* Parse HTML from underscores templates, defined in the this.config.tmpls | |
* @return {string} html | |
*/ | |
parse: function () { | |
var htmlLines = []; | |
htmlLines.push( this.tmpls.status( { status: this.statusBadgeText() } ) ); | |
if ( ! this.isWorkingTime() ) { // only display outside working hours | |
htmlLines.push( this.tmpls.onlineAgain( { timeToOnline: this.getTimeToOnline() } ) ); | |
} | |
htmlLines.push( this.tmpls.officialHour( { workingRange: this.officialHoursText() } ) ); | |
htmlLines.push( this.tmpls.yourOurTime( { | |
yourTime: this.clientTime.format( 'ddd, h:mm a' ), | |
ourTime: this.supportTime.format( 'ddd, h:mm a' ), | |
} ) ); | |
return htmlLines.join( '<br />' ); | |
}, | |
/** | |
* Update client and support time anew | |
* @return this | |
*/ | |
updateTimes: function () { | |
this.clientTime = this.moment(); | |
this.supportTime = this.moment().utc().zone( this.clientTime.isDST() ? -120 : -60 ); | |
// can use this in moment v2.10.3+ | |
// this.supportTime = this.moment().utc().utcOffset( this.clientTime.isDST() ? 120 : 60 ); | |
this.workingHours = this.setWorkingHours(); | |
return this; | |
}, | |
/** | |
* Check if it is a working day | |
* @return {Boolean} | |
*/ | |
isWorkingDay: function () { | |
return _.contains( this.config.workingDays, this.supportTime.day() ); | |
}, | |
/** | |
* Check if support team is online now = time now is between end and start | |
* @return {Boolean} | |
*/ | |
isWorkingTime: function () { | |
return ( this.supportTime.isAfter( this.workingHours.start ) && this.supportTime.isBefore( this.workingHours.end ) ); | |
// can use this in moment v2.10.3+ | |
// return this.supportTime.isBetween( this.workingHours.start, this.workingHours.end ); | |
}, | |
/** | |
* Return support team status based on the working time | |
* @return {string} online/offline | |
*/ | |
statusBadgeText: function () { | |
if ( this.isWorkingTime() ) { | |
return 'online'; | |
} | |
return 'offline'; | |
}, | |
/** | |
* Return the start and end working hours as moment objects. | |
* If current time is a working day before the support ended shift start/end represent the points in time for the current day, | |
* otherwise for the next working day. | |
* @return {object} start/end | |
*/ | |
setWorkingHours: function () { | |
if ( ! this.isWorkingDay() || this.supportTime.hour() >= this.config.workingHours.end ) { // set to the next working day | |
var nextWorkingDay = this.getNextWorkingDay( this.supportTime.clone() ); | |
return { | |
start: nextWorkingDay.clone().hour( this.config.workingHours.start ).startOf( 'hour' ), | |
end: nextWorkingDay.clone().hour( this.config.workingHours.end ).startOf( 'hour' ) | |
}; | |
} | |
else { // start/end in the same day | |
return { | |
start: this.supportTime.clone().hour( this.config.workingHours.start ).startOf( 'hour' ), | |
end: this.supportTime.clone().hour( this.config.workingHours.end ).startOf( 'hour' ) | |
}; | |
} | |
}, | |
/** | |
* Get the next working day, based on the config. | |
* @return {moment} | |
*/ | |
getNextWorkingDay: function ( fromDay ) { | |
var nextDay = fromDay.add( 1, 'days' ); | |
if ( _.contains( this.config.workingDays, nextDay.day() ) ) { | |
return nextDay; | |
} | |
else { | |
return this.getNextWorkingDay( nextDay ); | |
} | |
}, | |
/** | |
* Returns the human readable text when we're online again in format: in 3 hours | |
* @return {string} | |
*/ | |
getTimeToOnline: function () { | |
return this.workingHours.start.from( this.clientTime ); | |
// can use this in moment v2.10.3+ | |
// return this.clientTime.to( this.workingHours.start ); | |
}, | |
/** | |
* Display the official working hours based on the config. | |
* Calling this function only once and caching output. | |
* @return {string} | |
*/ | |
officialHoursText: _.once( function () { | |
var str = _.template( '<%- dayStart %>-<%- dayEnd %> / <%- hourStart %>-<%- hourEnd %> (GMT+<%- tz %>)' ); | |
return str( { | |
dayStart: this.moment().day( _.min( this.config.workingDays ) ).format( 'ddd' ), | |
dayEnd: this.moment().day( _.max( this.config.workingDays ) ).format( 'ddd' ), | |
hourStart: this.moment().hour( this.config.workingHours.start ).startOf( 'hour' ).format( 'ha' ), | |
hourEnd: this.moment().hour( this.config.workingHours.end ).startOf( 'hour' ).format( 'ha' ), | |
tz: this.moment().isDST() ? 2 : 1, | |
} ); | |
} ), | |
} ); | |
// only instance of the class above | |
var supportStatus = new SupportStatus(); | |
var updateSupportHTML = function () { | |
$( '#js-support-time' ).html( supportStatus.updateTimes().parse() ); | |
}; | |
updateSupportHTML(); | |
// update every 30 seconds | |
setInterval( updateSupportHTML, 30*1000 ); | |
})(); | |
} ); | |
</script> | |
</head> | |
<body> | |
<div id="js-support-time"></div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment