Sunday 1 May 2016

Image mapping in Salesforce using jQuery

I had interesting requirement in one of my assignment couple of months back, thought I should share with the community.

The requirement came from construction industry client for managing the injuries of labors to track the health and safety. We used image-mapster jQuery library to demonstrate the human body so that support agent can create the injury details after clicking the body part and send the information directly to health and safety department.

The purpose of this solution is to track the common injuries and reasons to know which safety systems need more investment in order to make them better.

Technically, we have defined the HTML image maps for the body parts. I have used three images which are shown below and added them as static resource in Salesforce

This image is used to show the background which defines the structure of the body

This image is used to highlight the part of the body
This image is used to show the selected part when the mouse is hovered


All the images overlay each other and give the effect of single image. When the user hovers the body part it changes the color and display the name of the part, after clicking it shows the form with the auto populated values based on the selection, on submission of form it creates the injury detail record in Salesforce as shown below:




Code Snippet for Visualforce page:


<apex:page standardController="Case">

    <apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" />
    <apex:includeScript value="{!URLFOR($Resource.AbsoluteBeginners, '/AbsoluteBeginners/scripts/jquery.imagemapster.js')}"/>

<style>

@import "https://fonts.googleapis.com/css?family=Raleway";

#caseInjuryForm{
    width:100%;
    height:100%;
    opacity:.95;
    top:0;
    left:0;
    display:none;
    position:fixed;
    background-color:#313131;
    overflow:auto
}

img#close {
    position:absolute;
    right:-14px;
    top:-14px;
    cursor:pointer
}

div#popupCase {
    position:absolute;
    left:50%;
    top:17%;
    margin-left:-202px;
    font-family:'Raleway',sans-serif
}
#caseform {
    max-width:300px;
    min-width:250px; 
    padding:10px 50px;
    border:2px solid gray;
    border-radius:10px;
    font-family:raleway;
    background-color:#fff
}

#casep {
    margin-top:30px
}

#caseh2 {
    background-color:#FEFFED;
    padding:20px 35px;
    margin:-10px -50px;
    text-align:center;
    border-radius:10px 10px 0 0
}

#casehr {
    margin:10px -50px;
    border:0;
    border-top:1px solid #ccc
}

.caseinput {
    width:82%;
    padding:10px;
    margin-top:30px;
    border:1px solid #ccc;
    padding-left:40px;
    font-size:16px;
    font-family:raleway
}

#casename {
    background-image:url(../images/name.jpg);
    background-repeat:no-repeat;
    background-position:5px 7px
}

#caseemail {
    background-image:url(../images/email.png);
    background-repeat:no-repeat; 
    background-position:5px 7px
}

#casetextarea {
    background-image:url(../images/msg.png);
    background-repeat:no-repeat;
    background-position:5px 7px;
    width:82%;
    height:95px;
    padding:10px;
    resize:none;
    margin-top:30px;
    border:1px solid #ccc;
    padding-left:40px;
    font-size:16px;
    font-family:raleway;
    margin-bottom:30px
}


#casesubmit {
    text-decoration:none;
    width:100%;
    text-align:center;
    display:block;
    background-color:#FFBC00;
    color:#fff;
    border:1px solid #FFCB00;
    padding:10px 0;
    font-size:20px;
    cursor:pointer;
    border-radius:5px
}

#casespan {
    color:red;
    font-weight:700
}

#casebutton {
    width:10%;
    height:45px;
    border-radius:3px;
    background-color:#cd853f;
    color:#fff;
    font-family:'Raleway',sans-serif;
    font-size:18px;
    cursor:pointer
}


</style>
    
    <script type="text/javascript" src="/soap/ajax/28.0/connection.js"></script>
    <script type="text/javascript" src="/soap/ajax/28.0/apex.js"></script>
    <script language="JavaScript">
        
        sforce.connection.sessionId = "{!$Api.Session_ID}";
        $(document).ready(function(){
            
            document.getElementById('caseInjuryForm').style.display = "none";
            
            $('#human-body-map').mapster({
                singleselect : true,
                render_highlight: {
                    fillColor: '2aff00',
                    stroke: false,
                    fade: false,
                    altImage: '{!URLFOR($Resource.HumanBodyMap, '/HumanBodyMap2.gif')}'
                    
                },
                render_select: {
                    fillColor: 'ff000c',
                    stroke: false,
                    altImage: '{!URLFOR($Resource.HumanBodyMap, '/HumanBodyMap1.gif')}'  
                },
                mapKey:'datapart',
                fillOpacity : 1,
                areas: [
                {
                    key: 'RightHandPalm',
                    selected: true
                },
                {
                    key: 'LeftHandPalm',
                    selected: true
                },
                {
                    key: 'RightLegKnee',
                    selected: true
                }]
            });
        
        });
        
        function div_show(title) {
            document.getElementById('caseInjuryForm').style.display = "block";
            var res = title.split("-");
            document.getElementById('partOfBody').value=res[0];
            document.getElementById('side').value=res[1];
            document.getElementById('detailPartBody').value=res[2];
        }
        
        function div_hide() {
            document.getElementById('caseInjuryForm').style.display = "none";
        }
        
        
        function InjurySubmit(){
            var createRecord = new Array();     
            
            var createInjuryDetail = new sforce.SObject("Injury_Detail__c");
            createInjuryDetail.Name = 'SalesforceZone Demo'     
            createInjuryDetail.Case__c= '{!Case.Id}';    
            createInjuryDetail.Part_of_body_injured__c = document.getElementById('partOfBody').value;
            createInjuryDetail.Side__c = document.getElementById('side').value;
            createInjuryDetail.Detail_of_part_of_body_injured__c = document.getElementById('detailPartBody').value;
            createInjuryDetail.Nature_of_injury__c = document.getElementById('natureInjury').value;
            createInjuryDetail.Aggravation_Description__c = document.getElementById('description').value;
            
            createRecord.push(createInjuryDetail);        
            sforce.connection.create(createRecord);
            document.getElementById('caseInjuryForm').style.display = "none";
            window.open("/"+'{!Case.id}','_parent');
            
        }
    </script>
        
    <div id="image">
        <div id="mapster_wrap_0" style="display: block; position: relative; padding: 0px; width: 400px; height: 400px;">
            <img class="mapster_el" src="{!URLFOR($Resource.HumanBodyMap,'/HumanBodyMap1.gif')}" style="display: none;"/>
            <img class="mapster_el" src="{!URLFOR($Resource.HumanBodyMap,'/HumanBodyMap1.gif')}"  style="display: none;"/>
            <img class="mapster_el" src="{!URLFOR($Resource.HumanBodyMap,'/HumanBodyMap1.gif')}" style="display: none;"/>
            <img id="human-body-map"  src="{!URLFOR($Resource.HumanBodyMap,'/HumanBodyMap.gif')}" border="0" width="800" height="600" orgWidth="800" orgHeight="600" usemap="#human-body-map" alt="human-body-map" />
        </div>
    </div>
    
    <map name="human-body-map">
        <area href="#" shape="poly" datapart="RightHandPalm" title="Hand-Right-Palm of Hand"  coords="81,332,94,315,106,305,114,307,124,310,125,324,119,336,117,344,114,351,111,357,105,363,103,362,100,368,93,364" onClick="div_show(this.title);return false" alt="" />
        <area href="#" shape="poly" datapart="LeftHandPalm" title="Hand-Left-Palm of Hand"  coords="304,312,322,307,333,311,341,317,346,327,345,333,337,332,336,341,337,356,336,361,334,364,332,366,328,367,325,368,317,361,311,345,307,333"  onClick="div_show(this.title);return false"  alt=""/>
        <area href="#" shape="poly" datapart="RightLegKnee" title="Leg-Right-Knee"  coords="170,398,180,410,192,414,201,418,205,433,203,442,194,441,184,440,175,435,175,434,171,433" onClick="div_show(this.title);return false" alt=""/>
    </map>
    
    <div id="caseInjuryForm">
        
        <div id="popupCase">
        <!-- Case Injury Details Form -->
        <form action="#" id="caseform" method="post" name="caseform">
        <img id="close" src="{!$Resource.close}" onclick ="div_hide()" />
        <h2 id="caseh2">Case Injury Details</h2>
        <hr id="casehr"/>
        <input id="partOfBody" class="caseinput" name="casename" placeholder="Part of body injured" type="text"/>
        <input id="side" class="caseinput" name="caseemail" placeholder="Side" type="text"/>
        <input id="detailPartBody" class="caseinput" name="caseemail" placeholder="Detail of part of body injured" type="text"/>
        <input id="natureInjury" class="caseinput" list="injuryList" name="caseemail" placeholder="Nature of injury" />
        <datalist id="injuryList">
            <option value="Abrasion" />
            <option value="Aggravation" />  
            <option value="Allergy"  />
            <option value="Amputation" />
            <option value="Animal" />
            <option value="Bruise" />
            <option value="Burn" />
            <option value="Chemical" />
            <option value="Choking/Suffocation" />  
            <option value="Concussion" />
            <option value="Crush/Bruise" />
            <option value="Dehydration" />  
            <option value="Dislocation" />      
            <option value="Electric shock" />
            <option value="Foreign body" />
            <option value="Fracture" />
            <option value="Hearing loss" />
            <option value="Heat stroke" />
            <option value="Intercranial Injury" />
        </datalist> 
        
        <input id="description" class="caseinput" name="caseemail" placeholder="Aggravation Description" type="text"/>
        <a onClick="InjurySubmit()" id="casesubmit">Submit Case Injury</a>
        
        </form>
        </div>
        <!-- Popup Div Ends Here -->
    </div>
    
</apex:page>


Download jQuery plugin from here
http://www.outsharked.com/imagemapster/

Define your HTML image maps here
http://www.image-mapper.com/

Useful link to setup the page
http://members.shaw.ca/sites/AbsoluteBeginners/beginner1.htm

Feel free comment below if anything is over pedantic. Cheers