jsclock-0.8.coffee | |
---|---|
! JS Clock - jQuery Plugin version 0.8 http://thiago-cavalcanti.github.com/JS-Clock/ Copyright (c) 2010 Thiago Cavalcanti Pimenta. Dual licensed under the MIT and GPL version 3 licenses. Check mit.txt and gpl.txt on this distribution for the respective licensing text. Date: 2011-01-23 (Sun, 23 Jan 2011) | |
Use this way: $('some-selector').jsclock(); to replace the innerHTML of the selected elements with a clock in sync with the client time (uses Javascript's Date object) OR pass in some time string (server time, for example) in HH:MM:SS format, like this: $('some-selector').jsclock('14:29:36'); to have it count the time independently of the client time (built-in plugin clockwork algorithm, NOT Javascript's Date object). NOTE: if at all possible, do try to measure the mean delay introduced by the network and account for it in the time string you pass into this plugin. You CAN use more than one such clock on a single page, just try to make sure that if you do so with multiple clocks showing the same time you use Sizzle to do it, like this: $('one-selector, another-selector, yet-another-selector').jsclock(); You should try to reduce the number of calls to JS Clock to just one for each time string so DON'T do this: $('first-selector').jsclock('14:29:36'); $('second-selector').jsclock('14:29:36'); $('third-selector').jsclock(); $('fourth-selector').jsclock(); If you want to, you can pass in some options such as "showCenti" and "countdown", like this: $('some-selector').jsclock({showCenti:true}); to show a client time clock with Centiseconds display. $('some-selector').jsclock('00:00:10',{countdown:true, showCenti:true, callback:function(){ $(this).html('boom!'); }}); to show a countdown timer that ends with a "boom!". If you set countdown to true you MUST define a time string as a starting point! The callback is entirely optional, if it isn't present the countdown timer will simply wrap around to 23:59:59. :) You can get the current time of the latest enabled clock like this: var myClock = $('some-selector').jsclock(14:29:36); var timeNow = myClock.jsclock.getTime(); Similarly, it is possible to stop, restart, and toggle the latest enabled clock like this: $('some-selector').jsclock.stopClock(); $('some-selector').jsclock.startClock(); $('some-selector').jsclock.toggleClock(); TODO: see ROADMAP file in this distribution. | $ = jQuery
$.fn.jsclock = (sTime, oConfig) -> |
Save a reference for use later. | that = this |
This needs to be visible from everywhere. | sCurrentTime = "" |
Avoids checking for it's existence later on. | unless oConfig?
oConfig = {} |
Return the current time string if needed. | $.fn.jsclock.getTime = ->
return sCurrentTime |
Stop! | $.fn.jsclock.stopClock = ->
oConfig.stopClock = true |
Start again... | $.fn.jsclock.startClock = ->
if oConfig.stopClock is true
oConfig.stopClock = false
if sTime is null
that.jsclock(sTime, oConfig)
else
that.jsclock(sCurrentTime, oConfig)
$.fn.jsclock.toggleClock = ->
if oConfig.stopClock is true
that.jsclock.startClock()
else that.jsclock.stopClock()
@each -> |
Correct the parameters assignments if only the configuration object has been passed in. | if typeof sTime is "object"
oConfig = sTime
sTime = null |
We'll need these later. | iCurrentHour = 0
iCurrentMinute = 0
iCurrentSecond = 0
iCurrentCenti = 0 |
This is a utility function used by all approaches. | updateTimeString = ->
addLeadingZero = (iTimeStringFragment) ->
if iTimeStringFragment < 10 and iTimeStringFragment.length isnt 2
iTimeStringFragment = "0" + iTimeStringFragment
return iTimeStringFragment
iCurrentHour = addLeadingZero(iCurrentHour)
iCurrentMinute = addLeadingZero(iCurrentMinute)
iCurrentSecond = addLeadingZero(iCurrentSecond)
iCurrentCenti = addLeadingZero(iCurrentCenti)
if oConfig.showCenti is true
sCurrentTime = "#{iCurrentHour}:#{iCurrentMinute}:#{iCurrentSecond}:#{iCurrentCenti}"
else
sCurrentTime = "#{iCurrentHour}:#{iCurrentMinute}:#{iCurrentSecond}"
that.html(sCurrentTime)
if oConfig.stopClock is true
clearTimeout(clockLoop) |
This RegEx matches time strings either in the format HH:MM:SS or in the format HH:MM:SS:CC / Hours, minutes and seconds are all REQUIRED, as are the leading zeros, if any. Centiseconds are entirely optional, even if showCenti is true. | rValidateTimeString = /// ^
( # First the hours.
(
[01][0-9] # From 00 hours to 19 hours.
)
| (
2[0-3] # From 20 to 23 hours.
)
)
: # Ye old separator.
[0-5][0-9] # From 00 to 59 minutes.
:
[0-5][0-9] # Same as above, now for seconds.
(
:
[0-9][0-9] # From 00 to 99 centiseconds.
)? # Ignore if not specified.
$ ///i |
Checking if the configuration values exist and, if so, if they're valid. Warn and cease if there is a problem. | if oConfig.countdown?
if typeof oConfig.countdown isnt "boolean"
that.html('countdown value must either be "true" or "false".')
return false
if oConfig.showCenti?
if typeof oConfig.showCenti isnt "boolean"
that.html('showCenti value must either be "true" or "false".')
return false
if oConfig.callback?
if typeof oConfig.callback isnt "function"
that.html('callback must be a function!')
return false |
If a time string has been passed we'll use a clockwork algorithm. | if sTime |
Need to make sure it's a valid time string before proceeding. | if rValidateTimeString.test(sTime)
aTime = sTime.split(':')
iCurrentHour = aTime[0]
iCurrentMinute = aTime[1]
iCurrentSecond = aTime[2]
iCurrentCenti = aTime[3]
if oConfig.countdown is true |
Reverse clockwork algorithm. | reverseClockwork = ->
baseclock = ->
if iCurrentSecond > 0
iCurrentSecond--
else
iCurrentSecond = 59
if iCurrentMinute > 0
iCurrentMinute--
else
iCurrentMinute = 59
if iCurrentHour > 0
iCurrentHour--
else
if typeof oConfig.callback is "function"
oConfig.callback.call(that)
clearTimeout(clockloop)
else
iCurrentHour = 23
simpleclock = ->
updateTimeString()
baseclock()
clockloop = (setTimeout(simpleclock, 1000))
fullclock = ->
if iCurrentCenti > 0
iCurrentCenti--
else
iCurrentCenti = 99
baseclock()
updateTimeString()
clockloop = (setTimeout(fullclock, 10))
if oConfig.showCenti is true
fullclock()
else simpleclock()
reverseClockwork()
else |
Clockwork algorithm. | clockwork = ->
baseclock = ->
if iCurrentSecond < 59
iCurrentSecond++
else
iCurrentSecond = 0
if iCurrentMinute < 59
iCurrentMinute++
else
iCurrentMinute = 0
if iCurrentHour < 23
iCurrentHour++
else
iCurrentHour = 0
simpleclock = ->
baseclock()
updateTimeString()
clockLoop = (setTimeout(simpleclock, 1000))
fullclock = ->
if iCurrentCenti < 99
iCurrentCenti++
else
iCurrentCenti = 0
baseclock()
updateTimeString()
clockLoop = (setTimeout(fullclock, 10))
if oConfig.showCenti is true
fullclock()
else simpleclock()
clockwork() |
Warn developer if he/she messed up the time parameter to this plugin. | else
that.html('Time string <strong>must</strong> be either in the format
"HH:MM:SS" or in the "HH:MM:SS:CC" format. Hours, minutes and
seconds are all <strong>REQUIRED</strong>, as are the leading zeros,
if any. Centiseconds are entirely optional, even if showCenti is
true.')
else |
Complain if the user wishes to countdown from an undefined time... | if oConfig.countdown is true
that.html('You must specify a time string to countdown from!')
return false
else |
If there's no time string let the Date object do the heavy-lifting. | clientClock = ->
baseclock = ->
oCurrentDate = new Date()
iCurrentHour = oCurrentDate.getHours()
iCurrentMinute = oCurrentDate.getMinutes()
iCurrentSecond = oCurrentDate.getSeconds()
simpleclock = ->
baseclock()
updateTimeString()
clockLoop = (setTimeout(simpleclock, 1000))
fullclock = ->
if bFirstTime?
if iCurrentCenti < 99
iCurrentCenti++
else
iCurrentCenti = 0
baseclock()
else
baseclock()
oCurrentDate = new Date()
iCurrentCenti = oCurrentDate.getMilliseconds().toString()
.substr(0,2)
bFirstTime = true
updateTimeString()
(setTimeout(fullclock, 10))
if oConfig.showCenti is true
fullclock()
else simpleclock()
clientClock()
|