7

I am using Thomas J Bradley's plugin for drawing two signatures at the bottom of a html form, which is then converted to a pdf using dompdf and sent by email as an attachment using sendmail.

Everything works well except the fact that i can't seem to be able to redraw the signatures on to the pdf file without saving them to disk which i would like to avoid.

Mr. Bradley provided several methods for regenerating the signature but i need some advices on how to pass the signature data along with the form values to the pdf converter preferably 'on the fly' (without saving the data to disk or database).

I would appreciate any answer. If you need any sample code, please let me know.

Thank you in advance!

katalin_2003
  • 787
  • 1
  • 16
  • 30

2 Answers2

9

Instead of regenerating the signature you should capture the signature image. Signature Pad can return the signature as an image encoded as a data URI. dompdf understands data URIs so you can use this to generate your PDF. If you're targeting a platform that doesn't support that method the author has plenty of options for converting the signature server side.

The process in a nutshell is to capture the image output on form submission, pass it to the server, and dynamically populate your HTML with the signature for PDF generation. No need to save the image.

I've not used Signature Pad, so I'm using the author's HTML template as a base for the sample code.

Client Side

<form method="post" action="" class="sigPad">
  <label for="name">Print your name</label>
  <input type="text" name="name" id="name" class="name">
  <p class="typeItDesc">Review your signature</p>
  <p class="drawItDesc">Draw your signature</p>
  <ul class="sigNav">
    <li class="typeIt"><a href="#type-it" class="current">Type It</a></li>
    <li class="drawIt"><a href="#draw-it">Draw It</a></li>
    <li class="clearButton"><a href="#clear">Clear</a></li>
  </ul>
  <div class="sig sigWrapper">
    <div class="typed"></div>
    <canvas class="pad" width="198" height="55"></canvas>
    <input type="hidden" name="output" class="output">
    <input type="hidden" name="imgOutput" class="imgOutput">
  </div>
  <button type="submit">I accept the terms of this agreement.</button>
</form>
<script>
  var sig;
  $( document ).ready( function ( ) {
    sig = $('.sigPad').signaturePad();
  } );
  $( '.sigPad' ).submit( function ( evt ) {
    $( '.imgOutput' ).val( sig.getSignatureImage( ) );
  } );
</script>

Server Side

<?php
$img_output = $_POST['imgOutput'];
if ( base64_encode( base64_decode( $img_output ) ) === $img_output ) {
  require_oncde 'dompdf_config.inc.php';
  $html = '<p>Your Signature:</p><p><img src="' . $img_output . '"></p>';
  $dompdf = new DOMPDF;
  $dompdf->load_html( $html );
  $dompdf->render( );
  $dompdf->stream( );
} else {
  // exception logic ... "your signature was not valid"
}
?>

Simple validation on the signature image as valid base64 from How to check if a string is base64 valid

Community
  • 1
  • 1
BrianS
  • 13,284
  • 15
  • 62
  • 125
  • Hello, Brian. Thank you so much for your answer. Unfortunately it won't render on the pdf but i think we're not far. Here's a small sample using your example: http://www.filedropper.com/test_13 If i echo $img_output after the else{ // exception logic ... "your signature was not valid" } i get a beautiful string of this format: [{"lx":20,"ly":34,"mx":20,"my":34},…]. Will i be able to draw a line in the pdf using these? Just an idea. – katalin_2003 Jul 01 '13 at 22:00
  • 1
    A minor error on my part. The variable `sig` should be initialized outside the document load function. The way I originally wrote it `sig` was local to the jQuery event handler. I updated my sample code. – BrianS Jul 02 '13 at 03:20
4

Brian, you rock ! I had to do the following to get it to work, since we were checking for this line included data:image/png;base64, .

But with your help and some digging around i obtained a pdf with the signature on it :) This is the code in case somebody needs it in the future.

the html part :

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="jquery.signaturepad.css" media="screen">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script type="text/javascript" src="jquery.signaturepad.min.js"></script>
</head>
<body>
<form method="post" action="pdf.php" class="sigPad">
  <label for="name">Print your name</label>
  <input type="text" name="name" id="name" class="name">
  <p class="drawItDesc">Draw your signature</p>
  <ul class="sigNav">

    <li class="drawIt"><a href="#draw-it">Draw It</a></li>
    <li class="clearButton"><a href="#clear">Clear</a></li>
  </ul>
  <div class="sig sigWrapper">
    <canvas class="pad" width="198" height="55"></canvas>
    
    <input type="hidden" name="imgOutput" class="imgOutput">
  </div>
  <button type="submit">I accept the terms of this agreement.</button>
</form>

<script>
    var sig;
  $(document).ready(function() {
    /*sig = $('.sigPad').signaturePad();*/
    sig = $('.sigPad').signaturePad({drawOnly:true});
  });
  $('.sigPad').submit(function(evt) {
    $('.imgOutput').val( sig.getSignatureImage() );
  });  
</script>

</body>
</html>

pdf.php :

<?php
if(isset($_POST['imgOutput'])){$img_output = $_POST['imgOutput'];}

$bse = preg_replace('#^data:image/[^;]+;base64,#', '', $img_output );

if ( base64_encode( base64_decode($bse) ) === $bse ) {

  require_once 'dompdf/dompdf_config.inc.php';
  $html = '<!DOCTYPE html><html><head></head><body><p>Your signature:</p>
  <br />
  <img src="'. $img_output .'"></body></html>';
  $dompdf = new DOMPDF;
  $dompdf->load_html($html);
  $dompdf->render();
  $dompdf->stream("test.pdf");
} 
else {
    echo ("ERROR !");
}
?>

Many thanks to @Thomas J Bradley, the dompdf team and @BrianS who saved the day.

katalin_2003
  • 787
  • 1
  • 16
  • 30
  • 1
    no worries ... perhaps someone else will upvote the answer. You can, however, check it as having answered your question (since it's yours). – BrianS Jul 02 '13 at 15:03