1
votes

I'm using the signature-pad JavaScript library to have people digitally sign documents (this is just for testing, nothing legally binding, etc.) but I'm having a hard time passing the signature result back to Flask/Python from JS.

The following code is my HTML form, it submits the form.stu_name field perfectly, and even triggers my JS to "submit"(meaning the code executes and a new window opens displaying the signature) but I'm not sure how to submit the JS result back to Flask - see the second code block example for more.

<div class="container">
    {% from "_formhelper.html" import render_field %}
    <form id="upload-form" method="POST" action="/sixth_form/" enctype="multipart/form-data">
    <dl>
      {{render_field(form.stu_name)}}
        </dl>
        <p>Student Signature</p>
<div class="wrapper">
  <img src="{{ url_for('static', filename='images/grey.jpeg') }}" width=400 height=200 />
  <canvas id="signature-pad" class="signature-pad" width=400 height=200></canvas>
</div>
<div>
  <button id="clear" type="Button">Clear</button>
</div>
<br>
    <p><input id="finalsub" type="submit" value="Submit"></p>
    </form>
</div>

Here's the script itself, when run it opens a new window with the result of the signature presented as an URI encoded image (that part is fine, I can decode it later in Python), what I need help with - Instead of opening a new window I want to submit the image back to Flask and then store it in a variable so I can append it to another image. I'm not very knowledgeable with JS, so any suggestions are very welcome!

<script>
var signaturePad = new SignaturePad(document.getElementById('signature-pad'), {
  backgroundColor: 'rgba(255, 255, 255, 0)',
  penColor: 'rgb(0, 0, 0)'
});
var saveButton = document.getElementById('finalsub');
var cancelButton = document.getElementById('clear');

saveButton.addEventListener('click', function (event) {
  var data = signaturePad.toDataURL('image/png');

// Send data to server instead...
  window.open(data);
});

cancelButton.addEventListener('click', function (event) {
  signaturePad.clear();
});
</script>
1

1 Answers

1
votes

This answer seems to be what you're looking for. This is using jQuery however. To do this in pure JavaScript look at this answer. Then to access the file you would use flask.request.files.

A blind (read: untested) example would be:

$(function() {
    $('#upload-file-btn').click(function() {
        var data = signaturePad.toDataURL('image/png');
        $.ajax({
            type: 'POST',
            url: '/uploadUrl',
            data: data,
            contentType: false,
            cache: false,
            processData: false,
            async: false,
            success: function(data) {
                console.log('Success!');
            },
        });
    });
});

Now in your flask's endpoint view function, you can access the file's data via flask.request.files.

Note: As I said this is untested, and I don't know if the ajax config (for instance making the request synchronous or setting contentType to false) are all necessary. My intuition would be to rewrite it like this:

NOT TESTED

$(function() {
    $('#upload-file-btn').click(function() {
        var data = signaturePad.toDataURL('image/png');
        $.ajax({
            type: 'POST',
            url: '/uploadUrl',
            data: data,
            contentType: 'image/png'
        }).done(function(data) {
            console.log('Success!');
        }).fail(function(data) {
            console.log('Fail!');
        });
    });
});