Files
DocuSighn/js/signature.js

308 lines
10 KiB
JavaScript

// Configure pdf.js worker
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
const canvas = document.getElementById('signatureCanvas');
const ctx = canvas.getContext('2d');
let isDrawing = false;
let hasSignature = false;
let ws = null;
let currentPdf = null;
let pdfDoc = null;
let currentPageNum = 1;
let totalPages = 1;
connectWebSocket();
function connectWebSocket() {
// Use current host (works for localhost, IP addresses, and reverse proxy)
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsHost = window.location.hostname;
// If using HTTPS (reverse proxy), use same port as page (usually 443, no port needed)
// If using HTTP directly, use port 8080
const wsPort = window.location.protocol === 'https:' ? '' : ':8080';
const wsUrl = `${wsProtocol}//${wsHost}${wsPort}`;
console.log('Verbinde WebSocket zu:', wsUrl);
ws = new WebSocket(wsUrl);
ws.onopen = () => {
console.log('WebSocket verbunden');
document.getElementById('loadingSection').style.display = 'none';
document.getElementById('waitingSection').style.display = 'block';
// Register as signature station
ws.send(JSON.stringify({
type: 'register_signature'
}));
};
ws.onmessage = async (event) => {
const data = JSON.parse(event.data);
if (data.type === 'already_connected') {
console.log('⚠️ Bereits eine andere Signatur-Station verbunden');
// Show warning message
const warning = document.getElementById('alreadyConnectedWarning');
if (warning) {
warning.style.display = 'block';
}
} else if (data.type === 'pdf') {
console.log('PDF empfangen');
currentPdf = new Uint8Array(data.pdf);
// Show PDF notification
document.getElementById('waitingSection').style.display = 'none';
document.getElementById('signatureSection').style.display = 'block';
document.getElementById('pdfDisplay').classList.add('show');
// Render ALL pages of PDF
await renderPdfPreview(currentPdf);
// Clear previous signature if any
clearSignature();
} else if (data.type === 'page_change') {
currentPageNum = data.pageNum;
totalPages = data.totalPages;
// Scroll to the specific page
const pageCanvas = document.getElementById(`page-canvas-${data.pageNum}`);
if (pageCanvas) {
pageCanvas.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
} else if (data.type === 'signature_placed') {
console.log('✅ Unterschrift wurde platziert! Reset in 5 Sekunden...');
console.log('Empfangene Daten:', JSON.stringify(data));
// Show immediate feedback
const successMsg = document.getElementById('successMessage');
successMsg.classList.add('show');
// Reset after 5 seconds
setTimeout(() => {
console.log('Auto-Reset wird durchgeführt...');
// Clear signature
clearSignature();
// Hide success message
document.getElementById('successMessage').classList.remove('show');
// Hide PDF and signature section, show waiting
document.getElementById('signatureSection').style.display = 'none';
document.getElementById('pdfDisplay').classList.remove('show');
document.getElementById('waitingSection').style.display = 'block';
// Reset PDF data
currentPdf = null;
pdfDoc = null;
currentPageNum = 1;
totalPages = 1;
console.log('Bereit für nächste Unterschrift');
}, 5000);
} else if (data.type === 'discard') {
console.log('🔄 Verwerfen-Nachricht empfangen, setze zurück...');
resetSignatureStation();
}
};
ws.onerror = (error) => {
console.error('WebSocket Fehler:', error);
document.getElementById('loadingSection').innerHTML =
'<p style="color: #dc3545;">❌ Verbindung zum Server fehlgeschlagen.</p>';
};
ws.onclose = () => {
console.log('WebSocket getrennt');
setTimeout(connectWebSocket, 1000);
};
}
async function renderPdfPreview(pdfBytes, pageNum = null) {
try {
// Create fresh copy to prevent detachment
const safeCopy = new Uint8Array(pdfBytes.buffer.slice(0));
console.log('renderPdfPreview aufgerufen mit', pdfBytes.length, 'bytes');
const loadingTask = pdfjsLib.getDocument({ data: safeCopy });
pdfDoc = await loadingTask.promise;
totalPages = pdfDoc.numPages;
// Update page info
document.getElementById('pageInfoSignature').textContent = `${totalPages} Seite${totalPages > 1 ? 'n' : ''}`;
// Get container
const container = document.getElementById('pdfPagesContainer');
container.innerHTML = ''; // Clear existing content
// Render all pages
for (let pageNum = 1; pageNum <= totalPages; pageNum++) {
// Add page separator if not first page
if (pageNum > 1) {
const separator = document.createElement('div');
separator.className = 'page-separator';
separator.textContent = `Seite ${pageNum}`;
container.appendChild(separator);
} else {
// First page indicator
const separator = document.createElement('div');
separator.className = 'page-separator';
separator.textContent = `Seite 1`;
container.appendChild(separator);
}
// Create canvas for this page
const canvas = document.createElement('canvas');
canvas.className = 'pdf-preview-canvas';
canvas.id = `page-canvas-${pageNum}`;
container.appendChild(canvas);
// Render page
const page = await pdfDoc.getPage(pageNum);
const ctx = canvas.getContext('2d');
const viewport = page.getViewport({ scale: 1.2 });
canvas.width = viewport.width;
canvas.height = viewport.height;
const renderContext = {
canvasContext: ctx,
viewport: viewport
};
await page.render(renderContext).promise;
}
console.log('Alle', totalPages, 'Seiten erfolgreich gerendert');
} catch (error) {
console.error('Fehler beim Rendern der PDF Vorschau:', error);
}
}
// Canvas setup
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
function startDrawing(e) {
isDrawing = true;
const pos = getPosition(e);
ctx.beginPath();
ctx.moveTo(pos.x, pos.y);
}
function draw(e) {
if (!isDrawing) return;
e.preventDefault();
const pos = getPosition(e);
ctx.lineTo(pos.x, pos.y);
ctx.stroke();
hasSignature = true;
document.getElementById('submitButton').disabled = false;
}
function stopDrawing() {
isDrawing = false;
}
function getPosition(e) {
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const scaleY = canvas.height / rect.height;
if (e.touches && e.touches.length > 0) {
return {
x: (e.touches[0].clientX - rect.left) * scaleX,
y: (e.touches[0].clientY - rect.top) * scaleY
};
}
return {
x: (e.clientX - rect.left) * scaleX,
y: (e.clientY - rect.top) * scaleY
};
}
// Mouse events
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
// Touch events
canvas.addEventListener('touchstart', startDrawing);
canvas.addEventListener('touchmove', draw);
canvas.addEventListener('touchend', stopDrawing);
// Clear button
document.getElementById('clearButton').addEventListener('click', () => {
clearSignature();
});
function clearSignature() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
hasSignature = false;
document.getElementById('submitButton').disabled = true;
document.getElementById('successMessage').classList.remove('show');
document.getElementById('errorMessage').classList.remove('show');
}
function resetSignatureStation() {
console.log('=== SIGNATUR-STATION ZURÜCKSETZEN ===');
// Clear signature canvas
clearSignature();
// Hide success and error messages
document.getElementById('successMessage').classList.remove('show');
document.getElementById('errorMessage').classList.remove('show');
// Hide PDF and signature section, show waiting
document.getElementById('signatureSection').style.display = 'none';
document.getElementById('pdfDisplay').classList.remove('show');
document.getElementById('waitingSection').style.display = 'block';
// Clear PDF pages container
const container = document.getElementById('pdfPagesContainer');
if (container) {
container.innerHTML = '';
}
// Reset PDF data
currentPdf = null;
pdfDoc = null;
currentPageNum = 1;
totalPages = 1;
console.log('Signatur-Station zurückgesetzt - bereit für neue PDF');
}
// Submit button
document.getElementById('submitButton').addEventListener('click', async () => {
if (!hasSignature || !ws || ws.readyState !== WebSocket.OPEN) return;
try {
// Get signature as data URL
const signatureDataUrl = canvas.toDataURL('image/png');
// Send to server (no session ID needed)
ws.send(JSON.stringify({
type: 'signature',
signature: signatureDataUrl
}));
// Show success message
document.getElementById('successMessage').classList.add('show');
document.getElementById('submitButton').disabled = true;
console.log('Unterschrift gesendet, warte auf Platzierungs-Bestätigung...');
} catch (error) {
console.error('Fehler beim Senden:', error);
document.getElementById('errorMessage').classList.add('show');
}
});