PDF Signing Tool for Blogger

0

 # 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.

Post a Comment

0 Comments
* Please Don't Spam Here. All the Comments are Reviewed by Admin.

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Learn More
Accept !