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
London BenLondon Ben 

Sample S-Control - provides recip view of Contact -> Opportunity Contact Roles

Hello Guys & Gals,
 
I thought I'd throw this out to the community as something that others might find useful.
 
I've had to implement this a number of times now - as no doubt some of you have already seen - there is no related list to show the opportunity contact roles for a 'contact'
 
This S-Control provides pretty much the same functionality.
 
Any suggestions to improve this are welcome... let me know if you find this useful.
 
Ben :)
 
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
<link href="/dCSS/Theme2/default/common.css" type="text/css" media="handheld,print,projection,screen,tty,tv"  rel="stylesheet" >
<link href="/dCSS/Theme2/default/custom.css" type="text/css" media="handheld,print,projection,screen,tty,tv"  rel="stylesheet" >

<html>
<head>
<script src="/soap/ajax/10.0/connection.js" type="text/javascript"></script>
<script type="text/javascript" src="/js/functions.js"></script>
<script>
function Init() {

   //////////////////////////////////////////////////////////////////////////////////////////////////
   //                                                
   //             Developed March 2008   
   //               by Ben Ingram                    
   //           beningram@hotmail.com              
   //  May be re-used or altered so long as the credit remains :)                                              
   //                                                
   //                                                
   //  This s-Control for salesforce.com provides  
   //  visibility of all oportunities for which a  
   //  contact is listed as an Opportunity Contact 
   //                                                
   //  To Implement this s-Control:
   //    1. Add a new s-Control of type HTML
   //    2. Insert this code (all) into the HTML Body of the new Control
   //    3. Name the control something appropriate such as 'Contact_Opportunity_Roles'
   //    4. Edit the appropriate page layout for 'Contacts'
   //    5. Create a 'new section' to contain this inline s-control
   //       I recommend immediately preceding the related list area
   //    6. Drag the s-control from the list on the right into your new section
   //    7. Set the properties of this s-control to set the height = 100
   //    8. Enjoy :)
   //    
   //////////////////////////////////////////////////////////////////////////////////////////////////

  try{

    // Query the SOQL to return the related OpportunityContact records, along with the parent Opportunity details as required
    var SearchString="Select Id, ContactId, Role, IsPrimary, OpportunityId, Opportunity.Name, Opportunity.StageName From OpportunityContactRole Where ContactId = '{!Contact.Id}' ";
    var queryResults = sforce.connection.query(SearchString);
    var queryRecords = queryResults.getArray('records');
    var txtOutput = ""

    if (queryRecords.length > 0){
 
      // Rows returned, so first setup the column headers (hard coded - potentially revise this)
      var txtOutput = "<table class='list' width='100%' border='0' cellspacing='0' cellpadding='0'>";
      txtOutput = txtOutput + "<tr class='headerRow' height=20>";
      txtOutput = txtOutput + "<th nowrap>Opportunity</th>";
      txtOutput = txtOutput + "<th nowrap>Stage</th>";
      txtOutput = txtOutput + "<th nowrap>Role</th>";
      txtOutput = txtOutput + "<th nowrap>Is Primary</th></tr>";

      // Next Loop through the result array (row by row)
      for (var i = 0; i < queryRecords.length; i++) {

        // queryRecord = the Current row within the array
        var queryRecord = queryRecords[i];

        // OppRecord = the sub array row containing the linked Opportunity details
        var OppRecord = queryRecord.get("Opportunity");

 // Now build the results output row by row 
        txtOutput = txtOutput + "<tr class='dataRow' onmouseover=hiOn(this) onmouseout=hiOff(this)>";
        txtOutput = txtOutput + "<td class='datacell'><a href='/"+ queryRecord.get("OpportunityId") +"' target=_parent>" + OppRecord.get("Name") + "</a></td>";
        txtOutput = txtOutput + "<td> "+ OppRecord.get("StageName") + "</td>";
        txtOutput = txtOutput + "<td> "+ queryRecord.get("Role") + "</td>";

 // Display the standard grid checkbox image (checked or unchecked as appropriate)
        if(queryRecord.get("IsPrimary")=="true"){
          txtOutput = txtOutput + "<td><img src='/img/checkbox_checked.gif' alt='Checked' width='21' height='16' class='checkImg' title='Checked' /></td></tr>";} else {
          txtOutput = txtOutput + "<td><img src='/img/checkbox_unchecked.gif' alt='Not Checked' width='21' height='16' class='checkImg' title='Not Checked' /></td></tr>";
        } // end if (queryRecord.get("IsPrimary")=="true")
      } //end of array loop

     // Get rid of ugly white box by filling the gap with empty space 
     if (queryRecords.length == 1){
 txtOutput = txtOutput + "</table>&nbsp;<br> &nbsp;<br> &nbsp;";
 }
     if (queryRecords.length == 2){
 txtOutput = txtOutput + "</table>&nbsp;<br> &nbsp;";
 }
     if (queryRecords.length > 2){
 txtOutput = txtOutput + "</table>"; 
 }
    } else { 
      // there were no rows returnd from the SOQL query - so build a message to inform the user that this contact is not related to any opportunities
      txtOutput=txtOutput + "<font face = 'Verdana' size = '2'>This Contact has no specified Opportunity Contact Roles</font><br> &nbsp;<br> &nbsp;<br> &nbsp;<br> &nbsp;<br> &nbsp;<br>";
    }
 
  // Substitute the div mainBody contents for the generated HTML content
  document.getElementById("mainBody").innerHTML = txtOutput;

  }
  catch (error)
    {
      alert(error.faultstring);
    }
 
  }

</script>
</head>

<body class='account' onload="Init();" >
  <div class="bPageBlock secondaryPalette" style="border-top:0px; border-bottom:0px; margin-bottom:0px; padding-bottom:0px">
    <div id="mainBody"  class=pbBody style="margin-right:0px">
    </div>
  </div>
</body>
</html>

 
Best Answer chosen by Admin (Salesforce Developers) 
pacmanpacman
A little change dynamically sizes the related list.   See "resizeIframe" in below code.

Paul

In the below example I needed to show on a contact page view the roles that contact had in any account.  



Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
<link href="/dCSS/Theme2/default/common.css" type="text/css" media="handheld,print,projection,screen,tty,tv"  rel="stylesheet" >
<link href="/dCSS/Theme2/default/custom.css" type="text/css" media="handheld,print,projection,screen,tty,tv"  rel="stylesheet" >

<html>
<head>
<script src="/soap/ajax/10.0/connection.js" type="text/javascript"></script>
<script type="text/javascript" src="/js/functions.js"></script>
<script>
 function resizeIframe() {
  var thisWindow = window.name;
  if(thisWindow){
   var iframes = parent.document.getElementsByName(thisWindow);
   if (iframes && iframes.length == 1) {
    var height = document.body.scrollHeight;
    iframes[0].style.height = height + "px";
   }
  }
 }
function Init() {

   //////////////////////////////////////////////////////////////////////////////////////////////////
   //                                                
   //             Developed March 2008   
   //               by Ben Ingram                    
   //           beningram@hotmail.com              
   //  May be re-used or altered so long as the credit remains :)                                              
   //                                                
   //                                                
   //  This s-Control for salesforce.com provides  
   //  visibility of all oportunities for which a  
   //  contact is listed as an Opportunity Contact 
   //                                                
   //  To Implement this s-Control:
   //    1. Add a new s-Control of type HTML
   //    2. Insert this code (all) into the HTML Body of the new Control
   //    3. Name the control something appropriate such as 'Contact_Opportunity_Roles'
   //    4. Edit the appropriate page layout for 'Contacts'
   //    5. Create a 'new section' to contain this inline s-control
   //       I recommend immediately preceding the related list area
   //    6. Drag the s-control from the list on the right into your new section
   //    7. Set the properties of this s-control to set the height = 100
   //    8. Enjoy :)
   //    
   //////////////////////////////////////////////////////////////////////////////////////////////////

  try{

    // Query the SOQL to return the related OpportunityContact records, along with the parent Opportunity details as required
    var SearchString="Select a.AccountId, a.Account.Name, a.Role from AccountContactRole a where contact.id = '{!Contact.Id}' ";
    var queryResults = sforce.connection.query(SearchString);
    var queryRecords = queryResults.getArray('records');
    var txtOutput = ""

    if (queryRecords.length > 0){
 
      // Rows returned, so first setup the column headers (hard coded - potentially revise this)
      var txtOutput = "<table class='list' width='100%' border='0' cellspacing='0' cellpadding='0'>";
      txtOutput = txtOutput + "<tr class='headerRow' height=20>";
      txtOutput = txtOutput + "<th nowrap>Account Name</th>";
      txtOutput = txtOutput + "<th nowrap>Role</th>";
      txtOutput = txtOutput + "</tr>"

      // Next Loop through the result array (row by row)
      for (var i = 0; i < queryRecords.length; i++) 
      {
        var queryRecord = queryRecords[i];
        var AccountRecord = queryRecord.get("Account");
        txtOutput = txtOutput + "<tr class='dataRow' onmouseover=hiOn(this) onmouseout=hiOff(this)>";
        txtOutput = txtOutput + "<td class='datacell'><a href='/"+ queryRecord.get("AccountId") +"' target=_parent>" + AccountRecord.get("Name") + "</a></td>";
        txtOutput = txtOutput + "<td> "+ queryRecord.get("Role") + "</td>";
        txtOutput = txtOutput + "</tr>";
      }  
        
//      txtOutput = txtOutput + "</table>";

// removed code here
if (queryRecords.length == 1){
txtOutput = txtOutput + "</table>&nbsp;<br> &nbsp;<br> &nbsp;";
}
if (queryRecords.length == 2){
txtOutput = txtOutput + "</table>&nbsp;<br> &nbsp;";
}
if (queryRecords.length > 2){
txtOutput = txtOutput + "</table>";
}
} else {
// there were no rows returnd from the SOQL query - so build a message to inform the user that this contact is not related to any opportunities
txtOutput=txtOutput + "<font face = 'Verdana' size = '2'>This Contact has no specified Opportunity Contact Roles</font><br> &nbsp;<br> &nbsp;<br> &nbsp;<br> &nbsp;<br> &nbsp;<br>";
} 
 
   
 
  // Substitute the div mainBody contents for the generated HTML content
  document.getElementById("mainBody").innerHTML = txtOutput;

  }
  catch (error)
    {
      alert(error.faultstring);
    }
 
  }

</script>
</head>

<body class='contact' onload="Init();resizeIframe()" >
  <div class="bPageBlock secondaryPalette" style="border-top:0px; border-bottom:0px; margin-bottom:0px; padding-bottom:0px">
    <div id="mainBody"  class=pbBody style="margin-right:0px">
    </div>
  </div>
</body>
</html>

 


All Answers

CrmzepherCrmzepher

Hello,

Fantastic code!! This will help a great deal with my slaes teams as we don´t use the Accounts Tab at their level due to the types of products we sell. I provides just the ensight that they need for the Oppsthat have already been posted and helps reenforce the importance of associating the right Contact with the Opportunity.

Great job.

crmzepher

RRCRRC
I'm getting an API_Disabled_for_ORG error. We're new to SFDC and this is one code we are glad is available. What do i need to do? Please advise.
RRC
London BenLondon Ben
RRCRRC
Professional. Just found out we have to pay extra to have API activated. Bummer. Thanks though.
pacmanpacman
A little change dynamically sizes the related list.   See "resizeIframe" in below code.

Paul

In the below example I needed to show on a contact page view the roles that contact had in any account.  



Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
<link href="/dCSS/Theme2/default/common.css" type="text/css" media="handheld,print,projection,screen,tty,tv"  rel="stylesheet" >
<link href="/dCSS/Theme2/default/custom.css" type="text/css" media="handheld,print,projection,screen,tty,tv"  rel="stylesheet" >

<html>
<head>
<script src="/soap/ajax/10.0/connection.js" type="text/javascript"></script>
<script type="text/javascript" src="/js/functions.js"></script>
<script>
 function resizeIframe() {
  var thisWindow = window.name;
  if(thisWindow){
   var iframes = parent.document.getElementsByName(thisWindow);
   if (iframes && iframes.length == 1) {
    var height = document.body.scrollHeight;
    iframes[0].style.height = height + "px";
   }
  }
 }
function Init() {

   //////////////////////////////////////////////////////////////////////////////////////////////////
   //                                                
   //             Developed March 2008   
   //               by Ben Ingram                    
   //           beningram@hotmail.com              
   //  May be re-used or altered so long as the credit remains :)                                              
   //                                                
   //                                                
   //  This s-Control for salesforce.com provides  
   //  visibility of all oportunities for which a  
   //  contact is listed as an Opportunity Contact 
   //                                                
   //  To Implement this s-Control:
   //    1. Add a new s-Control of type HTML
   //    2. Insert this code (all) into the HTML Body of the new Control
   //    3. Name the control something appropriate such as 'Contact_Opportunity_Roles'
   //    4. Edit the appropriate page layout for 'Contacts'
   //    5. Create a 'new section' to contain this inline s-control
   //       I recommend immediately preceding the related list area
   //    6. Drag the s-control from the list on the right into your new section
   //    7. Set the properties of this s-control to set the height = 100
   //    8. Enjoy :)
   //    
   //////////////////////////////////////////////////////////////////////////////////////////////////

  try{

    // Query the SOQL to return the related OpportunityContact records, along with the parent Opportunity details as required
    var SearchString="Select a.AccountId, a.Account.Name, a.Role from AccountContactRole a where contact.id = '{!Contact.Id}' ";
    var queryResults = sforce.connection.query(SearchString);
    var queryRecords = queryResults.getArray('records');
    var txtOutput = ""

    if (queryRecords.length > 0){
 
      // Rows returned, so first setup the column headers (hard coded - potentially revise this)
      var txtOutput = "<table class='list' width='100%' border='0' cellspacing='0' cellpadding='0'>";
      txtOutput = txtOutput + "<tr class='headerRow' height=20>";
      txtOutput = txtOutput + "<th nowrap>Account Name</th>";
      txtOutput = txtOutput + "<th nowrap>Role</th>";
      txtOutput = txtOutput + "</tr>"

      // Next Loop through the result array (row by row)
      for (var i = 0; i < queryRecords.length; i++) 
      {
        var queryRecord = queryRecords[i];
        var AccountRecord = queryRecord.get("Account");
        txtOutput = txtOutput + "<tr class='dataRow' onmouseover=hiOn(this) onmouseout=hiOff(this)>";
        txtOutput = txtOutput + "<td class='datacell'><a href='/"+ queryRecord.get("AccountId") +"' target=_parent>" + AccountRecord.get("Name") + "</a></td>";
        txtOutput = txtOutput + "<td> "+ queryRecord.get("Role") + "</td>";
        txtOutput = txtOutput + "</tr>";
      }  
        
//      txtOutput = txtOutput + "</table>";

// removed code here
if (queryRecords.length == 1){
txtOutput = txtOutput + "</table>&nbsp;<br> &nbsp;<br> &nbsp;";
}
if (queryRecords.length == 2){
txtOutput = txtOutput + "</table>&nbsp;<br> &nbsp;";
}
if (queryRecords.length > 2){
txtOutput = txtOutput + "</table>";
}
} else {
// there were no rows returnd from the SOQL query - so build a message to inform the user that this contact is not related to any opportunities
txtOutput=txtOutput + "<font face = 'Verdana' size = '2'>This Contact has no specified Opportunity Contact Roles</font><br> &nbsp;<br> &nbsp;<br> &nbsp;<br> &nbsp;<br> &nbsp;<br>";
} 
 
   
 
  // Substitute the div mainBody contents for the generated HTML content
  document.getElementById("mainBody").innerHTML = txtOutput;

  }
  catch (error)
    {
      alert(error.faultstring);
    }
 
  }

</script>
</head>

<body class='contact' onload="Init();resizeIframe()" >
  <div class="bPageBlock secondaryPalette" style="border-top:0px; border-bottom:0px; margin-bottom:0px; padding-bottom:0px">
    <div id="mainBody"  class=pbBody style="margin-right:0px">
    </div>
  </div>
</body>
</html>

 


This was selected as the best answer
Book_GuyBook_Guy

This is great code.  Thanks for posting. 

 

I set up your S Control.  How can I access the Stage field with a formula field in the Contact Object?  I'd like to create a formula field to determine if a Contact has an Opportunity in the "Active" Stage. The ultimate goal is to create a View with all the Clients who have an Opportunity in this Stage.

 

Thank you.

 

David

SA_AdminSA_Admin

Hi London Ben,

 

By fluke I found your posting and I could really use this code right now.  Do you by any chance have a visualforce/apex version? 

 

Thank you!

 

PrintStewardPrintSteward

Hello Ben,

 

I recently edited a similar S-control having an issue making changes visible to users. I can see everything just fine as a System administrator...

 

Brandon