# PDF Signing Tool for Blogger
Here's a complete JavaScript implementation of a PDF signing tool similar to ilovepdf.com's sign-pdf functionality that you can paste directly into your Blogger HTML/JavaScript gadget:
```html
<div class="pdf-signer-container">
<h2>Sign PDF Documents Online</h2>
<div class="upload-section">
<div class="drop-zone" id="dropZone">
<input type="file" id="fileInput" accept=".pdf" style="display: none;">
<div class="drop-zone-content">
<i class="fas fa-cloud-upload-alt"></i>
<p>Drag & drop your PDF file here or</p>
<button id="selectFileBtn" class="btn-primary">Select File</button>
</div>
</div>
<div class="file-info" id="fileInfo" style="display: none;">
<p><strong>Selected file:</strong> <span id="fileName"></span></p>
<button id="clearFileBtn" class="btn-secondary">Change File</button>
</div>
</div>
<div class="signing-section" id="signingSection" style="display: none;">
<h3>Add Your Signature</h3>
<div class="signature-options">
<div class="tab-buttons">
<button class="tab-btn active" data-tab="draw">Draw</button>
<button class="tab-btn" data-tab="type">Type</button>
<button class="tab-btn" data-tab="upload">Upload</button>
</div>
<div class="tab-content active" data-tab="draw">
<canvas id="signatureCanvas" width="400" height="200"></canvas>
<div class="canvas-controls">
<button id="clearCanvasBtn" class="btn-secondary">Clear</button>
<button id="undoCanvasBtn" class="btn-secondary">Undo</button>
</div>
</div>
<div class="tab-content" data-tab="type">
<input type="text" id="typedSignature" placeholder="Type your name here">
<div class="font-selector">
<label for="fontFamily">Font:</label>
<select id="fontFamily">
<option value="'Brush Script MT', cursive">Brush Script</option>
<option value="'Dancing Script', cursive">Dancing Script</option>
<option value="'Pacifico', cursive">Pacifico</option>
<option value="'Great Vibes', cursive">Great Vibes</option>
<option value="Arial, sans-serif">Arial</option>
</select>
</div>
</div>
<div class="tab-content" data-tab="upload">
<input type="file" id="signatureUpload" accept="image/*" style="display: none;">
<button id="uploadSignBtn" class="btn-primary">Upload Signature Image</button>
<div id="signaturePreview" style="display: none; margin-top: 15px;">
<img id="uploadedSignature" src="" alt="Your signature" style="max-width: 300px; max-height: 150px;">
<button id="removeSignBtn" class="btn-secondary" style="margin-left: 10px;">Remove</button>
</div>
</div>
</div>
<div class="signature-position">
<h3>Position Your Signature</h3>
<div class="pdf-preview-container">
<canvas id="pdfPreview" width="500" height="700"></canvas>
<div id="signaturePlaceholder" class="signature-placeholder" draggable="true">
<div class="signature-preview"></div>
<div class="resize-handle"></div>
</div>
</div>
<div class="position-controls">
<button id="addSignatureBtn" class="btn-primary">Add Signature</button>
<button id="resetPositionBtn" class="btn-secondary">Reset Position</button>
</div>
</div>
</div>
<div class="download-section" id="downloadSection" style="display: none;">
<h3>Your Signed PDF is Ready</h3>
<button id="downloadBtn" class="btn-download">
<i class="fas fa-download"></i> Download Signed PDF
</button>
<button id="newDocumentBtn" class="btn-secondary">Sign Another Document</button>
</div>
<div class="loading-overlay" id="loadingOverlay" style="display: none;">
<div class="loading-spinner"></div>
<p>Processing your document...</p>
</div>
</div>
<style>
.pdf-signer-container {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
h2, h3 {
color: #333;
margin-bottom: 15px;
}
.upload-section {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 30px;
text-align: center;
margin-bottom: 20px;
transition: border-color 0.3s;
}
.upload-section:hover {
border-color: #4a89dc;
}
.drop-zone {
cursor: pointer;
}
.drop-zone-content {
color: #666;
}
.drop-zone-content i {
font-size: 48px;
color: #4a89dc;
margin-bottom: 10px;
}
.btn-primary {
background-color: #4a89dc;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
.btn-primary:hover {
background-color: #3a70c2;
}
.btn-secondary {
background-color: #f5f7fa;
color: #333;
border: 1px solid #ddd;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
.btn-secondary:hover {
background-color: #e6e9ed;
}
.btn-download {
background-color: #37bc9b;
color: white;
border: none;
padding: 12px 25px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
margin-right: 10px;
}
.btn-download:hover {
background-color: #2fa58a;
}
.file-info {
margin-top: 15px;
padding: 10px;
background: #f5f7fa;
border-radius: 4px;
}
.signing-section {
margin-top: 30px;
}
.tab-buttons {
display: flex;
margin-bottom: 15px;
border-bottom: 1px solid #ddd;
}
.tab-btn {
padding: 8px 20px;
background: none;
border: none;
border-bottom: 3px solid transparent;
cursor: pointer;
font-size: 14px;
color: #666;
}
.tab-btn.active {
color: #4a89dc;
border-bottom-color: #4a89dc;
}
.tab-content {
display: none;
margin-bottom: 20px;
}
.tab-content.active {
display: block;
}
#signatureCanvas {
border: 1px solid #ddd;
border-radius: 4px;
background: white;
cursor: crosshair;
}
.canvas-controls {
margin-top: 10px;
}
.canvas-controls button {
margin-right: 10px;
}
#typedSignature {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.font-selector {
margin-top: 10px;
}
.font-selector select {
padding: 5px;
border: 1px solid #ddd;
border-radius: 4px;
}
.pdf-preview-container {
position: relative;
margin: 20px 0;
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
width: fit-content;
}
#pdfPreview {
display: block;
background: #f5f5f5;
}
.signature-placeholder {
position: absolute;
border: 2px dashed #4a89dc;
background: rgba(74, 137, 220, 0.1);
display: none;
cursor: move;
}
.signature-preview {
width: 100%;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.resize-handle {
position: absolute;
right: -5px;
bottom: -5px;
width: 10px;
height: 10px;
background: #4a89dc;
cursor: nwse-resize;
}
.position-controls {
margin-top: 15px;
}
.download-section {
text-align: center;
margin-top: 30px;
padding: 20px;
background: #f5f7fa;
border-radius: 8px;
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1000;
}
.loading-spinner {
border: 5px solid #f3f3f3;
border-top: 5px solid #4a89dc;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin-bottom: 15px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Elements
const fileInput = document.getElementById('fileInput');
const selectFileBtn = document.getElementById('selectFileBtn');
const dropZone = document.getElementById('dropZone');
const fileInfo = document.getElementById('fileInfo');
const fileName = document.getElementById('fileName');
const clearFileBtn = document.getElementById('clearFileBtn');
const signingSection = document.getElementById('signingSection');
const downloadSection = document.getElementById('downloadSection');
const loadingOverlay = document.getElementById('loadingOverlay');
// Tab elements
const tabBtns = document.querySelectorAll('.tab-btn');
const tabContents = document.querySelectorAll('.tab-content');
// Signature canvas elements
const signatureCanvas = document.getElementById('signatureCanvas');
const clearCanvasBtn = document.getElementById('clearCanvasBtn');
const undoCanvasBtn = document.getElementById('undoCanvasBtn');
const ctx = signatureCanvas.getContext('2d');
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let drawingHistory = [];
let currentStep = -1;
// Typed signature elements
const typedSignature = document.getElementById('typedSignature');
const fontFamily = document.getElementById('fontFamily');
// Upload signature elements
const signatureUpload = document.getElementById('signatureUpload');
const uploadSignBtn = document.getElementById('uploadSignBtn');
const signaturePreview = document.getElementById('signaturePreview');
const uploadedSignature = document.getElementById('uploadedSignature');
const removeSignBtn = document.getElementById('removeSignBtn');
// PDF preview elements
const pdfPreview = document.getElementById('pdfPreview');
const signaturePlaceholder = document.getElementById('signaturePlaceholder');
const signaturePreviewDiv = signaturePlaceholder.querySelector('.signature-preview');
const addSignatureBtn = document.getElementById('addSignatureBtn');
const resetPositionBtn = document.getElementById('resetPositionBtn');
// Download elements
const downloadBtn = document.getElementById('downloadBtn');
const newDocumentBtn = document.getElementById('newDocumentBtn');
// Variables
let pdfDoc = null;
let currentPage = 1;
let currentSignature = null;
let signatureType = 'draw';
let signatureData = null;
let signatureDimensions = { width: 150, height: 50 };
// Initialize
initCanvas();
setupEventListeners();
function initCanvas() {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, signatureCanvas.width, signatureCanvas.height);
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
}
function setupEventListeners() {
// File selection
selectFileBtn.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', handleFileSelect);
// Drag and drop
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.style.borderColor = '#4a89dc';
});
dropZone.addEventListener('dragleave', () => {
dropZone.style.borderColor = '#ccc';
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.style.borderColor = '#ccc';
if (e.dataTransfer.files.length) {
fileInput.files = e.dataTransfer.files;
handleFileSelect({ target: fileInput });
}
});
clearFileBtn.addEventListener('click', resetFileSelection);
// Tab switching
tabBtns.forEach(btn => {
btn.addEventListener('click', () => {
tabBtns.forEach(b => b.classList.remove('active'));
tabContents.forEach(c => c.classList.remove('active'));
btn.classList.add('active');
const tabName = btn.getAttribute('data-tab');
document.querySelector(`.tab-content[data-tab="${tabName}"]`).classList.add('active');
signatureType = tabName;
});
});
// Drawing signature
signatureCanvas.addEventListener('mousedown', startDrawing);
signatureCanvas.addEventListener('mousemove', draw);
signatureCanvas.addEventListener('mouseup', stopDrawing);
signatureCanvas.addEventListener('mouseout', stopDrawing);
signatureCanvas.addEventListener('touchstart', (e) => {
e.preventDefault();
const touch = e.touches[0];
const mouseEvent = new MouseEvent('mousedown', {
clientX: touch.clientX,
clientY: touch.clientY
});
signatureCanvas.dispatchEvent(mouseEvent);
});
signatureCanvas.addEventListener('touchmove', (e) => {
e.preventDefault();
const touch = e.touches[0];
const mouseEvent = new MouseEvent('mousemove', {
clientX: touch.clientX,
clientY: touch.clientY
});
signatureCanvas.dispatchEvent(mouseEvent);
});
signatureCanvas.addEventListener('touchend', (e) => {
e.preventDefault();
const mouseEvent = new MouseEvent('mouseup');
signatureCanvas.dispatchEvent(mouseEvent);
});
clearCanvasBtn.addEventListener('click', clearCanvas);
undoCanvasBtn.addEventListener('click', undoCanvas);
// Typed signature
typedSignature.addEventListener('input', updateTypedSignaturePreview);
fontFamily.addEventListener('change', updateTypedSignaturePreview);
// Upload signature
uploadSignBtn.addEventListener('click', () => signatureUpload.click());
signatureUpload.addEventListener('change', handleSignatureUpload);
removeSignBtn.addEventListener('click', removeUploadedSignature);
// Signature positioning
addSignatureBtn.addEventListener('click', addSignatureToPDF);
resetPositionBtn.addEventListener('click', resetSignaturePosition);
// Download
downloadBtn.addEventListener('click', downloadSignedPDF);
newDocumentBtn.addEventListener('click', resetAll);
}
function handleFileSelect(e) {
const file = e.target.files[0];
if (!file) return;
if (file.type !== 'application/pdf') {
alert('Please select a PDF file.');
return;
}
fileName.textContent = file.name;
fileInfo.style.display = 'block';
dropZone.style.display = 'none';
// Load PDF
loadingOverlay.style.display = 'flex';
const reader = new FileReader();
reader.onload = function(event) {
const typedArray = new Uint8Array(event.target.result);
// Load PDF using pdf.js
pdfjsLib.getDocument(typedArray).promise.then(function(pdf) {
pdfDoc = pdf;
loadingOverlay.style.display = 'none';
signingSection.style.display = 'block';
renderPDFPage();
}).catch(function(error) {
loadingOverlay.style.display = 'none';
alert('Error loading PDF: ' + error.message);
});
};
reader.readAsArrayBuffer(file);
}
function resetFileSelection() {
fileInput.value = '';
fileName.textContent = '';
fileInfo.style.display = 'none';
dropZone.style.display = 'block';
signingSection.style.display = 'none';
pdfDoc = null;
}
function renderPDFPage() {
pdfDoc.getPage(currentPage).then(function(page) {
const viewport = page.getViewport({ scale: 0.8 });
const canvasContext = pdfPreview.getContext('2d');
pdfPreview.height = viewport.height;
pdfPreview.width = viewport.width;
page.render({
canvasContext: canvasContext,
viewport: viewport
});
});
}
// Drawing functions
function startDrawing(e) {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
// Save current canvas state
if (currentStep < drawingHistory.length - 1) {
drawingHistory = drawingHistory.slice(0, currentStep + 1);
}
drawingHistory.push(signatureCanvas.toDataURL());
currentStep++;
}
function draw(e) {
if (!isDrawing) return;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
[lastX, lastY] = [e.offsetX, e.offsetY];
}
function stopDrawing() {
isDrawing = false;
}
function clearCanvas() {
ctx.clearRect(0, 0, signatureCanvas.width, signatureCanvas.height);
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, signatureCanvas.width, signatureCanvas.height);
ctx.strokeStyle = '#000';
drawingHistory = [];
currentStep = -1;
}
function undoCanvas() {
if (currentStep <= 0) {
clearCanvas();
return;
}
currentStep--;
const img = new Image();
img.onload = function() {
ctx.clearRect(0, 0, signatureCanvas.width, signatureCanvas.height);
ctx.drawImage(img, 0, 0);
};
img.src = drawingHistory[currentStep];
}
// Typed signature functions
function updateTypedSignaturePreview() {
if (!typedSignature.value.trim()) return;
// For preview in the placeholder
const tempCanvas = document.createElement('canvas');
tempCanvas.width = 300;
tempCanvas.height = 100;
const tempCtx = tempCanvas.getContext('2d');
tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height);
tempCtx.font = `24px ${fontFamily.value}`;
tempCtx.fillStyle = '#000';
tempCtx.textBaseline = 'middle';
tempCtx.textAlign = 'center';
tempCtx.fillText(typedSignature.value, tempCanvas.width / 2, tempCanvas.height / 2);
signatureData = tempCanvas.toDataURL();
}
// Upload signature functions
function handleSignatureUpload(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(event) {
uploadedSignature.src = event.target.result;
signaturePreview.style.display = 'block';
signatureData = event.target.result;
};
reader.readAsDataURL(file);
}
function removeUploadedSignature() {
signatureUpload.value = '';
signaturePreview.style.display = 'none';
signatureData = null;
}
// Signature positioning functions
function addSignatureToPDF() {
if (!signatureData) {
alert('Please create or upload a signature first.');
return;
}
// Get signature based on type
let signatureImg;
if (signatureType === 'draw') {
signatureImg = signatureCanvas.toDataURL();
} else if (signatureType === 'type') {
if (!typedSignature.value.trim()) {
alert('Please type your signature.');
return;
}
updateTypedSignaturePreview();
signatureImg = signatureData;
} else if (signatureType === 'upload') {
if (!signatureData) {
alert('Please upload a signature image.');
return;
}
signatureImg = signatureData;
}
// Show signature placeholder
signaturePlaceholder.style.display = 'block';
signaturePlaceholder.style.width = `${signatureDimensions.width}px`;
signaturePlaceholder.style.height = `${signatureDimensions.height}px`;
signaturePlaceholder.style.left = '50px';
signaturePlaceholder.style.top = '50px';
signaturePreviewDiv.style.backgroundImage = `url(${signatureImg})`;
// Make draggable
makeDraggable(signaturePlaceholder);
makeResizable(signaturePlaceholder);
}
function resetSignaturePosition() {
signaturePlaceholder.style.left = '50px';
signaturePlaceholder.style.top = '50px';
signaturePlaceholder.style.width = `${signatureDimensions.width}px`;
signaturePlaceholder.style.height = `${signatureDimensions.height}px`;
}
function makeDraggable(element) {
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
element.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// Get the mouse cursor position at startup
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// Calculate the new cursor position
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// Set the element's new position
element.style.top = (element.offsetTop - pos2) + "px";
element.style.left = (element.offsetLeft - pos1) + "px";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
}
}
function makeResizable(element) {
const resizeHandle = element.querySelector('.resize-handle');
let startX, startY, startWidth, startHeight;
resizeHandle.onmousedown = initResize;
function initResize(e) {
e.preventDefault();
startX = e.clientX;
startY = e.clientY;
startWidth = parseInt(document.defaultView.getComputedStyle(element).width, 10);
startHeight = parseInt(document.defaultView.getComputedStyle(element).height, 10);
document.documentElement.addEventListener('mousemove', doResize, false);
document.documentElement.addEventListener('mouseup', stopResize, false);
}
function doResize(e) {
element.style.width = (startWidth + e.clientX - startX) + 'px';
element.style.height = (startHeight + e.clientY - startY) + 'px';
}
function stopResize() {
document.documentElement.removeEventListener('mousemove', doResize, false);
document.documentElement.removeEventListener('mouseup', stopResize, false);
}
}
// Download functions
function downloadSignedPDF() {
if (!pdfDoc || !signaturePlaceholder.style.display || signaturePlaceholder.style.display === 'none') {
alert('Please add a signature to your document first.');
return;
}
loadingOverlay.style.display = 'flex';
// Get signature position and dimensions
const rect = signaturePlaceholder.getBoundingClientRect();
const pdfRect = pdfPreview.getBoundingClientRect();
const x = rect.left - pdfRect.left;
const y = rect.top - pdfRect.top;
const width = rect.width;
const height = rect.height;
// Scale factors (PDF coordinates are different from canvas coordinates)
const scaleX = pdfPreview.width / pdfRect.width;
const scaleY = pdfPreview.height / pdfRect.height;
const pdfX = x * scaleX;
const pdfY = y * scaleY;
const pdfWidth = width * scaleX;
const pdfHeight = height * scaleY;
// Create a new PDF with the signature
const pdfBytes = await pdfDoc.getData();
const loadingTask = pdfjsLib.getDocument({ data: pdfBytes });
const pdfDocument = await loadingTask.promise;
// Create a new PDF document to write to
const { PDFDocument, rgb } = PDFLib;
const pdfDoc = await PDFDocument.load(pdfBytes);
// Embed the signature image
let signatureImage;
if (signatureType === 'draw') {
const pngImageBytes = await fetch(signatureCanvas.toDataURL('image/png'))
.then(res => res.arrayBuffer());
signatureImage = await pdfDoc.embedPng(pngImageBytes);
} else if (signatureType === 'type') {
// For typed signatures, we'll create a temporary canvas and embed it
const tempCanvas = document.createElement('canvas');
tempCanvas.width = width;
tempCanvas.height = height;
const tempCtx = tempCanvas.getContext('2d');
tempCtx.font = `${height * 0.6}px ${fontFamily.value}`;
tempCtx.fillStyle = '#000';
tempCtx.textBaseline = 'middle';
tempCtx.textAlign = 'center';
tempCtx.fillText(typedSignature.value, width / 2, height / 2);
const pngImageBytes = await new Promise(resolve => {
tempCanvas.toBlob(blob => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.readAsArrayBuffer(blob);
}, 'image/png');
});
signatureImage = await pdfDoc.embedPng(pngImageBytes);
} else if (signatureType === 'upload') {
const uploadedImageBytes = await fetch(signatureData)
.then(res => res.arrayBuffer());
signatureImage = await pdfDoc.embedPng(uploadedImageBytes);
}
// Add signature to each page (or just the first page for simplicity)
const pages = pdfDoc.getPages();
const firstPage = pages[0];
firstPage.drawImage(signatureImage, {
x: pdfX,
y: firstPage.getHeight() - pdfY - pdfHeight, // PDF y-coordinate starts from bottom
width: pdfWidth,
height: pdfHeight,
});
// Save the modified PDF
const modifiedPdfBytes = await pdfDoc.save();
// Create download link
const blob = new Blob([modifiedPdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'signed_' + fileName.textContent;
document.body.appendChild(a);
a.click();
// Clean up
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
loadingOverlay.style.display = 'none';
downloadSection.style.display = 'block';
signingSection.style.display = 'none';
}, 100);
}
function resetAll() {
// Reset file selection
fileInput.value = '';
fileName.textContent = '';
fileInfo.style.display = 'none';
dropZone.style.display = 'block';
// Reset signature
clearCanvas();
typedSignature.value = '';
removeUploadedSignature();
signaturePlaceholder.style.display = 'none';
// Reset UI
signingSection.style.display = 'none';
downloadSection.style.display = 'none';
// Reset variables
pdfDoc = null;
currentSignature = null;
signatureData = null;
}
// Load required libraries
function loadScript(src, callback) {
const script = document.createElement('script');
script.src = src;
script.onload = callback;
document.head.appendChild(script);
}
// Load PDF.js
loadScript('https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.min.js', function() {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.worker.min.js';
});
// Load PDF-Lib
loadScript('https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.16.0/pdf-lib.min.js');
// Load Font Awesome for icons
loadScript('https://kit.fontawesome.com/a076d05399.js');
});
</script>
```
## How to Use This Code in Blogger
1. Go to your Blogger dashboard
2. Navigate to "Layout" or "Theme" depending on your Blogger version
3. Click on "Add a Gadget"
4. Select "HTML/JavaScript"
5. Paste the entire code above into the content area
6. Save the gadget
## Features Implemented
1. **PDF Upload**:
- Drag and drop interface
- File selection button
- PDF validation
2. **Signature Creation**:
- Draw signature with mouse/touch
- Type signature with font selection
- Upload signature image
3. **Signature Positioning**:
- Drag to position signature
- Resize signature
- Visual preview on PDF
4. **Download**:
- Generates signed PDF
- Proper filename with "signed_" prefix
- Option to start over
5. **Responsive Design**:
- Works on desktop and mobile
- Clean, user-friendly interface
The code uses PDF.js for PDF rendering and PDF-Lib for PDF modification, loaded from CDNs for easy implementation. All functionality is contained within this single code block for easy pasting into Blogger.