\");\n this.container.addClass('time_circles');\n this.container.appendTo(this.element);\n\n \/\/ Determine the needed width and height of TimeCircles.\n var height = this.element.offsetHeight;\n var width = this.element.offsetWidth;\n if (height === 0) {\n height = $(this.element).height();\n }\n if (width === 0) {\n width = $(this.element).width();\n }\n\n if (height === 0 && width > 0) {\n height = width \/ this.data.drawn_units.length;\n }\n else if (width === 0 && height > 0) {\n width = height * this.data.drawn_units.length;\n }\n\n \/\/ Create our canvas and set it to the appropriate size.\n var canvasElement = document.createElement('canvas');\n canvasElement.width = width;\n canvasElement.height = height;\n\n \/\/ Add canvas elements.\n this.data.attributes.canvas = $(canvasElement);\n this.data.attributes.canvas.appendTo(this.container);\n\n \/\/ Check if the browser has browser support.\n var canvasSupported = isCanvasSupported();\n \/\/ If the browser doesn't have browser support, check if explorer canvas is loaded.\n \/\/ (A javascript library that adds canvas support to browsers that don't have it).\n if (!canvasSupported && typeof G_vmlCanvasManager !== \"undefined\") {\n G_vmlCanvasManager.initElement(canvasElement);\n limited_mode = true;\n canvasSupported = true;\n }\n if (canvasSupported) {\n this.data.attributes.context = canvasElement.getContext('2d');\n }\n\n this.data.attributes.item_size = Math.min(width \/ this.data.drawn_units.length, height);\n this.data.attributes.line_width = this.data.attributes.item_size * this.config.fg_width;\n this.data.attributes.radius = ((this.data.attributes.item_size * 0.8) - this.data.attributes.line_width) \/ 2;\n this.data.attributes.outer_radius = this.data.attributes.radius + 0.5 * Math.max(this.data.attributes.line_width, this.data.attributes.line_width * this.config.bg_width);\n\n \/\/ Prepare Time Elements.\n var i = 0;\n for (var key in this.data.text_elements) {\n if (!this.config.time[key].show) {\n continue;\n }\n\n var textElement = $(\"
\");\n textElement.addClass('textDiv_' + key);\n textElement.css(\"top\", Math.round(0.35 * this.data.attributes.item_size));\n textElement.css(\"left\", Math.round(i++ * this.data.attributes.item_size));\n textElement.css(\"width\", this.data.attributes.item_size);\n textElement.appendTo(this.container);\n\n var headerElement = $(\"
\");\n headerElement.text(this.config.time[key].text); \/\/ Options.\n headerElement.css(\"font-size\", Math.round(this.config.text_size * this.data.attributes.item_size));\n headerElement.appendTo(textElement);\n\n var numberElement = $(\"\");\n numberElement.css(\"font-size\", Math.round(this.config.number_size * this.data.attributes.item_size));\n numberElement.appendTo(textElement);\n\n this.data.text_elements[key] = numberElement;\n }\n\n this.start();\n if (!this.config.start) {\n this.data.paused = true;\n }\n\n \/\/ Set up interval fallback.\n var _this = this;\n this.data.interval_fallback = useWindow.setInterval(function() {\n _this.update.call(_this, true);\n }, 100);\n };\n\n TC_Instance.prototype.update = function(nodraw) {\n if (typeof nodraw === \"undefined\") {\n nodraw = false;\n }\n else if (nodraw && this.data.paused) {\n return;\n }\n\n if (limited_mode) {\n \/\/ Per unit clearing doesn't work in IE8 using explorer canvas, so do it in one time. The downside is that radial fade cant be used.\n this.data.attributes.context.clearRect(0, 0, this.data.attributes.canvas[0].width, this.data.attributes.canvas[0].hright);\n }\n var diff, old_diff;\n\n var prevDate = this.data.prev_time;\n var curDate = new Date();\n this.data.prev_time = curDate;\n\n if (prevDate === null) {\n prevDate = curDate;\n }\n\n \/\/ If not counting past zero, and time < 0, then simply draw the zero point once, and call stop.\n if (!this.config.count_past_zero) {\n if (curDate > this.data.attributes.ref_date) {\n for (var i = 0; i < this.data.drawn_units.length; i++) {\n var key = this.data.drawn_units[i];\n\n \/\/ Set the text value.\n this.data.text_elements[key].text(\"0\");\n var x = (i * this.data.attributes.item_size) + (this.data.attributes.item_size \/ 2);\n var y = this.data.attributes.item_size \/ 2;\n var color = this.config.time[key].color;\n this.drawArc(x, y, color, 0);\n }\n this.stop();\n return;\n }\n }\n\n \/\/ Compare current time with reference.\n diff = (this.data.attributes.ref_date - curDate) \/ 1000;\n old_diff = (this.data.attributes.ref_date - prevDate) \/ 1000;\n\n var floor = this.config.animation !== \"smooth\";\n\n var visible_times = parse_times(diff, old_diff, this.data.total_duration, this.data.drawn_units, floor);\n var all_times = parse_times(diff, old_diff, secondsIn[\"Years\"], allUnits, floor);\n\n var i = 0;\n var j = 0;\n var lastKey = null;\n\n var cur_shown = this.data.drawn_units.slice();\n for (var i in allUnits) {\n var key = allUnits[i];\n\n \/\/ Notify (all) listeners.\n if (Math.floor(all_times.raw_time[key]) !== Math.floor(all_times.raw_old_time[key])) {\n this.notifyListeners(key, Math.floor(all_times.time[key]), Math.floor(diff), \"all\");\n }\n\n if (cur_shown.indexOf(key) < 0) {\n continue;\n }\n\n \/\/ Notify (visible) listeners.\n if (Math.floor(visible_times.raw_time[key]) !== Math.floor(visible_times.raw_old_time[key])) {\n this.notifyListeners(key, Math.floor(visible_times.time[key]), Math.floor(diff), \"visible\");\n }\n\n if (!nodraw) {\n \/\/ Set the text value.\n this.data.text_elements[key].text(Math.floor(Math.abs(visible_times.time[key])));\n\n var x = (j * this.data.attributes.item_size) + (this.data.attributes.item_size \/ 2);\n var y = this.data.attributes.item_size \/ 2;\n var color = this.config.time[key].color;\n\n if (this.config.animation === \"smooth\") {\n if (lastKey !== null && !limited_mode) {\n if (Math.floor(visible_times.time[lastKey]) > Math.floor(visible_times.old_time[lastKey])) {\n this.radialFade(x, y, color, 1, key);\n this.data.state.fading[key] = true;\n }\n else if (Math.floor(visible_times.time[lastKey]) < Math.floor(visible_times.old_time[lastKey])) {\n this.radialFade(x, y, color, 0, key);\n this.data.state.fading[key] = true;\n }\n }\n if (!this.data.state.fading[key]) {\n this.drawArc(x, y, color, visible_times.pct[key]);\n }\n }\n else {\n this.animateArc(x, y, color, visible_times.pct[key], visible_times.old_pct[key], (new Date()).getTime() + tick_duration);\n }\n }\n lastKey = key;\n j++;\n }\n\n \/\/ Dont request another update if we should be paused.\n if (this.data.paused || nodraw) {\n return;\n }\n\n \/\/ We need this for our next frame either way.\n var _this = this;\n var update = function() {\n _this.update.call(_this);\n };\n\n \/\/ Either call next update immediately, or in a second.\n if (this.config.animation === \"smooth\") {\n \/\/ Smooth animation, Queue up the next frame.\n this.data.animation_frame = useWindow.requestAnimationFrame(update, _this.element, _this);\n }\n else {\n \/\/ Tick animation, Don't queue until very slightly after the next second happens.\n var delay = (diff % 1) * 1000;\n if (delay < 0) {\n delay = 1000 + delay;\n }\n delay += 50;\n\n _this.data.animation_frame = useWindow.setTimeout(function() {\n _this.data.animation_frame = useWindow.requestAnimationFrame(update, _this.element, _this);\n }, delay);\n }\n };\n\n TC_Instance.prototype.animateArc = function(x, y, color, target_pct, cur_pct, animation_end) {\n if (this.data.attributes.context === null) {\n return;\n }\n\n var diff = cur_pct - target_pct;\n if (Math.abs(diff) > 0.5) {\n if (target_pct === 0) {\n this.radialFade(x, y, color, 1);\n }\n else {\n this.radialFade(x, y, color, 0);\n }\n }\n else {\n var progress = (tick_duration - (animation_end - (new Date()).getTime())) \/ tick_duration;\n if (progress > 1) {\n progress = 1;\n }\n\n var pct = (cur_pct * (1 - progress)) + (target_pct * progress);\n this.drawArc(x, y, color, pct);\n\n if (progress >= 1) {\n return;\n }\n var _this = this;\n useWindow.requestAnimationFrame(function() {\n _this.animateArc(x, y, color, target_pct, cur_pct, animation_end);\n }, this.element);\n }\n };\n\n TC_Instance.prototype.drawArc = function(x, y, color, pct) {\n if (this.data.attributes.context === null) {\n return;\n }\n\n var clear_radius = Math.max(this.data.attributes.outer_radius, this.data.attributes.item_size \/ 2);\n if (!limited_mode) {\n this.data.attributes.context.clearRect(\n x - clear_radius,\n y - clear_radius,\n clear_radius * 2,\n clear_radius * 2\n );\n }\n\n if (this.config.use_background) {\n this.data.attributes.context.beginPath();\n this.data.attributes.context.arc(x, y, this.data.attributes.radius, 0, 2 * Math.PI, false);\n this.data.attributes.context.lineWidth = this.data.attributes.line_width * this.config.bg_width;\n\n \/\/ Line color.\n this.data.attributes.context.strokeStyle = this.config.circle_bg_color;\n this.data.attributes.context.stroke();\n }\n\n \/\/ Direction.\n var startAngle, endAngle, counterClockwise;\n var defaultOffset = (-0.5 * Math.PI);\n var fullCircle = 2 * Math.PI;\n startAngle = defaultOffset + (this.config.start_angle \/ 360 * fullCircle);\n var offset = (2 * pct * Math.PI);\n\n if (this.config.direction === \"Both\") {\n counterClockwise = false;\n startAngle -= (offset \/ 2);\n endAngle = startAngle + offset;\n }\n else {\n if (this.config.direction === \"Clockwise\") {\n counterClockwise = false;\n endAngle = startAngle + offset;\n }\n else {\n counterClockwise = true;\n endAngle = startAngle - offset;\n }\n }\n\n this.data.attributes.context.beginPath();\n this.data.attributes.context.arc(x, y, this.data.attributes.radius, startAngle, endAngle, counterClockwise);\n this.data.attributes.context.lineWidth = this.data.attributes.line_width;\n\n \/\/ Line color.\n this.data.attributes.context.strokeStyle = color;\n this.data.attributes.context.stroke();\n };\n\n TC_Instance.prototype.radialFade = function(x, y, color, from, key) {\n \/\/ TODO: Make fade_time option.\n var rgb = hexToRgb(color);\n var _this = this; \/\/ We have a few inner scopes here that will need access to our instance.\n\n var step = 0.2 * ((from === 1) ? -1 : 1);\n var i;\n for (i = 0; from <= 1 && from >= 0; i++) {\n \/\/ Create inner scope so our variables are not changed by the time the Timeout triggers.\n (function() {\n var delay = 50 * i;\n var rgba = \"rgba(\" + rgb.r + \", \" + rgb.g + \", \" + rgb.b + \", \" + (Math.round(from * 10) \/ 10) + \")\";\n useWindow.setTimeout(function() {\n _this.drawArc(x, y, rgba, 1);\n }, delay);\n }());\n from += step;\n }\n if (typeof key !== undefined) {\n useWindow.setTimeout(function() {\n _this.data.state.fading[key] = false;\n }, 50 * i);\n }\n };\n\n TC_Instance.prototype.timeLeft = function() {\n if (this.data.paused && typeof this.data.timer === \"number\") {\n return this.data.timer;\n }\n var now = new Date();\n return ((this.data.attributes.ref_date - now) \/ 1000);\n };\n\n TC_Instance.prototype.start = function() {\n useWindow.cancelAnimationFrame(this.data.animation_frame);\n useWindow.clearTimeout(this.data.animation_frame)\n\n \/\/ Check if a date was passed in html attribute or jquery data.\n var attr_data_date = $(this.element).data('date');\n if (typeof attr_data_date === \"undefined\") {\n attr_data_date = $(this.element).attr('data-date');\n }\n if (typeof attr_data_date === \"string\") {\n this.data.attributes.ref_date = parse_date(attr_data_date);\n }\n \/\/ Check if this is an unpause of a timer.\n else if (typeof this.data.timer === \"number\") {\n if (this.data.paused) {\n this.data.attributes.ref_date = (new Date()).getTime() + (this.data.timer * 1000);\n }\n }\n else {\n \/\/ Try to get data-timer.\n var attr_data_timer = $(this.element).data('timer');\n if (typeof attr_data_timer === \"undefined\") {\n attr_data_timer = $(this.element).attr('data-timer');\n }\n if (typeof attr_data_timer === \"string\") {\n attr_data_timer = parseFloat(attr_data_timer);\n }\n if (typeof attr_data_timer === \"number\") {\n this.data.timer = attr_data_timer;\n this.data.attributes.ref_date = (new Date()).getTime() + (attr_data_timer * 1000);\n }\n else {\n \/\/ Data-timer and data-date were both not set.\n \/\/ Use config date.\n this.data.attributes.ref_date = this.config.ref_date;\n }\n }\n\n \/\/ Start running.\n this.data.paused = false;\n this.update.call(this);\n };\n\n TC_Instance.prototype.restart = function() {\n this.data.timer = false;\n this.start();\n };\n\n TC_Instance.prototype.stop = function() {\n if (typeof this.data.timer === \"number\") {\n this.data.timer = this.timeLeft(this);\n }\n \/\/ Stop running.\n this.data.paused = true;\n useWindow.cancelAnimationFrame(this.data.animation_frame);\n };\n\n TC_Instance.prototype.destroy = function() {\n this.clearListeners();\n this.stop();\n useWindow.clearInterval(this.data.interval_fallback);\n this.data.interval_fallback = null;\n\n this.container.remove();\n $(this.element).removeAttr('data-tc-id');\n $(this.element).removeData('tc-id');\n };\n\n TC_Instance.prototype.setOptions = function(options) {\n if (this.config === null) {\n this.default_options.ref_date = new Date();\n this.config = $.extend(true, {}, this.default_options);\n }\n $.extend(true, this.config, options);\n\n \/\/ Use window.top if use_top_frame is true.\n if (this.config.use_top_frame) {\n useWindow = window.top;\n }\n else {\n useWindow = window;\n }\n updateUsedWindow();\n\n this.data.total_duration = this.config.total_duration;\n if (typeof this.data.total_duration === \"string\") {\n if (typeof secondsIn[this.data.total_duration] !== \"undefined\") {\n \/\/ If set to Years, Months, Days, Hours or Minutes, fetch the secondsIn value for that.\n this.data.total_duration = secondsIn[this.data.total_duration];\n }\n else if (this.data.total_duration === \"Auto\") {\n \/\/ If set to auto, total_duration is the size of 1 unit, of the unit type bigger than the largest shown.\n for (var i = 0; i < Object.keys(this.config.time).length; i++) {\n var unit = Object.keys(this.config.time)[i];\n if (this.config.time[unit].show) {\n this.data.total_duration = secondsIn[nextUnits[unit]];\n break;\n }\n }\n }\n else {\n \/\/ If it's a string, but neither of the above, user screwed up.\n this.data.total_duration = secondsIn[\"Years\"];\n notification.exception({\n debuginfo: '',\n msg: \"Valid values for TimeCircles config.total_duration are either numeric, or (string) Years, Months, Days, Hours, Minutes, Auto\"\n });\n }\n }\n };\n\n TC_Instance.prototype.addListener = function(f, context, type) {\n if (typeof f !== \"function\") {\n return;\n }\n if (typeof type === \"undefined\") {\n type = \"visible\";\n }\n this.listeners[type].push({func: f, scope: context});\n };\n\n TC_Instance.prototype.notifyListeners = function(unit, value, total, type) {\n for (var i = 0; i < this.listeners[type].length; i++) {\n var listener = this.listeners[type][i];\n listener.func.apply(listener.scope, [unit, value, total]);\n }\n };\n\n TC_Instance.prototype.default_options = {\n ref_date: new Date(),\n start: true,\n animation: \"smooth\",\n count_past_zero: true,\n circle_bg_color: \"#60686F\",\n use_background: true,\n fg_width: 0.1,\n bg_width: 1.2,\n text_size: 0.07,\n number_size: 0.28,\n total_duration: \"Auto\",\n direction: \"Clockwise\",\n use_top_frame: false,\n start_angle: 0,\n time: {\n Days: {\n show: true,\n text: \"Days\",\n color: \"#FC6\"\n },\n Hours: {\n show: true,\n text: \"Hours\",\n color: \"#9CF\"\n },\n Minutes: {\n show: true,\n text: \"Minutes\",\n color: \"#BFB\"\n },\n Seconds: {\n show: true,\n text: \"Seconds\",\n color: \"#F99\"\n }\n }\n };\n\n \/\/ Time circle class.\n var TC_Class = function(elements, options) {\n this.elements = elements;\n this.options = options;\n this.foreach();\n };\n\n TC_Class.prototype.getInstance = function(element) {\n var instance;\n\n var cur_id = $(element).data(\"tc-id\");\n if (typeof cur_id === \"undefined\") {\n cur_id = guid();\n $(element).attr(\"data-tc-id\", cur_id);\n }\n if (typeof TC_Instance_List[cur_id] === \"undefined\") {\n var options = this.options;\n var element_options = $(element).data('options');\n if (typeof element_options === \"string\") {\n element_options = JSON.parse(element_options);\n }\n if (typeof element_options === \"object\") {\n options = $.extend(true, {}, this.options, element_options);\n }\n instance = new TC_Instance(element, options);\n TC_Instance_List[cur_id] = instance;\n }\n else {\n instance = TC_Instance_List[cur_id];\n if (typeof this.options !== \"undefined\") {\n instance.setOptions(this.options);\n }\n }\n return instance;\n };\n\n TC_Class.prototype.addTime = function(seconds_to_add) {\n this.foreach(function(instance) {\n instance.addTime(seconds_to_add);\n });\n };\n\n TC_Class.prototype.foreach = function(callback) {\n var _this = this;\n this.elements.each(function() {\n var instance = _this.getInstance(this);\n if (typeof callback === \"function\") {\n callback(instance);\n }\n });\n return this;\n };\n\n TC_Class.prototype.start = function() {\n this.foreach(function(instance) {\n instance.start();\n });\n return this;\n };\n\n TC_Class.prototype.stop = function() {\n this.foreach(function(instance) {\n instance.stop();\n });\n return this;\n };\n\n TC_Class.prototype.restart = function() {\n this.foreach(function(instance) {\n instance.restart();\n });\n return this;\n };\n\n TC_Class.prototype.rebuild = function() {\n this.foreach(function(instance) {\n instance.initialize(false);\n });\n return this;\n };\n\n TC_Class.prototype.getTime = function() {\n return this.getInstance(this.elements[0]).timeLeft();\n };\n\n TC_Class.prototype.addListener = function(f, type) {\n if (typeof type === \"undefined\") {\n type = \"visible\";\n }\n var _this = this;\n this.foreach(function(instance) {\n instance.addListener(f, _this.elements, type);\n });\n return this;\n };\n\n TC_Class.prototype.destroy = function() {\n this.foreach(function(instance) {\n instance.destroy();\n });\n return this;\n };\n\n TC_Class.prototype.end = function() {\n return this.elements;\n };\n\n $.fn.TimeCircles = function(options) {\n return new TC_Class(this, options);\n };\n}));\n"],"file":"TimeCircles.min.js"}