531 lines
27 KiB
HTML
531 lines
27 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>ELSA - Elektronischer Semesterapparat</title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<link rel="stylesheet" href="/static/styles.css">
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css">
|
||
</head>
|
||
<body>
|
||
<header class="site-header">
|
||
<div class="container header-inner">
|
||
<div class="header-left">
|
||
<img class="logo" src="https://www.ph-freiburg.de/_assets/cc3dd7db45300ecc1f3aeed85bda5532/Images/logo-big-blue.svg" alt="PH Freiburg Logo" />
|
||
<div class="brand">
|
||
<div class="brand-title">Bibliothek der Pädagogischen Hochschule Freiburg</div>
|
||
<div class="brand-sub">Hochschulbibliothek · ELSA</div>
|
||
</div>
|
||
</div>
|
||
<button type="button" id="theme-toggle" class="theme-toggle" aria-label="Switch to dark mode" title="Switch to dark mode">
|
||
<span class="mdi mdi-theme-light-dark" aria-hidden="true"></span>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="container">
|
||
<section class="card">
|
||
<h1>ELSA - Elektronischer Semesterapparat</h1>
|
||
|
||
<div class="legal-notice">
|
||
<h3><span class="mdi mdi-information"></span> Rechtlicher Hinweis</h3>
|
||
<p>
|
||
Das Urheberrecht gestattet gemäß § 60a UrhG zur Veranschaulichung des Unterrichts die Bereitstellung elektronischer Kopien bis max. 15% von veröffentlichten Werken, von einzelnen Aufsätzen aus Fachzeitschriften und von Werken geringen Umfangs (max. 25 S. Gesamtumfang) für einen genau abgegrenzten Benutzerkreis wie den Teilnehmenden einer Lehrveranstaltung, die sich auf ILIAS angemeldet haben.
|
||
</p>
|
||
</div>
|
||
|
||
<form method="post" action="/elsa/submit" class="request-form">
|
||
<h2>Allgemeine Informationen</h2>
|
||
<div class="grid-form">
|
||
<div class="form-field">
|
||
<label for="name">Name</label>
|
||
<input type="text" name="name" id="name" required>
|
||
</div>
|
||
<div class="form-field">
|
||
<label for="lastname">Nachname</label>
|
||
<input type="text" name="lastname" id="lastname" required>
|
||
</div>
|
||
<div class="form-field">
|
||
<label for="title">Titel (optional)</label>
|
||
<input type="text" name="title" id="title">
|
||
</div>
|
||
<div class="form-field">
|
||
<label for="mail">Email</label>
|
||
<input type="email" name="mail" id="mail" required>
|
||
</div>
|
||
|
||
<div class="form-field">
|
||
<label for="subject">Fach</label>
|
||
<select name="subject" id="subject" required>
|
||
<option value="">-- Auswählen --</option>
|
||
<option>Biologie</option>
|
||
<option>Chemie</option>
|
||
<option>Deutsch</option>
|
||
<option>Englisch</option>
|
||
<option>Erziehungswirtschaft</option>
|
||
<option>Französisch</option>
|
||
<option>Geographie</option>
|
||
<option>Geschichte</option>
|
||
<option>Gesundheitspädagogik</option>
|
||
<option>Haushalt / Textil</option>
|
||
<option>Kunst</option>
|
||
<option>Mathematik / Informatik</option>
|
||
<option>Medien in der Bildung</option>
|
||
<option>Musik</option>
|
||
<option>Philosophie</option>
|
||
<option>Physik</option>
|
||
<option>Politikwissenschaft</option>
|
||
<option>Prorektorat Lehre und Studium</option>
|
||
<option>Psychologie</option>
|
||
<option>Soziologie</option>
|
||
<option>Sport</option>
|
||
<option>Technik</option>
|
||
<option>Theologie</option>
|
||
<option>Wirtschaftslehre</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-field">
|
||
<label for="classname">Veranstaltungsname</label>
|
||
<input type="text" name="classname" id="classname" required>
|
||
</div>
|
||
<div class="form-field">
|
||
<label for="usage_date_from">Nutzungszeitraum von</label>
|
||
<input type="date" name="usage_date_from" id="usage_date_from" required>
|
||
</div>
|
||
<div class="form-field">
|
||
<label for="usage_date_to">Nutzungszeitraum bis</label>
|
||
<input type="date" name="usage_date_to" id="usage_date_to" required>
|
||
</div>
|
||
<div class="form-field">
|
||
<label for="availability_date">Bereitstellungsdatum</label>
|
||
<input type="date" name="availability_date" id="availability_date" required>
|
||
</div>
|
||
</div>
|
||
|
||
<h2>Medien</h2>
|
||
<div class="media-controls">
|
||
<button type="button" id="btn-monografie" class="btn btn-secondary" onclick="addMediaType('monografie')" title="Monografie Sektion hinzufügen">
|
||
<span class="mdi mdi-book"></span> + Monografie
|
||
</button>
|
||
<button type="button" id="btn-zeitschriftenartikel" class="btn btn-secondary" onclick="addMediaType('zeitschriftenartikel')" title="Zeitschriftenartikel Sektion hinzufügen">
|
||
<span class="mdi mdi-newspaper"></span> + Zeitschriftenartikel
|
||
</button>
|
||
<button type="button" id="btn-herausgeberwerk" class="btn btn-secondary" onclick="addMediaType('herausgeberwerk')" title="Herausgeberwerk Sektion hinzufügen">
|
||
<span class="mdi mdi-book-multiple"></span> + Herausgeberwerk
|
||
</button>
|
||
</div>
|
||
|
||
<div id="media-sections"></div>
|
||
|
||
<div class="form-field" style="margin-top: 20px;">
|
||
<label for="message">Nachricht (optional)</label>
|
||
<textarea name="message" id="message" rows="4" placeholder="Zusätzliche Anmerkungen oder Hinweise..."></textarea>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button type="submit" class="btn btn-primary">Absenden</button>
|
||
</div>
|
||
</form>
|
||
</section>
|
||
</main>
|
||
|
||
<script>
|
||
let mediaCounter = {
|
||
monografie: 0,
|
||
zeitschriftenartikel: 0,
|
||
herausgeberwerk: 0
|
||
};
|
||
|
||
let sectionCounter = 0;
|
||
|
||
// Track signature validations: { signature: { totalPages: int, requestedPages: int, inputs: [elements] } }
|
||
let signatureTracking = {};
|
||
|
||
// Debounce timer for signature validation
|
||
let validationTimers = {};
|
||
|
||
// Theme toggle functionality (in IIFE to avoid polluting global scope)
|
||
(function() {
|
||
const STORAGE_KEY = 'theme';
|
||
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||
const saved = localStorage.getItem(STORAGE_KEY);
|
||
|
||
function setTheme(theme) {
|
||
document.documentElement.setAttribute('data-theme', theme);
|
||
localStorage.setItem(STORAGE_KEY, theme);
|
||
const btn = document.getElementById('theme-toggle');
|
||
if (btn) {
|
||
const label = theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode';
|
||
btn.setAttribute('aria-label', label);
|
||
btn.title = label;
|
||
}
|
||
}
|
||
|
||
setTheme(saved || (prefersDark ? 'dark' : 'light'));
|
||
|
||
const btn = document.getElementById('theme-toggle');
|
||
if (btn) {
|
||
btn.addEventListener('click', () => {
|
||
const current = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light';
|
||
setTheme(current === 'dark' ? 'light' : 'dark');
|
||
});
|
||
}
|
||
})();
|
||
|
||
// Media management functions (global scope for onclick handlers)
|
||
function addMediaType(type) {
|
||
const btn = document.getElementById('btn-' + type);
|
||
// Prevent duplicate sections of same type
|
||
if (btn && btn.disabled) { return; }
|
||
const container = document.getElementById('media-sections');
|
||
const sectionId = 'section-' + sectionCounter++;
|
||
|
||
const section = document.createElement('div');
|
||
section.className = 'media-section';
|
||
section.id = sectionId;
|
||
section.setAttribute('data-type', type);
|
||
|
||
let title = '';
|
||
let tableHtml = '';
|
||
|
||
if (type === 'monografie') {
|
||
title = 'Monografie';
|
||
tableHtml = '<table class="data-table media-table" id="table-' + sectionId + '">' +
|
||
'<tr>' +
|
||
'<th>Autor<br>(Nachname, Vorname)</th>' +
|
||
'<th>Jahr</th>' +
|
||
'<th>Auflage</th>' +
|
||
'<th>Titel</th>' +
|
||
'<th>Signatur</th>' +
|
||
'<th>Seiten von</th>' +
|
||
'<th>Seiten bis</th>' +
|
||
'<th></th>' +
|
||
'</tr>' +
|
||
'</table>';
|
||
} else if (type === 'zeitschriftenartikel') {
|
||
title = 'Zeitschriftenartikel';
|
||
tableHtml = '<table class="data-table media-table" id="table-' + sectionId + '">' +
|
||
'<tr>' +
|
||
'<th>Autor<br>(Nachname, Vorname)</th>' +
|
||
'<th>Jahr</th>' +
|
||
'<th>Band</th>' +
|
||
'<th>Titel des Artikels</th>' +
|
||
'<th>Titel der Zeitschrift</th>' +
|
||
'<th>Signatur</th>' +
|
||
'<th>Seiten von</th>' +
|
||
'<th>Seiten bis</th>' +
|
||
'<th></th>' +
|
||
'</tr>' +
|
||
'</table>';
|
||
} else if (type === 'herausgeberwerk') {
|
||
title = 'Herausgeberwerk';
|
||
tableHtml = '<table class="data-table media-table" id="table-' + sectionId + '">' +
|
||
'<tr>' +
|
||
'<th>Herausgeber<br>(Nachname, Vorname)</th>' +
|
||
'<th>Titel des Werks</th>' +
|
||
'<th>Jahr</th>' +
|
||
'<th>Auflage</th>' +
|
||
'<th>Autor des Artikels<br>(Nachname, Vorname)</th>' +
|
||
'<th>Titel des Artikels</th>' +
|
||
'<th>Signatur</th>' +
|
||
'<th>Seiten von</th>' +
|
||
'<th>Seiten bis</th>' +
|
||
'<th></th>' +
|
||
'</tr>' +
|
||
'</table>';
|
||
}
|
||
|
||
section.innerHTML = '<div class="media-section-header">' +
|
||
'<h3><span class="mdi ' + getIconForType(type) + '"></span> ' + title + '</h3>' +
|
||
'<button type="button" class="btn-icon" onclick="removeMediaSection(\'' + sectionId + '\')" title="Sektion entfernen">' +
|
||
'<span class="mdi mdi-close"></span>' +
|
||
'</button>' +
|
||
'</div>' +
|
||
tableHtml +
|
||
'<button type="button" class="btn btn-secondary btn-sm" onclick="addMediaRow(\'' + sectionId + '\', \'' + type + '\')">' +
|
||
'+ Eintrag hinzufügen' +
|
||
'</button>';
|
||
|
||
container.appendChild(section);
|
||
// Disable button for this type until section removed
|
||
if (btn) {
|
||
btn.disabled = true;
|
||
btn.title = 'Sektion bereits hinzugefügt – entfernen zum erneuten Hinzufügen';
|
||
}
|
||
|
||
// Add first row automatically
|
||
addMediaRow(sectionId, type);
|
||
}
|
||
|
||
function getIconForType(type) {
|
||
const icons = {
|
||
'monografie': 'mdi-book',
|
||
'zeitschriftenartikel': 'mdi-newspaper',
|
||
'herausgeberwerk': 'mdi-book-multiple'
|
||
};
|
||
return icons[type] || 'mdi-file';
|
||
}
|
||
|
||
function addMediaRow(sectionId, type) {
|
||
const table = document.getElementById('table-' + sectionId);
|
||
const row = table.insertRow(-1);
|
||
const rowId = sectionId + '-row-' + mediaCounter[type]++;
|
||
row.id = rowId;
|
||
|
||
if (type === 'monografie') {
|
||
row.innerHTML = '<td><input type="text" name="monografie_author[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="monografie_year[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="monografie_edition[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="monografie_title[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="monografie_signature[]" data-section="' + sectionId + '" placeholder="Optional"></td>' +
|
||
'<td><input type="number" name="monografie_pages_from[]" data-section="' + sectionId + '" required min="1"></td>' +
|
||
'<td><input type="number" name="monografie_pages_to[]" data-section="' + sectionId + '" required min="1"></td>' +
|
||
'<td><button type="button" class="btn-icon" onclick="removeRow(\'' + rowId + '\')" title="Zeile entfernen"><span class="mdi mdi-delete"></span></button></td>';
|
||
attachSignatureListeners(row);
|
||
} else if (type === 'zeitschriftenartikel') {
|
||
row.innerHTML = '<td><input type="text" name="zeitschrift_author[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="zeitschrift_year[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="zeitschrift_volume[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="zeitschrift_article_title[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="zeitschrift_journal_title[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="zeitschrift_signature[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="number" name="zeitschrift_pages_from[]" data-section="' + sectionId + '" required min="1"></td>' +
|
||
'<td><input type="number" name="zeitschrift_pages_to[]" data-section="' + sectionId + '" required min="1"></td>' +
|
||
'<td><button type="button" class="btn-icon" onclick="removeRow(\'' + rowId + '\')" title="Zeile entfernen"><span class="mdi mdi-delete"></span></button></td>';
|
||
} else if (type === 'herausgeberwerk') {
|
||
row.innerHTML = '<td><input type="text" name="herausgeber_publisher[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="herausgeber_work_title[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="herausgeber_year[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="herausgeber_edition[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="herausgeber_article_author[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="herausgeber_article_title[]" data-section="' + sectionId + '" required></td>' +
|
||
'<td><input type="text" name="herausgeber_signature[]" data-section="' + sectionId + '" placeholder="Optional"></td>' +
|
||
'<td><input type="number" name="herausgeber_pages_from[]" data-section="' + sectionId + '" required min="1"></td>' +
|
||
'<td><input type="number" name="herausgeber_pages_to[]" data-section="' + sectionId + '" required min="1"></td>' +
|
||
'<td><button type="button" class="btn-icon" onclick="removeRow(\'' + rowId + '\')" title="Zeile entfernen"><span class="mdi mdi-delete"></span></button></td>';
|
||
attachSignatureListeners(row);
|
||
}
|
||
}
|
||
|
||
function removeRow(rowId) {
|
||
const row = document.getElementById(rowId);
|
||
if (row) {
|
||
const signatureInput = row.querySelector('input[name*="_signature"]');
|
||
if (signatureInput) {
|
||
cleanupSignatureTracking(signatureInput);
|
||
}
|
||
row.remove();
|
||
updateSubmitButton();
|
||
}
|
||
}
|
||
|
||
function removeMediaSection(sectionId) {
|
||
const section = document.getElementById(sectionId);
|
||
if (section) {
|
||
if (confirm('Möchten Sie diese Sektion wirklich entfernen?')) {
|
||
const type = section.getAttribute('data-type');
|
||
// Clean up tracking for removed rows
|
||
const rows = section.querySelectorAll('tr[id]');
|
||
rows.forEach(row => {
|
||
const signatureInput = row.querySelector('input[name*="_signature"]');
|
||
if (signatureInput) {
|
||
cleanupSignatureTracking(signatureInput);
|
||
}
|
||
});
|
||
section.remove();
|
||
// Re-enable button for this media type
|
||
const btn = document.getElementById('btn-' + type);
|
||
if (btn) {
|
||
btn.disabled = false;
|
||
btn.title = 'Sektion hinzufügen';
|
||
}
|
||
updateSubmitButton();
|
||
}
|
||
}
|
||
}
|
||
|
||
function validateSignature(signatureInput, pagesFromInput, pagesToInput) {
|
||
const signature = signatureInput.value.trim();
|
||
|
||
if (!signature) {
|
||
// Clear validation state if signature is empty
|
||
signatureInput.classList.remove('signature-validating', 'signature-valid', 'signature-invalid');
|
||
return;
|
||
}
|
||
|
||
// Clear any existing timer for this input
|
||
const inputId = signatureInput.id || signatureInput.name;
|
||
if (validationTimers[inputId]) {
|
||
clearTimeout(validationTimers[inputId]);
|
||
}
|
||
|
||
// Show validating state
|
||
signatureInput.classList.add('signature-validating');
|
||
signatureInput.classList.remove('signature-valid', 'signature-invalid');
|
||
|
||
// Debounce the API call
|
||
validationTimers[inputId] = setTimeout(async () => {
|
||
try {
|
||
const response = await fetch('/api/validate-signature?signature=' + encodeURIComponent(signature));
|
||
const data = await response.json();
|
||
|
||
if (data.valid) {
|
||
// Initialize tracking for this signature if needed
|
||
if (!signatureTracking[signature]) {
|
||
signatureTracking[signature] = {
|
||
totalPages: data.total_pages,
|
||
inputs: []
|
||
};
|
||
} else {
|
||
signatureTracking[signature].totalPages = data.total_pages;
|
||
}
|
||
|
||
// Track this input
|
||
const existingIndex = signatureTracking[signature].inputs.findIndex(
|
||
item => item.signature === signatureInput
|
||
);
|
||
if (existingIndex === -1) {
|
||
signatureTracking[signature].inputs.push({
|
||
signature: signatureInput,
|
||
pagesFrom: pagesFromInput,
|
||
pagesTo: pagesToInput
|
||
});
|
||
}
|
||
|
||
signatureInput.classList.remove('signature-validating');
|
||
signatureInput.classList.add('signature-valid');
|
||
signatureInput.title = 'Signatur gefunden: ' + data.total_pages + ' Seiten';
|
||
|
||
// Recalculate all pages for this signature
|
||
checkSignatureThreshold(signature);
|
||
} else {
|
||
signatureInput.classList.remove('signature-validating');
|
||
signatureInput.classList.add('signature-invalid');
|
||
signatureInput.title = data.error || 'Signatur nicht gefunden';
|
||
updateSubmitButton();
|
||
}
|
||
} catch (error) {
|
||
signatureInput.classList.remove('signature-validating');
|
||
signatureInput.classList.add('signature-invalid');
|
||
signatureInput.title = 'Validierungsfehler';
|
||
updateSubmitButton();
|
||
}
|
||
}, 800);
|
||
}
|
||
|
||
function checkSignatureThreshold(signature) {
|
||
const tracking = signatureTracking[signature];
|
||
if (!tracking) return;
|
||
|
||
let totalRequestedPages = 0;
|
||
const threshold = Math.ceil(tracking.totalPages * 0.15);
|
||
|
||
// Calculate total requested pages across all inputs for this signature
|
||
tracking.inputs.forEach(item => {
|
||
const from = parseInt(item.pagesFrom.value) || 0;
|
||
const to = parseInt(item.pagesTo.value) || 0;
|
||
if (from > 0 && to > 0 && to >= from) {
|
||
totalRequestedPages += (to - from + 1);
|
||
}
|
||
});
|
||
|
||
const isOverThreshold = totalRequestedPages > threshold;
|
||
|
||
// Update all rows with this signature
|
||
tracking.inputs.forEach(item => {
|
||
const row = item.signature.closest('tr');
|
||
if (row) {
|
||
if (isOverThreshold) {
|
||
row.classList.add('threshold-exceeded');
|
||
item.signature.title = 'Warnung: Gesamtanzahl der Seiten (' + totalRequestedPages + ') überschreitet 15% (' + threshold + ' Seiten)';
|
||
} else {
|
||
row.classList.remove('threshold-exceeded');
|
||
item.signature.title = 'Signatur gefunden: ' + tracking.totalPages + ' Seiten (Aktuell: ' + totalRequestedPages + '/' + threshold + ')';
|
||
}
|
||
}
|
||
});
|
||
|
||
updateSubmitButton();
|
||
}
|
||
|
||
function cleanupSignatureTracking(signatureInput) {
|
||
const signature = signatureInput.value.trim();
|
||
if (signature && signatureTracking[signature]) {
|
||
signatureTracking[signature].inputs = signatureTracking[signature].inputs.filter(
|
||
item => item.signature !== signatureInput
|
||
);
|
||
|
||
// Remove signature from tracking if no more inputs
|
||
if (signatureTracking[signature].inputs.length === 0) {
|
||
delete signatureTracking[signature];
|
||
} else {
|
||
// Recalculate for remaining inputs
|
||
checkSignatureThreshold(signature);
|
||
}
|
||
}
|
||
}
|
||
|
||
function updateSubmitButton() {
|
||
const submitButton = document.querySelector('button[type="submit"]');
|
||
const hasInvalidSignatures = document.querySelectorAll('.signature-invalid').length > 0;
|
||
const hasThresholdExceeded = document.querySelectorAll('.threshold-exceeded').length > 0;
|
||
|
||
if (hasInvalidSignatures || hasThresholdExceeded) {
|
||
submitButton.disabled = true;
|
||
if (hasThresholdExceeded) {
|
||
submitButton.title = 'Formular kann nicht abgesendet werden: 15%-Grenze überschritten';
|
||
} else {
|
||
submitButton.title = 'Formular kann nicht abgesendet werden: Ungültige Signaturen';
|
||
}
|
||
} else {
|
||
submitButton.disabled = false;
|
||
submitButton.title = '';
|
||
}
|
||
}
|
||
|
||
function attachSignatureListeners(row) {
|
||
const signatureInput = row.querySelector('input[name*="_signature"]');
|
||
const pagesFromInput = row.querySelector('input[name*="_pages_from"]');
|
||
const pagesToInput = row.querySelector('input[name*="_pages_to"]');
|
||
|
||
if (signatureInput && pagesFromInput && pagesToInput) {
|
||
// Generate unique ID if not present
|
||
if (!signatureInput.id) {
|
||
signatureInput.id = 'sig-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
|
||
}
|
||
|
||
// Validate on signature change
|
||
signatureInput.addEventListener('input', () => {
|
||
const oldSignature = signatureInput.dataset.lastSignature || '';
|
||
const newSignature = signatureInput.value.trim();
|
||
|
||
// Cleanup old signature tracking if it changed
|
||
if (oldSignature && oldSignature !== newSignature) {
|
||
const tempInput = document.createElement('input');
|
||
tempInput.value = oldSignature;
|
||
cleanupSignatureTracking(tempInput);
|
||
}
|
||
|
||
signatureInput.dataset.lastSignature = newSignature;
|
||
validateSignature(signatureInput, pagesFromInput, pagesToInput);
|
||
});
|
||
|
||
// Recalculate when page range changes
|
||
pagesFromInput.addEventListener('input', () => {
|
||
const signature = signatureInput.value.trim();
|
||
if (signature && signatureTracking[signature]) {
|
||
checkSignatureThreshold(signature);
|
||
}
|
||
});
|
||
|
||
pagesToInput.addEventListener('input', () => {
|
||
const signature = signatureInput.value.trim();
|
||
if (signature && signatureTracking[signature]) {
|
||
checkSignatureThreshold(signature);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|