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.
- checksums.yaml +4 -4
- data/bin/showoff +28 -9
- data/lib/keymap.rb +145 -1
- data/lib/showoff.rb +184 -63
- data/lib/showoff/version.rb +1 -1
- data/lib/showoff_utils.rb +76 -39
- data/public/css/TimeCircles.css +42 -0
- data/public/css/presenter.css +161 -45
- data/public/css/showoff.css +185 -75
- data/public/favicon.ico +0 -0
- data/public/js/TimeCircles.js +984 -0
- data/public/js/presenter.js +147 -64
- data/public/js/showoff.js +224 -85
- data/views/download.erb +21 -24
- data/views/header.erb +5 -2
- data/views/index.erb +20 -10
- data/views/presenter.erb +19 -11
- data/views/stats.erb +47 -49
- metadata +28 -16
- data/public/css/close.png +0 -0
- data/public/css/run_code-dim.png +0 -0
- data/public/css/run_code.png +0 -0
- data/public/js/keyDictionary.json +0 -139
data/public/css/showoff.css
CHANGED
@@ -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
|
-
|
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
|
-
.
|
543
|
+
.highlight .language-shell {
|
514
544
|
display: block;
|
515
|
-
background-color: #
|
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
|
-
|
523
|
-
code
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
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
|
-
|
533
|
-
|
534
|
-
|
560
|
+
.execute:after {
|
561
|
+
font-family: FontAwesome;
|
562
|
+
content: "\F144";
|
563
|
+
position: absolute;
|
564
|
+
right: .5em;
|
535
565
|
}
|
536
566
|
|
537
|
-
|
538
|
-
|
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
|
-
|
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
|
-
.
|
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
|
-
|
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
|
-
.
|
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
|
-
|
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
|
-
|
682
|
-
|
683
|
-
|
722
|
+
#download {
|
723
|
+
max-width: 90%;
|
724
|
+
margin: 0 auto;
|
684
725
|
}
|
685
|
-
|
686
|
-
|
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
|
782
|
-
|
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
|
-
/*
|
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
|
-
.
|
945
|
+
.notes-section {
|
871
946
|
display: block;
|
872
947
|
clear: both;
|
873
|
-
|
948
|
+
margin-top: 1em;
|
949
|
+
border-top: 2px dashed #999;
|
874
950
|
}
|
875
951
|
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
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));
|