Initial Commit

This commit is contained in:
„Lupus
2026-01-31 17:26:25 +00:00
commit 6be71e29f7
54 changed files with 66318 additions and 0 deletions

162
src/CSS/adminpanel.css Normal file
View File

@@ -0,0 +1,162 @@
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Lato:300,400,700');
html, body, h1, h2, h3, h4, h5, h6, p, li, ol, ul, pre {
margin: 0;
padding: 0;
}
html, body { min-height: 100%; }
body {
background-color: #345;
background-image: linear-gradient(to bottom, #0009, transparent);
color: #eee;
font-family: 'Lato', sans-serif;
font-size: 62.5%;
padding: 0 20px;
box-sizing: border-box;
}
code {
background: #fff1;
font-family: 'Inconsolata', monospace;
padding: .2em .4em;
}
.content {
background-color: #fff;
border-radius: 8px;
box-sizing: border-box;
color: #666;
font-size: 1.6em;
line-height: 1.4em;
margin: 20px auto;
margin-top: 80px;
padding: 20px;
width: 100%;
max-width: 800px;
}
.content ul {
margin: .5em 2em;
padding: 0;
}
#footer {
background-color: #246c;
background-image: linear-gradient(to bottom, transparent, #0009);
border-top: 1px solid #fff3;
box-shadow: inset 0 1px 0 #fff3, 0 0 32px #000;
overflow: hidden;
padding: 8px;
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 9001;
}
#footer a {
color: #85c6f6;
padding: 1em 0;
text-decoration: none;
}
#footer ul {
display: flex;
list-style: none;
justify-content: center;
font-size: 2em;
font-weight: 300;
}
#footer ul li {
padding: 0 .5em;
}
/* Appearance */
.links {
background-color: #123;
background-image: linear-gradient(to bottom, #0003, transparent);
border-bottom: 1px solid #0003;
box-shadow: 0 0 32px #0003;
font-size: 2em;
font-weight: 300;
}
.links > a {
color: #9ab;
padding: .75em;
text-align: center;
text-decoration: none;
transition: all .5s;
}
.links > a:hover {
background: #ffffff06;
color: #adf;
}
.links > .line {
background: #68a;
height: 1px;
pointer-events: none;
}
/* The Magic */
#header {
position: fixed;
top: 0;
left: 0;
right: 0;
}
.links {
display: grid;
grid-template-columns: repeat(var(--items), 1fr);
position: relative;
}
.links > .line {
opacity: 0;
transition: all .5s;
position: absolute;
bottom: 0;
left: var(--left, calc(100% / var(--items) * (var(--index) - 1)));
width: var(--width, calc(100% / var(--items)));
--index: 0;
}
.links > a:hover ~ .line {
opacity: 1;
}
.links > a:nth-of-type(1):hover ~ .line { --index: 1; }
.links > a:nth-of-type(2):hover ~ .line { --index: 2; }
.links > a:nth-of-type(3):hover ~ .line { --index: 3; }
.links > a:nth-of-type(4):hover ~ .line { --index: 4; }
.links > a:nth-of-type(5):hover ~ .line { --index: 5; }
.links > a:nth-of-type(6):hover ~ .line { --index: 6; }
.links > a:nth-of-type(7):hover ~ .line { --index: 7; }
.links > a:nth-of-type(8):hover ~ .line { --index: 8; }
.links > a:nth-of-type(9):hover ~ .line { --index: 9; }
.links > a:nth-of-type(10):hover ~ .line { --index: 10; }
.links > a:last-of-type:hover ~ .line { --index: var(--items); }
.hidden {
display: none;
}
.nav-bar {
list-style: none;
padding: 0;
margin: 0;
display: flex;
background-color: #123;
border-bottom: 1px solid #0003;
box-shadow: 0 0 32px #0003;
font-size: 2em;
font-weight: 300;
}
.nav-item {
/* flex-grow: 1; */
width: 25%; /* Jedes Element nimmt 25% der Breite ein */
text-align: center;
}
.nav-item a {
display: block;
padding: 1em;
text-decoration: none;
color: #9ab;
transition: background-color 0.3s, color 0.3s;
}
.nav-item a:hover {
background-color: #ffffff06;
color: #adf;
}

125
src/CSS/adminpanel2.css Normal file
View File

@@ -0,0 +1,125 @@
body {
background: #1690A7;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
*{
font-family: sans-serif;
box-sizing: border-box;
}
form {
width: 500px;
height: 460px;
border: 2px solid #ccc;
padding: 30px;
background: #fff;
border-radius: 15px;
}
h2 {
text-align: center;
margin-bottom: 40px;
color: black;
}
input {
display: block;
border: 2px solid #ccc;
width: 95%;
padding: 10px;
margin: 10px auto;
border-radius: 5px;
}
label {
color: #888;
font-size: 18px
padding: 10px;
}
button {
float: right;
background: #555;
padding: 10px 15px;
color: #fff;
border-radius: 5px;
margin-right: 10px;
border: none;
}
button:hover {
opacity: 0.7;
}
/* Verstecke die Standard-Checkbox */
input.admin[type="checkbox"] {
display: none;
}
/* Stilisierung des Labels für die Checkbox */
.checkbox-container label {
position: relative;
display: inline-block;
vertical-align: middle;
cursor: pointer;
padding-left: 25px; /* Abstand zwischen Checkbox und Label */
font-size: 16px;
color: red;
margin-left: 0.5%;
}
/* Gestalten der benutzerdefinierten Checkbox */
.checkbox-container label:before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%); /* Zentrieren vertikal */
width: 20px;
height: 20px;
border: 1px solid #ccc;
background-color: #fff;
}
/* Ändern des Aussehens der benutzerdefinierten Checkbox, wenn sie aktiviert ist */
.checkbox-container input.admin:checked + label:before {
background-color: red;
}
/* Stilisierung des Häkchens */
.checkbox-container input.admin:checked + label:after {
content: '\2713';
font-size: 14px;
color: white;
display: block;
position: absolute;
top: 50%;
left: 4px; /* Abstand von links */
transform: translateY(-50%); /* Zentrieren vertikal */
}
.error {
background: #F2DEDE;
color: #A94442;
}
.error {
background: #F2DEDE;
color: #A94442;
padding: 10px;
width: 95%;
border-radius: 5px;
margin: 20px auto;
}
.message{
background: #b9d5bc;
color: #09b91d;
padding: 10px;
width: 95%;
border-radius: 5px;
margin: 20px auto;
}

1704
src/CSS/bootstrap5.calendaricons.css vendored Normal file

File diff suppressed because it is too large Load Diff

11266
src/CSS/bootstrap5.calendartheme.css vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
body {
transition: background-color 0.5s ease;
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.slider-container {
position: fixed;
bottom: 0.1%;
left: 0.1%;
padding: 20px;
}
.slider {
-webkit-appearance: none;
appearance: none;
width: 40px;
height: 20px;
background: #ccc;
outline: none;
opacity: 0.7;
border-radius: 20px;
margin-right: 10px;
display: inline-block;
position: relative;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 15px;
height: 15px;
background: #2196F3;
border-radius: 50%;
cursor: pointer;
position: relative;
z-index: 2;
}
.slider::-moz-range-thumb {
width: 15px;
height: 15px;
background: #2196F3;
border-radius: 50%;
cursor: pointer;
position: relative;
z-index: 2;
}
.slider::-moz-range-track {
width: 100%;
height: 40px;
background: #ccc;
border-radius: 20px;
}

1426
src/CSS/fullcalendar.min.css vendored Normal file

File diff suppressed because it is too large Load Diff

97
src/CSS/home.css Normal file
View File

@@ -0,0 +1,97 @@
#loader-container {
display: none; /* Anfangs verstecken */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* Hintergrund unscharf machen */
display: flex;
justify-content: center;
align-items: center;
z-index: 9999; /* sicherstellen, dass es über allem anderen liegt */
}
#loader {
border: 8px solid #f3f3f3; /* Hellgrauer Rand */
border-top: 8px solid #3498db; /* Blaue Ladeanzeige */
border-radius: 50%;
width: 60px;
height: 60px;
animation: spin 1s linear infinite; /* Animationsdrehung */
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.fc-toolbar-title {
color: black;
font-family: 'Lato', sans-serif;
}
.white {
color: white;
}
.fc-event {
font-size: 18px;
}
.fc-event-title {
white-space: normal;
}
.fc-event-title-container {
height: 25px;
white-space: normal;
}
.button {
position: fixed;
left: 0.1%;
top: 0.1%;
background-color: #2e3cb8;
border: none;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 18px;
margin: 4px 2px;
cursor: pointer;
}
.button-blue:hover {
background: #21388c;
}
.hidden {
display: none;
}
.button-logout {
position: fixed;
right: 0.1%;
top: 0.1%;
background-color: #2e3cb8;
border: none;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 15px;
margin: 4px 2px;
cursor: pointer;
}
.button-admin {
position: fixed;
left: 0.1%;
top: 0.1%;
background-color: #2e3cb8;
border: none;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 15px;
margin: 60px 2px;
cursor: pointer;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

75
src/CSS/index.css Normal file
View File

@@ -0,0 +1,75 @@
body {
background: #1690A7;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
*{
font-family: sans-serif;
box-sizing: border-box;
}
form {
width: 500px;
border: 2px solid #ccc;
padding: 30px;
background: #fff;
border-radius: 15px
}
h2 {
text-align: center;
margin-bottom: 40px;
}
input {
display: block;
border: 2px solid #ccc;
width: 95%;
padding: 10px;
margin: 10px auto;
border-radius: 5px;
}
label {
color: #888;
font-size: 18px
padding: 10px;
}
button {
float: right;
background: #555;
padding: 10px 15px;
color: #fff;
border-radius: 5px;
margin-right: 10px;
border: none;
}
button:hover {
opacity: 0.7;
}
.error {
background: #F2DEDE;
color: #A94442;
}
.error {
background: #F2DEDE;
color: #A94442;
padding: 10px;
width: 95%;
border-radius: 5px;
margin: 20px auto;
}
.message{
background: #b9d5bc;
color: #09b91d;
padding: 10px;
width: 95%;
border-radius: 5px;
margin: 20px auto;
}

1314
src/CSS/jquery-ui.css vendored Normal file

File diff suppressed because it is too large Load Diff

24
src/CSS/searchtable.css Normal file
View File

@@ -0,0 +1,24 @@
body {
padding-right: 10%;
padding-left: 10%;
}
tr:nth-child(even) {
background-color: #dddddd;
}
.lni-search {
position: relative;
top: 33px;
left: 15px;
}
#myInput {
background-position: 10px 12px;
background-repeat: no-repeat;
width: 100%:
font-size: 16px;
padding: 22px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}

98
src/CSS/searchtable2.css Normal file
View File

@@ -0,0 +1,98 @@
#myTable {
margin-left: auto;
margin-right: auto;
border-collapse: collapse;
width: 100%;
border: 1px solid #ddd;
font-size: 18px;
}
#myTable th, #myTable td {
text-align: center;
padding: 12px;
}
#myTable tr {
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
background-color:#f1f1f1:
}
#loader-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* Hintergrund unscharf machen */
display: none; /* Anfangs verstecken */
justify-content: center;
align-items: center;
z-index: 9999; /* sicherstellen, dass es über allem anderen liegt */
}
#loader {
border: 8px solid #f3f3f3; /* Hellgrauer Rand */
border-top: 8px solid #3498db; /* Blaue Ladeanzeige */
border-radius: 50%;
width: 60px;
height: 60px;
animation: spin 1s linear infinite; /* Animationsdrehung */
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.inputField{
display: inline-block;
margin:0;
margin:0 0 7px 0;
background: linear-gradient(21deg, #10abff, #1beabd);
border-radius: 5px;
width: 150px;
height: 25px;
font-size: 16px;
background: #fff;
}
.hidden {
display: none;
}
.button {
transition-duration: 0.2s;
position: absolute;
left: 5px;
top: 5px;
background-color: #2e3cb8;
border: none;
color: white;
padding: 10px 25px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 18px;
margin: 4px 2px;
cursor: pointer;
}
.button-blue:hover {
background: #21388c;
}
.button-round {
transition-duration: 0.4s;
background-color: #ffffff;
border: none;
color: #000;
padding: 8px 14px;
text-align: center;
text-decoration: none;
font-size: 16px;
border-radius: 10px;
border: 2px solid #949494;
}
.button-round:hover{
background-color: #949494;
color: white;
}

107
src/CSS/showeventdata2.css Normal file
View File

@@ -0,0 +1,107 @@
#myTable {
margin-left: auto;
margin-right: auto;
border-collapse: collapse;
width: 100%;
border: 1px solid #ddd;
font-size: 18px;
}
#myTable th, #myTable td {
text-align: center;
padding: 12px;
}
#myTable tr {
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
background-color:#f1f1f1:
}
#loader-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* Hintergrund unscharf machen */
display: none; /* Anfangs verstecken */
justify-content: center;
align-items: center;
z-index: 9999; /* sicherstellen, dass es über allem anderen liegt */
}
#loader {
border: 8px solid #f3f3f3; /* Hellgrauer Rand */
border-top: 8px solid #3498db; /* Blaue Ladeanzeige */
border-radius: 50%;
width: 60px;
height: 60px;
animation: spin 1s linear infinite; /* Animationsdrehung */
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.spalte2 {
font-size: 19px;
}
.inputField{
display: inline-block;
margin:0;
margin:0 0 7px 0;
background: linear-gradient(21deg, #10abff, #1beabd);
border-radius: 5px;
width: 150px;
height: 25px;
font-size: 16px;
background: #fff;
}
.hidden {
display: none;
}
.button {
transition-duration: 0.2s;
position: absolute;
left: 5px;
top: 5px;
background-color: #2e3cb8;
border: none;
color: white;
padding: 10px 25px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 18px;
margin: 4px 2px;
cursor: pointer;
}
.button-blue:hover {
background: #21388c;
}
.button-round {
transition-duration: 0.4s;
background-color: #ffffff;
border: none;
color: #000;
padding: 8px 14px;
text-align: center;
text-decoration: none;
font-size: 16px;
border-radius: 10px;
border: 2px solid #949494;
box-shadow: 0 1px #999;
}
.button-round:hover{
background-color: #949494;
color: white;
}
.button-round:active {
background-color: #6e6e6e;
box-shadow: 0 1px #666;
transform: translateY(1px);
}

33
src/JS/autologout.js Normal file
View File

@@ -0,0 +1,33 @@
// Funktion zum Logout nach einer bestimmten Zeit
function delayedLogout() {
// Setze den Timeout auf 5 Minuten (300000 Millisekunden)
var timeout = 300000; // 5 Minuten in Millisekunden
// Timeout-Funktion zum Ausführen des Logouts
var logoutTimeout;
function startLogoutTimer() {
logoutTimeout = setTimeout(logout, timeout);
}
function resetLogoutTimer() {
clearTimeout(logoutTimeout); // Timer zurücksetzen
startLogoutTimer(); // Timer neu starten
}
function logout() {
// Weiterleitung auf die logout.php-Seite
window.location.href = "logout.php";
}
// Starte den Timer beim Laden der Seite
startLogoutTimer();
// Reagiere auf Benutzerinteraktionen
document.addEventListener("click", resetLogoutTimer);
//document.addEventListener("mousemove", resetLogoutTimer);
document.addEventListener("keypress", resetLogoutTimer);
}
// Starte den Timer beim Laden der Seite
window.onload = delayedLogout;

7
src/JS/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

19
src/JS/changeColor.js Normal file
View File

@@ -0,0 +1,19 @@
function changeColor(darkMode) {
calendar.refetchEvents();
var dayNames = document.querySelectorAll('a.fc-col-header-cell-cushion');
var dayNumbers = document.querySelectorAll('.fc-daygrid-day-number');
var color;
if (darkMode) {
color = "white";
document.getElementById('fc-dom-1').classList.add('white');
} else {
color = "black";
document.getElementById('fc-dom-1').classList.remove('white');
}
dayNames.forEach((dayname) => {
dayname.style.color = color;
});
dayNumbers.forEach((daynumber) => {
daynumber.style.color = color;
});
}

183
src/JS/events.js Normal file
View File

@@ -0,0 +1,183 @@
document.addEventListener('DOMContentLoaded', function() {
var queryString = window.location.search;
var urlParams = new URLSearchParams(queryString);
var calendarEl = document.getElementById('calendar');
var year = new Date().getFullYear();
var month = new Date().getMonth() + 1;
var day = new Date().getDate();
var currentday = year + "-" + month + "-" + day;
currentday = moment(currentday, 'YYYY-MM-DD').format('YYYY-MM-DD');
var calendar = new FullCalendar.Calendar(calendarEl, {
datesSet: function() {
changeColor(darkMode);
},
events: {
url: './src/PHP/load.php',
method: 'GET',
failure:function() {
console.log('Es gab einen Fehler beim Laden der Ereignisse.');
}
},
loading: function (isLoading) {
var loadingTimeout = 1000; // 1 Sekunde
if (isLoading) {
loadingTimer = setTimeout(function() {
showLoader();
}, loadingTimeout);
}
else {
hideLoader();
clearTimeout(loadingTimer);
}
},
themeSystem: 'bootstrap5',
dayHeaderFormat: {
weekday: 'long'
},
firstDay: 1,
initialDate: currentday,
weekNumbers: true,
headerToolbar: {
left: "prev,next today",
center: "title",
right: 'dayGridMonth,timeGridWeek,timeGridDay',
},
locale: 'de',
eventColor: '#3b91ed',
eventDurationEditable: false,
navLinks: false,
editable:true,
selectable:true,
longPressDelay: 200,
eventLongPressDelay: 200,
selectLongPressDelay: 200,
dateClick: function(info)
{
var date = moment(info.date, 'YYYY-MM-DD').format('YYYY-MM-DD');
console.log(date);
window.location.href = "./src/PHP/searchtable2.php?date=" + date;
},
eventDrop: function(info) {
var id = info.event.id;
var mealdate = moment(info.event.start, 'YYYY-MM-DD').format('YYYY-MM-DD');
console.log(mealdate, id);
// Funktion zum Schließen des Modals
var closeModal = function() {
jQuery('#myModal').remove(); // Entferne das Modal
};
// HTML-Code für das Modal
var modalHtml = '<div id="myModal" class="modal">' +
'<div class="modal-content">' +
'<p style="text-align: center;">Was möchtest du mit dem Eintrag machen?</p>' +
'<button class="custom-button move-button">Eintrag verschieben</button>' +
'<button class="custom-button copy-button">Eintrag kopieren</button>' +
'<button class="custom-button modalbutton">Abbrechen</button>' +
'</div></div>';
// Füge das Modal zum body hinzu
jQuery('body').append(modalHtml);
// Zeige das Modal an
var modal = jQuery('#myModal');
modal.show();
// Verschiebe das Modal nach oben oder unten
var modalContent = modal.find('.modal-content');
var windowHeight = jQuery(window).height();
var modalHeight = modalContent.height();
var modalTop = (windowHeight - modalHeight) / 2;
modalContent.css('top', modalTop);
var modalWidth = modalContent.width();
var newModalWidth = modalWidth * 0.3; // 60% der ursprünglichen Breite
modalContent.css('width', newModalWidth);
modalContent.css('margin-left', 'auto');
modalContent.css('margin-right', 'auto');
// Stelle sicher, dass die Buttons das richtige Styling haben
jQuery('.custom-button').css({
'background-color': '#4CAF50',
'border': 'none',
'color': 'white',
'padding': '10px 20px',
'text-align': 'center',
'text-decoration': 'none',
'display': 'inline-block',
'font-size': '16px',
'margin': '4px 2px',
'cursor': 'pointer',
'border-radius': '4px'
});
// Hover-Effekt für die Buttons
jQuery('.custom-button:hover').css('background-color', '#45a049');
jQuery('.modalbutton').css('background-color', '#f44336');
jQuery('.modalbutton:hover').css('background-color', '#d32f2f');
// Wenn auf "Eintrag verschieben" geklickt wird
jQuery(document).on('click', '.move-button', function() {
jQuery.ajax({
url:"./src/PHP/update2.php",
type:"POST",
data:{mealdate:mealdate, id:id},
success: function() {
closeModal();
calendar.refetchEvents();
}
});
});
// Wenn auf "Eintrag kopieren" geklickt wird
jQuery(document).on('click', '.copy-button', function() {
jQuery.ajax({
url:"./src/PHP/duplicate.php",
type:"POST",
data:{mealdate:mealdate, id:id},
success: function() {
closeModal();
calendar.refetchEvents();
}
});
});
// Wenn auf "Abbrechen" geklickt wird
jQuery(document).on('click', '.modalbutton', function() {
closeModal();
calendar.refetchEvents();
});
},
eventClick: function(info)
{
var date = moment(event.start, 'YYYY-MM-DD').format('YYYY-MM-DD');
var mealname = event.title;
var id = info.event.id;
console.log(date, mealname, id);
window.location.href = "./src/PHP/showeventdata2.php?id=" + id;
},
eventMouseEnter: function(mouseEnterInfo) {
},
eventMouseLeave: function(mouseLeaveInfo) {
},
eventDidMount: function(info) {
if (darkMode) {
info.el.style.backgroundColor = '#FF8C00';
info.el.style.borderColor = '#FF8C00';
} else {
info.el.style.backgroundColor = 'rgb(59, 145, 237)';
info.el.style.borderColor = 'rgb(59, 145, 237)';
}
}
});
globalThis.calendar = calendar;
/*$('.custom-all-day').each(function() {
var lines = $(this).text().split('<br>').length;
$(this).height(lines * 20);
});*/
var calendardate = urlParams.get('calendardate');
if (calendardate === "" || calendardate === null) {
calendardate = currentday;
}
calendar.gotoDate(calendardate);
calendar.render();
});

14673
src/JS/fullcalendar.min.js vendored Normal file

File diff suppressed because one or more lines are too long

10881
src/JS/jquery-3.6.0.js vendored Normal file

File diff suppressed because it is too large Load Diff

16
src/JS/jquery-ui.custom.min.js vendored Normal file

File diff suppressed because one or more lines are too long

19062
src/JS/jquery-ui.js vendored Normal file

File diff suppressed because it is too large Load Diff

4
src/JS/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

209
src/JS/jquery.ui.touch.js vendored Normal file
View File

@@ -0,0 +1,209 @@
/**
* jQuery.UI.iPad plugin
* Copyright (c) 2010 Stephen von Takach
* licensed under MIT.
* Date: 27/8/2010
*
* Project Home:
* http://code.google.com/p/jquery-ui-for-ipad-and-iphone/
*
* Modified: 19/01/2012
* Organized as a proper plugin and added addTouch()
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var lastTap = null; // Holds last tapped element (so we can compare for double tap)
var tapValid = false; // Are we still in the .6 second window where a double tap can occur
var tapTimeout = null; // The timeout reference
var rightClickPending = false; // Is a right click still feasible
var rightClickEvent = null; // the original event
var holdTimeout = null; // timeout reference
var cancelMouseUp = false; // prevents a click from occuring as we want the context menu
function cancelTap() {
tapValid = false;
};
function cancelHold() {
if (rightClickPending) {
window.clearTimeout(holdTimeout);
rightClickPending = false;
rightClickEvent = null;
}
};
function startHold(event) {
if (rightClickPending)
return;
rightClickPending = true; // We could be performing a right click
rightClickEvent = (event.changedTouches)[0];
holdTimeout = window.setTimeout(doRightClick, 800);
};
function doRightClick() {
rightClickPending = false;
// We need to mouse up (as we were down)
var first = rightClickEvent,
simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent("mouseup", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0, null);
first.target.dispatchEvent(simulatedEvent);
// Emulate a right click
simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent("mousedown", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 2, null);
first.target.dispatchEvent(simulatedEvent);
// Show a context menu
simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent("contextmenu", true, true, window, 1, first.screenX + 50, first.screenY + 5, first.clientX + 50, first.clientY + 5,
false, false, false, false, 2, null);
first.target.dispatchEvent(simulatedEvent);
// Note: I don't mouse up the right click here however feel free to add if required
cancelMouseUp = true;
rightClickEvent = null; // Release memory
};
// mouse over event then mouse down
function iPadTouchStart(event) {
var touches = event.changedTouches,
first = touches[0],
type = "mouseover",
simulatedEvent = document.createEvent("MouseEvent");
// Mouse over first - I have live events attached on mouse over
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0, null);
first.target.dispatchEvent(simulatedEvent);
type = "mousedown";
simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0, null);
first.target.dispatchEvent(simulatedEvent);
if (!tapValid) {
lastTap = first.target;
tapValid = true;
tapTimeout = window.setTimeout(cancelTap, 600);
startHold(event);
}
else {
window.clearTimeout(tapTimeout);
// If a double tap is still a possibility and the elements are the same then perform a double click
if (first.target == lastTap) {
lastTap = null;
tapValid = false;
type = "click";
simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
type = "dblclick";
simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
}
else {
lastTap = first.target;
tapValid = true;
tapTimeout = window.setTimeout(cancelTap, 600);
startHold(event);
}
}
};
function iPadTouchHandler(event) {
var type = "",
button = 0; /*left*/
if (event.touches.length > 1)
return;
switch (event.type) {
case "touchstart":
if ($(event.changedTouches[0].target).is("select")) {
return;
}
iPadTouchStart(event); /*We need to trigger two events here to support one touch drag and drop*/
event.preventDefault();
return false;
break;
case "touchmove":
cancelHold();
type = "mousemove";
event.preventDefault();
break;
case "touchend":
if (cancelMouseUp) {
cancelMouseUp = false;
event.preventDefault();
return false;
}
cancelHold();
type = "mouseup";
break;
default:
return;
}
var touches = event.changedTouches,
first = touches[0],
simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, button, null);
first.target.dispatchEvent(simulatedEvent);
if (type == "mouseup" && tapValid && first.target == lastTap) { // This actually emulates the ipads default behaviour (which we prevented)
simulatedEvent = document.createEvent("MouseEvent"); // This check avoids click being emulated on a double tap
simulatedEvent.initMouseEvent("click", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, button, null);
first.target.dispatchEvent(simulatedEvent);
}
};
var touchAvailable = ("ontouchend" in document);
$.fn.addTouch = function() {
if (touchAvailable) {
this.each(function(i,el){
el.addEventListener("touchstart", iPadTouchHandler, false);
el.addEventListener("touchmove", iPadTouchHandler, false);
el.addEventListener("touchend", iPadTouchHandler, false);
el.addEventListener("touchcancel", iPadTouchHandler, false);
});
}
};
}));

10
src/JS/loader.js Normal file
View File

@@ -0,0 +1,10 @@
// JavaScript, um die Ladeanimation zu aktivieren/deaktivieren
function showLoader() {
document.getElementById("loader-container").style.display = "flex";
document.body.style.overflow = "hidden"; // Um das Scrollen zu deaktivieren
}
function hideLoader() {
document.getElementById("loader-container").style.display = "none";
document.body.style.overflow = "auto"; // Um das Scrollen wieder zu aktivieren
}

1933
src/JS/locale-all.js Normal file

File diff suppressed because it is too large Load Diff

551
src/JS/moment.min.js vendored Normal file
View File

@@ -0,0 +1,551 @@
//! moment.js
//! version : 2.17.1
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return od.apply(null,arguments)}
// This is done to register the method called with moment()
// without creating circular dependencies.
function b(a){od=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){
// IE8 will treat undefined and null as object if it wasn't for
// input != null
return null!=a&&"[object Object]"===Object.prototype.toString.call(a)}function e(a){var b;for(b in a)
// even if its not own property I'd still call it non-empty
return!1;return!0}function f(a){return"number"==typeof a||"[object Number]"===Object.prototype.toString.call(a)}function g(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function h(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function i(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function j(a,b){for(var c in b)i(b,c)&&(a[c]=b[c]);return i(b,"toString")&&(a.toString=b.toString),i(b,"valueOf")&&(a.valueOf=b.valueOf),a}function k(a,b,c,d){return rb(a,b,c,d,!0).utc()}function l(){
// We need to deep clone this object.
return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function m(a){return null==a._pf&&(a._pf=l()),a._pf}function n(a){if(null==a._isValid){var b=m(a),c=qd.call(b.parsedDateParts,function(a){return null!=a}),d=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c);if(a._strict&&(d=d&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour),null!=Object.isFrozen&&Object.isFrozen(a))return d;a._isValid=d}return a._isValid}function o(a){var b=k(NaN);return null!=a?j(m(b),a):m(b).userInvalidated=!0,b}function p(a){return void 0===a}function q(a,b){var c,d,e;if(p(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),p(b._i)||(a._i=b._i),p(b._f)||(a._f=b._f),p(b._l)||(a._l=b._l),p(b._strict)||(a._strict=b._strict),p(b._tzm)||(a._tzm=b._tzm),p(b._isUTC)||(a._isUTC=b._isUTC),p(b._offset)||(a._offset=b._offset),p(b._pf)||(a._pf=m(b)),p(b._locale)||(a._locale=b._locale),rd.length>0)for(c in rd)d=rd[c],e=b[d],p(e)||(a[d]=e);return a}
// Moment prototype object
function r(b){q(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),
// Prevent infinite loop in case updateOffset creates new moment
// objects.
sd===!1&&(sd=!0,a.updateOffset(this),sd=!1)}function s(a){return a instanceof r||null!=a&&null!=a._isAMomentObject}function t(a){return a<0?Math.ceil(a)||0:Math.floor(a)}function u(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=t(b)),c}
// compare two arrays, return the number of differences
function v(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;d<e;d++)(c&&a[d]!==b[d]||!c&&u(a[d])!==u(b[d]))&&g++;return g+f}function w(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function x(b,c){var d=!0;return j(function(){if(null!=a.deprecationHandler&&a.deprecationHandler(null,b),d){for(var e,f=[],g=0;g<arguments.length;g++){if(e="","object"==typeof arguments[g]){e+="\n["+g+"] ";for(var h in arguments[0])e+=h+": "+arguments[0][h]+", ";e=e.slice(0,-2)}else e=arguments[g];f.push(e)}w(b+"\nArguments: "+Array.prototype.slice.call(f).join("")+"\n"+(new Error).stack),d=!1}return c.apply(this,arguments)},c)}function y(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),td[b]||(w(c),td[b]=!0)}function z(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function A(a){var b,c;for(c in a)b=a[c],z(b)?this[c]=b:this["_"+c]=b;this._config=a,
// Lenient ordinal parsing accepts just a number in addition to
// number + (possibly) stuff coming from _ordinalParseLenient.
this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function B(a,b){var c,e=j({},a);for(c in b)i(b,c)&&(d(a[c])&&d(b[c])?(e[c]={},j(e[c],a[c]),j(e[c],b[c])):null!=b[c]?e[c]=b[c]:delete e[c]);for(c in a)i(a,c)&&!i(b,c)&&d(a[c])&&(
// make sure changes to properties don't modify parent config
e[c]=j({},e[c]));return e}function C(a){null!=a&&this.set(a)}function D(a,b,c){var d=this._calendar[a]||this._calendar.sameElse;return z(d)?d.call(b,c):d}function E(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function F(){return this._invalidDate}function G(a){return this._ordinal.replace("%d",a)}function H(a,b,c,d){var e=this._relativeTime[c];return z(e)?e(a,b,c,d):e.replace(/%d/i,a)}function I(a,b){var c=this._relativeTime[a>0?"future":"past"];return z(c)?c(b):c.replace(/%s/i,b)}function J(a,b){var c=a.toLowerCase();Dd[c]=Dd[c+"s"]=Dd[b]=a}function K(a){return"string"==typeof a?Dd[a]||Dd[a.toLowerCase()]:void 0}function L(a){var b,c,d={};for(c in a)i(a,c)&&(b=K(c),b&&(d[b]=a[c]));return d}function M(a,b){Ed[a]=b}function N(a){var b=[];for(var c in a)b.push({unit:c,priority:Ed[c]});return b.sort(function(a,b){return a.priority-b.priority}),b}function O(b,c){return function(d){return null!=d?(Q(this,b,d),a.updateOffset(this,c),this):P(this,b)}}function P(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function Q(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}
// MOMENTS
function R(a){return a=K(a),z(this[a])?this[a]():this}function S(a,b){if("object"==typeof a){a=L(a);for(var c=N(a),d=0;d<c.length;d++)this[c[d].unit](a[c[d].unit])}else if(a=K(a),z(this[a]))return this[a](b);return this}function T(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}
// token: 'M'
// padded: ['MM', 2]
// ordinal: 'Mo'
// callback: function () { this.month() + 1 }
function U(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Id[a]=e),b&&(Id[b[0]]=function(){return T(e.apply(this,arguments),b[1],b[2])}),c&&(Id[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function V(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function W(a){var b,c,d=a.match(Fd);for(b=0,c=d.length;b<c;b++)Id[d[b]]?d[b]=Id[d[b]]:d[b]=V(d[b]);return function(b){var e,f="";for(e=0;e<c;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}}
// format date using native date object
function X(a,b){return a.isValid()?(b=Y(b,a.localeData()),Hd[b]=Hd[b]||W(b),Hd[b](a)):a.localeData().invalidDate()}function Y(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Gd.lastIndex=0;d>=0&&Gd.test(a);)a=a.replace(Gd,c),Gd.lastIndex=0,d-=1;return a}function Z(a,b,c){$d[a]=z(b)?b:function(a,d){return a&&c?c:b}}function $(a,b){return i($d,a)?$d[a](b._strict,b._locale):new RegExp(_(a))}
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
function _(a){return aa(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function aa(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function ba(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),f(b)&&(d=function(a,c){c[b]=u(a)}),c=0;c<a.length;c++)_d[a[c]]=d}function ca(a,b){ba(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function da(a,b,c){null!=b&&i(_d,a)&&_d[a](b,c._a,c,a)}function ea(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function fa(a,b){return a?c(this._months)?this._months[a.month()]:this._months[(this._months.isFormat||ke).test(b)?"format":"standalone"][a.month()]:this._months}function ga(a,b){return a?c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[ke.test(b)?"format":"standalone"][a.month()]:this._monthsShort}function ha(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for(
// this is not used
this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;d<12;++d)f=k([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=je.call(this._shortMonthsParse,g),e!==-1?e:null):(e=je.call(this._longMonthsParse,g),e!==-1?e:null):"MMM"===b?(e=je.call(this._shortMonthsParse,g),e!==-1?e:(e=je.call(this._longMonthsParse,g),e!==-1?e:null)):(e=je.call(this._longMonthsParse,g),e!==-1?e:(e=je.call(this._shortMonthsParse,g),e!==-1?e:null))}function ia(a,b,c){var d,e,f;if(this._monthsParseExact)return ha.call(this,a,b,c);
// TODO: add sorting
// Sorting makes sure if one month (or abbr) is a prefix of another
// see sorting in computeMonthsParse
for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;d<12;d++){
// test the regex
if(
// make the regex if we don't have it already
e=k([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}
// MOMENTS
function ja(a,b){var c;if(!a.isValid())
// No op
return a;if("string"==typeof b)if(/^\d+$/.test(b))b=u(b);else
// TODO: Another silent failure?
if(b=a.localeData().monthsParse(b),!f(b))return a;return c=Math.min(a.date(),ea(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ka(b){return null!=b?(ja(this,b),a.updateOffset(this,!0),this):P(this,"Month")}function la(){return ea(this.year(),this.month())}function ma(a){return this._monthsParseExact?(i(this,"_monthsRegex")||oa.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):(i(this,"_monthsShortRegex")||(this._monthsShortRegex=ne),this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex)}function na(a){return this._monthsParseExact?(i(this,"_monthsRegex")||oa.call(this),a?this._monthsStrictRegex:this._monthsRegex):(i(this,"_monthsRegex")||(this._monthsRegex=oe),this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex)}function oa(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;b<12;b++)
// make the regex if we don't have it already
c=k([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(
// Sorting makes sure if one month (or abbr) is a prefix of another it
// will match the longer piece.
d.sort(a),e.sort(a),f.sort(a),b=0;b<12;b++)d[b]=aa(d[b]),e[b]=aa(e[b]);for(b=0;b<24;b++)f[b]=aa(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")}
// HELPERS
function pa(a){return qa(a)?366:365}function qa(a){return a%4===0&&a%100!==0||a%400===0}function ra(){return qa(this.year())}function sa(a,b,c,d,e,f,g){
//can't just apply() to create a date:
//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
var h=new Date(a,b,c,d,e,f,g);
//the date constructor remaps years 0-99 to 1900-1999
return a<100&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function ta(a){var b=new Date(Date.UTC.apply(null,arguments));
//the Date.UTC function remaps years 0-99 to 1900-1999
return a<100&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}
// start-of-first-week - start-of-year
function ua(a,b,c){var// first-week day -- which january is always in the first week (4 for iso, 1 for other)
d=7+b-c,
// first-week day local weekday -- which local weekday is fwd
e=(7+ta(a,0,d).getUTCDay()-b)%7;return-e+d-1}
//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
function va(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ua(a,d,e),j=1+7*(b-1)+h+i;return j<=0?(f=a-1,g=pa(f)+j):j>pa(a)?(f=a+1,g=j-pa(a)):(f=a,g=j),{year:f,dayOfYear:g}}function wa(a,b,c){var d,e,f=ua(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return g<1?(e=a.year()-1,d=g+xa(e,b,c)):g>xa(a.year(),b,c)?(d=g-xa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function xa(a,b,c){var d=ua(a,b,c),e=ua(a+1,b,c);return(pa(a)-d+e)/7}
// HELPERS
// LOCALES
function ya(a){return wa(a,this._week.dow,this._week.doy).week}function za(){return this._week.dow}function Aa(){return this._week.doy}
// MOMENTS
function Ba(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function Ca(a){var b=wa(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}
// HELPERS
function Da(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function Ea(a,b){return"string"==typeof a?b.weekdaysParse(a)%7||7:isNaN(a)?null:a}function Fa(a,b){return a?c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]:this._weekdays}function Ga(a){return a?this._weekdaysShort[a.day()]:this._weekdaysShort}function Ha(a){return a?this._weekdaysMin[a.day()]:this._weekdaysMin}function Ia(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;d<7;++d)f=k([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=je.call(this._weekdaysParse,g),e!==-1?e:null):"ddd"===b?(e=je.call(this._shortWeekdaysParse,g),e!==-1?e:null):(e=je.call(this._minWeekdaysParse,g),e!==-1?e:null):"dddd"===b?(e=je.call(this._weekdaysParse,g),e!==-1?e:(e=je.call(this._shortWeekdaysParse,g),e!==-1?e:(e=je.call(this._minWeekdaysParse,g),e!==-1?e:null))):"ddd"===b?(e=je.call(this._shortWeekdaysParse,g),e!==-1?e:(e=je.call(this._weekdaysParse,g),e!==-1?e:(e=je.call(this._minWeekdaysParse,g),e!==-1?e:null))):(e=je.call(this._minWeekdaysParse,g),e!==-1?e:(e=je.call(this._weekdaysParse,g),e!==-1?e:(e=je.call(this._shortWeekdaysParse,g),e!==-1?e:null)))}function Ja(a,b,c){var d,e,f;if(this._weekdaysParseExact)return Ia.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;d<7;d++){
// test the regex
if(
// make the regex if we don't have it already
e=k([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}
// MOMENTS
function Ka(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Da(a,this.localeData()),this.add(a-b,"d")):b}function La(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Ma(a){if(!this.isValid())return null!=a?this:NaN;
// behaves the same as moment#day except
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
// as a setter, sunday should belong to the previous week.
if(null!=a){var b=Ea(a,this.localeData());return this.day(this.day()%7?b:b-7)}return this.day()||7}function Na(a){return this._weekdaysParseExact?(i(this,"_weekdaysRegex")||Qa.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):(i(this,"_weekdaysRegex")||(this._weekdaysRegex=ue),this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex)}function Oa(a){return this._weekdaysParseExact?(i(this,"_weekdaysRegex")||Qa.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(i(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=ve),this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Pa(a){return this._weekdaysParseExact?(i(this,"_weekdaysRegex")||Qa.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(i(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=we),this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Qa(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],h=[],i=[],j=[];for(b=0;b<7;b++)
// make the regex if we don't have it already
c=k([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),h.push(e),i.push(f),j.push(d),j.push(e),j.push(f);for(
// Sorting makes sure if one weekday (or abbr) is a prefix of another it
// will match the longer piece.
g.sort(a),h.sort(a),i.sort(a),j.sort(a),b=0;b<7;b++)h[b]=aa(h[b]),i[b]=aa(i[b]),j[b]=aa(j[b]);this._weekdaysRegex=new RegExp("^("+j.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")}
// FORMATTING
function Ra(){return this.hours()%12||12}function Sa(){return this.hours()||24}function Ta(a,b){U(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}
// PARSING
function Ua(a,b){return b._meridiemParse}
// LOCALES
function Va(a){
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
// Using charAt should be more compatible.
return"p"===(a+"").toLowerCase().charAt(0)}function Wa(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Xa(a){return a?a.toLowerCase().replace("_","-"):a}
// pick the locale from the array
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
function Ya(a){for(var b,c,d,e,f=0;f<a.length;){for(e=Xa(a[f]).split("-"),b=e.length,c=Xa(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=Za(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&v(e,c,!0)>=b-1)
//the next array item is better than a shallower substring of this one
break;b--}f++}return null}function Za(a){var b=null;
// TODO: Find a better way to register and load all the locales in Node
if(!Be[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=xe._abbr,require("./locale/"+a),
// because defineLocale currently also sets the global locale, we
// want to undo that for lazy loaded locales
$a(b)}catch(a){}return Be[a]}
// This function will load locale and then set the global locale. If
// no arguments are passed in, it will simply return the current global
// locale key.
function $a(a,b){var c;
// moment.duration._locale = moment._locale = data;
return a&&(c=p(b)?bb(a):_a(a,b),c&&(xe=c)),xe._abbr}function _a(a,b){if(null!==b){var c=Ae;if(b.abbr=a,null!=Be[a])y("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),c=Be[a]._config;else if(null!=b.parentLocale){if(null==Be[b.parentLocale])return Ce[b.parentLocale]||(Ce[b.parentLocale]=[]),Ce[b.parentLocale].push({name:a,config:b}),null;c=Be[b.parentLocale]._config}
// backwards compat for now: also set the locale
// make sure we set the locale AFTER all child locales have been
// created, so we won't end up with the child locale set.
return Be[a]=new C(B(c,b)),Ce[a]&&Ce[a].forEach(function(a){_a(a.name,a.config)}),$a(a),Be[a]}
// useful for testing
return delete Be[a],null}function ab(a,b){if(null!=b){var c,d=Ae;
// MERGE
null!=Be[a]&&(d=Be[a]._config),b=B(d,b),c=new C(b),c.parentLocale=Be[a],Be[a]=c,
// backwards compat for now: also set the locale
$a(a)}else
// pass null for config to unupdate, useful for tests
null!=Be[a]&&(null!=Be[a].parentLocale?Be[a]=Be[a].parentLocale:null!=Be[a]&&delete Be[a]);return Be[a]}
// returns locale data
function bb(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return xe;if(!c(a)){if(
//short-circuit everything else
b=Za(a))return b;a=[a]}return Ya(a)}function cb(){return wd(Be)}function db(a){var b,c=a._a;return c&&m(a).overflow===-2&&(b=c[be]<0||c[be]>11?be:c[ce]<1||c[ce]>ea(c[ae],c[be])?ce:c[de]<0||c[de]>24||24===c[de]&&(0!==c[ee]||0!==c[fe]||0!==c[ge])?de:c[ee]<0||c[ee]>59?ee:c[fe]<0||c[fe]>59?fe:c[ge]<0||c[ge]>999?ge:-1,m(a)._overflowDayOfYear&&(b<ae||b>ce)&&(b=ce),m(a)._overflowWeeks&&b===-1&&(b=he),m(a)._overflowWeekday&&b===-1&&(b=ie),m(a).overflow=b),a}
// date from iso format
function eb(a){var b,c,d,e,f,g,h=a._i,i=De.exec(h)||Ee.exec(h);if(i){for(m(a).iso=!0,b=0,c=Ge.length;b<c;b++)if(Ge[b][1].exec(i[1])){e=Ge[b][0],d=Ge[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=He.length;b<c;b++)if(He[b][1].exec(i[3])){
// match[2] should be 'T' or space
f=(i[2]||" ")+He[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!Fe.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),kb(a)}else a._isValid=!1}
// date from iso format or fallback
function fb(b){var c=Ie.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(eb(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}
// Pick the first defined of two or three arguments.
function gb(a,b,c){return null!=a?a:null!=b?b:c}function hb(b){
// hooks is actually the exported moment object
var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}
// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
function ib(a){var b,c,d,e,f=[];if(!a._d){
// Default to current date.
// * if no year, month, day of month are given, default to today
// * if day of month is given, default month and year
// * if month is given, default only year
// * if year is given, don't default anything
for(d=hb(a),
//compute day of the year from weeks and weekdays
a._w&&null==a._a[ce]&&null==a._a[be]&&jb(a),
//if the day of the year is set, figure out what it is
a._dayOfYear&&(e=gb(a._a[ae],d[ae]),a._dayOfYear>pa(e)&&(m(a)._overflowDayOfYear=!0),c=ta(e,0,a._dayOfYear),a._a[be]=c.getUTCMonth(),a._a[ce]=c.getUTCDate()),b=0;b<3&&null==a._a[b];++b)a._a[b]=f[b]=d[b];
// Zero out whatever was not defaulted, including time
for(;b<7;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];
// Check for 24:00:00.000
24===a._a[de]&&0===a._a[ee]&&0===a._a[fe]&&0===a._a[ge]&&(a._nextDay=!0,a._a[de]=0),a._d=(a._useUTC?ta:sa).apply(null,f),
// Apply timezone offset from input. The actual utcOffset can be changed
// with parseZone.
null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[de]=24)}}function jb(a){var b,c,d,e,f,g,h,i;if(b=a._w,null!=b.GG||null!=b.W||null!=b.E)f=1,g=4,
// TODO: We need to take the current isoWeekYear, but that depends on
// how we interpret now (local, utc, fixed offset). So create
// a now version of current config (take local/utc/offset flags, and
// create now).
c=gb(b.GG,a._a[ae],wa(sb(),1,4).year),d=gb(b.W,1),e=gb(b.E,1),(e<1||e>7)&&(i=!0);else{f=a._locale._week.dow,g=a._locale._week.doy;var j=wa(sb(),f,g);c=gb(b.gg,a._a[ae],j.year),
// Default to current week.
d=gb(b.w,j.week),null!=b.d?(
// weekday -- low day numbers are considered next week
e=b.d,(e<0||e>6)&&(i=!0)):null!=b.e?(
// local weekday -- counting starts from begining of week
e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):
// default to begining of week
e=f}d<1||d>xa(c,f,g)?m(a)._overflowWeeks=!0:null!=i?m(a)._overflowWeekday=!0:(h=va(c,d,e,f,g),a._a[ae]=h.year,a._dayOfYear=h.dayOfYear)}
// date from string and format string
function kb(b){
// TODO: Move this to another part of the creation flow to prevent circular deps
if(b._f===a.ISO_8601)return void eb(b);b._a=[],m(b).empty=!0;
// This array is used to make a Date, either with `new Date` or `Date.UTC`
var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=Y(b._f,b._locale).match(Fd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match($(f,b))||[])[0],
// console.log('token', token, 'parsedInput', parsedInput,
// 'regex', getParseRegexForToken(token, config));
d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&m(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),
// don't parse if it's not a known token
Id[f]?(d?m(b).empty=!1:m(b).unusedTokens.push(f),da(f,d,b)):b._strict&&!d&&m(b).unusedTokens.push(f);
// add remaining unparsed input length to the string
m(b).charsLeftOver=i-j,h.length>0&&m(b).unusedInput.push(h),
// clear _12h flag if hour is <= 12
b._a[de]<=12&&m(b).bigHour===!0&&b._a[de]>0&&(m(b).bigHour=void 0),m(b).parsedDateParts=b._a.slice(0),m(b).meridiem=b._meridiem,
// handle meridiem
b._a[de]=lb(b._locale,b._a[de],b._meridiem),ib(b),db(b)}function lb(a,b,c){var d;
// Fallback
return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&b<12&&(b+=12),d||12!==b||(b=0),b):b}
// date from string and array of format strings
function mb(a){var b,c,d,e,f;if(0===a._f.length)return m(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=q({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],kb(b),n(b)&&(
// if there is any input that was not parsed add a penalty for that format
f+=m(b).charsLeftOver,
//or tokens
f+=10*m(b).unusedTokens.length,m(b).score=f,(null==d||f<d)&&(d=f,c=b));j(a,c||b)}function nb(a){if(!a._d){var b=L(a._i);a._a=h([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),ib(a)}}function ob(a){var b=new r(db(pb(a)));
// Adding is smart enough around DST
return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function pb(a){var b=a._i,d=a._f;return a._locale=a._locale||bb(a._l),null===b||void 0===d&&""===b?o({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),s(b)?new r(db(b)):(g(b)?a._d=b:c(d)?mb(a):d?kb(a):qb(a),n(a)||(a._d=null),a))}function qb(b){var d=b._i;void 0===d?b._d=new Date(a.now()):g(d)?b._d=new Date(d.valueOf()):"string"==typeof d?fb(b):c(d)?(b._a=h(d.slice(0),function(a){return parseInt(a,10)}),ib(b)):"object"==typeof d?nb(b):f(d)?
// from milliseconds
b._d=new Date(d):a.createFromInputFallback(b)}function rb(a,b,f,g,h){var i={};
// object construction must be done this way.
// https://github.com/moment/moment/issues/1423
return f!==!0&&f!==!1||(g=f,f=void 0),(d(a)&&e(a)||c(a)&&0===a.length)&&(a=void 0),i._isAMomentObject=!0,i._useUTC=i._isUTC=h,i._l=f,i._i=a,i._f=b,i._strict=g,ob(i)}function sb(a,b,c,d){return rb(a,b,c,d,!1)}
// Pick a moment m from moments so that m[fn](other) is true for all
// other. This relies on the function fn to be transitive.
//
// moments should either be an array of moment objects or an array, whose
// first element is an array of moment objects.
function tb(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return sb();for(d=b[0],e=1;e<b.length;++e)b[e].isValid()&&!b[e][a](d)||(d=b[e]);return d}
// TODO: Use [].sort instead?
function ub(){var a=[].slice.call(arguments,0);return tb("isBefore",a)}function vb(){var a=[].slice.call(arguments,0);return tb("isAfter",a)}function wb(a){var b=L(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;
// representation for dateAddRemove
this._milliseconds=+k+1e3*j+// 1000
6e4*i+// 1000 * 60
1e3*h*60*60,//using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
// Because of dateAddRemove treats 24 hours as different from a
// day when working around DST, we need to store them separately
this._days=+g+7*f,
// It is impossible translate months into days without knowing
// which months you are are talking about, so we have to store
// it separately.
this._months=+e+3*d+12*c,this._data={},this._locale=bb(),this._bubble()}function xb(a){return a instanceof wb}function yb(a){return a<0?Math.round(-1*a)*-1:Math.round(a)}
// FORMATTING
function zb(a,b){U(a,0,0,function(){var a=this.utcOffset(),c="+";return a<0&&(a=-a,c="-"),c+T(~~(a/60),2)+b+T(~~a%60,2)})}function Ab(a,b){var c=(b||"").match(a);if(null===c)return null;var d=c[c.length-1]||[],e=(d+"").match(Me)||["-",0,0],f=+(60*e[1])+u(e[2]);return 0===f?0:"+"===e[0]?f:-f}
// Return a moment from input, that is local/utc/zone equivalent to model.
function Bb(b,c){var d,e;
// Use low-level api, because this fn is low-level api.
return c._isUTC?(d=c.clone(),e=(s(b)||g(b)?b.valueOf():sb(b).valueOf())-d.valueOf(),d._d.setTime(d._d.valueOf()+e),a.updateOffset(d,!1),d):sb(b).local()}function Cb(a){
// On Firefox.24 Date#getTimezoneOffset returns a floating point.
// https://github.com/moment/moment/pull/1871
return 15*-Math.round(a._d.getTimezoneOffset()/15)}
// MOMENTS
// keepLocalTime = true means only change the timezone, without
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
// +0200, so we adjust the time as needed, to be valid.
//
// Keeping the time actually adds/subtracts (one hour)
// from the actual represented time. That is why we call updateOffset
// a second time. In case it wants us to change the offset again
// _changeInProgress == true case, then we have to adjust, because
// there is no such time in the given timezone.
function Db(b,c){var d,e=this._offset||0;if(!this.isValid())return null!=b?this:NaN;if(null!=b){if("string"==typeof b){if(b=Ab(Xd,b),null===b)return this}else Math.abs(b)<16&&(b=60*b);return!this._isUTC&&c&&(d=Cb(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Tb(this,Ob(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?e:Cb(this)}function Eb(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Fb(a){return this.utcOffset(0,a)}function Gb(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Cb(this),"m")),this}function Hb(){if(null!=this._tzm)this.utcOffset(this._tzm);else if("string"==typeof this._i){var a=Ab(Wd,this._i);null!=a?this.utcOffset(a):this.utcOffset(0,!0)}return this}function Ib(a){return!!this.isValid()&&(a=a?sb(a).utcOffset():0,(this.utcOffset()-a)%60===0)}function Jb(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Kb(){if(!p(this._isDSTShifted))return this._isDSTShifted;var a={};if(q(a,this),a=pb(a),a._a){var b=a._isUTC?k(a._a):sb(a._a);this._isDSTShifted=this.isValid()&&v(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Lb(){return!!this.isValid()&&!this._isUTC}function Mb(){return!!this.isValid()&&this._isUTC}function Nb(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Ob(a,b){var c,d,e,g=a,
// matching against regexp is expensive, do it on demand
h=null;// checks for null or undefined
return xb(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:f(a)?(g={},b?g[b]=a:g.milliseconds=a):(h=Ne.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:u(h[ce])*c,h:u(h[de])*c,m:u(h[ee])*c,s:u(h[fe])*c,ms:u(yb(1e3*h[ge]))*c}):(h=Oe.exec(a))?(c="-"===h[1]?-1:1,g={y:Pb(h[2],c),M:Pb(h[3],c),w:Pb(h[4],c),d:Pb(h[5],c),h:Pb(h[6],c),m:Pb(h[7],c),s:Pb(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=Rb(sb(g.from),sb(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new wb(g),xb(a)&&i(a,"_locale")&&(d._locale=a._locale),d}function Pb(a,b){
// We'd normally use ~~inp for this, but unfortunately it also
// converts floats to ints.
// inp may be undefined, so careful calling replace on it.
var c=a&&parseFloat(a.replace(",","."));
// apply sign while we're at it
return(isNaN(c)?0:c)*b}function Qb(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Rb(a,b){var c;return a.isValid()&&b.isValid()?(b=Bb(b,a),a.isBefore(b)?c=Qb(a,b):(c=Qb(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}
// TODO: remove 'name' arg after deprecation is removed
function Sb(a,b){return function(c,d){var e,f;
//invert the arguments, but complain about it
return null===d||isNaN(+d)||(y(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ob(c,d),Tb(this,e,a),this}}function Tb(b,c,d,e){var f=c._milliseconds,g=yb(c._days),h=yb(c._months);b.isValid()&&(e=null==e||e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&Q(b,"Date",P(b,"Date")+g*d),h&&ja(b,P(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function Ub(a,b){var c=a.diff(b,"days",!0);return c<-6?"sameElse":c<-1?"lastWeek":c<0?"lastDay":c<1?"sameDay":c<2?"nextDay":c<7?"nextWeek":"sameElse"}function Vb(b,c){
// We want to compare the start of today, vs this.
// Getting start-of-today depends on whether we're local/utc/offset or not.
var d=b||sb(),e=Bb(d,this).startOf("day"),f=a.calendarFormat(this,e)||"sameElse",g=c&&(z(c[f])?c[f].call(this,d):c[f]);return this.format(g||this.localeData().calendar(f,this,sb(d)))}function Wb(){return new r(this)}function Xb(a,b){var c=s(a)?a:sb(a);return!(!this.isValid()||!c.isValid())&&(b=K(p(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf())}function Yb(a,b){var c=s(a)?a:sb(a);return!(!this.isValid()||!c.isValid())&&(b=K(p(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf())}function Zb(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function $b(a,b){var c,d=s(a)?a:sb(a);return!(!this.isValid()||!d.isValid())&&(b=K(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf()))}function _b(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function ac(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function bc(a,b,c){var d,e,f,g;// 1000
// 1000 * 60
// 1000 * 60 * 60
// 1000 * 60 * 60 * 24, negate dst
// 1000 * 60 * 60 * 24 * 7, negate dst
return this.isValid()?(d=Bb(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=K(b),"year"===b||"month"===b||"quarter"===b?(g=cc(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:t(g)):NaN):NaN}function cc(a,b){
// difference in months
var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),
// b is in (anchor - 1 month, anchor + 1 month)
f=a.clone().add(e,"months");
//check for negative zero, return zero if negative zero
// linear across the month
// linear across the month
return b-f<0?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function dc(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function ec(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?z(Date.prototype.toISOString)?this.toDate().toISOString():X(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):X(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}/**
* Return a human readable representation of a moment that can
* also be evaluated to get a new moment which is the same
*
* @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
*/
function fc(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var a="moment",b="";this.isLocal()||(a=0===this.utcOffset()?"moment.utc":"moment.parseZone",b="Z");var c="["+a+'("]',d=0<this.year()&&this.year()<=9999?"YYYY":"YYYYYY",e="-MM-DD[T]HH:mm:ss.SSS",f=b+'[")]';return this.format(c+d+e+f)}function gc(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=X(this,b);return this.localeData().postformat(c)}function hc(a,b){return this.isValid()&&(s(a)&&a.isValid()||sb(a).isValid())?Ob({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function ic(a){return this.from(sb(),a)}function jc(a,b){return this.isValid()&&(s(a)&&a.isValid()||sb(a).isValid())?Ob({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function kc(a){return this.to(sb(),a)}
// If passed a locale key, it will set the locale for this
// instance. Otherwise, it will return the locale configuration
// variables for this instance.
function lc(a){var b;return void 0===a?this._locale._abbr:(b=bb(a),null!=b&&(this._locale=b),this)}function mc(){return this._locale}function nc(a){
// the following switch intentionally omits break keywords
// to utilize falling through the cases.
switch(a=K(a)){case"year":this.month(0);/* falls through */
case"quarter":case"month":this.date(1);/* falls through */
case"week":case"isoWeek":case"day":case"date":this.hours(0);/* falls through */
case"hour":this.minutes(0);/* falls through */
case"minute":this.seconds(0);/* falls through */
case"second":this.milliseconds(0)}
// weeks are a special case
// quarters are also special
return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function oc(a){
// 'date' is an alias for 'day', so it should be considered as such.
return a=K(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function pc(){return this._d.valueOf()-6e4*(this._offset||0)}function qc(){return Math.floor(this.valueOf()/1e3)}function rc(){return new Date(this.valueOf())}function sc(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function tc(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function uc(){
// new Date(NaN).toJSON() === null
return this.isValid()?this.toISOString():null}function vc(){return n(this)}function wc(){return j({},m(this))}function xc(){return m(this).overflow}function yc(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function zc(a,b){U(0,[a,a.length],0,b)}
// MOMENTS
function Ac(a){return Ec.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function Bc(a){return Ec.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Cc(){return xa(this.year(),1,4)}function Dc(){var a=this.localeData()._week;return xa(this.year(),a.dow,a.doy)}function Ec(a,b,c,d,e){var f;return null==a?wa(this,d,e).year:(f=xa(a,d,e),b>f&&(b=f),Fc.call(this,a,b,c,d,e))}function Fc(a,b,c,d,e){var f=va(a,b,c,d,e),g=ta(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}
// MOMENTS
function Gc(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}
// HELPERS
// MOMENTS
function Hc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function Ic(a,b){b[ge]=u(1e3*("0."+a))}
// MOMENTS
function Jc(){return this._isUTC?"UTC":""}function Kc(){return this._isUTC?"Coordinated Universal Time":""}function Lc(a){return sb(1e3*a)}function Mc(){return sb.apply(null,arguments).parseZone()}function Nc(a){return a}function Oc(a,b,c,d){var e=bb(),f=k().set(d,b);return e[c](f,a)}function Pc(a,b,c){if(f(a)&&(b=a,a=void 0),a=a||"",null!=b)return Oc(a,b,c,"month");var d,e=[];for(d=0;d<12;d++)e[d]=Oc(a,d,c,"month");return e}
// ()
// (5)
// (fmt, 5)
// (fmt)
// (true)
// (true, 5)
// (true, fmt, 5)
// (true, fmt)
function Qc(a,b,c,d){"boolean"==typeof a?(f(b)&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,f(b)&&(c=b,b=void 0),b=b||"");var e=bb(),g=a?e._week.dow:0;if(null!=c)return Oc(b,(c+g)%7,d,"day");var h,i=[];for(h=0;h<7;h++)i[h]=Oc(b,(h+g)%7,d,"day");return i}function Rc(a,b){return Pc(a,b,"months")}function Sc(a,b){return Pc(a,b,"monthsShort")}function Tc(a,b,c){return Qc(a,b,c,"weekdays")}function Uc(a,b,c){return Qc(a,b,c,"weekdaysShort")}function Vc(a,b,c){return Qc(a,b,c,"weekdaysMin")}function Wc(){var a=this._data;return this._milliseconds=Ze(this._milliseconds),this._days=Ze(this._days),this._months=Ze(this._months),a.milliseconds=Ze(a.milliseconds),a.seconds=Ze(a.seconds),a.minutes=Ze(a.minutes),a.hours=Ze(a.hours),a.months=Ze(a.months),a.years=Ze(a.years),this}function Xc(a,b,c,d){var e=Ob(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}
// supports only 2.0-style add(1, 's') or add(duration)
function Yc(a,b){return Xc(this,a,b,1)}
// supports only 2.0-style subtract(1, 's') or subtract(duration)
function Zc(a,b){return Xc(this,a,b,-1)}function $c(a){return a<0?Math.floor(a):Math.ceil(a)}function _c(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;
// if we have a mix of positive and negative values, bubble down first
// check: https://github.com/moment/moment/issues/2166
// The following code bubbles up values, see the tests for
// examples of what that means.
// convert days to months
// 12 months -> 1 year
return f>=0&&g>=0&&h>=0||f<=0&&g<=0&&h<=0||(f+=864e5*$c(bd(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=t(f/1e3),i.seconds=a%60,b=t(a/60),i.minutes=b%60,c=t(b/60),i.hours=c%24,g+=t(c/24),e=t(ad(g)),h+=e,g-=$c(bd(e)),d=t(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function ad(a){
// 400 years have 146097 days (taking into account leap year rules)
// 400 years have 12 months === 4800
return 4800*a/146097}function bd(a){
// the reverse of daysToMonths
return 146097*a/4800}function cd(a){var b,c,d=this._milliseconds;if(a=K(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+ad(b),"month"===a?c:c/12;switch(
// handle milliseconds separately because of floating point math errors (issue #1867)
b=this._days+Math.round(bd(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;
// Math.floor prevents floating point math errors here
case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}
// TODO: Use this.as('ms')?
function dd(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*u(this._months/12)}function ed(a){return function(){return this.as(a)}}function fd(a){return a=K(a),this[a+"s"]()}function gd(a){return function(){return this._data[a]}}function hd(){return t(this.days()/7)}
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
function id(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function jd(a,b,c){var d=Ob(a).abs(),e=of(d.as("s")),f=of(d.as("m")),g=of(d.as("h")),h=of(d.as("d")),i=of(d.as("M")),j=of(d.as("y")),k=e<pf.s&&["s",e]||f<=1&&["m"]||f<pf.m&&["mm",f]||g<=1&&["h"]||g<pf.h&&["hh",g]||h<=1&&["d"]||h<pf.d&&["dd",h]||i<=1&&["M"]||i<pf.M&&["MM",i]||j<=1&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,id.apply(null,k)}
// This function allows you to set the rounding function for relative time strings
function kd(a){return void 0===a?of:"function"==typeof a&&(of=a,!0)}
// This function allows you to set a threshold for relative time strings
function ld(a,b){return void 0!==pf[a]&&(void 0===b?pf[a]:(pf[a]=b,!0))}function md(a){var b=this.localeData(),c=jd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function nd(){
// for ISO strings we do not use the normal bubbling rules:
// * milliseconds bubble up until they become hours
// * days do not bubble at all
// * months bubble up until they become years
// This is because there is no context-free conversion between hours and days
// (think of clock changes)
// and also not between days and months (28-31 days per month)
var a,b,c,d=qf(this._milliseconds)/1e3,e=qf(this._days),f=qf(this._months);
// 3600 seconds -> 60 minutes -> 1 hour
a=t(d/60),b=t(a/60),d%=60,a%=60,
// 12 months -> 1 year
c=t(f/12),f%=12;
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(m<0?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var od,pd;pd=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;d<c;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1};var qd=pd,rd=a.momentProperties=[],sd=!1,td={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var ud;ud=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)i(a,b)&&c.push(b);return c};var vd,wd=ud,xd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},yd={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},zd="Invalid date",Ad="%d",Bd=/\d{1,2}/,Cd={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Dd={},Ed={},Fd=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Gd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Hd={},Id={},Jd=/\d/,Kd=/\d\d/,Ld=/\d{3}/,Md=/\d{4}/,Nd=/[+-]?\d{6}/,Od=/\d\d?/,Pd=/\d\d\d\d?/,Qd=/\d\d\d\d\d\d?/,Rd=/\d{1,3}/,Sd=/\d{1,4}/,Td=/[+-]?\d{1,6}/,Ud=/\d+/,Vd=/[+-]?\d+/,Wd=/Z|[+-]\d\d:?\d\d/gi,Xd=/Z|[+-]\d\d(?::?\d\d)?/gi,Yd=/[+-]?\d+(\.\d{1,3})?/,Zd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,$d={},_d={},ae=0,be=1,ce=2,de=3,ee=4,fe=5,ge=6,he=7,ie=8;vd=Array.prototype.indexOf?Array.prototype.indexOf:function(a){
// I know
var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1};var je=vd;
// FORMATTING
U("M",["MM",2],"Mo",function(){return this.month()+1}),U("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),U("MMMM",0,0,function(a){return this.localeData().months(this,a)}),
// ALIASES
J("month","M"),
// PRIORITY
M("month",8),
// PARSING
Z("M",Od),Z("MM",Od,Kd),Z("MMM",function(a,b){return b.monthsShortRegex(a)}),Z("MMMM",function(a,b){return b.monthsRegex(a)}),ba(["M","MM"],function(a,b){b[be]=u(a)-1}),ba(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);
// if we didn't find a month name, mark the date as invalid.
null!=e?b[be]=e:m(c).invalidMonth=a});
// LOCALES
var ke=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,le="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),me="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),ne=Zd,oe=Zd;
// FORMATTING
U("Y",0,0,function(){var a=this.year();return a<=9999?""+a:"+"+a}),U(0,["YY",2],0,function(){return this.year()%100}),U(0,["YYYY",4],0,"year"),U(0,["YYYYY",5],0,"year"),U(0,["YYYYYY",6,!0],0,"year"),
// ALIASES
J("year","y"),
// PRIORITIES
M("year",1),
// PARSING
Z("Y",Vd),Z("YY",Od,Kd),Z("YYYY",Sd,Md),Z("YYYYY",Td,Nd),Z("YYYYYY",Td,Nd),ba(["YYYYY","YYYYYY"],ae),ba("YYYY",function(b,c){c[ae]=2===b.length?a.parseTwoDigitYear(b):u(b)}),ba("YY",function(b,c){c[ae]=a.parseTwoDigitYear(b)}),ba("Y",function(a,b){b[ae]=parseInt(a,10)}),
// HOOKS
a.parseTwoDigitYear=function(a){return u(a)+(u(a)>68?1900:2e3)};
// MOMENTS
var pe=O("FullYear",!0);
// FORMATTING
U("w",["ww",2],"wo","week"),U("W",["WW",2],"Wo","isoWeek"),
// ALIASES
J("week","w"),J("isoWeek","W"),
// PRIORITIES
M("week",5),M("isoWeek",5),
// PARSING
Z("w",Od),Z("ww",Od,Kd),Z("W",Od),Z("WW",Od,Kd),ca(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=u(a)});var qe={dow:0,// Sunday is the first day of the week.
doy:6};
// FORMATTING
U("d",0,"do","day"),U("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),U("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),U("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),U("e",0,0,"weekday"),U("E",0,0,"isoWeekday"),
// ALIASES
J("day","d"),J("weekday","e"),J("isoWeekday","E"),
// PRIORITY
M("day",11),M("weekday",11),M("isoWeekday",11),
// PARSING
Z("d",Od),Z("e",Od),Z("E",Od),Z("dd",function(a,b){return b.weekdaysMinRegex(a)}),Z("ddd",function(a,b){return b.weekdaysShortRegex(a)}),Z("dddd",function(a,b){return b.weekdaysRegex(a)}),ca(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);
// if we didn't get a weekday name, mark the date as invalid
null!=e?b.d=e:m(c).invalidWeekday=a}),ca(["d","e","E"],function(a,b,c,d){b[d]=u(a)});
// LOCALES
var re="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),se="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),te="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),ue=Zd,ve=Zd,we=Zd;U("H",["HH",2],0,"hour"),U("h",["hh",2],0,Ra),U("k",["kk",2],0,Sa),U("hmm",0,0,function(){return""+Ra.apply(this)+T(this.minutes(),2)}),U("hmmss",0,0,function(){return""+Ra.apply(this)+T(this.minutes(),2)+T(this.seconds(),2)}),U("Hmm",0,0,function(){return""+this.hours()+T(this.minutes(),2)}),U("Hmmss",0,0,function(){return""+this.hours()+T(this.minutes(),2)+T(this.seconds(),2)}),Ta("a",!0),Ta("A",!1),
// ALIASES
J("hour","h"),
// PRIORITY
M("hour",13),Z("a",Ua),Z("A",Ua),Z("H",Od),Z("h",Od),Z("HH",Od,Kd),Z("hh",Od,Kd),Z("hmm",Pd),Z("hmmss",Qd),Z("Hmm",Pd),Z("Hmmss",Qd),ba(["H","HH"],de),ba(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),ba(["h","hh"],function(a,b,c){b[de]=u(a),m(c).bigHour=!0}),ba("hmm",function(a,b,c){var d=a.length-2;b[de]=u(a.substr(0,d)),b[ee]=u(a.substr(d)),m(c).bigHour=!0}),ba("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[de]=u(a.substr(0,d)),b[ee]=u(a.substr(d,2)),b[fe]=u(a.substr(e)),m(c).bigHour=!0}),ba("Hmm",function(a,b,c){var d=a.length-2;b[de]=u(a.substr(0,d)),b[ee]=u(a.substr(d))}),ba("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[de]=u(a.substr(0,d)),b[ee]=u(a.substr(d,2)),b[fe]=u(a.substr(e))});var xe,ye=/[ap]\.?m?\.?/i,ze=O("Hours",!0),Ae={calendar:xd,longDateFormat:yd,invalidDate:zd,ordinal:Ad,ordinalParse:Bd,relativeTime:Cd,months:le,monthsShort:me,week:qe,weekdays:re,weekdaysMin:te,weekdaysShort:se,meridiemParse:ye},Be={},Ce={},De=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Ee=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Fe=/Z|[+-]\d\d(?::?\d\d)?/,Ge=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],
// YYYYMM is NOT allowed by the standard
["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],He=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ie=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=x("value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),
// constant that refers to the ISO standard
a.ISO_8601=function(){};var Je=x("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=sb.apply(null,arguments);return this.isValid()&&a.isValid()?a<this?this:a:o()}),Ke=x("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=sb.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:o()}),Le=function(){return Date.now?Date.now():+new Date};zb("Z",":"),zb("ZZ",""),
// PARSING
Z("Z",Xd),Z("ZZ",Xd),ba(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ab(Xd,a)});
// HELPERS
// timezone chunker
// '+10:00' > ['10', '00']
// '-1530' > ['-15', '30']
var Me=/([\+\-]|\d\d)/gi;
// HOOKS
// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
a.updateOffset=function(){};
// ASP.NET json date format regex
var Ne=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Oe=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Ob.fn=wb.prototype;var Pe=Sb(1,"add"),Qe=Sb(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Re=x("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});
// FORMATTING
U(0,["gg",2],0,function(){return this.weekYear()%100}),U(0,["GG",2],0,function(){return this.isoWeekYear()%100}),zc("gggg","weekYear"),zc("ggggg","weekYear"),zc("GGGG","isoWeekYear"),zc("GGGGG","isoWeekYear"),
// ALIASES
J("weekYear","gg"),J("isoWeekYear","GG"),
// PRIORITY
M("weekYear",1),M("isoWeekYear",1),
// PARSING
Z("G",Vd),Z("g",Vd),Z("GG",Od,Kd),Z("gg",Od,Kd),Z("GGGG",Sd,Md),Z("gggg",Sd,Md),Z("GGGGG",Td,Nd),Z("ggggg",Td,Nd),ca(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=u(a)}),ca(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),
// FORMATTING
U("Q",0,"Qo","quarter"),
// ALIASES
J("quarter","Q"),
// PRIORITY
M("quarter",7),
// PARSING
Z("Q",Jd),ba("Q",function(a,b){b[be]=3*(u(a)-1)}),
// FORMATTING
U("D",["DD",2],"Do","date"),
// ALIASES
J("date","D"),
// PRIOROITY
M("date",9),
// PARSING
Z("D",Od),Z("DD",Od,Kd),Z("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),ba(["D","DD"],ce),ba("Do",function(a,b){b[ce]=u(a.match(Od)[0],10)});
// MOMENTS
var Se=O("Date",!0);
// FORMATTING
U("DDD",["DDDD",3],"DDDo","dayOfYear"),
// ALIASES
J("dayOfYear","DDD"),
// PRIORITY
M("dayOfYear",4),
// PARSING
Z("DDD",Rd),Z("DDDD",Ld),ba(["DDD","DDDD"],function(a,b,c){c._dayOfYear=u(a)}),
// FORMATTING
U("m",["mm",2],0,"minute"),
// ALIASES
J("minute","m"),
// PRIORITY
M("minute",14),
// PARSING
Z("m",Od),Z("mm",Od,Kd),ba(["m","mm"],ee);
// MOMENTS
var Te=O("Minutes",!1);
// FORMATTING
U("s",["ss",2],0,"second"),
// ALIASES
J("second","s"),
// PRIORITY
M("second",15),
// PARSING
Z("s",Od),Z("ss",Od,Kd),ba(["s","ss"],fe);
// MOMENTS
var Ue=O("Seconds",!1);
// FORMATTING
U("S",0,0,function(){return~~(this.millisecond()/100)}),U(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),U(0,["SSS",3],0,"millisecond"),U(0,["SSSS",4],0,function(){return 10*this.millisecond()}),U(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),U(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),U(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),U(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),U(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),
// ALIASES
J("millisecond","ms"),
// PRIORITY
M("millisecond",16),
// PARSING
Z("S",Rd,Jd),Z("SS",Rd,Kd),Z("SSS",Rd,Ld);var Ve;for(Ve="SSSS";Ve.length<=9;Ve+="S")Z(Ve,Ud);for(Ve="S";Ve.length<=9;Ve+="S")ba(Ve,Ic);
// MOMENTS
var We=O("Milliseconds",!1);
// FORMATTING
U("z",0,0,"zoneAbbr"),U("zz",0,0,"zoneName");var Xe=r.prototype;Xe.add=Pe,Xe.calendar=Vb,Xe.clone=Wb,Xe.diff=bc,Xe.endOf=oc,Xe.format=gc,Xe.from=hc,Xe.fromNow=ic,Xe.to=jc,Xe.toNow=kc,Xe.get=R,Xe.invalidAt=xc,Xe.isAfter=Xb,Xe.isBefore=Yb,Xe.isBetween=Zb,Xe.isSame=$b,Xe.isSameOrAfter=_b,Xe.isSameOrBefore=ac,Xe.isValid=vc,Xe.lang=Re,Xe.locale=lc,Xe.localeData=mc,Xe.max=Ke,Xe.min=Je,Xe.parsingFlags=wc,Xe.set=S,Xe.startOf=nc,Xe.subtract=Qe,Xe.toArray=sc,Xe.toObject=tc,Xe.toDate=rc,Xe.toISOString=ec,Xe.inspect=fc,Xe.toJSON=uc,Xe.toString=dc,Xe.unix=qc,Xe.valueOf=pc,Xe.creationData=yc,
// Year
Xe.year=pe,Xe.isLeapYear=ra,
// Week Year
Xe.weekYear=Ac,Xe.isoWeekYear=Bc,
// Quarter
Xe.quarter=Xe.quarters=Gc,
// Month
Xe.month=ka,Xe.daysInMonth=la,
// Week
Xe.week=Xe.weeks=Ba,Xe.isoWeek=Xe.isoWeeks=Ca,Xe.weeksInYear=Dc,Xe.isoWeeksInYear=Cc,
// Day
Xe.date=Se,Xe.day=Xe.days=Ka,Xe.weekday=La,Xe.isoWeekday=Ma,Xe.dayOfYear=Hc,
// Hour
Xe.hour=Xe.hours=ze,
// Minute
Xe.minute=Xe.minutes=Te,
// Second
Xe.second=Xe.seconds=Ue,
// Millisecond
Xe.millisecond=Xe.milliseconds=We,
// Offset
Xe.utcOffset=Db,Xe.utc=Fb,Xe.local=Gb,Xe.parseZone=Hb,Xe.hasAlignedHourOffset=Ib,Xe.isDST=Jb,Xe.isLocal=Lb,Xe.isUtcOffset=Mb,Xe.isUtc=Nb,Xe.isUTC=Nb,
// Timezone
Xe.zoneAbbr=Jc,Xe.zoneName=Kc,
// Deprecations
Xe.dates=x("dates accessor is deprecated. Use date instead.",Se),Xe.months=x("months accessor is deprecated. Use month instead",ka),Xe.years=x("years accessor is deprecated. Use year instead",pe),Xe.zone=x("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Eb),Xe.isDSTShifted=x("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Kb);var Ye=C.prototype;Ye.calendar=D,Ye.longDateFormat=E,Ye.invalidDate=F,Ye.ordinal=G,Ye.preparse=Nc,Ye.postformat=Nc,Ye.relativeTime=H,Ye.pastFuture=I,Ye.set=A,
// Month
Ye.months=fa,Ye.monthsShort=ga,Ye.monthsParse=ia,Ye.monthsRegex=na,Ye.monthsShortRegex=ma,
// Week
Ye.week=ya,Ye.firstDayOfYear=Aa,Ye.firstDayOfWeek=za,
// Day of Week
Ye.weekdays=Fa,Ye.weekdaysMin=Ha,Ye.weekdaysShort=Ga,Ye.weekdaysParse=Ja,Ye.weekdaysRegex=Na,Ye.weekdaysShortRegex=Oa,Ye.weekdaysMinRegex=Pa,
// Hours
Ye.isPM=Va,Ye.meridiem=Wa,$a("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===u(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),
// Side effect imports
a.lang=x("moment.lang is deprecated. Use moment.locale instead.",$a),a.langData=x("moment.langData is deprecated. Use moment.localeData instead.",bb);var Ze=Math.abs,$e=ed("ms"),_e=ed("s"),af=ed("m"),bf=ed("h"),cf=ed("d"),df=ed("w"),ef=ed("M"),ff=ed("y"),gf=gd("milliseconds"),hf=gd("seconds"),jf=gd("minutes"),kf=gd("hours"),lf=gd("days"),mf=gd("months"),nf=gd("years"),of=Math.round,pf={s:45,// seconds to minute
m:45,// minutes to hour
h:22,// hours to day
d:26,// days to month
M:11},qf=Math.abs,rf=wb.prototype;
// Deprecations
// Side effect imports
// FORMATTING
// PARSING
// Side effect imports
return rf.abs=Wc,rf.add=Yc,rf.subtract=Zc,rf.as=cd,rf.asMilliseconds=$e,rf.asSeconds=_e,rf.asMinutes=af,rf.asHours=bf,rf.asDays=cf,rf.asWeeks=df,rf.asMonths=ef,rf.asYears=ff,rf.valueOf=dd,rf._bubble=_c,rf.get=fd,rf.milliseconds=gf,rf.seconds=hf,rf.minutes=jf,rf.hours=kf,rf.days=lf,rf.weeks=hd,rf.months=mf,rf.years=nf,rf.humanize=md,rf.toISOString=nd,rf.toString=nd,rf.toJSON=nd,rf.locale=lc,rf.localeData=mc,rf.toIsoString=x("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",nd),rf.lang=Re,U("X",0,0,"unix"),U("x",0,0,"valueOf"),Z("x",Vd),Z("X",Yd),ba("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),ba("x",function(a,b,c){c._d=new Date(u(a))}),a.version="2.17.1",b(sb),a.fn=Xe,a.min=ub,a.max=vb,a.now=Le,a.utc=k,a.unix=Lc,a.months=Rc,a.isDate=g,a.locale=$a,a.invalid=o,a.duration=Ob,a.isMoment=s,a.weekdays=Tc,a.parseZone=Mc,a.localeData=bb,a.isDuration=xb,a.monthsShort=Sc,a.weekdaysMin=Vc,a.defineLocale=_a,a.updateLocale=ab,a.locales=cb,a.weekdaysShort=Uc,a.normalizeUnits=K,a.relativeTimeRounding=kd,a.relativeTimeThreshold=ld,a.calendarFormat=Ub,a.prototype=Xe,a});

638
src/JS/tooltip.js Normal file
View File

@@ -0,0 +1,638 @@
(function (global, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports', 'module', './util'], factory);
} else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
factory(exports, module, require('./util'));
} else {
var mod = {
exports: {}
};
factory(mod.exports, mod, global.Util);
global.tooltip = mod.exports;
}
})(this, function (exports, module, _util) {
/* global Tether */
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
var _Util = _interopRequireDefault(_util);
/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.2): tooltip.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/
var Tooltip = (function ($) {
/**
* Check for Tether dependency
* Tether - http://github.hubspot.com/tether/
*/
if (window.Tether === undefined) {
throw new Error('Bootstrap tooltips require Tether (http://github.hubspot.com/tether/)');
}
/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/
var NAME = 'tooltip';
var VERSION = '4.0.0-alpha';
var DATA_KEY = 'bs.tooltip';
var EVENT_KEY = '.' + DATA_KEY;
var JQUERY_NO_CONFLICT = $.fn[NAME];
var TRANSITION_DURATION = 150;
var CLASS_PREFIX = 'bs-tether';
var Default = {
animation: true,
template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div></div>',
trigger: 'hover focus',
title: '',
delay: 0,
html: false,
selector: false,
placement: 'top',
offset: '0 0',
constraints: []
};
var DefaultType = {
animation: 'boolean',
template: 'string',
title: '(string|element|function)',
trigger: 'string',
delay: '(number|object)',
html: 'boolean',
selector: '(string|boolean)',
placement: '(string|function)',
offset: 'string',
constraints: 'array'
};
var AttachmentMap = {
TOP: 'bottom center',
RIGHT: 'middle left',
BOTTOM: 'top center',
LEFT: 'middle right'
};
var HoverState = {
IN: 'in',
OUT: 'out'
};
var Event = {
HIDE: 'hide' + EVENT_KEY,
HIDDEN: 'hidden' + EVENT_KEY,
SHOW: 'show' + EVENT_KEY,
SHOWN: 'shown' + EVENT_KEY,
INSERTED: 'inserted' + EVENT_KEY,
CLICK: 'click' + EVENT_KEY,
FOCUSIN: 'focusin' + EVENT_KEY,
FOCUSOUT: 'focusout' + EVENT_KEY,
MOUSEENTER: 'mouseenter' + EVENT_KEY,
MOUSELEAVE: 'mouseleave' + EVENT_KEY
};
var ClassName = {
FADE: 'fade',
IN: 'in'
};
var Selector = {
TOOLTIP: '.tooltip',
TOOLTIP_INNER: '.tooltip-inner'
};
var TetherClass = {
element: false,
enabled: false
};
var Trigger = {
HOVER: 'hover',
FOCUS: 'focus',
CLICK: 'click',
MANUAL: 'manual'
};
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
var Tooltip = (function () {
function Tooltip(element, config) {
_classCallCheck(this, Tooltip);
// private
this._isEnabled = true;
this._timeout = 0;
this._hoverState = '';
this._activeTrigger = {};
this._tether = null;
// protected
this.element = element;
this.config = this._getConfig(config);
this.tip = null;
this._setListeners();
}
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/
// getters
_createClass(Tooltip, [{
key: 'enable',
// public
value: function enable() {
this._isEnabled = true;
}
}, {
key: 'disable',
value: function disable() {
this._isEnabled = false;
}
}, {
key: 'toggleEnabled',
value: function toggleEnabled() {
this._isEnabled = !this._isEnabled;
}
}, {
key: 'toggle',
value: function toggle(event) {
if (event) {
var dataKey = this.constructor.DATA_KEY;
var context = $(event.currentTarget).data(dataKey);
if (!context) {
context = new this.constructor(event.currentTarget, this._getDelegateConfig());
$(event.currentTarget).data(dataKey, context);
}
context._activeTrigger.click = !context._activeTrigger.click;
if (context._isWithActiveTrigger()) {
context._enter(null, context);
} else {
context._leave(null, context);
}
} else {
if ($(this.getTipElement()).hasClass(ClassName.IN)) {
this._leave(null, this);
return;
}
this._enter(null, this);
}
}
}, {
key: 'dispose',
value: function dispose() {
clearTimeout(this._timeout);
this.cleanupTether();
$.removeData(this.element, this.constructor.DATA_KEY);
$(this.element).off(this.constructor.EVENT_KEY);
if (this.tip) {
$(this.tip).remove();
}
this._isEnabled = null;
this._timeout = null;
this._hoverState = null;
this._activeTrigger = null;
this._tether = null;
this.element = null;
this.config = null;
this.tip = null;
}
}, {
key: 'show',
value: function show() {
var _this = this;
var showEvent = $.Event(this.constructor.Event.SHOW);
if (this.isWithContent() && this._isEnabled) {
$(this.element).trigger(showEvent);
var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);
if (showEvent.isDefaultPrevented() || !isInTheDom) {
return;
}
var tip = this.getTipElement();
var tipId = _Util['default'].getUID(this.constructor.NAME);
tip.setAttribute('id', tipId);
this.element.setAttribute('aria-describedby', tipId);
this.setContent();
if (this.config.animation) {
$(tip).addClass(ClassName.FADE);
}
var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
var attachment = this._getAttachment(placement);
$(tip).data(this.constructor.DATA_KEY, this).appendTo(document.body);
$(this.element).trigger(this.constructor.Event.INSERTED);
this._tether = new Tether({
attachment: attachment,
element: tip,
target: this.element,
classes: TetherClass,
classPrefix: CLASS_PREFIX,
offset: this.config.offset,
constraints: this.config.constraints,
addTargetClasses: false
});
_Util['default'].reflow(tip);
this._tether.position();
$(tip).addClass(ClassName.IN);
var complete = function complete() {
var prevHoverState = _this._hoverState;
_this._hoverState = null;
$(_this.element).trigger(_this.constructor.Event.SHOWN);
if (prevHoverState === HoverState.OUT) {
_this._leave(null, _this);
}
};
if (_Util['default'].supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
$(this.tip).one(_Util['default'].TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);
return;
}
complete();
}
}
}, {
key: 'hide',
value: function hide(callback) {
var _this2 = this;
var tip = this.getTipElement();
var hideEvent = $.Event(this.constructor.Event.HIDE);
var complete = function complete() {
if (_this2._hoverState !== HoverState.IN && tip.parentNode) {
tip.parentNode.removeChild(tip);
}
_this2.element.removeAttribute('aria-describedby');
$(_this2.element).trigger(_this2.constructor.Event.HIDDEN);
_this2.cleanupTether();
if (callback) {
callback();
}
};
$(this.element).trigger(hideEvent);
if (hideEvent.isDefaultPrevented()) {
return;
}
$(tip).removeClass(ClassName.IN);
if (_Util['default'].supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
$(tip).one(_Util['default'].TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
} else {
complete();
}
this._hoverState = '';
}
// protected
}, {
key: 'isWithContent',
value: function isWithContent() {
return Boolean(this.getTitle());
}
}, {
key: 'getTipElement',
value: function getTipElement() {
return this.tip = this.tip || $(this.config.template)[0];
}
}, {
key: 'setContent',
value: function setContent() {
var $tip = $(this.getTipElement());
this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
$tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
this.cleanupTether();
}
}, {
key: 'setElementContent',
value: function setElementContent($element, content) {
var html = this.config.html;
if (typeof content === 'object' && (content.nodeType || content.jquery)) {
// content is a DOM node or a jQuery
if (html) {
if (!$(content).parent().is($element)) {
$element.empty().append(content);
}
} else {
$element.text($(content).text());
}
} else {
$element[html ? 'html' : 'text'](content);
}
}
}, {
key: 'getTitle',
value: function getTitle() {
var title = this.element.getAttribute('data-original-title');
if (!title) {
title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
}
return title;
}
}, {
key: 'cleanupTether',
value: function cleanupTether() {
if (this._tether) {
this._tether.destroy();
}
}
// private
}, {
key: '_getAttachment',
value: function _getAttachment(placement) {
return AttachmentMap[placement.toUpperCase()];
}
}, {
key: '_setListeners',
value: function _setListeners() {
var _this3 = this;
var triggers = this.config.trigger.split(' ');
triggers.forEach(function (trigger) {
if (trigger === 'click') {
$(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, $.proxy(_this3.toggle, _this3));
} else if (trigger !== Trigger.MANUAL) {
var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN;
var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT;
$(_this3.element).on(eventIn, _this3.config.selector, $.proxy(_this3._enter, _this3)).on(eventOut, _this3.config.selector, $.proxy(_this3._leave, _this3));
}
});
if (this.config.selector) {
this.config = $.extend({}, this.config, {
trigger: 'manual',
selector: ''
});
} else {
this._fixTitle();
}
}
}, {
key: '_fixTitle',
value: function _fixTitle() {
var titleType = typeof this.element.getAttribute('data-original-title');
if (this.element.getAttribute('title') || titleType !== 'string') {
this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
this.element.setAttribute('title', '');
}
}
}, {
key: '_enter',
value: function _enter(event, context) {
var dataKey = this.constructor.DATA_KEY;
context = context || $(event.currentTarget).data(dataKey);
if (!context) {
context = new this.constructor(event.currentTarget, this._getDelegateConfig());
$(event.currentTarget).data(dataKey, context);
}
if (event) {
context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
}
if ($(context.getTipElement()).hasClass(ClassName.IN) || context._hoverState === HoverState.IN) {
context._hoverState = HoverState.IN;
return;
}
clearTimeout(context._timeout);
context._hoverState = HoverState.IN;
if (!context.config.delay || !context.config.delay.show) {
context.show();
return;
}
context._timeout = setTimeout(function () {
if (context._hoverState === HoverState.IN) {
context.show();
}
}, context.config.delay.show);
}
}, {
key: '_leave',
value: function _leave(event, context) {
var dataKey = this.constructor.DATA_KEY;
context = context || $(event.currentTarget).data(dataKey);
if (!context) {
context = new this.constructor(event.currentTarget, this._getDelegateConfig());
$(event.currentTarget).data(dataKey, context);
}
if (event) {
context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
}
if (context._isWithActiveTrigger()) {
return;
}
clearTimeout(context._timeout);
context._hoverState = HoverState.OUT;
if (!context.config.delay || !context.config.delay.hide) {
context.hide();
return;
}
context._timeout = setTimeout(function () {
if (context._hoverState === HoverState.OUT) {
context.hide();
}
}, context.config.delay.hide);
}
}, {
key: '_isWithActiveTrigger',
value: function _isWithActiveTrigger() {
for (var trigger in this._activeTrigger) {
if (this._activeTrigger[trigger]) {
return true;
}
}
return false;
}
}, {
key: '_getConfig',
value: function _getConfig(config) {
config = $.extend({}, this.constructor.Default, $(this.element).data(), config);
if (config.delay && typeof config.delay === 'number') {
config.delay = {
show: config.delay,
hide: config.delay
};
}
_Util['default'].typeCheckConfig(NAME, config, this.constructor.DefaultType);
return config;
}
}, {
key: '_getDelegateConfig',
value: function _getDelegateConfig() {
var config = {};
if (this.config) {
for (var key in this.config) {
if (this.constructor.Default[key] !== this.config[key]) {
config[key] = this.config[key];
}
}
}
return config;
}
// static
}], [{
key: '_jQueryInterface',
value: function _jQueryInterface(config) {
return this.each(function () {
var data = $(this).data(DATA_KEY);
var _config = typeof config === 'object' ? config : null;
if (!data && /destroy|hide/.test(config)) {
return;
}
if (!data) {
data = new Tooltip(this, _config);
$(this).data(DATA_KEY, data);
}
if (typeof config === 'string') {
if (data[config] === undefined) {
throw new Error('No method named "' + config + '"');
}
data[config]();
}
});
}
}, {
key: 'VERSION',
get: function get() {
return VERSION;
}
}, {
key: 'Default',
get: function get() {
return Default;
}
}, {
key: 'NAME',
get: function get() {
return NAME;
}
}, {
key: 'DATA_KEY',
get: function get() {
return DATA_KEY;
}
}, {
key: 'Event',
get: function get() {
return Event;
}
}, {
key: 'EVENT_KEY',
get: function get() {
return EVENT_KEY;
}
}, {
key: 'DefaultType',
get: function get() {
return DefaultType;
}
}]);
return Tooltip;
})();
$.fn[NAME] = Tooltip._jQueryInterface;
$.fn[NAME].Constructor = Tooltip;
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT;
return Tooltip._jQueryInterface;
};
return Tooltip;
})(jQuery);
module.exports = Tooltip;
});

164
src/PHP/adminpanel.php Normal file
View File

@@ -0,0 +1,164 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name']) && $_SESSION['admin'] == 1) {
?>
<!DOCTYPE html>
<html>
<head>
<title>Adminpanel</title>
<link rel="stylesheet" type="text/css" href="../CSS/adminpanel2.css">
<link rel="stylesheet" type="text/css" href="../CSS/adminpanel.css">
<style>
</style>
</head>
<body onload="showTab('createuser')">
<header id="header">
<ul class="nav-bar">
<li class="nav-item"><a href="#" onclick="goback()">zurück zum Kalender</a></li>
<li class="nav-item"><a href="#" onclick="showTab('usermanagement')">User Management</a></li>
<li class="nav-item"><a href="#" onclick="showTab('createuser')">Create New User</a></li>
<li class="nav-item"><a href="#" onclick="showTab('backup')">Backup</a></li>
</ul>
</header>
<div id="content hidden">
<div id="usermanagement" class="tab-content hidden">
<h2>User Management</h2>
<p>Coming soon!</p>
</div>
<div id="createuser" class="tab-content hidden">
<form id="form" action="javascript:createuser();" method="post">
<h2>Create new user</h2>
<p class="error hidden" id="error">Bitte alle Felder überprüfen!</p>
<p class="message hidden" id="message">Benutzer erfolgreich erstellt!</p>
<label>Username</label>
<input type="text" name="uname" placeholder="Username" id="username"><br>
<label>Password</label>
<input type="password" name="password" placeholder="Password" id="password"><br>
<label>Name</label>
<input type="text" name="name" placeholder="Full Name" id="name"><br>
<label>Mandant</label>
<input type="text" name="mandt" placeholder="Mandant" id="mandt"><br>
<div class="checkbox-container">
<input class="admin" type="checkbox" id="admin" name="admin">
<label for="admin">Admin</label>
</div><br>
<button type="submit">Create user</button>
</form>
</div>
<div id="backup" class="tab-content hidden">
<h2>Backup</h2>
<p>Coming soon!</p>
</div>
</div>
<script src="../JS/jquery.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
showTab('createuser');
});
function showTab(tabId) {
// Verstecke alle Tabs
var tabs = document.getElementsByClassName("tab-content");
for (var i = 0; i < tabs.length; i++) {
tabs[i].classList.add("hidden");
}
// Zeige den ausgewählten Tab an
document.getElementById(tabId).classList.remove("hidden");
}
function createuser() {
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
var error = document.getElementById("error");
var message = document.getElementById("message");
var form = document.getElementById('form');
var username = document.getElementById("username");
var password = document.getElementById("password");
var name = document.getElementById("name");
var mandt = document.getElementById("mandt");
var adminCheckbox = document.getElementById("admin");
var admin = adminCheckbox.checked ? 1 : 0;
var test = username === "";
var test2 = password === "";
var test3 = name === "";
var test4 = mandt === "";
if (test || test2 || test3 || test4) {
form.style.height = '550px';
error.classList.remove("hidden");
//alert("Fehler: Bitte alle Eingaben überprüfen!");
} else {
$.ajax({
url:"../PHP/createuser.php",
type:"POST",
data:{user_name:username.value, password:password.value, name:name.value, mandt:mandt.value, admin:admin}
})
username.value = ''; // Leert das Textfeld
password.value = ''; // Leert das Textfeld
name.value = ''; // Leert das Textfeld
mandt.value = ''; // Leert das Textfeld
adminCheckbox.checked = false; // Setzt die Checkbox zurück
form.style.height = '550px';
message.classList.remove("hidden");
delay(4000).then(() => {
message.classList.add("hidden");
form.style.height = '460px';
});
};
};
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
function goback() {
window.location.href = "../../home.php";
}
</script>
</body>
<script>
// Funktion zum Logout nach einer bestimmten Zeit
function delayedLogout() {
// Setze den Timeout auf 5 Minuten (300000 Millisekunden)
var timeout = 300000; // 5 Minuten in Millisekunden
// Timeout-Funktion zum Ausführen des Logouts
var logoutTimeout;
function startLogoutTimer() {
logoutTimeout = setTimeout(logout, timeout);
}
function resetLogoutTimer() {
clearTimeout(logoutTimeout); // Timer zurücksetzen
startLogoutTimer(); // Timer neu starten
}
function logout() {
// Weiterleitung auf die logout.php-Seite
window.location.href = "../../logout.php";
}
// Starte den Timer beim Laden der Seite
startLogoutTimer();
// Reagiere auf Benutzerinteraktionen
document.addEventListener("click", resetLogoutTimer);
//document.addEventListener("mousemove", resetLogoutTimer);
document.addEventListener("keypress", resetLogoutTimer);
}
// Starte den Timer beim Laden der Seite
window.onload = delayedLogout;
</script>
</html>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

27
src/PHP/connection.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<?php
/* Database connection start */
$servername = "localhost";
$username = "foody";
$password = "M9wdHGTwhNc*u9a@JKU^";
$dbname = "foodydb";
($conn = new PDO('mysql:host=localhost;dbname=foodydb', $username, $password)) or
die("Connection failed: " . mysqli_connect_error());
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

12
src/PHP/connection2.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
$servername = "localhost";
$username = "foody";
$password = "M9wdHGTwhNc*u9a@JKU^";
$dbname = "foodydb";
$conn = mysqli_connect($servername, $username, $password, $dbname);
if (!$conn) {
echo "Connection failed!";
}
?>

12
src/PHP/connection3.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
$servername = "localhost";
$username = "foody";
$password = "M9wdHGTwhNc*u9a@JKU^";
$dbname = "foodydb";
$mysqli = mysqli_connect($servername, $username, $password, $dbname);
if (!$mysqli) {
echo "Connection failed!";
}
?>

31
src/PHP/createuser.php Normal file
View File

@@ -0,0 +1,31 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<?php
include_once "./connection.php";
if(isset($_POST['user_name']))
{
$hashed_password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$admin = isset($_POST['admin']) && $_POST['admin'] == 1 ? 1 : 0;
$query = 'INSERT INTO users (user_name, password, name, mandt, admin) VALUES (:user_name, :password, :name, :mandt, :admin)';
$statement = $conn->prepare($query);
$statement->execute(
array(
':user_name' => $_POST['user_name'],
':password' => $hashed_password,
':name' => $_POST['name'],
':mandt' => $_POST['mandt'],
':admin' => $admin,
)
);
}
?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

28
src/PHP/delete.php Normal file
View File

@@ -0,0 +1,28 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<html>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"></META>
</html>
<?php
include_once "./connection.php";
$query = "DELETE from foody_main WHERE id=:id AND mandt=:mandt";
$statement = $conn->prepare($query);
$statement->execute(
array(
':id' => $_POST['id'],
':mandt' => $_SESSION['mandt'],
)
);
?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

30
src/PHP/duplicate.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<html>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"></META>
</html>
<?php
include_once "./connection.php";
if(isset($_POST['id']))
{
$query = "INSERT INTO foody_main (mealname, mealdate, mealadditive, mealsupplement1, mealsupplement2, mealsupplement3, mandt) SELECT mealname, mealdate, mealadditive, mealsupplement1, mealsupplement2, mealsupplement3, mandt from foody_main WHERE id=:id AND mandt=:mandt; UPDATE foody_main SET mealdate=:mealdate, mandt=:mandt WHERE id=(SELECT id from foody_main ORDER BY id DESC LIMIT 0, 1) AND mandt=:mandt;";
$statement = $conn->prepare($query);
$statement->execute(
array(
':id' => $_POST['id'],
':mealdate' => $_POST['mealdate'],
':mandt' => $_SESSION['mandt'],
)
);
}
?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

34
src/PHP/insert.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<html>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"></META>
</html>
<?php
include_once "./connection.php";
if(isset($_POST['mealname']))
{
$query = 'INSERT INTO foody_main (mealname, mealdate, mealadditive, mealsupplement1, mealsupplement2, mealsupplement3, mandt) VALUES (:mealname, :mealdate, :mealadditive, :mealsupplement1, :mealsupplement2, :mealsupplement3, :mandt)';
$statement = $conn->prepare($query);
$statement->execute(
array(
':mealname' => $_POST['mealname'],
':mealdate' => $_POST['mealdate'],
':mealadditive' => $_POST['mealadditive'],
':mealsupplement1' => $_POST['mealsupplement1'],
':mealsupplement2' => $_POST['mealsupplement2'],
':mealsupplement3' => $_POST['mealsupplement3'],
':mandt' => $_SESSION['mandt'],
)
);
}
?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

52
src/PHP/load.php Normal file
View File

@@ -0,0 +1,52 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<?php
include_once "./connection.php";
$color = 'black';
$classNames = ['custom-all-day'];
$start = explode("T", $_GET['start'])[0];
$end = explode("T", $_GET['end'])[0];
$data = array();
$query = "SELECT id, mealname, mealdate FROM foody_main WHERE mandt = :mandt AND (
(DATE_FORMAT(mealdate, '%Y-%m') >= DATE_FORMAT(:start, '%Y-%m') AND DATE_FORMAT(mealdate, '%Y-%m') < DATE_FORMAT(:end, '%Y-%m'))
OR
(DATE_FORMAT(mealdate, '%Y-%m') >= DATE_FORMAT(:start - INTERVAL 1 MONTH, '%Y-%m') AND DATE_FORMAT(mealdate, '%Y-%m') < DATE_FORMAT(:end - INTERVAL 1 MONTH, '%Y-%m'))
OR
(DATE_FORMAT(mealdate, '%Y-%m') >= DATE_FORMAT(:start - INTERVAL 2 MONTH, '%Y-%m') AND DATE_FORMAT(mealdate, '%Y-%m') < DATE_FORMAT(:end - INTERVAL 2 MONTH, '%Y-%m'))
OR
(DATE_FORMAT(mealdate, '%Y-%m') >= DATE_FORMAT(:start + INTERVAL 1 MONTH, '%Y-%m') AND DATE_FORMAT(mealdate, '%Y-%m') < DATE_FORMAT(:end + INTERVAL 1 MONTH, '%Y-%m')));";
$statement = $conn->prepare($query);
$statement->execute(
array(
':mandt' => $_SESSION['mandt'],
':start' => $start,
':end' => $end,
)
);
$result = $statement->fetchAll();
foreach($result as $row)
{
$data[] = array(
'id' => $row["id"],
'title' => $row["mealname"],
'start' => $row["mealdate"],
'textColor' => $color,
'classNames' => $classNames,
);
}
echo json_encode($data);
?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

76
src/PHP/registration.php Normal file
View File

@@ -0,0 +1,76 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<html>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"></META>
<head>
<style>
.hidden {
display: none;
}
</style>
<title>Login</title>
<link rel="stylesheet" type="text/css" href="../CSS/index.css">
</head>
<body oncontextmenu="return false;">
<form action="javascript:createuser();" method="post">
<h2>Create new user</h2>
<p class="error hidden" id="error">Bitte alle Felder überprüfen!</p>
<label>Username</label>
<input type="text" name="uname" placeholder="Username" id="username"><br>
<label>Password</label>
<input type="password" name="password" placeholder="Password" id="password"><br>
<label>Name</label>
<input type="text" name="name" placeholder="Full Name" id="name"><br>
<label>Mandant</label>
<input type="text" name="mandt" placeholder="Mandant" id="mandt"><br>
<button type="submit">Create user</button>
</form>
<script src='../JS/jquery.min.js'></script>
<script>
function createuser() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var name = document.getElementById("name").value;
var mandt = document.getElementById("mandt").value;
var test = username === "";
var test2 = password === "";
var test3 = name === "";
var test4 = mandt === "";
if (test || test2 || test3 || test4) {
var error = document.getElementById("error");
error.classList.toggle("hidden");
//alert("Fehler: Bitte alle Eingaben überprüfen!");
} else {
$.ajax({
url:"../PHP/insert.php",
type:"POST",
data:{user_name:username, password:password, name:name, mandt:mandt}
})
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
delay(1000).then(() => window.location.href = "../../home.php?calendardate=" + date);
//console.log('ran after 1 second passed'));
//window.location.href = "../../home.php";
};
};
function goback() {
window.location.href = "../../home.php?calendardate=";
};
</script>
</body>
</html>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

204
src/PHP/searchtable2.php Normal file
View File

@@ -0,0 +1,204 @@
<?php
session_start();
function delayedLogout($seconds) {
sleep($seconds); // Pausiere die Ausführung für die angegebene Anzahl von Sekunden
// Führe das Logout-Skript aus
session_unset(); // Lösche alle Session-Variablen
session_destroy(); // Zerstöre die Session
header("Location: ./logout.php"); // Leite auf die Logout-Seite weiter
exit(); // Beende das Skript
}
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<html>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"></META>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<link rel="stylesheet" type="text/css" href="../CSS/searchtable.css" />
<link rel="stylesheet" type="text/css" href="../CSS/searchtable2.css" />
</head>
<body>
<div id="loader-container">
<div id="loader"></div>
</div>
<button class="button button-blue" onclick="goback()">zurück zum Kalender</button>
<?php
include './connection2.php';
$query = "SELECT DISTINCT mealname FROM foody_main WHERE mandt={$_SESSION['mandt']} ORDER BY mealname";
$query2 = "SELECT DISTINCT mealadditive FROM foody_main WHERE mandt={$_SESSION['mandt']} ORDER BY mealadditive";
$query3 = "SELECT supplementname FROM supplementfoods WHERE mandt={$_SESSION['mandt']} ORDER BY supplementname";
$result2 = mysqli_query($conn, $query);
$result3 = mysqli_query($conn, $query2);
$result4 = mysqli_query($conn, $query3);
$timestamp = strtotime($_GET['date']);
$date = date("d-m-Y", $timestamp );
?>
<h1 style="font-family: 'Lato', sans-serif;
font-weight: 600;
font-size: 2.3em;
color: black;
text-align: center;">Neuer Eintrag</h1>
<table id="myTable">
<tr>
<th style="font-size: 20px">Gericht</th>
<td>
<input class= "inputField" type="text" list="Gerichtname" autocomplete="off" id="Gericht">
<datalist id="Gerichtname">
<?php while($row = mysqli_fetch_array($result2)) { ?>
<option value="<?php echo $row['mealname']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Gerichtzusatz</th>
<td>
<input class= "inputField" type="text" list="Gerichtzusatzname" autocomplete="off" id="Gerichtzusatz">
<datalist id="Gerichtzusatzname">
<?php while($row2 = mysqli_fetch_array($result3)) { ?>
<option value="<?php echo $row2['mealadditive']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Beilage 1</th>
<td>
<input class= "inputField" type="text" list="Beilage_1name" autocomplete="off" id="Beilage_1">
<datalist id="Beilage_1name">
<?php while($row3 = mysqli_fetch_array($result4)) { ?>
<option value="<?php echo $row3['supplementname']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Beilage 2</th>
<td>
<input class= "inputField" type="text" list="Beilage_1name" autocomplete="off" id="Beilage_2">
<datalist id="Beilage_1name">
<?php while($row3 = mysqli_fetch_array($result4)) { ?>
<option value="<?php echo $row3['supplementname']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Beilage 3</th>
<td>
<input class= "inputField" type="text" list="Beilage_1name" autocomplete="off" id="Beilage_3">
<datalist id="Beilage_1name">
<?php while($row3 = mysqli_fetch_array($result4)) { ?>
<option value="<?php echo $row3['supplementname']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 19px">Datum</th>
<td>
<?php $date = date("Y-m-d", $timestamp ); ?>
<input class= "inputField" type="date" list="mealdate" autocomplete="off" id="mealdate" value="<?php echo $date ?>">
</td>
</tr>
</table>
<button class="button-round" style="position: relative;
font-size: 15px;" onclick="addevent();">Hinzufügen</button>
<?php mysqli_close($conn); ?>
<script>
// JavaScript, um die Ladeanimation zu aktivieren/deaktivieren
function showLoader() {
document.getElementById("loader-container").style.display = "flex";
document.body.style.overflow = "hidden"; // Um das Scrollen zu deaktivieren
}
function hideLoader() {
document.getElementById("loader-container").style.display = "none";
document.body.style.overflow = "auto"; // Um das Scrollen wieder zu aktivieren
}
// Beispiel für die Verwendung:
// Rufe showLoader() auf, wenn du die Ladeanimation anzeigen möchtest
// Rufe hideLoader() auf, wenn die Seite fertig geladen ist
// Zum Beispiel: showLoader() beim Klicken auf einen Button, hideLoader() nach dem Laden einer AJAX-Anfrage usw.
</script>
<script src='../JS/jquery.min.js'></script>
<script>
function addevent() {
var gericht = document.getElementById("Gericht").value;
var gerichtzusatz = document.getElementById("Gerichtzusatz").value;
var beilage1 = document.getElementById("Beilage_1").value;
var beilage2 = document.getElementById("Beilage_2").value;
var beilage3 = document.getElementById("Beilage_3").value;
var date = document.getElementById("mealdate").value;
var test = gericht === "";
var test2 = date === "";
console.log(gericht, gerichtzusatz, beilage1, beilage2, beilage3, date);
if (test || test2) {
alert("Fehler: Bitte alle Eingaben überprüfen!");
} else {
$.ajax({
url:"../PHP/insert.php",
type:"POST",
data:{mealname:gericht, mealdate:date, mealadditive:gerichtzusatz, mealsupplement1:beilage1, mealsupplement2:beilage2, mealsupplement3:beilage3}
})
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
showLoader();
delay(1000).then(() => window.location.href = "../../home.php?calendardate=" + date);
//console.log('ran after 1 second passed'));
//window.location.href = "../../home.php";
};
};
function goback() {
var date = document.getElementById("mealdate").value;
window.location.href = "../../home.php?calendardate=" + date;
};
</script>
<script>
// Funktion zum Logout nach einer bestimmten Zeit
function delayedLogout() {
// Setze den Timeout auf 5 Minuten (300000 Millisekunden)
var timeout = 300000; // 5 Minuten in Millisekunden
// Timeout-Funktion zum Ausführen des Logouts
var logoutTimeout;
function startLogoutTimer() {
logoutTimeout = setTimeout(logout, timeout);
}
function resetLogoutTimer() {
clearTimeout(logoutTimeout); // Timer zurücksetzen
startLogoutTimer(); // Timer neu starten
}
function logout() {
// Weiterleitung auf die logout.php-Seite
window.location.href = "../../logout.php";
}
// Starte den Timer beim Laden der Seite
startLogoutTimer();
// Reagiere auf Benutzerinteraktionen
document.addEventListener("click", resetLogoutTimer);
//document.addEventListener("mousemove", resetLogoutTimer);
document.addEventListener("keypress", resetLogoutTimer);
}
// Starte den Timer beim Laden der Seite
window.onload = delayedLogout;
</script>
</body>
</html>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

252
src/PHP/showeventdata2.php Normal file
View File

@@ -0,0 +1,252 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<html>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"></META>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<link rel="stylesheet" type="text/css" href="../CSS/searchtable.css" />
<link rel="stylesheet" type="text/css" href="../CSS/showeventdata2.css" />
</head>
</html>
<?php
include './connection2.php';
$id = $_GET["id"];
$query = "SELECT DISTINCT mealname FROM foody_main WHERE mandt={$_SESSION['mandt']} ORDER BY mealname";
$query2 = "SELECT DISTINCT mealadditive FROM foody_main WHERE mandt={$_SESSION['mandt']} ORDER BY mealadditive";
$query3 = "SELECT supplementname FROM supplementfoods WHERE mandt={$_SESSION['mandt']} ORDER BY supplementname";
$result = mysqli_query($conn,"SELECT * FROM foody_main WHERE ID=$id");
$result1 = mysqli_query($conn,"SELECT * FROM foody_main WHERE ID=$id");
$result2 = mysqli_query($conn, $query);
$result3 = mysqli_query($conn, $query2);
$result4 = mysqli_query($conn, $query3);
$row = mysqli_fetch_array($result);
$row1 = mysqli_fetch_array($result1);
$timestamp = strtotime($row1["mealdate"]);
$date = date("d-m-Y", $timestamp );
?>
<html>
<style>
</style>
<body>
<div id="loader-container">
<div id="loader"></div>
</div>
<button class="button button-blue" onclick="goback()">zurück zum Kalender</button>
<div>
<h1 style="font-family: 'Lato', sans-serif;
font-weight: 600;
font-size: 2.3em;
color: black;
text-align: center;"><?php echo $row['mealname']; ?></h1>
<button class="button-round" style="position: relative; font-size: 15px;" onclick="showinputfields()">Bearbeiten</button>
<table id="myTable">
<tr>
<th style="font-size: 20px">Gericht</th>
<td class="spalte2"><?php echo $row1['mealname']; ?></td>
<td class="hidden" id="z2">
<input class= "inputField" type="text" list="Gerichtname" autocomplete="off" id="Gericht" value="<?php echo $row1['mealname']; ?>">
<datalist id="Gerichtname">
<?php while($row = mysqli_fetch_array($result2)) { ?>
<option value="<?php echo $row['mealname']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Gerichtzusatz</th>
<td class="spalte2"><?php echo $row1['mealadditive']; ?></td>
<td class="hidden" id="z3">
<input class= "inputField" type="text" list="Gerichtzusatzname" autocomplete="off" id="Gerichtzusatz" value="<?php echo $row1['mealadditive']; ?>">
<datalist id="Gerichtzusatzname">
<?php while($row2 = mysqli_fetch_array($result3)) { ?>
<option value="<?php echo $row2['mealadditive']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Beilage 1</th>
<td class="spalte2"><?php echo $row1['mealsupplement1']; ?></td>
<td class="hidden" id="z4">
<input class= "inputField" type="text" list="Beilage_1name" autocomplete="off" id="Beilage_1" value="<?php echo $row1['mealsupplement1']; ?>">
<datalist id="Beilage_1name">
<?php while($row3 = mysqli_fetch_array($result4)) { ?>
<option value="<?php echo $row3['supplementname']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Beilage 2</th>
<td class="spalte2"><?php echo $row1['mealsupplement2']; ?></td>
<td class="hidden" id="z5">
<input class= "inputField" type="text" list="Beilage_1name" autocomplete="off" id="Beilage_2" value="<?php echo $row1['mealsupplement2']; ?>">
<datalist id="Beilage_1name">
<?php while($row3 = mysqli_fetch_array($result4)) { ?>
<option value="<?php echo $row3['supplementname']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Beilage 3</th>
<td class="spalte2"><?php echo $row1['mealsupplement3']; ?></td>
<td class="hidden" id="z6">
<input class= "inputField" type="text" list="Beilage_1name" autocomplete="off" id="Beilage_3" value="<?php echo $row1['mealsupplement3']; ?>">
<datalist id="Beilage_1name">
<?php while($row3 = mysqli_fetch_array($result4)) { ?>
<option value="<?php echo $row3['supplementname']; ?>"></option>
<?php } ?>
</datalist>
</td>
</tr>
<tr>
<th style="font-size: 20px">Datum</th>
<td class="spalte2"><?php echo $date ?></td>
<?php $date = date("Y-m-d", $timestamp ); ?>
<td class="hidden" id="z7">
<input class= "inputField" type="date" list="mealdate" autocomplete="off" id="mealdate" value="<?php echo $date ?>">
</td>
</tr>
</table>
<button style="position: relative;
font-size: 15px;" onclick="changedata()" class="hidden button-round" id="b2">Änderungen übernehmen</button>
<button style="position: relative;
font-size: 15px;" onclick="deletedata()" class="hidden button-round" id="b3">Löschen</button>
</div>
</body>
</html>
<script>
// JavaScript, um die Ladeanimation zu aktivieren/deaktivieren
function showLoader() {
document.getElementById("loader-container").style.display = "flex";
document.body.style.overflow = "hidden"; // Um das Scrollen zu deaktivieren
}
function hideLoader() {
document.getElementById("loader-container").style.display = "none";
document.body.style.overflow = "auto"; // Um das Scrollen wieder zu aktivieren
}
// Beispiel für die Verwendung:
// Rufe showLoader() auf, wenn du die Ladeanimation anzeigen möchtest
// Rufe hideLoader() auf, wenn die Seite fertig geladen ist
// Zum Beispiel: showLoader() beim Klicken auf einen Button, hideLoader() nach dem Laden einer AJAX-Anfrage usw.
</script>
<script src='../JS/jquery.min.js'></script>
<script src='../JS/moment.min.js'></script>
<script>
function showinputfields() {
var z2 = document.getElementById("z2");
z2.classList.toggle("hidden");
var z3 = document.getElementById("z3");
z3.classList.toggle("hidden");
var z4 = document.getElementById("z4");
z4.classList.toggle("hidden");
var z5 = document.getElementById("z5");
z5.classList.toggle("hidden");
var z6 = document.getElementById("z6");
z6.classList.toggle("hidden");
var z7 = document.getElementById("z7");
z7.classList.toggle("hidden");
var b2 = document.getElementById("b2");
b2.classList.toggle("hidden");
var b3 = document.getElementById("b3");
b3.classList.toggle("hidden");
};
function changedata() {
var id = '<?=$id?>';
var gericht = document.getElementById("Gericht").value;
var gerichtzusatz = document.getElementById("Gerichtzusatz").value;
var beilage1 = document.getElementById("Beilage_1").value;
var beilage2 = document.getElementById("Beilage_2").value;
var beilage3 = document.getElementById("Beilage_3").value;
var mealdate = document.getElementById("mealdate").value;
var date = document.getElementById("mealdate").value;
var test = gericht === "";
var test2 = date === "";
console.log(gericht, gerichtzusatz, beilage1, beilage2, beilage3, mealdate, id);
if (test || test2) {
alert("Fehler: Bitte alle Eingaben überprüfen!");
} else {
$.ajax({
url:"../PHP/update.php",
type:"POST",
data:{mealname:gericht, mealdate:mealdate, mealadditive:gerichtzusatz, mealsupplement1:beilage1, mealsupplement2:beilage2, mealsupplement3:beilage3, id:id}
})
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
showLoader();
delay(1000).then(() => window.location.reload());
}
};
function deletedata() {
if (confirm('Wirklich löschen?')) {
var date = '<?=$date?>';
var id = '<?=$id?>';
console.log(id);
$.ajax({
url:"../PHP/delete.php",
type:"POST",
data:{id:id}
})
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
showLoader();
delay(1000).then(() => window.location.href = "../../home.php?calendardate=" + date);
//window.location.href = "../../home.php";
}
};
function goback() {
var date = document.getElementById("mealdate").value;
window.location.href = "../../home.php?calendardate=" + date;
};
</script>
<script>
// Funktion zum Logout nach einer bestimmten Zeit
function delayedLogout() {
// Setze den Timeout auf 5 Minuten (300000 Millisekunden)
var timeout = 300000; // 5 Minuten in Millisekunden
// Timeout-Funktion zum Ausführen des Logouts
var logoutTimeout;
function startLogoutTimer() {
logoutTimeout = setTimeout(logout, timeout);
}
function resetLogoutTimer() {
clearTimeout(logoutTimeout); // Timer zurücksetzen
startLogoutTimer(); // Timer neu starten
}
function logout() {
// Weiterleitung auf die logout.php-Seite
window.location.href = "../../logout.php";
}
// Starte den Timer beim Laden der Seite
startLogoutTimer();
// Reagiere auf Benutzerinteraktionen
document.addEventListener("click", resetLogoutTimer);
//document.addEventListener("mousemove", resetLogoutTimer);
document.addEventListener("keypress", resetLogoutTimer);
}
// Starte den Timer beim Laden der Seite
window.onload = delayedLogout;
</script>
<?php mysqli_close($conn); ?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

3
src/PHP/sort.php Normal file
View File

@@ -0,0 +1,3 @@
<?php
session_start();
?>

35
src/PHP/update.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<html>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"></META>
</html>
<?php
include_once "./connection.php";
if(isset($_POST["id"]))
{
$query = 'UPDATE foody_main SET mealname=:mealname, mealdate=:mealdate, mealadditive=:mealadditive, mealsupplement1=:mealsupplement1, mealsupplement2=:mealsupplement2, mealsupplement3=:mealsupplement3 WHERE id=:id AND mandt=:mandt';
$statement = $conn->prepare($query);
$statement->execute(
array(
':id' => $_POST['id'],
':mealname' => $_POST['mealname'],
':mealdate' => $_POST['mealdate'],
':mealadditive' => $_POST['mealadditive'],
':mealsupplement1' => $_POST['mealsupplement1'],
':mealsupplement2' => $_POST['mealsupplement2'],
':mealsupplement3' => $_POST['mealsupplement3'],
':mandt' => $_SESSION['mandt'],
)
);
}
?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>

30
src/PHP/update2.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
session_start();
if (isset($_SESSION['id']) && isset($_SESSION['user_name'])) {
?>
<html>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"></META>
</html>
<?php
include_once "./connection.php";
if(isset($_POST["id"]))
{
$query = 'UPDATE foody_main SET mealdate=:mealdate WHERE id=:id AND mandt=:mandt';
$statement = $conn->prepare($query);
$statement->execute(
array(
':id' => $_POST['id'],
':mealdate' => $_POST['mealdate'],
':mandt' => $_SESSION['mandt'],
)
);
}
?>
<?php
} else {
header("Location: ../../index.php");
exit();
}
?>