PageSourceSearch

https://sioldz.com/wp-content/plugins/countdown-timer-ultimate/assets/js/wpcdt-timecircles.js?ver=2.6.9

js sioldz.com collected 2026-10-04 21:58:28 UTC 26,531 bytes, 932 lines download raw bytes

vendor: 1,173 bytes, lines 1-48
1(function($) {
2
3	var useWindow = window;
4
5	/* From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys */
6	if (!Object.keys) {
7		Object.keys = (function() {
8			'use strict';
9			var hasOwnProperty = Object.prototype.hasOwnProperty,
10					hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
11					dontEnums = [
12						'toString',
13						'toLocaleString',
14						'valueOf',
15						'hasOwnProperty',
16						'isPrototypeOf',
17						'propertyIsEnumerable',
18						'constructor'
19					],
20					dontEnumsLength = dontEnums.length;
21
22			return function(obj) {
23				if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
24					throw new TypeError('Object.keys called on non-object');
25				}
26
27				var result = [], prop, i;
28
29				for (prop in obj) {
30					if (hasOwnProperty.call(obj, prop)) {
31						result.push(prop);
32					}
33				}
34
35				if (hasDontEnumBug) {
36					for (i = 0; i < dontEnumsLength; i++) {
37						if (hasOwnProperty.call(obj, dontEnums[i])) {
38							result.push(dontEnums[i]);
39						}
40					}
41				}
42				return result;
43			};
44		}());
45	}
46
47	/* Used to disable some features on IE8 */
48	var limited_mode = false;
49	var tick_duration = 200; // in ms
50
51	var debug = (location.hash === "#debug");
52	function debug_log(msg) {
53		if (debug) {
54			console.log(msg);
55		}
56	}
57
58	var allUnits = ["Days", "Hours", "Minutes", "Seconds"];
59	var nextUnits = {
60		Seconds: "Minutes",
61		Minutes: "Hours",
62		Hours: "Days",
63		Days: "Years"
64	};
65	var secondsIn = {
66		Seconds: 1,
67		Minutes: 60,
68		Hours: 3600,
69		Days: 86400,
70		Months: 2678400,
71		Years: 31536000
72	};
73
74	/**
75	 * Converts hex color code into object containing integer values for the r,g,b use
76	 * This function (hexToRgb) originates from:
77	 * http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
78	 * @param {string} hex color code
79	 */
80	function hexToRgb(hex) {
81		// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
82		var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
83		hex = hex.replace(shorthandRegex, function(m, r, g, b) {
84			return r + r + g + g + b + b;
85		});
86
87		var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
88		return result ? {
89			r: parseInt(result[1], 16),
90			g: parseInt(result[2], 16),
91			b: parseInt(result[3], 16)
92		} : null;
93	}
94
95	function isCanvasSupported() {
96		var elem = document.createElement('canvas');
97		return !!(elem.getContext && elem.getContext('2d'));
98	}
99
100	/**
101	 * Function s4() and guid() originate from:
102	 * http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
103	 */
104	function s4() {
105		return Math.floor((1 + Math.random()) * 0x10000)
106				.toString(16)
107				.substring(1);
108	}
109
110	/**
111	 * Creates a unique id
112	 * @returns {String}
113	 */
114	function guid() {
115		return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
116				s4() + '-' + s4() + s4() + s4();
117	}
118
119	/**
120	 * Array.prototype.indexOf fallback for IE8
121	 * @param {Mixed} mixed
122	 * @returns {Number}
123	 */
124	if (!Array.prototype.indexOf) {
125		Array.prototype.indexOf = function(elt /*, from*/)
126		{
127			var len = this.length >>> 0;
128
129			var from = Number(arguments[1]) || 0;
130			from = (from < 0)
131					? Math.ceil(from)
132					: Math.floor(from);
133			if (from < 0)
134				from += len;
135
136			for (; from < len; from++)
137			{
138				if (from in this &&
139						this[from] === elt)
140					return from;
141			}
142			return -1;
143		};
144	}
145
146	function parse_date(str) {
147		var match = str.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{1,2}:[0-9]{2}:[0-9]{2}$/);
148		if (match !== null && match.length > 0) {
149			var parts = str.split(" ");
150			var date = parts[0].split("-");
151			var time = parts[1].split(":");
152			return new Date(date[0], date[1] - 1, date[2], time[0], time[1], time[2]);
153		}
154		/* Fallback for different date formats */
155		var d = Date.parse(str);
156		if (!isNaN(d))
157			return d;
158		d = Date.parse(str.replace(/-/g, '/').replace('T', ' '));
159		if (!isNaN(d))
160			return d;
161		/* Cant find anything */
162		return new Date();
163	}
164
165	function parse_times(diff, old_diff, total_duration, units, floor) {
166		var raw_time = {};
167		var raw_old_time = {};
168		var time = {};
169		var pct = {};
170		var old_pct = {};
171		var old_time = {};
172
173		var greater_unit = null;
174		for(var i = 0; i < units.length; i++) {
175			var unit = units[i];
176			var maxUnits;
177
178			if (greater_unit === null) {
179				maxUnits = total_duration / secondsIn[unit];
180			}
181			else {
182				maxUnits = secondsIn[greater_unit] / secondsIn[unit];
183			}
184
185			var curUnits = (diff / secondsIn[unit]);
186			var oldUnits = (old_diff / secondsIn[unit]);
187
188			if(floor) {
189				if(curUnits > 0) curUnits = Math.floor(curUnits);
190				else curUnits = Math.ceil(curUnits);
191				if(oldUnits > 0) oldUnits = Math.floor(oldUnits);
192				else oldUnits = Math.ceil(oldUnits);
193			}
194
195			if (unit !== "Days") {
196				curUnits = curUnits % maxUnits;
197				oldUnits = oldUnits % maxUnits;
198			}
199
200			raw_time[unit] = curUnits;
201			time[unit] = Math.abs(curUnits);
202			raw_old_time[unit] = oldUnits;
203			old_time[unit] = Math.abs(oldUnits);
204			pct[unit] = Math.abs(curUnits) / maxUnits;
205			old_pct[unit] = Math.abs(oldUnits) / maxUnits;
206
207			greater_unit = unit;
208		}
209
210		return {
211			raw_time: raw_time,
212			raw_old_time: raw_old_time,
213			time: time,
214			old_time: old_time,
215			pct: pct,
216			old_pct: old_pct
217		};
218	}
219
220	var TC_Instance_List = {};
221	function updateUsedWindow() {
222		if(typeof useWindow.TC_Instance_List !== "undefined") {
223			TC_Instance_List = useWindow.TC_Instance_List;
224		}
225		else {
226			useWindow.TC_Instance_List = TC_Instance_List;
227		}
228		initializeAnimationFrameHandler(useWindow);
229	};
230
231	function initializeAnimationFrameHandler(w) {
232		var vendors = ['webkit', 'moz'];
233		for (var x = 0; x < vendors.length && !w.requestAnimationFrame; ++x) {
234			w.requestAnimationFrame = w[vendors[x] + 'RequestAnimationFrame'];
235			w.cancelAnimationFrame = w[vendors[x] + 'CancelAnimationFrame'];
236		}
237
238		if (!w.requestAnimationFrame || !w.cancelAnimationFrame) {
239			w.requestAnimationFrame = function(callback, element, instance) {
240				if (typeof instance === "undefined")
241					instance = {data: {last_frame: 0}};
242				var currTime = new Date().getTime();
243				var timeToCall = Math.max(0, 16 - (currTime - instance.data.last_frame));
244				var id = w.setTimeout(function() {
245					callback(currTime + timeToCall);
246				}, timeToCall);
247				instance.data.last_frame = currTime + timeToCall;
248				return id;
249			};
250			w.cancelAnimationFrame = function(id) {
251				clearTimeout(id);
252			};
253		}
254	};
255
256	var TC_Instance = function(element, options) {
257		this.element = element;
258		this.container;
259		this.listeners = null;
260		this.data = {
261			paused: false,
262			last_frame: 0,
263			animation_frame: null,
264			interval_fallback: null,
265			timer: false,
266			total_duration: null,
267			prev_time: null,
268			drawn_units: [],
269			text_elements: {
270				Days: null,
271				Hours: null,
272				Minutes: null,
273				Seconds: null
274			},
275			attributes: {
276				canvas: null,
277				context: null,
278				item_size: null,
279				line_width: null,
280				radius: null,
281				outer_radius: null
282			},
283			state: {
284				fading: {
285					Days: false,
286					Hours: false,
287					Minutes: false,
288					Seconds: false
289				}
290			}
291		};
292
293		this.config = null;
294		this.setOptions(options);
295		this.initialize();
296	};
297
298	TC_Instance.prototype.clearListeners = function() {
299		this.listeners = { all: [], visible: [] };
300	};
301
302	TC_Instance.prototype.addTime = function(seconds_to_add) {
303		if(this.data.attributes.ref_date instanceof Date) {
304			var d = this.data.attributes.ref_date;
305			d.setSeconds(d.getSeconds() + seconds_to_add);
306		}
307		else if(!isNaN(this.data.attributes.ref_date)) {
308			this.data.attributes.ref_date += (seconds_to_add * 1000);
309		}
310	};
311
312	TC_Instance.prototype.initialize = function(clear_listeners) {
313		/* Initialize drawn units */
314		this.data.drawn_units = [];
315		for(var i = 0; i < Object.keys(this.config.time).length; i++) {
316			var unit = Object.keys(this.config.time)[i];
317			if (this.config.time[unit].show) {
318				this.data.drawn_units.push(unit);
319			}
320		}
321
322		/* Avoid stacking */
323		$(this.element).children('div.time_circles').remove();
324
325		if (typeof clear_listeners === "undefined")
326			clear_listeners = true;
327		if (clear_listeners || this.listeners === null) {
328			this.clearListeners();
329		}
330		this.container = $("<div>");
331		this.container.addClass('time_circles');
332		this.container.appendTo(this.element);
333
334		/* Determine the needed width and height of TimeCircles */
335		var height = this.element.offsetHeight;
336		var width = this.element.offsetWidth;
337		if (height === 0)
338			height = $(this.element).height();
339		if (width === 0)
340			width = $(this.element).width();
341
342		if (height === 0 && width > 0)
343			height = width / this.data.drawn_units.length;
344		else if (width === 0 && height > 0)
345			width = height * this.data.drawn_units.length;
346
347		/* Create our canvas and set it to the appropriate size */
348		var canvasElement = document.createElement('canvas');
349		canvasElement.width = width;
350		canvasElement.height = height;
351
352		/* Add canvas elements */
353		this.data.attributes.canvas = $(canvasElement);
354		this.data.attributes.canvas.appendTo(this.container);
355
356		/* Check if the browser has browser support */
357		var canvasSupported = isCanvasSupported();
358		/* If the browser doesn't have browser support, check if explorer canvas is loaded */
359		/* (A javascript library that adds canvas support to browsers that don't have it) */
360		if(!canvasSupported && typeof G_vmlCanvasManager !== "undefined") {
361			G_vmlCanvasManager.initElement(canvasElement);
362			limited_mode = true;
363			canvasSupported = true;
364		}
365		if(canvasSupported) {
366			this.data.attributes.context = canvasElement.getContext('2d');
367		}
368
369		this.data.attributes.item_size = Math.min(width / this.data.drawn_units.length, height);
370		this.data.attributes.line_width = this.data.attributes.item_size * this.config.fg_width;
371		this.data.attributes.radius = ((this.data.attributes.item_size * 0.8) - this.data.attributes.line_width) / 2;
372		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);
373
374		/* Prepare Time Elements */
375		var i = 0;
376		for (var key in this.data.text_elements) {
377			if (!this.config.time[key].show)
378				continue;
379
380			var textElement = $("<div>");
381			textElement.addClass('textDiv_' + key);
382			textElement.css("top", Math.round(0.35 * this.data.attributes.item_size));
383			textElement.css("left", Math.round(i++ * this.data.attributes.item_size));
384			textElement.css("width", this.data.attributes.item_size);
385			textElement.appendTo(this.container);
386
387			var headerElement = $("<h4>");
388			headerElement.text(this.config.time[key].text); /* Options */
389			headerElement.css("font-size", Math.round(this.config.text_size * this.data.attributes.item_size));
390			headerElement.css("line-height", Math.round(this.config.text_size * this.data.attributes.item_size) + "px");
391			headerElement.appendTo(textElement);
392
393			var numberElement = $("<span>");
394			numberElement.css("font-size", Math.round(3 * this.config.text_size * this.data.attributes.item_size));
395			numberElement.css("line-height", Math.round(this.config.text_size * this.data.attributes.item_size) + "px");
396			numberElement.appendTo(textElement);
397
398			this.data.text_elements[key] = numberElement;
399		}
400
401		this.start();
402		if (!this.config.start) {
403			this.data.paused = true;
404		}
405
406		/* Set up interval fallback */
407		var _this = this;
408		this.data.interval_fallback = useWindow.setInterval(function(){
409			_this.update.call(_this, true);
410		}, 100);
411	};
412
413	TC_Instance.prototype.update = function(nodraw) {
414		if(typeof nodraw === "undefined") {
415			nodraw = false;
416		}
417		else if(nodraw && this.data.paused) {
418			return;
419		}
420
421		if(limited_mode) {
422			/* 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 */
423			this.data.attributes.context.clearRect(0, 0, this.data.attributes.canvas[0].width, this.data.attributes.canvas[0].hright);
424		}
425		var diff, old_diff;
426
427		var prevDate = this.data.prev_time;
428		var curDate = new Date();
429		this.data.prev_time = curDate;
430
431		if (prevDate === null)
432			prevDate = curDate;
433
434		/* If not counting past zero, and time < 0, then simply draw the zero point once, and call stop */
435		if (!this.config.count_past_zero) {
436			if (curDate > this.data.attributes.ref_date) {
437				for(var i = 0; i < this.data.drawn_units.length; i++) {
438					var key = this.data.drawn_units[i];
439
440					/* Set the text value */
441					this.data.text_elements[key].text("0");
442					var x = (i * this.data.attributes.item_size) + (this.data.attributes.item_size / 2);
443					var y = this.data.attributes.item_size / 2;
444					var color = this.config.time[key].color;
445					this.drawArc(x, y, color, 0);
446				}
447				this.stop();
448				return;
449			}
450		}
451
452		/* Compare current time with reference */
453		diff = (this.data.attributes.ref_date - curDate) / 1000;
454		old_diff = (this.data.attributes.ref_date - prevDate) / 1000;
455
456		var floor = this.config.animation !== "smooth";
457
458		var visible_times = parse_times(diff, old_diff, this.data.total_duration, this.data.drawn_units, floor);
459		var all_times = parse_times(diff, old_diff, secondsIn["Years"], allUnits, floor);
460
461		var i = 0;
462		var j = 0;
463		var lastKey = null;
464
465		var cur_shown = this.data.drawn_units.slice();
466		for (var i in allUnits) {
467			var key = allUnits[i];
468
469			/* Notify (all) listeners */
470			if (Math.floor(all_times.raw_time[key]) !== Math.floor(all_times.raw_old_time[key])) {
471				this.notifyListeners(key, Math.floor(all_times.time[key]), Math.floor(diff), "all");
472			}
473
474			if (cur_shown.indexOf(key) < 0)
475				continue;
476
477			/* Notify (visible) listeners */
478			if (Math.floor(visible_times.raw_time[key]) !== Math.floor(visible_times.raw_old_time[key])) {
479				this.notifyListeners(key, Math.floor(visible_times.time[key]), Math.floor(diff), "visible");
480			}
481
482			if(!nodraw) {
483				/* Set the text value */
484				this.data.text_elements[key].text(Math.floor(Math.abs(visible_times.time[key])));
485
486				var x = (j * this.data.attributes.item_size) + (this.data.attributes.item_size / 2);
487				var y = this.data.attributes.item_size / 2;
488				var color = this.config.time[key].color;
489
490				if (this.config.animation === "smooth") {
491					if (lastKey !== null && !limited_mode) {
492						if (Math.floor(visible_times.time[lastKey]) > Math.floor(visible_times.old_time[lastKey])) {
493							this.radialFade(x, y, color, 1, key);
494							this.data.state.fading[key] = true;
495						}
496						else if (Math.floor(visible_times.time[lastKey]) < Math.floor(visible_times.old_time[lastKey])) {
497							this.radialFade(x, y, color, 0, key);
498							this.data.state.fading[key] = true;
499						}
500					}
501					if (!this.data.state.fading[key]) {
502						this.drawArc(x, y, color, visible_times.pct[key]);
503					}
504				}
505				else {
506					this.animateArc(x, y, color, visible_times.pct[key], visible_times.old_pct[key], (new Date()).getTime() + tick_duration);
507				}
508			}
509			lastKey = key;
510			j++;
511		}
512
513		/* Dont request another update if we should be paused */
514		if(this.data.paused || nodraw) {
515			return;
516		}
517
518		/* We need this for our next frame either way */
519		var _this = this;
520		var update = function() {
521			_this.update.call(_this);
522		};
523
524		/* Either call next update immediately, or in a second */
525		if (this.config.animation === "smooth") {
526			/* Smooth animation, Queue up the next frame */
527			this.data.animation_frame = useWindow.requestAnimationFrame(update, _this.element, _this);
528		}
529		else {
530			/* Tick animation, Don't queue until very slightly after the next second happens */
531			var delay = (diff % 1) * 1000;
532			if (delay < 0)
533				delay = 1000 + delay;
534			delay += 50;
535
536			_this.data.animation_frame = useWindow.setTimeout(function() {
537				_this.data.animation_frame = useWindow.requestAnimationFrame(update, _this.element, _this);
538			}, delay);
539		}
540	};
541
542	TC_Instance.prototype.animateArc = function(x, y, color, target_pct, cur_pct, animation_end) {
543		if (this.data.attributes.context === null)
544			return;
545
546		var diff = cur_pct - target_pct;
547		if (Math.abs(diff) > 0.5) {
548			if (target_pct === 0) {
549				this.radialFade(x, y, color, 1);
550			}
551			else {
552				this.radialFade(x, y, color, 0);
553			}
554		}
555		else {
556			var progress = (tick_duration - (animation_end - (new Date()).getTime())) / tick_duration;
557			if (progress > 1)
558				progress = 1;
559
560			var pct = (cur_pct * (1 - progress)) + (target_pct * progress);
561			this.drawArc(x, y, color, pct);
562
563			/*var show_pct = */
564			if (progress >= 1)
565				return;
566			var _this = this;
567			useWindow.requestAnimationFrame(function() {
568				_this.animateArc(x, y, color, target_pct, cur_pct, animation_end);
569			}, this.element);
570		}
571	};
572
573	TC_Instance.prototype.drawArc = function(x, y, color, pct) {
574		if (this.data.attributes.context === null)
575			return;
576
577		var clear_radius = Math.max(this.data.attributes.outer_radius, this.data.attributes.item_size / 2);
578		if(!limited_mode) {
579			this.data.attributes.context.clearRect(
580					x - clear_radius,
581					y - clear_radius,
582					clear_radius * 2,
583					clear_radius * 2
584					);
585		}
586
587		if (this.config.use_background) {
588			this.data.attributes.context.beginPath();
589			this.data.attributes.context.arc(x, y, this.data.attributes.radius, 0, 2 * Math.PI, false);
590			this.data.attributes.context.lineWidth = this.data.attributes.line_width * this.config.bg_width;
591
592			/* line color */
593			this.data.attributes.context.strokeStyle = this.config.circle_bg_color;
594			this.data.attributes.context.stroke();
595		}
596
597		/* Direction */
598		var startAngle, endAngle, counterClockwise;
599		var defaultOffset = (-0.5 * Math.PI);
600		var fullCircle = 2 * Math.PI;
601		startAngle = defaultOffset + (this.config.start_angle / 360 * fullCircle);
602		var offset = (2 * pct * Math.PI);
603
604		if (this.config.direction === "Both") {
605			counterClockwise = false;
606			startAngle -= (offset / 2);
607			endAngle = startAngle + offset;
608		}
609		else {
610			if (this.config.direction === "Clockwise") {
611				counterClockwise = false;
612				endAngle = startAngle + offset;
613			}
614			else {
615				counterClockwise = true;
616				endAngle = startAngle - offset;
617			}
618		}
619
620		this.data.attributes.context.beginPath();
621		this.data.attributes.context.arc(x, y, this.data.attributes.radius, startAngle, endAngle, counterClockwise);
622		this.data.attributes.context.lineWidth = this.data.attributes.line_width;
623
624		/* line color */
625		this.data.attributes.context.strokeStyle = color;
626		this.data.attributes.context.stroke();
627	};
628
629	TC_Instance.prototype.radialFade = function(x, y, color, from, key) {
630		/* TODO: Make fade_time option */
631		var rgb = hexToRgb(color);
632		var _this = this; /* We have a few inner scopes here that will need access to our instance */
633
634		var step = 0.2 * ((from === 1) ? -1 : 1);
635		var i;
636		for (i = 0; from <= 1 && from >= 0; i++) {
637			/* Create inner scope so our variables are not changed by the time the Timeout triggers */
638			(function() {
639				var delay = 50 * i;
640				var rgba = "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", " + (Math.round(from * 10) / 10) + ")";
641				useWindow.setTimeout(function() {
642					_this.drawArc(x, y, rgba, 1);
643				}, delay);
644			}());
645			from += step;
646		}
647		if (typeof key !== undefined) {
648			useWindow.setTimeout(function() {
649				_this.data.state.fading[key] = false;
650			}, 50 * i);
651		}
652	};
653
654	TC_Instance.prototype.timeLeft = function() {
655		if (this.data.paused && typeof this.data.timer === "number") {
656			return this.data.timer;
657		}
658		var now = new Date();
659		return ((this.data.attributes.ref_date - now) / 1000);
660	};
661
662	TC_Instance.prototype.start = function() {
663		useWindow.cancelAnimationFrame(this.data.animation_frame);
664		useWindow.clearTimeout(this.data.animation_frame)
665
666		/* Check if a date was passed in html attribute or jquery data */
667		var attr_data_date = $(this.element).data('date');
668		if (typeof attr_data_date === "undefined") {
669			attr_data_date = $(this.element).attr('data-date');
670		}
671		if (typeof attr_data_date === "string") {
672			this.data.attributes.ref_date = parse_date(attr_data_date);
673		}
674		/* Check if this is an unpause of a timer */
675		else if (typeof this.data.timer === "number") {
676			if (this.data.paused) {
677				this.data.attributes.ref_date = (new Date()).getTime() + (this.data.timer * 1000);
678			}
679		}
680		else {
681			/* Try to get data-timer */
682			var attr_data_timer = $(this.element).data('timer');
683			if (typeof attr_data_timer === "undefined") {
684				attr_data_timer = $(this.element).attr('data-timer');
685			}
686			if (typeof attr_data_timer === "string") {
687				attr_data_timer = parseFloat(attr_data_timer);
688			}
689			if (typeof attr_data_timer === "number") {
690				this.data.timer = attr_data_timer;
691				this.data.attributes.ref_date = (new Date()).getTime() + (attr_data_timer * 1000);
692			}
693			else {
694				/* data-timer and data-date were both not set
695				use config date */
696				this.data.attributes.ref_date = this.config.ref_date;
697			}
698		}
699
700		/* Start running */
701		this.data.paused = false;
702		this.update.call(this);
703	};
704
705	TC_Instance.prototype.restart = function() {
706		this.data.timer = false;
707		this.start();
708	};
709
710	TC_Instance.prototype.stop = function() {
711		if (typeof this.data.timer === "number") {
712			this.data.timer = this.timeLeft(this);
713		}
714		/* Stop running */
715		this.data.paused = true;
716		useWindow.cancelAnimationFrame(this.data.animation_frame);
717	};
718
719	TC_Instance.prototype.destroy = function() {
720		this.clearListeners();
721		this.stop();
722		useWindow.clearInterval(this.data.interval_fallback);
723		this.data.interval_fallback = null;
724
725		this.container.remove();
726		$(this.element).removeAttr('data-tc-id');
727		$(this.element).removeData('tc-id');
728	};
729
730	TC_Instance.prototype.setOptions = function(options) {
731		if (this.config === null) {
732			this.default_options.ref_date = new Date();
733			this.config = $.extend(true, {}, this.default_options);
734		}
735		$.extend(true, this.config, options);
736
737		/* Use window.top if use_top_frame is true */
738		if(this.config.use_top_frame) {
739			useWindow = window.top;
740		}
741		else {
742			useWindow = window;
743		}
744		updateUsedWindow();
745
746		this.data.total_duration = this.config.total_duration;
747		if (typeof this.data.total_duration === "string") {
748			if (typeof secondsIn[this.data.total_duration] !== "undefined") {
749				/* If set to Years, Months, Days, Hours or Minutes, fetch the secondsIn value for that */
750				this.data.total_duration = secondsIn[this.data.total_duration];
751			}
752			else if (this.data.total_duration === "Auto") {
753				/* If set to auto, total_duration is the size of 1 unit, of the unit type bigger than the largest shown */
754				for(var i = 0; i < Object.keys(this.config.time).length; i++) {
755					var unit = Object.keys(this.config.time)[i];
756					if (this.config.time[unit].show) {
757						this.data.total_duration = secondsIn[nextUnits[unit]];
758						break;
759					}
760				}
761			}
762			else {
763				/* If it's a string, but neither of the above, user screwed up. */
764				this.data.total_duration = secondsIn["Years"];
765				console.error("Valid values for TimeCircles config.total_duration are either numeric, or (string) Years, Months, Days, Hours, Minutes, Auto");
766			}
767		}
768	};
769
770	TC_Instance.prototype.addListener = function(f, context, type) {
771		if (typeof f !== "function")
772			return;
773		if (typeof type === "undefined")
774			type = "visible";
775		this.listeners[type].push({func: f, scope: context});
776	};
777
778	TC_Instance.prototype.notifyListeners = function(unit, value, total, type) {
779		for (var i = 0; i < this.listeners[type].length; i++) {
780			var listener = this.listeners[type][i];
781			listener.func.apply(listener.scope, [unit, value, total]);
782		}
783	};
784
785	TC_Instance.prototype.default_options = {
786		ref_date: new Date(),
787		start: true,
788		animation: "smooth",
789		count_past_zero: true,
790		circle_bg_color: "#313332",
791		use_background: true,
792		fg_width: 0.1,
793		bg_width: 1.2,
794		text_size: 0.07,
795		total_duration: "Auto",
796		direction: "Clockwise",
797		use_top_frame: false,
798		start_angle: 0,
799		time: {
800			Days: {
801				show: true,
802				text: "Days",
803				color: "#e3be32"
804			},
805			Hours: {
806				show: true,
807				text: "Hours",
808				color: "#36b0e3"
809			},
810			Minutes: {
811				show: true,
812				text: "Minutes",
813				color: "#75bf44"
814			},
815			Seconds: {
816				show: true,
817				text: "Seconds",
818				color: "#66c5af"
819			}
820		}
821	};
822
823	/* Time circle class */
824	var TC_Class = function(elements, options) {
825		this.elements = elements;
826		this.options = options;
827		this.foreach();
828	};
829
830	TC_Class.prototype.getInstance = function(element) {
831		var instance;
832
833		var cur_id = $(element).data("tc-id");
834		if (typeof cur_id === "undefined") {
835			cur_id = guid();
836			$(element).attr("data-tc-id", cur_id);
837		}
838		if (typeof TC_Instance_List[cur_id] === "undefined") {
839			var options = this.options;
840			var element_options = $(element).data('options');
841			if (typeof element_options === "string") {
842				element_options = JSON.parse(element_options);
843			}
844			if (typeof element_options === "object") {
845				options = $.extend(true, {}, this.options, element_options);
846			}
847			instance = new TC_Instance(element, options);
848			TC_Instance_List[cur_id] = instance;
849		}
850		else {
851			instance = TC_Instance_List[cur_id];
852			if (typeof this.options !== "undefined") {
853				instance.setOptions(this.options);
854			}
855		}
856		return instance;
857	};
858
859	TC_Class.prototype.addTime = function(seconds_to_add) {
860		this.foreach(function(instance) {
861			instance.addTime(seconds_to_add);
862		});
863	};
864
865	TC_Class.prototype.foreach = function(callback) {
866		var _this = this;
867		this.elements.each(function() {
868			var instance = _this.getInstance(this);
869			if (typeof callback === "function") {
870				callback(instance);
871			}
872		});
873		return this;
874	};
875
876	TC_Class.prototype.start = function() {
877		this.foreach(function(instance) {
878			instance.start();
879		});
880		return this;
881	};
882
883	TC_Class.prototype.stop = function() {
884		this.foreach(function(instance) {
885			instance.stop();
886		});
887		return this;
888	};
889
890	TC_Class.prototype.restart = function() {
891		this.foreach(function(instance) {
892			instance.restart();
893		});
894		return this;
895	};
896
897	TC_Class.prototype.rebuild = function() {
898		this.foreach(function(instance) {
899			instance.initialize(false);
900		});
901		return this;
902	};
903
904	TC_Class.prototype.getTime = function() {
905		return this.getInstance(this.elements[0]).timeLeft();
906	};
907
908	TC_Class.prototype.addListener = function(f, type) {
909		if (typeof type === "undefined")
910			type = "visible";
911		var _this = this;
912		this.foreach(function(instance) {
913			instance.addListener(f, _this.elements, type);
914		});
915		return this;
916	};
917
918	TC_Class.prototype.destroy = function() {
919		this.foreach(function(instance) {
920			instance.destroy();
921		});
922		return this;
923	};
924
925	TC_Class.prototype.end = function() {
926		return this.elements;
927	};
928
929	$.fn.TimeCircles = function(options) {
930		return new TC_Class(this, options);
931	};
932}(jQuery));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.