function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Gaby FrydmanGaby Frydman 

Picture attachment on Contact Page

Hi All, 

I have a rather neat controller with a visual force page that is called on button press to collect a signature. The end result is a file called "Signature.png" and is attached to the Notes and Attachments section on the contact object.

My question is: How can I have a visualforce page within the contact layout which would display the signature picture?

Reason is : to create a pdf of the contact page with their signature at the bottom

Currently my Controlelr for creating the signature attachment:
public with sharing class ehsSignatureExtensionController {

private final Contact ehs;

public ehsSignatureExtensionController(ApexPages.StandardController controller) {
    ehs = (Contact)controller.getRecord();
}

@RemoteAction public static RemoteSaveResult saveSignature(Id ehsId, String signatureBody) {
    Attachment a = new Attachment(ParentId=ehsId, name='Signature.png', ContentType='image/png', Body=EncodingUtil.base64Decode(signatureBody));
    Database.saveResult result = Database.insert(a,false);
    RemoteSaveResult newResult = new RemoteSaveResult();
    newResult.success = result.isSuccess();
    newResult.attachmentId = a.Id;
    newResult.errorMessage = result.isSuccess()?'':result.getErrors()[0].getMessage();
    return newResult;
}

public class RemoteSaveResult {
    public Boolean success;
    public Id attachmentId;
    public String errorMessage;
}

public pageReference cancel(){
    pageReference page = new PageReference('/'+ehs.id);
    page.setRedirect(true);
    return page;
}
}

My VF Page:
<apex:page docType="html-5.0" standardController="Contact" extensions="ehsSignatureExtensionController" sidebar="false" showHeader="false">

<script>var $j = jQuery.noConflict();</script>
<apex:stylesheet value="{!URLFOR($Resource.jquerymobile,'/jquerymobile/jquery.mobile-1.3.2.min.css')}"/>

<apex:includeScript value="{!URLFOR($Resource.jquerymobile,'/jquerymobile/jquery.mobile-1.3.2.min.js')}"/>

<canvas id="signatureCanvas" width="400" height="250" style="border: 1px solid black;"/>  
<apex:includeScript value="/soap/ajax/28.0/connection.js"/>

<script>

sforce.connection.sessionId = "{!$Api.Session_Id}";
var canvas = document.getElementById("signatureCanvas");
var context = canvas.getContext("2d");
var mouseButton = 0;
var lastX = lastY = null;
var ehsId = '{!Contact.Id}';

function saveSignature() {

    var image = canvas.toDataURL().split(',')[1];
    ehsSignatureExtensionController.saveSignature(ehsId,image,handleResult);
}

function handleResult(result,event) {
    if(result.success) {
        window.top.location.href='/'+ehsId;
    } else {
        alert('Error: '+result.errorMessage);
    }
}

function handleEvent(event) {
    if(event.type==="mousedown"||event.type==="touchstart") {
        mouseButton = event.which || 1;
        lastX = lastY = null;
    }
    if(event.type==="touchcancel" || event.type==="touchcancel" || event.type==="mouseup") {
        mouseButton = 0;
        lastX = lastY = null;
    }
    if((event.type==="touchmove" || event.type==="mousemove") && mouseButton) {
        var newX, newY;
        var canvasX = 0, canvasY = 0, obj = event.srcElement || event.target;
        do {
            canvasX += obj.offsetLeft;
            canvasY += obj.offsetTop;
        } while(obj = obj.offsetParent);
        if(event.targetTouches && event.targetTouches.length) {
            newX = event.targetTouches[0].clientX - (canvasX/2);
            newY = event.targetTouches[0].clientY - (canvasY/2);
        } else {
            newX = event.offsetX;
            newY = event.offsetY;
        }
        if(!lastX && !lastY) {
            lastX = newX;
            lastY = newY;
            context.beginPath();
            context.moveTo(lastX,lastY);
            context.lineTo(lastX,lastY,lastX,lastY);
            context.stroke();
        } else {
            context.beginPath();
            context.moveTo(lastX,lastY);
            context.lineTo(newX,newY);
            context.stroke();
            lastX = newX;
            lastY = newY;
        }
    }
    if(event.type=="touchmove" || event.type==="mousedrag" || (event.type==="selectstart" && (event.srcElement||event.target)===canvas)) {
        event.returnValue=false;
        event.stopPropagation();
        event.preventDefault();
        return false;
    }
}

canvas.addEventListener("mousedrag",handleEvent,true);
canvas.addEventListener("mousemove",handleEvent,true);
canvas.addEventListener("mousedown",handleEvent,true);
window.addEventListener("mouseup",handleEvent,true);
canvas.addEventListener("touchstart",handleEvent,true);
canvas.addEventListener("touchmove",handleEvent,true);
window.addEventListener("touchend",handleEvent,true);
window.addEventListener("selectstart",handleEvent,true);

</script>

<apex:form >
    <apex:commandButton value="Save Signature" onclick="saveSignature();return false;" styleClass="button"/>
    <apex:commandButton action="{!cancel}" value="Exit"/>
</apex:form>

</apex:page>

My button on the contact page:
{!REQUIRESCRIPT("/soap/ajax/23.0/connection.js")} 
{!REQUIRESCRIPT("/soap/ajax/23.0/apex.js")} 

var id = '{!Contact.Id}'; 
var url = "/apex/Signature?id=" + id + '&src=page'; 
var features = 'directories=no,menubar=no,titlebar=no,toolbar=no,width=450,height=460'; 
win = window.open(url,'', features); 
win.focus();

I am using JQuery Mobile standard library. 
Best Answer chosen by Gaby Frydman
Ashish_Sharma_DEVSFDCAshish_Sharma_DEVSFDC
Hi Gaby Frydman,

Use like below inline vf page on your detail page to display signature on page.

VF Page :
<apex:page standardController="Account" extensions="AttachmentExtension">
<apex:form >
<apex:image url="/servlet/servlet.FileDownload?file={!AttachFileId}"/>
</apex:form>
</apex:page>

Extension :
Public Class AttachmentExtension {

    String accId;
    
    public AttachmentExtension(ApexPages.StandardController stdController) {
        accId = stdController.getId();    
    }
    
    public String getAttachFileId() {
        String attachId = '';
        List<Attachment> attachedFiles = [select Id from Attachment where parentId =:accId order By LastModifiedDate DESC limit 1];
        if( attachedFiles != null && attachedFiles.size() > 0 ) {
            fileId = attachedFiles[0].Id;
        }
        return attachId;    
    }
}

Let us know if it helps you.
Mark this as BEST ANSWER if it helps you.

All Answers

Ashish_Sharma_DEVSFDCAshish_Sharma_DEVSFDC
Hi Gaby Frydman,

Use like below inline vf page on your detail page to display signature on page.

VF Page :
<apex:page standardController="Account" extensions="AttachmentExtension">
<apex:form >
<apex:image url="/servlet/servlet.FileDownload?file={!AttachFileId}"/>
</apex:form>
</apex:page>

Extension :
Public Class AttachmentExtension {

    String accId;
    
    public AttachmentExtension(ApexPages.StandardController stdController) {
        accId = stdController.getId();    
    }
    
    public String getAttachFileId() {
        String attachId = '';
        List<Attachment> attachedFiles = [select Id from Attachment where parentId =:accId order By LastModifiedDate DESC limit 1];
        if( attachedFiles != null && attachedFiles.size() > 0 ) {
            fileId = attachedFiles[0].Id;
        }
        return attachId;    
    }
}

Let us know if it helps you.
Mark this as BEST ANSWER if it helps you.
This was selected as the best answer
Gaby FrydmanGaby Frydman
Hi Ashish Sharma, 

Thanks a lot for the reply. This has worked brilliantly. 

Here is my code which works great:
Public Class AttachmentExtension {

    String conId;
    
    public AttachmentExtension(ApexPages.StandardController stdController) {
        conId = stdController.getId();    
    }
    
    public String getAttachFileId() {
        String attachId = 'Signature.png';
        List<Attachment> attachedFiles = [select Id from Attachment where parentId =:conId order By LastModifiedDate DESC limit 1];
        if( attachedFiles != null && attachedFiles.size() > 0 ) {
          attachId = attachedFiles[0].Id;
        }
        return attachId;    
    }
}