UNPKG

angularcountdown

Version:
1,230 lines (1,036 loc) 30.8 kB
/** * UI Component For Angular 1.x Applications * @version v0.1.1 - 2016-01-07 * @link https://github.com/jacobscarter/angular-countdown * @author Jacob Carter <jacob@ieksolutions.com> * @license MIT License, http://www.opensource.org/licenses/MIT */ 'use strict'; angular.module('angular-countdown', ['templates-angularcountdown']); angular.module('templates-angularcountdown', ['angularcountdown.html']); angular.module("angularcountdown.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("angularcountdown.html", "<div id=\"countdown\" ng-if=\"timespan\">\n" + " <div class=\"redballdays\" id=\"days\"></div>\n" + " <div class=\"redballhours\" id=\"hours\"></div>\n" + " <div class=\"redballminutes\" id=\"minutes\"></div>\n" + " <div class=\"redballseconds\" id=\"seconds\"></div>\n" + "</div>"); }]); 'use strict'; angular.module('angular-countdown', ['templates-angularcountdown']); 'use strict'; angular.module('angular-countdown').directive('countdown', ['$interval', function($interval) { /** * @license countdown.js v2.4.1 http://countdownjs.org * Copyright (c)2006-2014 Stephen M. McKamey. * Licensed under The MIT License. */ /*jshint bitwise:false */ /** * @public * @type {Object|null} */ var module; /** * API entry * @public * @param {function(Object)|Date|number} start the starting date * @param {function(Object)|Date|number} end the ending date * @param {number} units the units to populate * @return {Object|number} */ var countdown = ( /** * @param {Object} module CommonJS Module */ function(module) { /*jshint smarttabs:true */ 'use strict'; /** * @private * @const * @type {number} */ var MILLISECONDS = 0x001; /** * @private * @const * @type {number} */ var SECONDS = 0x002; /** * @private * @const * @type {number} */ var MINUTES = 0x004; /** * @private * @const * @type {number} */ var HOURS = 0x008; /** * @private * @const * @type {number} */ var DAYS = 0x010; /** * @private * @const * @type {number} */ var WEEKS = 0x020; /** * @private * @const * @type {number} */ var MONTHS = 0x040; /** * @private * @const * @type {number} */ var YEARS = 0x080; /** * @private * @const * @type {number} */ var DECADES = 0x100; /** * @private * @const * @type {number} */ var CENTURIES = 0x200; /** * @private * @const * @type {number} */ var MILLENNIA = 0x400; /** * @private * @const * @type {number} */ var DEFAULTS = YEARS|MONTHS|DAYS|HOURS|MINUTES|SECONDS; /** * @private * @const * @type {number} */ var MILLISECONDS_PER_SECOND = 1000; /** * @private * @const * @type {number} */ var SECONDS_PER_MINUTE = 60; /** * @private * @const * @type {number} */ var MINUTES_PER_HOUR = 60; /** * @private * @const * @type {number} */ var HOURS_PER_DAY = 24; /** * @private * @const * @type {number} */ var MILLISECONDS_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND; /** * @private * @const * @type {number} */ var DAYS_PER_WEEK = 7; /** * @private * @const * @type {number} */ var MONTHS_PER_YEAR = 12; /** * @private * @const * @type {number} */ var YEARS_PER_DECADE = 10; /** * @private * @const * @type {number} */ var DECADES_PER_CENTURY = 10; /** * @private * @const * @type {number} */ var CENTURIES_PER_MILLENNIUM = 10; /** * @private * @param {number} x number * @return {number} */ var ceil = Math.ceil; /** * @private * @param {number} x number * @return {number} */ var floor = Math.floor; /** * @private * @param {Date} ref reference date * @param {number} shift number of months to shift * @return {number} number of days shifted */ function borrowMonths(ref, shift) { var prevTime = ref.getTime(); // increment month by shift ref.setMonth( ref.getMonth() + shift ); // this is the trickiest since months vary in length return Math.round( (ref.getTime() - prevTime) / MILLISECONDS_PER_DAY ); } /** * @private * @param {Date} ref reference date * @return {number} number of days */ function daysPerMonth(ref) { var a = ref.getTime(); // increment month by 1 var b = new Date(a); b.setMonth( ref.getMonth() + 1 ); // this is the trickiest since months vary in length return Math.round( (b.getTime() - a) / MILLISECONDS_PER_DAY ); } /** * @private * @param {Date} ref reference date * @return {number} number of days */ function daysPerYear(ref) { var a = ref.getTime(); // increment year by 1 var b = new Date(a); b.setFullYear( ref.getFullYear() + 1 ); // this is the trickiest since years (periodically) vary in length return Math.round( (b.getTime() - a) / MILLISECONDS_PER_DAY ); } /** * @private * @const * @type {number} */ var LABEL_MILLISECONDS = 0; /** * @private * @const * @type {number} */ var LABEL_SECONDS = 1; /** * @private * @const * @type {number} */ var LABEL_MINUTES = 2; /** * @private * @const * @type {number} */ var LABEL_HOURS = 3; /** * @private * @const * @type {number} */ var LABEL_DAYS = 4; /** * @private * @const * @type {number} */ var LABEL_WEEKS = 5; /** * @private * @const * @type {number} */ var LABEL_MONTHS = 6; /** * @private * @const * @type {number} */ var LABEL_YEARS = 7; /** * @private * @const * @type {number} */ var LABEL_DECADES = 8; /** * @private * @const * @type {number} */ var LABEL_CENTURIES = 9; /** * @private * @const * @type {number} */ var LABEL_MILLENNIA = 10; /** * @private * @type {Array} */ var LABELS_SINGLUAR; /** * @private * @type {Array} */ var LABELS_PLURAL; /** * @private * @type {string} */ var LABEL_LAST; /** * @private * @type {string} */ var LABEL_DELIM; /** * @private * @param {number} value * @param {number} unit unit index into label list * @return {string} */ function plurality(value, unit) { return value+' '+((value === 1) ? LABELS_SINGLUAR[unit] : LABELS_PLURAL[unit]); } /** * Formats the entries as English labels * * @private * @param {Timespan} ts * @return {Array} */ var formatList; /** * Timespan representation of a duration of time * * @private * @this {Timespan} * @constructor */ function Timespan() {} /** * Formats the Timespan as a sentance * * @private * @return {string} */ Timespan.prototype.toString = function() { var label = formatList(this); var count = label.length; if (!count) { return ''; } if (count > 1) { label[count-1] = LABEL_LAST+label[count-1]; } return label.join(LABEL_DELIM); }; /** * Formats the Timespan as HTML * * @private * @param {string} tag HTML tag name to wrap each value * @return {string} */ Timespan.prototype.toHTML = function(tag) { tag = tag || 'span'; var label = formatList(this); var count = label.length; if (!count) { return ''; } for (var i=0; i<count; i++) { // wrap each unit in tag label[i] = '<'+tag+'>'+label[i]+'</'+tag+'>'; } if (--count) { label[count] = LABEL_LAST+label[count]; } return label.join(LABEL_DELIM); }; /** * Formats the entries as English labels * * @private * @param {Timespan} ts * @return {Array} */ formatList = function(ts) { var list = []; var value = ts.millennia; if (value) { list.push(plurality(value, LABEL_MILLENNIA)); } value = ts.centuries; if (value) { list.push(plurality(value, LABEL_CENTURIES)); } value = ts.decades; if (value) { list.push(plurality(value, LABEL_DECADES)); } value = ts.years; if (value) { list.push(plurality(value, LABEL_YEARS)); } value = ts.months; if (value) { list.push(plurality(value, LABEL_MONTHS)); } value = ts.weeks; if (value) { list.push(plurality(value, LABEL_WEEKS)); } value = ts.days; if (value) { list.push(plurality(value, LABEL_DAYS)); } value = ts.hours; if (value) { list.push(plurality(value, LABEL_HOURS)); } value = ts.minutes; if (value) { list.push(plurality(value, LABEL_MINUTES)); } value = ts.seconds; if (value) { list.push(plurality(value, LABEL_SECONDS)); } value = ts.milliseconds; if (value) { list.push(plurality(value, LABEL_MILLISECONDS)); } return list; }; /** * Borrow any underflow units, carry any overflow units * * @private * @param {Timespan} ts * @param {string} toUnit */ function rippleRounded(ts, toUnit) { switch (toUnit) { case 'seconds': if (ts.seconds !== SECONDS_PER_MINUTE || isNaN(ts.minutes)) { return; } // ripple seconds up to minutes ts.minutes++; ts.seconds = 0; /* falls through */ case 'minutes': if (ts.minutes !== MINUTES_PER_HOUR || isNaN(ts.hours)) { return; } // ripple minutes up to hours ts.hours++; ts.minutes = 0; /* falls through */ case 'hours': if (ts.hours !== HOURS_PER_DAY || isNaN(ts.days)) { return; } // ripple hours up to days ts.days++; ts.hours = 0; /* falls through */ case 'days': if (ts.days !== DAYS_PER_WEEK || isNaN(ts.weeks)) { return; } // ripple days up to weeks ts.weeks++; ts.days = 0; /* falls through */ case 'weeks': if (ts.weeks !== daysPerMonth(ts.refMonth)/DAYS_PER_WEEK || isNaN(ts.months)) { return; } // ripple weeks up to months ts.months++; ts.weeks = 0; /* falls through */ case 'months': if (ts.months !== MONTHS_PER_YEAR || isNaN(ts.years)) { return; } // ripple months up to years ts.years++; ts.months = 0; /* falls through */ case 'years': if (ts.years !== YEARS_PER_DECADE || isNaN(ts.decades)) { return; } // ripple years up to decades ts.decades++; ts.years = 0; /* falls through */ case 'decades': if (ts.decades !== DECADES_PER_CENTURY || isNaN(ts.centuries)) { return; } // ripple decades up to centuries ts.centuries++; ts.decades = 0; /* falls through */ case 'centuries': if (ts.centuries !== CENTURIES_PER_MILLENNIUM || isNaN(ts.millennia)) { return; } // ripple centuries up to millennia ts.millennia++; ts.centuries = 0; /* falls through */ } } /** * Ripple up partial units one place * * @private * @param {Timespan} ts timespan * @param {number} frac accumulated fractional value * @param {string} fromUnit source unit name * @param {string} toUnit target unit name * @param {number} conversion multiplier between units * @param {number} digits max number of decimal digits to output * @return {number} new fractional value */ function fraction(ts, frac, fromUnit, toUnit, conversion, digits) { if (ts[fromUnit] >= 0) { frac += ts[fromUnit]; delete ts[fromUnit]; } frac /= conversion; if (frac + 1 <= 1) { // drop if below machine epsilon return 0; } if (ts[toUnit] >= 0) { // ensure does not have more than specified number of digits ts[toUnit] = +(ts[toUnit] + frac).toFixed(digits); rippleRounded(ts, toUnit); return 0; } return frac; } /** * Ripple up partial units to next existing * * @private * @param {Timespan} ts * @param {number} digits max number of decimal digits to output */ function fractional(ts, digits) { var frac = fraction(ts, 0, 'milliseconds', 'seconds', MILLISECONDS_PER_SECOND, digits); if (!frac) { return; } frac = fraction(ts, frac, 'seconds', 'minutes', SECONDS_PER_MINUTE, digits); if (!frac) { return; } frac = fraction(ts, frac, 'minutes', 'hours', MINUTES_PER_HOUR, digits); if (!frac) { return; } frac = fraction(ts, frac, 'hours', 'days', HOURS_PER_DAY, digits); if (!frac) { return; } frac = fraction(ts, frac, 'days', 'weeks', DAYS_PER_WEEK, digits); if (!frac) { return; } frac = fraction(ts, frac, 'weeks', 'months', daysPerMonth(ts.refMonth)/DAYS_PER_WEEK, digits); if (!frac) { return; } frac = fraction(ts, frac, 'months', 'years', daysPerYear(ts.refMonth)/daysPerMonth(ts.refMonth), digits); if (!frac) { return; } frac = fraction(ts, frac, 'years', 'decades', YEARS_PER_DECADE, digits); if (!frac) { return; } frac = fraction(ts, frac, 'decades', 'centuries', DECADES_PER_CENTURY, digits); if (!frac) { return; } frac = fraction(ts, frac, 'centuries', 'millennia', CENTURIES_PER_MILLENNIUM, digits); // should never reach this with remaining fractional value if (frac) { throw new Error('Fractional unit overflow'); } } /** * Borrow any underflow units, carry any overflow units * * @private * @param {Timespan} ts */ function ripple(ts) { var x; if (ts.milliseconds < 0) { // ripple seconds down to milliseconds x = ceil(-ts.milliseconds / MILLISECONDS_PER_SECOND); ts.seconds -= x; ts.milliseconds += x * MILLISECONDS_PER_SECOND; } else if (ts.milliseconds >= MILLISECONDS_PER_SECOND) { // ripple milliseconds up to seconds ts.seconds += floor(ts.milliseconds / MILLISECONDS_PER_SECOND); ts.milliseconds %= MILLISECONDS_PER_SECOND; } if (ts.seconds < 0) { // ripple minutes down to seconds x = ceil(-ts.seconds / SECONDS_PER_MINUTE); ts.minutes -= x; ts.seconds += x * SECONDS_PER_MINUTE; } else if (ts.seconds >= SECONDS_PER_MINUTE) { // ripple seconds up to minutes ts.minutes += floor(ts.seconds / SECONDS_PER_MINUTE); ts.seconds %= SECONDS_PER_MINUTE; } if (ts.minutes < 0) { // ripple hours down to minutes x = ceil(-ts.minutes / MINUTES_PER_HOUR); ts.hours -= x; ts.minutes += x * MINUTES_PER_HOUR; } else if (ts.minutes >= MINUTES_PER_HOUR) { // ripple minutes up to hours ts.hours += floor(ts.minutes / MINUTES_PER_HOUR); ts.minutes %= MINUTES_PER_HOUR; } if (ts.hours < 0) { // ripple days down to hours x = ceil(-ts.hours / HOURS_PER_DAY); ts.days -= x; ts.hours += x * HOURS_PER_DAY; } else if (ts.hours >= HOURS_PER_DAY) { // ripple hours up to days ts.days += floor(ts.hours / HOURS_PER_DAY); ts.hours %= HOURS_PER_DAY; } while (ts.days < 0) { // NOTE: never actually seen this loop more than once // ripple months down to days ts.months--; ts.days += borrowMonths(ts.refMonth, 1); } // weeks is always zero here if (ts.days >= DAYS_PER_WEEK) { // ripple days up to weeks ts.weeks += floor(ts.days / DAYS_PER_WEEK); ts.days %= DAYS_PER_WEEK; } if (ts.months < 0) { // ripple years down to months x = ceil(-ts.months / MONTHS_PER_YEAR); ts.years -= x; ts.months += x * MONTHS_PER_YEAR; } else if (ts.months >= MONTHS_PER_YEAR) { // ripple months up to years ts.years += floor(ts.months / MONTHS_PER_YEAR); ts.months %= MONTHS_PER_YEAR; } // years is always non-negative here // decades, centuries and millennia are always zero here if (ts.years >= YEARS_PER_DECADE) { // ripple years up to decades ts.decades += floor(ts.years / YEARS_PER_DECADE); ts.years %= YEARS_PER_DECADE; if (ts.decades >= DECADES_PER_CENTURY) { // ripple decades up to centuries ts.centuries += floor(ts.decades / DECADES_PER_CENTURY); ts.decades %= DECADES_PER_CENTURY; if (ts.centuries >= CENTURIES_PER_MILLENNIUM) { // ripple centuries up to millennia ts.millennia += floor(ts.centuries / CENTURIES_PER_MILLENNIUM); ts.centuries %= CENTURIES_PER_MILLENNIUM; } } } } /** * Remove any units not requested * * @private * @param {Timespan} ts * @param {number} units the units to populate * @param {number} max number of labels to output * @param {number} digits max number of decimal digits to output */ function pruneUnits(ts, units, max, digits) { var count = 0; // Calc from largest unit to smallest to prevent underflow if (!(units & MILLENNIA) || (count >= max)) { // ripple millennia down to centuries ts.centuries += ts.millennia * CENTURIES_PER_MILLENNIUM; delete ts.millennia; } else if (ts.millennia) { count++; } if (!(units & CENTURIES) || (count >= max)) { // ripple centuries down to decades ts.decades += ts.centuries * DECADES_PER_CENTURY; delete ts.centuries; } else if (ts.centuries) { count++; } if (!(units & DECADES) || (count >= max)) { // ripple decades down to years ts.years += ts.decades * YEARS_PER_DECADE; delete ts.decades; } else if (ts.decades) { count++; } if (!(units & YEARS) || (count >= max)) { // ripple years down to months ts.months += ts.years * MONTHS_PER_YEAR; delete ts.years; } else if (ts.years) { count++; } if (!(units & MONTHS) || (count >= max)) { // ripple months down to days if (ts.months) { ts.days += borrowMonths(ts.refMonth, ts.months); } delete ts.months; if (ts.days >= DAYS_PER_WEEK) { // ripple day overflow back up to weeks ts.weeks += floor(ts.days / DAYS_PER_WEEK); ts.days %= DAYS_PER_WEEK; } } else if (ts.months) { count++; } if (!(units & WEEKS) || (count >= max)) { // ripple weeks down to days ts.days += ts.weeks * DAYS_PER_WEEK; delete ts.weeks; } else if (ts.weeks) { count++; } if (!(units & DAYS) || (count >= max)) { //ripple days down to hours ts.hours += ts.days * HOURS_PER_DAY; delete ts.days; } else if (ts.days) { count++; } if (!(units & HOURS) || (count >= max)) { // ripple hours down to minutes ts.minutes += ts.hours * MINUTES_PER_HOUR; delete ts.hours; } else if (ts.hours) { count++; } if (!(units & MINUTES) || (count >= max)) { // ripple minutes down to seconds ts.seconds += ts.minutes * SECONDS_PER_MINUTE; delete ts.minutes; } else if (ts.minutes) { count++; } if (!(units & SECONDS) || (count >= max)) { // ripple seconds down to milliseconds ts.milliseconds += ts.seconds * MILLISECONDS_PER_SECOND; delete ts.seconds; } else if (ts.seconds) { count++; } // nothing to ripple milliseconds down to // so ripple back up to smallest existing unit as a fractional value if (!(units & MILLISECONDS) || (count >= max)) { fractional(ts, digits); } } /** * Populates the Timespan object * * @private * @param {Timespan} ts * @param {?Date} start the starting date * @param {?Date} end the ending date * @param {number} units the units to populate * @param {number} max number of labels to output * @param {number} digits max number of decimal digits to output */ function populate(ts, start, end, units, max, digits) { var now = new Date(); ts.start = start = start || now; ts.end = end = end || now; ts.units = units; ts.value = end.getTime() - start.getTime(); if (ts.value < 0) { // swap if reversed var tmp = end; end = start; start = tmp; } // reference month for determining days in month ts.refMonth = new Date(start.getFullYear(), start.getMonth(), 15, 12, 0, 0); try { // reset to initial deltas ts.millennia = 0; ts.centuries = 0; ts.decades = 0; ts.years = end.getFullYear() - start.getFullYear(); ts.months = end.getMonth() - start.getMonth(); ts.weeks = 0; ts.days = end.getDate() - start.getDate(); ts.hours = end.getHours() - start.getHours(); ts.minutes = end.getMinutes() - start.getMinutes(); ts.seconds = end.getSeconds() - start.getSeconds(); ts.milliseconds = end.getMilliseconds() - start.getMilliseconds(); ripple(ts); pruneUnits(ts, units, max, digits); } finally { delete ts.refMonth; } return ts; } /** * Determine an appropriate refresh rate based upon units * * @private * @param {number} units the units to populate * @return {number} milliseconds to delay */ function getDelay(units) { if (units & MILLISECONDS) { // refresh very quickly return MILLISECONDS_PER_SECOND / 30; //30Hz } if (units & SECONDS) { // refresh every second return MILLISECONDS_PER_SECOND; //1Hz } if (units & MINUTES) { // refresh every minute return MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE; } if (units & HOURS) { // refresh hourly return MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE * MINUTES_PER_HOUR; } if (units & DAYS) { // refresh daily return MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY; } // refresh the rest weekly return MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY * DAYS_PER_WEEK; } /** * API entry point * * @public * @param {Date|number|null|function(Timespan,number)} start the starting date * @param {Date|number|null|function(Timespan,number)} end the ending date * @param {number} units the units to populate * @param {number} max number of labels to output * @param {number} digits max number of decimal digits to output * @return {Timespan|number} */ function countdown(start, end, units, max, digits) { var callback; // ensure some units or use defaults units = +units || DEFAULTS; // max must be positive max = (max > 0) ? max : NaN; // clamp digits to an integer between [0, 20] digits = (digits > 0) ? (digits < 20) ? Math.round(digits) : 20 : 0; // ensure start date if ('function' === typeof start) { callback = start; start = null; } else if (!(start instanceof Date)) { start = (start !== null && isFinite(start)) ? new Date(start) : null; } // ensure end date if ('function' === typeof end) { callback = end; end = null; } else if (!(end instanceof Date)) { end = (end !== null && isFinite(end)) ? new Date(end) : null; } if (!start && !end) { // used for unit testing return new Timespan(); } if (!callback) { return populate(new Timespan(), /** @type{?Date} */(start), /** @type{?Date} */(end), units, max, digits); } // base delay off units var delay = getDelay(units), timerId, fn = function() { callback( populate(new Timespan(), /** @type{?Date} */(start), /** @type{?Date} */(end), units, max, digits), timerId ); }; fn(); return (timerId = setInterval(fn, delay)); } /** * @public * @const * @type {number} */ countdown.MILLISECONDS = MILLISECONDS; /** * @public * @const * @type {number} */ countdown.SECONDS = SECONDS; /** * @public * @const * @type {number} */ countdown.MINUTES = MINUTES; /** * @public * @const * @type {number} */ countdown.HOURS = HOURS; /** * @public * @const * @type {number} */ countdown.DAYS = DAYS; /** * @public * @const * @type {number} */ countdown.WEEKS = WEEKS; /** * @public * @const * @type {number} */ countdown.MONTHS = MONTHS; /** * @public * @const * @type {number} */ countdown.YEARS = YEARS; /** * @public * @const * @type {number} */ countdown.DECADES = DECADES; /** * @public * @const * @type {number} */ countdown.CENTURIES = CENTURIES; /** * @public * @const * @type {number} */ countdown.MILLENNIA = MILLENNIA; /** * @public * @const * @type {number} */ countdown.DEFAULTS = DEFAULTS; /** * @public * @const * @type {number} */ countdown.ALL = MILLENNIA|CENTURIES|DECADES|YEARS|MONTHS|WEEKS|DAYS|HOURS|MINUTES|SECONDS|MILLISECONDS; /** * Override the unit labels * @public * @param {string|Array} singular a pipe ('|') delimited list of singular unit name overrides * @param {string|Array} plural a pipe ('|') delimited list of plural unit name overrides * @param {string} last a prefix for the last unit if more than one (default: 'and ') * @param {string} delim a delimiter to use between units (default: ', ') */ var setLabels = countdown.setLabels = function(singular, plural, last, delim) { singular = singular || []; if (singular.split) { singular = singular.split('|'); } plural = plural || []; if (plural.split) { plural = plural.split('|'); } for (var i=LABEL_MILLISECONDS; i<=LABEL_MILLENNIA; i++) { // override any specified units LABELS_SINGLUAR[i] = singular[i] || LABELS_SINGLUAR[i]; LABELS_PLURAL[i] = plural[i] || LABELS_PLURAL[i]; } LABEL_LAST = ('string' === typeof last) ? last : LABEL_LAST; LABEL_DELIM = ('string' === typeof delim) ? delim : LABEL_DELIM; }; /** * Revert to the default unit labels * @public */ var resetLabels = countdown.resetLabels = function() { LABELS_SINGLUAR = 'millisecond|second|minute|hour|day|week|month|year|decade|century|millennium'.split('|'); LABELS_PLURAL = 'milliseconds|seconds|minutes|hours|days|weeks|months|years|decades|centuries|millennia'.split('|'); LABEL_LAST = 'and '; LABEL_DELIM = ', '; }; resetLabels(); if (module && module.exports) { module.exports = countdown; } else if (typeof window.define === 'function' && typeof window.define.amd !== 'undefined') { window.define('countdown', [], function() { return countdown; }); } return countdown; })(module); return { restrict: 'EA', replace: true, transclude: true, scope: { stopdate : '@' }, templateUrl: function(element, attributes) { return 'angularcountdown.html'; }, link: function($scope) { var time = new Date($scope.stopdate).getTime(); $interval(function(){ $scope.timespan = countdown(null, time, countdown.DAYS|countdown.HOURS|countdown.MINUTES|countdown.SECONDS, 5); angular.element('#days').html($scope.timespan.days.toString()); angular.element('#hours').html($scope.timespan.hours.toString()); angular.element('#minutes').html($scope.timespan.minutes.toString()); angular.element('#seconds').html($scope.timespan.seconds.toString()); }, 1000); } }; }]);