0

I am working on an online application for my organization that uses PHP Symfony framework.

One of the forms that i am working on allows the user to log visits they have with a client. Every time they log the visit, they have to get a signature for the client on a form. We are attempting to bring this process to our web portal.

So the user may visit with a client multiple times a day, which would required that the user needs to capture multiple signatures through out the day and save them on the same form.

So, here is where i share that I am still rather noobish when it comes to JavaScript.

I create the signature pad objects, no problem...

{% for visit in serviceForm.visits %}
$(document).ready(function () {
var canvas{{ loop.index0 }} =
document.getElementById('signature_pad_service_form_visits_{{ 
loop.index0}}');



var signaturePad{{ loop.index0 }} = 
new SignaturePad(canvas{{ loop.index0 }}, {backgroundColor: 
'rgb(255, 255, 255)'});
});
{% endfor %}

But my noobish-ness shines when i try and use the two buttons that i have in my html template. These are the buttons that I have under the signature pad that are there to save the signature, or clear the pad.

<a href="#" class="btn btn-sm btn-primary signature_clear" data-sig-
pad="signature_pad_{{ form.vars.id }}" style="margin-right: 5px">Clear</a>
    <a href="#" class="btn btn-sm btn-primary signature_save"  data-sig-
pad="signature_pad_{{ form.vars.id }}" style="margin-right: 5px">Save 
Signature</a>

Here are the functions i have built in order to try and do the save / clear action. But obviously, they are not working. They simply clear the signature sheet, or download an empty jpg due to me re-creating the SignaturePad.

$(document).on('click', '.signature_clear', function (e) {
    e.preventDefault();
    {% if serviceForm.status != 'approved' %}
    var canvas = document.getElementById($(this).attr("data-sig-pad"));
    var sigPad = new SignaturePad(canvas);
    sigPad.clear()
    {% else %}
    alert("You cannot clear the signature of an approved document.");
    {% endif %}
});

$(document).on('click', '.signature_save', function (e) {
    e.preventDefault();
    {% if serviceForm.status != 'approved' %}
    var canvas = document.getElementById($(this).attr("data-sig-pad"));
    var sigPad = new SignaturePad(canvas);
    var dataUrl = sigPad.toDataURL("image/jpeg");
    download(dataUrl, "signature.jpg");
    {% endif %}
});

So my question... How would I refer to the signature pads that I have already created in the '$(document).ready(function () {' function in the event handlers for the two buttons.

Sorry if i am using incorrect terminology. Its my first question on here, so go easy :)

Mgulizia
  • 3
  • 3
  • A word of advice is to not use PHP interpolation to alter the flow of your javascript as it makes it very hard to debug or test. Instead use html classes to plug your javascript into the markup. – max Mar 20 '18 at 20:58

1 Answers1

0

The issue you are encountering here is lexical scope.

Scope in javascript operates differently to PHP. In a nutshell a scope has access to any scope shallower than itself and cannot access any scope that is deeper or more nested or at an equal level.

function 1() {
var scopeA;

  function 2() {
    var scopeB;
    scopeA;
  }

  function 3() {
    var scopeC;
    scopeA;

    function 4() {
      scopeA;
      scopeC;
      var scopeD;
    }
  }
}

You can see in the very basic example 1() only has access to scopeA whereas 4() has access to scopeA, C and D but not B because it is within function 2()'s scope.

Another fundamental topic of this that I recommend reading is around closures

Essentially any time you create a function in javascript you create a closure around any variables defined in that scope.

So in your question you are passing an anonymous function to jQuery's ready() method - so any variables defined in that function will not be accessible outside so you somehow need to be able to access those variables.

TLDR; You can either create the variables at a higher scope that is accessible to your event handlers OR move your event handlers into the anonymous function that is passed to the ready() method so they SHARE the same scope

Matthew Brent
  • 1,366
  • 11
  • 23