Created
May 17, 2010 13:27
-
-
Save dcneiner/403754 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
(function($){ | |
$.widget('pixel.countdown', { | |
options: { | |
milestones: [ | |
{ label: "one_minute", minute: 1 }, | |
{ label: "five_minutes", minute: 5, second: 30 } | |
], | |
interval: 1, // Interval in seconds to refresh the widget | |
formatter: function(min, sec){ | |
if(min === 0 && sec === 0){ | |
return "now."; | |
} else { | |
var second_label = sec + (sec == 1 ? " second." : " seconds."); | |
if( min === 0){ | |
return "in " + second_label; | |
} else { | |
return "in " + min + (min == 1 ? " minute" : " minutes") + " and " + second_label; | |
} | |
} | |
} | |
}, | |
_create: function(){ | |
var dateTime = this.element.attr('datetime') || this.element.text(), | |
hour, | |
min, | |
setup = false; | |
dateTime = dateTime.split('T'); | |
if( dateTime.length === 2 ){ | |
// Create a new date based on the year, month, day | |
this._endTime = new Date(dateTime[0]); | |
// Get hours and minutes | |
dateTime = dateTime[1].split(':'); | |
hour = parseInt( dateTime[0], 10); | |
min = parseInt( dateTime[1], 10); | |
if( !isNaN(hour) && !isNaN(min) ){ | |
this._endTime.setUTCHours(hour, min); | |
setup = true; | |
} | |
} | |
// In this case we fail silently, and remove the widget | |
// We could throw an error instead if wanted. | |
if (!setup){ | |
this.destroy(); // Undo everything we did | |
return false; | |
} | |
this._originalText = this.element.text(); | |
this.milestones = this._cleanMilestones(); | |
this.widgetEventPrefix = "countdown_"; | |
this._timer = window.setInterval($.proxy(this.update, this), this.options.interval * 1000); | |
this.update(); // call it initially to avoid 1 second delay | |
}, | |
timeLeft: function(){ | |
var left = this._endTime - (new Date()).getTime(), | |
min = left / 1000 / 60, | |
sec = min % 1 * 60; | |
min = parseInt(min, 10); | |
sec = Math.round(sec); | |
return left <= 0 ? [0, 0] : [min, sec]; | |
}, | |
update: function(){ | |
var timeLeft = this.timeLeft(), | |
vTL = timeLeft[0] + (timeLeft[1] / 100), | |
label; | |
if(this.milestones.length && this.milestones[0].time > vTL){ | |
label = this.milestones.shift().label; | |
this._trigger('milestone_reached', null, label); | |
} | |
if(vTL === 0){ | |
window.clearInterval(this._timer); | |
this._trigger('complete'); | |
} | |
this.element.text( | |
this.options.formatter.apply(this.element, timeLeft) | |
); | |
}, | |
_cleanMilestones: function(){ | |
var timeLeft = this.timeLeft(), | |
vTL = timeLeft[0] + (timeLeft[1] / 100), | |
milestones = $.map(this.options.milestones, function(ms){ | |
// Create a new literal that contains only the label | |
// and the min/sec as a single value | |
return { label: ms.label, time: ms.minute + ((ms.second || 0) / 100) }; | |
}), | |
size = milestones.length; | |
// Sort largest to smallest | |
milestones.sort(function(a,b){ | |
if (a.time === b.time) return 0; | |
else return a.time > b.time ? -1 : 1; | |
}); | |
// Remove expired milestones | |
while(milestones.length && milestones[0].time > vTL){ | |
milestones.shift(); | |
} | |
return milestones; | |
}, | |
_setOption: function(key, value){ | |
if (this.options[key] === value) { | |
return; // Do nothing, the value didn't change | |
} | |
switch (key){ | |
case "interval": | |
// Store the new value | |
this.options.interval = value; | |
// Clear the old timer | |
window.clearInterval(this._timer); | |
// Set a new timer based on the new interval | |
this._timer = window.setInterval( | |
$.proxy(this.update, this), | |
this.options.interval * 1000 | |
); | |
break; | |
case "formatter": | |
this.options.formatter = value; | |
this.update(); | |
break; | |
case "milestones": | |
this.options.milestones = value; | |
this.milestones = this._cleanMilestones(); | |
break; | |
default: | |
this.options[key] = value; | |
} | |
return this; | |
}, | |
destroy: function(){ | |
window.clearInterval( this._timer ); | |
this.element.text( this._originalText); | |
// Call the parent destroy method | |
$.Widget.prototype.destroy.call(this); | |
} | |
}); | |
}(jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment