Improved result tables and added dark mode. General improvements.
This commit is contained in:
parent
4843e664b1
commit
8648094fa9
229
common/main.css
229
common/main.css
@ -1,47 +1,216 @@
|
||||
body{
|
||||
font-family: "Red Hat Display", Myriad, Cantarell, "Noto Sans", "Liberation Sans","Trebuchet MS", Arial, Helvetica, sans-serif;
|
||||
:root {
|
||||
--accent-color-dark: #045d56;
|
||||
--button-color-dark: #045d56;
|
||||
--text-accent-color-dark: #1eb980;
|
||||
--table-border-dark: #00000000;
|
||||
--tr-color-dark: #1e1e1e;
|
||||
--tr-nth-color-dark: #121212;
|
||||
--table-highlight-dark: #616161;
|
||||
--dark-background-color: #121212;
|
||||
--dark-text-color: #eeeeee;
|
||||
}
|
||||
body.theme-dark {
|
||||
--background-color: var(--dark-background-color);
|
||||
--text-color: var(dark-text-color);
|
||||
}
|
||||
table {
|
||||
|
||||
body{
|
||||
--accent-color:#303f9f;
|
||||
--button-color: #303f9f;
|
||||
--text-accent-color:#303f9f;
|
||||
--table-border: #e0e0e0;
|
||||
--table-highlight: #c5cae9;;
|
||||
--tr-nth-color: #f2f2f2;
|
||||
--tr-color: none;
|
||||
|
||||
--background-color: #ffffff;
|
||||
--text-color: #000000;
|
||||
font-family: "Noto Sans", "Liberation Sans","Trebuchet MS", Arial, Helvetica, sans-serif;
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.5rem 10%;
|
||||
background-color: var(--accent-color);
|
||||
color: white;
|
||||
grid-gap: 10px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
||||
box-shadow: 0 .5rem 1.2rem rgba(0,0,0,.15) !important;
|
||||
}
|
||||
|
||||
|
||||
.header-brand{
|
||||
font-weight: 700;
|
||||
}
|
||||
header div{
|
||||
display: inline-block;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
header .spacer{
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
line-height: 1.1rem;
|
||||
}
|
||||
td, th {
|
||||
border: 1px solid rgb(192, 192, 192);
|
||||
padding: 0.8rem;
|
||||
}
|
||||
tr {
|
||||
transition: 0.1s;
|
||||
}
|
||||
tr:nth-child(even){background-color: #f2f2f2;}
|
||||
font-weight: 410;
|
||||
margin: 0.8rem;
|
||||
border-radius: 0.4rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 .5rem 1.2rem rgba(0,0,0,.15) !important;
|
||||
}
|
||||
|
||||
tr:hover {
|
||||
background-color: #c5cae9;
|
||||
}
|
||||
tr:visited {
|
||||
background-color:#c5cae9;
|
||||
}
|
||||
th {
|
||||
td, th {
|
||||
padding: 0.8rem;
|
||||
padding-left: 0.3rem;
|
||||
padding-right: 0.3rem;
|
||||
}
|
||||
tr {
|
||||
transition: 0.1s;
|
||||
background-color: var(--tr-color);
|
||||
}
|
||||
tr:nth-child(even){background-color: var(--tr-nth-color);}
|
||||
|
||||
tr:hover {
|
||||
background-color: var(--table-highlight);
|
||||
box-shadow: 0 .8rem 1.8rem rgba(0,0,0,.15) !important;
|
||||
}
|
||||
tr:visited {
|
||||
background-color:var(--table-highlight);
|
||||
}
|
||||
th {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
text-align: left;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
}
|
||||
h4 {
|
||||
}
|
||||
h4 {
|
||||
font-size: 20px;
|
||||
margin-bottom: 6px;
|
||||
margin-top: 20px;
|
||||
margin-left: 0.9rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.all-result{
|
||||
display: -ms-flexbox;
|
||||
-ms-flex-direction: column;
|
||||
-ms-flex-wrap: wrap;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
height: 50vw;
|
||||
gap: 1rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
.all-result-div{
|
||||
max-width: 25%;
|
||||
padding: 0 4px;
|
||||
}
|
||||
.all-result-div h4{
|
||||
margin-left: auto;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
@media only screen and (max-width: 1200px){
|
||||
.all-result{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
height: auto;
|
||||
gap: 1rem;
|
||||
}
|
||||
.hiddendiv {
|
||||
.all-result-div{
|
||||
max-width: 100%;
|
||||
padding: 0px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
body{
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
.hiddendiv {
|
||||
display:none;
|
||||
}
|
||||
.nav-link{
|
||||
font-weight: 700;
|
||||
}
|
||||
.fade{
|
||||
transition: 0.13s;
|
||||
}
|
||||
}
|
||||
.nav-link {
|
||||
font-weight: 600;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.nav-link:hover {
|
||||
box-shadow: 0 .5rem 1rem rgba(0,0,0,.15) !important;
|
||||
}
|
||||
|
||||
.button4:hover {background-color: #e7e7e7;}
|
||||
.button4:hover {
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
|
||||
.StatusDiv{
|
||||
color: #ffffffa2;
|
||||
}
|
||||
.nav-pills .nav-link{
|
||||
border-radius: .25rem;
|
||||
color: var(--text-accent-color);
|
||||
}
|
||||
.nav-pills .nav-link.active{
|
||||
color: #fff;
|
||||
background-color: var(--button-color);
|
||||
}
|
||||
.result-div{
|
||||
width: max-content;
|
||||
margin: auto;
|
||||
}
|
||||
.table-labels{
|
||||
font-weight: 900;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
header {
|
||||
flex-wrap: wrap;
|
||||
padding-left: 0.2rem;
|
||||
padding-right: 0.2rem;
|
||||
}
|
||||
.StatusDiv{
|
||||
margin-left: auto;
|
||||
}
|
||||
.header-brand {
|
||||
align-self: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
.ResultTable{
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
.result-div{
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
.result-div h4{
|
||||
margin: 0px;
|
||||
}
|
||||
.all-result-div{
|
||||
width: 100%;
|
||||
}
|
||||
.club-collum{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body.theme-auto {
|
||||
--background-color: var(--dark-background-color);
|
||||
--text-color: var(--dark-text-color);
|
||||
--tr-nth-color: var(--tr-nth-color-dark);
|
||||
--table-border: var(--table-border-dark);
|
||||
--table-highlight: var(--table-highlight-dark);
|
||||
--accent-color: var(--accent-color-dark);
|
||||
--text-accent-color: var(--text-accent-color-dark);
|
||||
--tr-color: var(--tr-color-dark);
|
||||
--button-color: var(--button-color-dark);
|
||||
}
|
||||
}
|
138
index.php
Normal file → Executable file
138
index.php
Normal file → Executable file
@ -11,7 +11,18 @@
|
||||
<link rel="stylesheet" href="common/main.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class="theme-auto">
|
||||
<header>
|
||||
<div id="header-brand">
|
||||
<img src="./common/kok-144x144.png" width="30" height="30" class="d-inline-block align-top" alt="" loading="lazy">
|
||||
Liveresultater
|
||||
</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="StatusDiv" id="lastUpdate">status</div>
|
||||
<div class="StatusDiv" id="lastMessage">status</div>
|
||||
</header>
|
||||
|
||||
<!--
|
||||
<nav class="navbar navbar-dark shadow" style="background-color: #303f9f;">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="#">
|
||||
@ -29,6 +40,8 @@
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
-->
|
||||
|
||||
<div class="container alert alert-warning hiddendiv" role="alert" id="ConnectionAlert">
|
||||
Du har mistet kontakten med serveren. Last inn sida på nytt får å koble til igjen <button type="button" class="btn btn-warning" onclick="location.reload()">Last inn på nytt</button>
|
||||
</div>
|
||||
@ -42,7 +55,7 @@
|
||||
|
||||
<div class="tab-content" id="classes-tab-content">
|
||||
<div class="tab-pane fade show active" id="alle" role="tabpanel" aria-labelledby="alle">
|
||||
<div class="container" id="alle-cont"></div>
|
||||
<div class="all-result" id="alle-cont"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -51,33 +64,26 @@
|
||||
<script>
|
||||
var tabsCreated = false;
|
||||
|
||||
function createTabs(tabArray) {
|
||||
function createTabs(tabArray, tabNameArray) {
|
||||
for (let i = 0; i < tabArray.length; i++) {
|
||||
let startStrTab = '<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-toggle="tab"'
|
||||
|
||||
let StrTab = startStrTab + 'id="' + tabArray[i] + '-tab" href="#' + tabArray[i] + '" aria-controls="' + tabArray[i] + '" aria-selected="false">' + tabArray[i].replace(/_/g, " ") + '</a></li>';
|
||||
let StrCont = '<div class="tab-pane fade show" id="' + tabArray[i] + '" role="tabpanel" aria-labelledby="' + tabArray[i] + '-tab"></div>'
|
||||
console.log(tabNameArray)
|
||||
let StrTab = startStrTab + 'id="' + tabArray[i] + '-tab" href="#' + tabArray[i] + '" aria-controls="' + tabArray[i] + '" aria-selected="false">' + tabNameArray[i].Class.Name + '</a></li>';
|
||||
let StrCont = '<div class="result-div tab-pane fade show" id="' + tabArray[i] + '" role="tabpanel" aria-labelledby="' + tabArray[i] + '-tab"></div>'
|
||||
document.getElementById("classes-tabs").innerHTML += StrTab;
|
||||
document.getElementById("classes-tab-content").innerHTML += StrCont;
|
||||
tabsCreated = true;
|
||||
}
|
||||
}
|
||||
|
||||
function diff_minutes(dt2, dt1) {
|
||||
|
||||
let diff = (dt2.getTime() - dt1.getTime()) / 1000;
|
||||
function TimeFormater(stamp) {
|
||||
//diff /= 60;
|
||||
let minutes = Math.floor(diff / 60);
|
||||
let seconds = diff - minutes * 60;
|
||||
let hours = Math.floor(diff / 3600);
|
||||
|
||||
let minutes = Math.floor(stamp / 60);
|
||||
let seconds = stamp - minutes * 60;
|
||||
let hours = Math.floor(stamp / 3600);
|
||||
return minutes + ":" + seconds;
|
||||
}
|
||||
|
||||
function diff_timestamp(dt2, dt1) {
|
||||
let diff = (dt2.getTime() - dt1.getTime()) / 1000;
|
||||
return diff;
|
||||
}
|
||||
|
||||
function sortTable(tableToCheck) {
|
||||
var table, rows, switching, i, x, y, shouldSwitch;
|
||||
table = document.getElementById(tableToCheck);
|
||||
@ -98,9 +104,7 @@
|
||||
x = rows[i].getElementsByTagName("td")[2];
|
||||
y = rows[i + 1].getElementsByTagName("td")[2];
|
||||
// Check if the two rows should switch place:
|
||||
console.log(parseInt(x.className, 10));
|
||||
console.log(parseInt(y.className, 10));
|
||||
if (parseInt(x.className, 10) > parseInt(y.className, 10)) {
|
||||
if (parseInt(x.persTime, 10) > parseInt(y.persTime, 10)) {
|
||||
// If so, mark as a switch and break the loop:
|
||||
shouldSwitch = true;
|
||||
break;
|
||||
@ -113,8 +117,8 @@
|
||||
switching = true;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (rows.length); i++) {
|
||||
rows[i].getElementsByTagName("td")[0].innerHTML = i+1;
|
||||
for (i = 1; i < (rows.length); i++) {
|
||||
rows[i].getElementsByTagName("td")[0].innerHTML = i+1+".";
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,40 +128,77 @@
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
let xmlObj = JSON.parse(this.responseText);
|
||||
|
||||
var classesArray = [];
|
||||
for (let i = 0; i < xmlObj.ClassResult.length; i++) {
|
||||
classesArray[i] = xmlObj.ClassResult[i].Class.Name.replace(/ /g, "_");;
|
||||
classesArray[i] = xmlObj.ClassResult[i].Class.Name.replace(/ |\//g, "_");;
|
||||
}
|
||||
console.log(classesArray);
|
||||
if (tabsCreated == false) {
|
||||
createTabs(classesArray);
|
||||
createTabs(classesArray, xmlObj.ClassResult);
|
||||
}
|
||||
document.getElementById("alle-cont").innerHTML = "";
|
||||
|
||||
//create tables
|
||||
|
||||
|
||||
for (let i = 0; i < xmlObj.ClassResult.length; i++) {
|
||||
let resultTable = '<table class="container" id="'+classesArray[i].replace(/ /g, "_")+'-table">'
|
||||
let tableLabels = '<tr class="table-labels"><td></td><td>Løper</td><td class="club-collum">Klubb</td><td>Tid</td><td>Diff</td></tr>';
|
||||
let resultTable = '<table class="ResultTable " id="'+classesArray[i]+'-table">'+tableLabels;
|
||||
let winnerTime;
|
||||
resultTable += '<h4>'+xmlObj.ClassResult[i].Class.Name+'</h4>';
|
||||
for (let k = 0; k < xmlObj.ClassResult[i].PersonResult.length; k++) {
|
||||
resultTable += '<tr><td id="Ranking"></td>'
|
||||
resultTable += '<tr><td id="Ranking"></td>';
|
||||
//add name
|
||||
resultTable += "<td>" + xmlObj.ClassResult[i].PersonResult[k].Person.Name.Given + " " + xmlObj.ClassResult[i].PersonResult[k].Person.Name.Family + "</td>"
|
||||
|
||||
let d1 = new Date(xmlObj.ClassResult[i].PersonResult[k].Result.FinishTime);
|
||||
let d2 = new Date(xmlObj.ClassResult[i].PersonResult[k].Result.StartTime);
|
||||
let timeUsed = diff_minutes(d1, d2);
|
||||
|
||||
resultTable += '<td class="'+diff_timestamp(d1, d2)+'">' + timeUsed + '</td>'
|
||||
resultTable += "</tr>"
|
||||
|
||||
//add club
|
||||
if (xmlObj.ClassResult[i].PersonResult[k].Organisation.Name!='[object Object]'){
|
||||
resultTable += '<td class="club-collum">' + xmlObj.ClassResult[i].PersonResult[k].Organisation.Name + '</td>'
|
||||
}
|
||||
else{
|
||||
resultTable += '<td class="club-collum">' + "" + '</td>'
|
||||
}
|
||||
|
||||
|
||||
let timeUsedStamp = xmlObj.ClassResult[i].PersonResult[k].Result.Time;
|
||||
let timeUsed = TimeFormater(timeUsedStamp);
|
||||
console.log(xmlObj.ClassResult[i].PersonResult[k].Result.Status );
|
||||
//Check if person is dsq and add uime
|
||||
let persStatus = xmlObj.ClassResult[i].PersonResult[k].Result.Status;
|
||||
if (persStatus == 'OK') {
|
||||
resultTable += '<td persTime="'+timeUsedStamp+'" persStatus="'+xmlObj.ClassResult[i].PersonResult[k].Result.Status+'">' + timeUsed + '</td>'
|
||||
}
|
||||
else if (persStatus == 'Disqualified') {
|
||||
resultTable += '<td persTime="'+timeUsedStamp+'" persStatus="'+xmlObj.ClassResult[i].PersonResult[k].Result.Status+'">' + 'DSQ' +'</td>';
|
||||
}
|
||||
else if (persStatus == 'Active'){
|
||||
resultTable += '<td persTime="'+timeUsedStamp+'" persStatus="'+xmlObj.ClassResult[i].PersonResult[k].Result.Status+'">' + 'Ikke i mål' +'</td>';
|
||||
}
|
||||
else {
|
||||
resultTable += '<td persTime="'+timeUsedStamp+'" persStatus="'+xmlObj.ClassResult[i].PersonResult[k].Result.Status+'">' + persStatus +'</td>';
|
||||
}
|
||||
|
||||
//add time difference to winner
|
||||
if (!xmlObj.ClassResult[i].PersonResult[k].Result.Position){
|
||||
resultTable += '<td>' + "" + '</td>'
|
||||
}
|
||||
else if (xmlObj.ClassResult[i].PersonResult[k].Result.Position!=1){
|
||||
let timeDiff = xmlObj.ClassResult[i].PersonResult[k].Result.Time-winnerTime;
|
||||
resultTable += '<td>+' + TimeFormater(timeDiff) + '</td>'
|
||||
}
|
||||
else if (xmlObj.ClassResult[i].PersonResult[k].Result.Position=1){
|
||||
winnerTime = xmlObj.ClassResult[i].PersonResult[k].Result.Time;
|
||||
resultTable += '<td>' + "" + '</td>'
|
||||
}
|
||||
resultTable += "</tr>";
|
||||
}
|
||||
document.getElementById(classesArray[i].replace(/ /g, "_")).innerHTML = resultTable;
|
||||
resultTable += "</table>"
|
||||
console.log(classesArray[i].replace(/ /g, "_")+'-table');
|
||||
sortTable(classesArray[i].replace(/ /g, "_")+'-table');
|
||||
document.getElementById(classesArray[i].replace(/ |\//g, "_")).innerHTML = resultTable;
|
||||
|
||||
sortTable(classesArray[i].replace(/ |\//g, "_")+'-table');
|
||||
|
||||
document.getElementById("alle-cont").innerHTML += '<div class="all-result-div">'+resultTable.replace(/-table/g, "-all-table")+'</div>';
|
||||
sortTable(classesArray[i].replace(/ |\//g, "_")+'-all-table');
|
||||
}
|
||||
|
||||
console.log(xmlObj)
|
||||
//console.log(xmlObj)
|
||||
}
|
||||
};
|
||||
xmlhttp.open("GET", "xmlToJson.php", true);
|
||||
@ -177,7 +218,6 @@
|
||||
|
||||
// Will display time in 10:30:23 format
|
||||
var formattedTime = hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
|
||||
|
||||
return formattedTime;
|
||||
}
|
||||
|
||||
@ -191,16 +231,12 @@
|
||||
statusArray = event.data.split(",");
|
||||
lastMessage = parseInt(statusArray[3], 10);
|
||||
console.log(statusArray);
|
||||
|
||||
//document.getElementById("result").innerHTML += event.data + "<br>";
|
||||
|
||||
document.getElementById("lastUpdate").innerHTML = "Siste oppdatering: " + mkTimeStr(statusArray[1]);
|
||||
document.getElementById("lastMessage").innerHTML = "Siste melding fra server: " + mkTimeStr(statusArray[2]);
|
||||
//document.getElementById("liveresult").innerHTML = event.data + "<br>";
|
||||
|
||||
document.getElementById("lastMessage").innerHTML = "Siste sjekket: " + mkTimeStr(statusArray[2]);
|
||||
updateInt = parseInt(statusArray[0], 10);
|
||||
console.log(updateInt);
|
||||
if (window.lastUpdate + 5 < parseInt(statusArray[1], 10)) {
|
||||
//check if update has accured
|
||||
if (parseInt(statusArray[1], 10) + 6 > parseInt(statusArray[2], 10)) {
|
||||
updateInt = 1;
|
||||
}
|
||||
if (lastUpdate == undefined) {
|
||||
@ -208,6 +244,7 @@
|
||||
}
|
||||
console.log(statusArray);
|
||||
|
||||
//update results
|
||||
if (updateInt == 1) {
|
||||
loadresults()
|
||||
console.log("Update!!!!! :=)");
|
||||
@ -244,5 +281,4 @@
|
||||
|
||||
<script src="common/bootstrap/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
4
updater.php
Normal file → Executable file
4
updater.php
Normal file → Executable file
@ -16,7 +16,7 @@ header('Access-Control-Expose-Headers: X-Events');
|
||||
|
||||
include 'lastSavedChange.php';
|
||||
|
||||
$resultFile = "ttime-res/Resultater.xml";
|
||||
$resultFile = "resultater/Resultater.xml";
|
||||
//load variable from last check
|
||||
$lastChange = filemtime($resultFile);
|
||||
$time = date('r');
|
||||
@ -31,7 +31,7 @@ if ($lastSavedChange<$lastChange){
|
||||
$var_str = var_export($lastChange, true);
|
||||
$var = "<?php\n\n\$lastSavedChange = $var_str;\n\n?>";
|
||||
file_put_contents('lastSavedChange.php', $var, LOCK_EX);
|
||||
$objXmlDocument = simplexml_load_file("ttime-res/Resultater.xml");
|
||||
$objXmlDocument = simplexml_load_file("resultater/Resultater.xml");
|
||||
|
||||
//xml to json
|
||||
if ($objXmlDocument === FALSE) {
|
||||
|
2
xmlToJson.php
Normal file → Executable file
2
xmlToJson.php
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
libxml_use_internal_errors(TRUE);
|
||||
$objXmlDocument = simplexml_load_file("ttime-res/Resultater.xml");
|
||||
$objXmlDocument = simplexml_load_file("resultater/Resultater.xml");
|
||||
|
||||
if ($objXmlDocument === FALSE) {
|
||||
foreach(libxml_get_errors() as $error) {
|
||||
|
Loading…
Reference in New Issue
Block a user