Read more

Capturing signatures on a touch device

Tobias Kraze
February 20, 2013Software engineer at makandra GmbH

If you need to capture signatures on an IPad or similar device, you can use Thomas J Bradley's excellent Signature Pad plugin for jQuery Show archive.org snapshot .

Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

To implement, just follow the steps on the Github page Show archive.org snapshot .

The form

If you have a model Signature with name: string, signature: text, you can use it with regular rails form like this:

- form_for @signature, :html => { :class => 'signature_form' } do |form|
  %dl
    %dt
      = form.label :name
    %dd
      = form.text_field :name
    %dt
      = form.label :signature
    %dd
      .sig.sigWrapper{:style => "width: #{Signature::WIDTH}px; height: #{Signature::HEIGHT}px;"}
        %canvas.pad{:width => Signature::WIDTH, :height => Signature::HEIGHT}
        = form.hidden_field :signature, :value => nil, :class => 'output'
         
:javascript
  $(function() {
    $('.signature_form')
    .signaturePad({
      drawOnly: true,
      validateFields: false,
      lineTop: #{Signature::HEIGHT - 30}
    })
    .regenerate(#{JSON.parse(@signature.signature || "[]").to_json});
  });

Generating a PNG

To save the signature as a png on the server, add this to your model (example with Paperclip Show archive.org snapshot ):

class Signature < ActiveRecord::Base
    HEIGHT = 160
    WIDTH = 480
   
    before_save :generate_image
    has_attached_file :image # options ...
    
          private

  def signature_present
    if signature.size <= 2
      errors.add(:signature, :blank)
    end
  end

  def generate_image
    instructions = JSON.parse(signature).map { |h| "line #{h['mx'].to_i},#{h['my'].to_i} #{h['lx'].to_i},#{h['ly'].to_i}" } * ' '
    image = StringIO.new
    Open3.popen3("convert -size #{WIDTH}x#{HEIGHT} xc:transparent -stroke blue -draw @- PNG:-") do |input, output, error|
      input.puts instructions
      input.close
      image.puts(output.read)
    end
    self.image = image
  end
end

Credits for image generation code go to Phil Hofmann Show archive.org snapshot .

Testing

I use the following cucumber step to sign the form. Put the attached file into spec/fixtures.

When /^I sign the form$/ do
  signature = File.read('spec/fixtures/signature.json')
  page.execute_script(<<-JAVASCRIPT)
    $('.signature_form').data('plugin-signaturePad').regenerate(#{signature});
  JAVASCRIPT
end
Tobias Kraze
February 20, 2013Software engineer at makandra GmbH
Posted by Tobias Kraze to makandra dev (2013-02-20 15:26)