diff --git a/trivia/static/script.js b/trivia/static/script.js
new file mode 100644
index 0000000..f5d9b04
--- /dev/null
+++ b/trivia/static/script.js
@@ -0,0 +1,62 @@
+// Client Constants
+const SCROLL_INTERVAL = 1500;
+const AUTOREFRESH_INTERVAL = 3000;
+
+// Client Variables
+let AUTOSCROLL = false;
+let AUTOREFRESH = false;
+
+// Client Timeouts
+let SCROLL_TIMEOUT;
+let REFRESH_TIMEOUT;
+
+// Scroll table once.
+function ScrollOnce(autoscroll) {
+ // If autoscroll has been disabled in between timer, this if statement will prevent it from executing.
+ if (AUTOSCROLL)
+ $(".team-row:first").appendTo("tbody")
+
+ // Restart autoscroll as needed.
+ if (autoscroll && AUTOSCROLL) {
+ setTimeout(function () {
+ ScrollOnce(true)
+ }, SCROLL_INTERVAL)
+ }
+}
+
+function ToggleAutoscroll() {
+ AUTOSCROLL = !AUTOSCROLL;
+
+ if (AUTOSCROLL) {
+ $(".js-scroll-row-start").hide();
+ $(".js-scroll-row-stop").show();
+ } else {
+ $(".js-scroll-row-start").show();
+ $(".js-scroll-row-stop").hide();
+ }
+}
+
+function ToggleAutorefresh() {
+ AUTOREFRESH = !AUTOREFRESH;
+
+ if (AUTOREFRESH) {
+ $(".js-refresh-start").hide();
+ $(".js-refresh-stop").show();
+ } else {
+ $(".js-refresh-start").show();
+ $(".js-refresh-stop").hide();
+ }
+}
+
+// Client Initialization
+$().ready(function () {
+ // Setup all click functions
+ $(".js-scroll-row-start").on("click", ToggleAutoscroll);
+ $(".js-scroll-row-stop").on("click", ToggleAutoscroll);
+
+ $(".js-refresh-start").on("click", ToggleAutorefresh);
+ $(".js-refresh-stop").on("click", ToggleAutorefresh).addClass("pointer");
+
+ ToggleAutoscroll()
+ ToggleAutorefresh()
+})
\ No newline at end of file
diff --git a/trivia/static/style.css b/trivia/static/style.css
index b84165a..e24cfbd 100644
--- a/trivia/static/style.css
+++ b/trivia/static/style.css
@@ -1,58 +1,60 @@
-table {
- height: 100%;
- width: 100%;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
+html { overflow-y: scroll; }
+body { font-family: Calibri, Arial, sans-serif; margin: 0; padding: 0; position: relative; }
+* { box-sizing: border-box; }
+
+.controls { float: right; font-size: 80%; padding-top: 0.25em; }
+.score-total { border-right: 1px dashed #333; font-weight: bold; }
+.score-team-name { position: relative; }
+.score-team-name span { left: 0; overflow: hidden; position: absolute; top: 0.25em; text-overflow: ellipsis; white-space: nowrap; width: 100%; }
+.score-team-name:before { content: " "; visibility: hidden; }
+
+/* Projector View */
+.ui-content { font-size: 300%; padding: 0.25em 0; }
+tr[data-row-index="0"] td { border-top: 0.25em solid #000; }
+
+.ui-header { background-color: #b51329; border-bottom: 2px solid #27233a; color: #fff; padding: 0.5em 1em; }
+.ui-content { padding: 0.5em 1em; }
+.ui-footer { }
+
+.center { text-align: center; }
+.pointer { cursor: pointer; }
+.right { text-align: right; }
+.small-no-wrap { white-space: nowrap; width: 1%; }
+
+.callout { border: 1px solid transparent; margin-bottom: 0.5em; padding: 0.5em; }
+.callout { background-color: #d9edf7; border-color: #bce8f1; color: #333; }
+.callout-danger { background-color: #fcc; border-color: #e55; }
+.callout-warning { background-color: #ffa; border-color: #e9e925; }
+.callout-success { background-color: #dfd; border-color: #5e5; }
+.callout-critical { background-color: #e68fe6; border-color: #cc2ecc; }
+
+.table { margin-bottom: 0.5em; width: 100%; }
+.table td { border-top: 1px solid #ddd; padding: 0.25em 0.5em; vertical-align: middle; }
+.table thead td, .thead td { border-bottom: 2px solid #ddd; font-weight: bold; vertical-align: bottom; }
+.table-striped { }
+.table-striped > tbody > tr:nth-child(odd) { background-color: #f0f0f0; }
+.table-striped > tbody > tr.has-warning:nth-child(odd) { background-color: #faf2cc; border-color: #f8e5be; }
+.table-hover > tbody > tr:hover { background-color: #e0e0e0; } /* hover needs to come after striped so that striped rows have hover */
+.table-hover > tbody > tr.has-warning:hover, .table-hover > tbody > tr.has-warning-hover:hover { background-color: #f8edb5; border-color: #f6e79d; }
+
+.ui-header {
+ background-color: #b51329;
+ border-bottom: 2px solid #27233a;
+ color: #fff;
+ padding: 0.5em 1em;
}
-body {
- margin: 0;
+.controls {
+ float: right;
+ font-size: 80%;
+ padding-top: 0.25em;
}
-th, td {
- font-family: Calibri, serif;
- font-size: large;
- font-weight: bold;
- /*padding: 5px;*/
- text-align: left;
+.ui-content {
+ padding: 0.5em 1em;
}
-thead {
- background-color: #333;
- color: #f6f6f6;
-}
-
-tbody tr:nth-child(even) {
- background-color: #DDD;
-}
-
-th {
- padding-left: 1rem;
-}
-
-th, td {
- font-size: 300%;
- padding-left: 1rem;
- width: 1rem;
-}
-
-.team-silent {
- font-style: italic;
- color: #676767;
-}
-
-th, td > div {
- height: 10%;
- overflow: hidden;
-}
-
-th, td {
- height: 20px;
-}
-
-.topnav {
- overflow: hidden;
+.small-no-wrap {
+ white-space: nowrap;
+ width: 1%;
}
\ No newline at end of file
diff --git a/trivia/templates/index.html b/trivia/templates/index.html
index acdb5ad..d18c84c 100644
--- a/trivia/templates/index.html
+++ b/trivia/templates/index.html
@@ -1,64 +1,62 @@
-
-
-
- Index
-
-
-
+
-
-
-
-
-
-
-
- | Rank |
- ID |
- Team Name |
- {% for i in range(scoreCount) %}
- {{ i + 1 }} |
- {% endfor %}
-
-
-
- {% for team in teams %}
-
- | {{ range(1, teams | length) | random }} |
- {{ team.id }} |
- {% if team.name | length > 0 %}
- {{ team.name }} |
- {% else %}
- Team {{ team.id }} |
- {% endif %}
- {% for score in team.scores %}
- {{ score }} |
+
+
+
+
+
+
+
+ | Rank |
+ ID |
+ Team Name |
+ {% for i in range(scoreCount) %}
+ {{ i + 1 }} |
+ {% endfor %}
+
+
+
+ {% for team in teams %}
+
+ | ? |
+ {{ team.id }} |
+ {% if team.name | length > 0 %}
+ {{ team.name }} |
+ {% else %}
+ Team {{ team.id }} |
+ {% endif %}
+ {% for score in team.scores %}
+ {{ score }} |
+ {% endfor %}
+
{% endfor %}
-
- {% endfor %}
-
-
-
-
-
+
+
+
+
+
+