showoff 0.12.0 → 0.12.1

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