Search code examples
javascriptasp-classicelectronic-signaturesignaturepad

Classic ASP and Signature Pad


I'm trying to get a Classic ASP version of this app to save images to my server: https://github.com/szimek/signature_pad

I've tried various combinations of using the Base64 output but have not had any success. I've searched this site and Googled but haven't been able to find anything that makes sense to me.

If anyone has any ideas on how to convert the output from Signature Pad to a server side image I would be very grateful!

The JS code is:

    var wrapper = document.getElementById("signature-pad"),
        clearButton = wrapper.querySelector("[data-action=clear]"),
        savePNGButton = wrapper.querySelector("[data-action=save-png]"),
        saveSVGButton = wrapper.querySelector("[data-action=save-svg]"),
        canvas = wrapper.querySelector("canvas"),
        signaturePad;

    // Adjust canvas coordinate space taking into account pixel ratio,
    // to make it look crisp on mobile devices.
    // This also causes canvas to be cleared.
    function resizeCanvas() {
        // When zoomed out to less than 100%, for some very strange reason,
        // some browsers report devicePixelRatio as less than 1
        // and only part of the canvas is cleared then.
        var ratio =  Math.max(window.devicePixelRatio || 1, 1);
        canvas.width = canvas.offsetWidth * ratio;
        canvas.height = canvas.offsetHeight * ratio;
        canvas.getContext("2d").scale(ratio, ratio);
    }

    window.onresize = resizeCanvas;
    resizeCanvas();

    signaturePad = new SignaturePad(canvas);

    clearButton.addEventListener("click", function (event) {
        signaturePad.clear();
    });

    savePNGButton.addEventListener("click", function (event) {
        if (signaturePad.isEmpty()) {
            alert("Please provide signature first.");
        } else {
            window.open(signaturePad.toDataURL());
        }
    });

    saveSVGButton.addEventListener("click", function (event) {
        if (signaturePad.isEmpty()) {
            alert("Please provide signature first.");
        } else {
            window.open(signaturePad.toDataURL('image/svg+xml'));
        }
    });

What I'm trying to do is have the "savePNGButton" spit out an actual PNG file that I can save to the server using Classic ASP, not the raw binary.


Solution

  • After getting some help elsewhere, I managed to solve this problem. First of all, I had the signature pad embedded at the bottom of a form, with the following code:

        <div id="signature-pad" class="m-signature-pad">                                                        
          <div class="m-signature-pad--body">
            <canvas id="imageData" name="imageData"></canvas>
          </div>                        
          <div class="m-signature-pad--footer">
            <div class="description" style="width: 100%; border-top: 1px dotted #999;"></div>
            <div class="left">
              <button type="button" class="btn btn-warning" data-action="clear">Clear signature</button>
            </div>
            <div class="right">
              <input type="submit" class="btn btn-primary" data-action="save-png" value="Sign and accept terms">
            </div>
          </div>                                
        </div>
    

    And inside the form, I had the following field:

        <input type="hidden" name="hiddenSignature" id="hiddenSignature" />
    

    Then on my page displaying the form submission, I used the following code (and added the GetTimeStamp function to capture the time stamp to append to the file name to make it unique):

        'Run functions to capture the customer signature
        'First function is to grab a timestamp to add to the file name
        Function GetTimeStamp ()
            Dim dd, mm, yy, hh, nn, ss
            Dim datevalue, timevalue, dtsnow, dtsvalue
    
            'Store DateTimeStamp once.
            dtsnow = Now()
    
            'Individual date components
            dd = Right("00" & Day(dtsnow), 2)
            mm = Right("00" & Month(dtsnow), 2)
            yy = Year(dtsnow)
            hh = Right("00" & Hour(dtsnow), 2)
            nn = Right("00" & Minute(dtsnow), 2)
            ss = Right("00" & Second(dtsnow), 2)
    
            'Build the date string in the format yyyy-mm-dd
            datevalue = yy & "_" & mm & "_" & dd
            'Build the time string in the format hh:mm:ss
            timevalue = hh & "_" & nn & "_" & ss
            'Concatenate both together to build the timestamp yyyy-mm-dd hh:mm:ss
            dtsvalue = datevalue & "_" & timevalue
            GetTimeStamp = dtsvalue
        End Function
    
        'Second, decode the Base64 string
        Function SaveToBase64 (base64String)
            Dim ImageFileName
            Dim Doc
            Dim nodeB64
    
            ImageFileName = "signature_" & GetTimeStamp() & ".jpg"
    
            Set Doc = Server.CreateObject("MSXML2.DomDocument")
            Set nodeB64 = Doc.CreateElement("b64")
            nodeB64.DataType = "bin.base64"
            nodeB64.Text = Mid(base64String, InStr(base64String, ",") + 1)
    
            Dim bStream
            Set bStream = server.CreateObject("ADODB.stream")
                bStream.type =  1
                bStream.Open()
                bStream.Write( nodeB64.NodeTypedValue )
                bStream.SaveToFile Server.Mappath("/uploads/signatures/" & ImageFileName), 2 
                bStream.close()
            Set bStream = nothing
        End Function
        SaveToBase64(CStr(Request.Form("hiddenSignature")))
    

    It then saves a JPG version of the image file to a path /uploads/signatures/ on the server.

    The app.js file from the signature pad download was modified to the following:

        var wrapper = document.getElementById("signature-pad"),
            clearButton = wrapper.querySelector("[data-action=clear]"),
            savePNGButton = wrapper.querySelector("[data-action=save-png]"),
            saveSVGButton = wrapper.querySelector("[data-action=save-svg]"),
            canvas = wrapper.querySelector("canvas"),
            signaturePad;
    
        // Adjust canvas coordinate space taking into account pixel ratio,
        // to make it look crisp on mobile devices.
        // This also causes canvas to be cleared.
        function resizeCanvas() {
            // When zoomed out to less than 100%, for some very strange reason,
            // some browsers report devicePixelRatio as less than 1
            // and only part of the canvas is cleared then.
            var ratio =  Math.max(window.devicePixelRatio || 1, 1);
            canvas.width = canvas.offsetWidth * ratio;
            canvas.height = canvas.offsetHeight * ratio;
            canvas.getContext("2d").scale(ratio, ratio);
        }
    
        window.onresize = resizeCanvas;
        resizeCanvas();
    
        signaturePad = new SignaturePad(canvas, {
            backgroundColor: 'rgb(255, 255, 255)'
        });
    
        clearButton.addEventListener("click", function (event) {
            signaturePad.clear();
        });
    
        savePNGButton.addEventListener("click", function (event) {
            if (signaturePad.isEmpty()) {
                alert("Please provide signature first.");
            } else {  
                $("#hiddenSignature").val(signaturePad.toDataURL("image/jpeg").replace("data:image/jpeg;base64,", ""));
            }
        });
    

    I hope this helps somebody else out, as it killed me (and my novice coding skills) getting it to work!