showoff 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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));