+ Start a Discussion
Kelly KKelly K 

Overriding lookup with a Visualforce page

Hi All,

 

I've gone through a couple of sites including 

  1. http://blog.jeffdouglas.com/2011/08/12/roll-your-own-salesforce-lookup-popup-window/
  2. http://bobbuzzard.blogspot.com/2010/09/visualforce-lookup.html
  3. http://boards.developerforce.com/t5/Visualforce-Development/Overriding-lookup-icon/m-p/196802#M26504 (no solution found)

The jist of what I'm trying to do is override all of our lookup on the account detail for the "Go Forward PM System" object. The reason why is that sometimes the name of the GFPM is different than the vendor that sells it. I can add additional filters to the standard lookup page, but this only filters off of the 'recently' viewed, which is not helpful since we have quite a few GFPM records.

 

However, I do not want to completely override our standard account page since we have several record types and layouts with over 100 fields on each. I am able to override the lookup, but I am having trouble passing the Id of the selection back to the account page. In both of the examples by Jeff and Bob, they are able to pass it back by having the field element specified as apex:inputfield. With apex:detail, is there a way to get the field Id to pass it back? If so how can I pass it back? I also humored the idea of using a hiddenInput, but ideally, I would like the user to be able to see that they modified the page (standard feel).

 

I have very limited javascript expereince, so that's where the additional struggle is coming from. Any education you gurus can provide would be greatly helpful.

 

Here's what I have so far:

Detail Page:

<apex:page standardController="Account">
    <script type="text/javascript"> 
   	
		function openLookup(baseURL, width, modified, searchParam) {
			var lookupType = baseURL.substr(baseURL.length-3,3); //This is the value for lktp
			//var lookupFieldId = baseURL.substr(baseURL.length-38,17); //This is the value for lknm, renamed as txtId
			//var lookupFormId = escapeUTF("{!$Component.detail}"); //This is the value for the other half of lknm, identifying the form, renamed as frm
			
			if(lookupType == "a1i") {
				var urlArr = baseURL.split("&");				
				var txtId = '';
				if(urlArr.length > 2) {
					urlArr = urlArr[1].split('=');
					txtId = urlArr[1];
				}
				
				baseURL = "/apex/GFPMCustomLookupSearch?txt=" + txtId + "&frm=" + escapeUTF("{!$Component.detail}");  		
			}
			
			openPopup(baseURL, "lookup", 350, 480, "width="+width+",height=480,toolbar=no,status=no,directories=no,menubar=no,resizable=yes,scrollable=no", true);
		}		
    </script>    
    <apex:form >
    	<apex:inputField value="{!account.Go_Forward_PM_System__c}"/>
    </apex:form>
    <apex:detail id="detail" inlineEdit="true"/>
</apex:page>

 

 

Lookup page: 

<apex:page controller="GFPMDynamicSearch" title="Search" showHeader="false" sideBar="false" tabStyle="Go_Forward_PM_System__c" id="pg">

	<apex:form id="form">
	<apex:actionFunction name="doSearchAF" action="{!searchGFPM}"/>
	<apex:outputPanel id="page" layout="block" style="margin:5px;padding:10px;padding-top:2px;">
		<apex:actionRegion >
			<apex:outputPanel id="top" layout="block" style="margin:5px;padding:10px;padding-top:2px;">
			<apex:outputLabel value="Search" style="font-weight:Bold;padding-right:10px;" for="txtSearch" />
				<apex:inputText id="txtSearch" value="{!searchText}" onkeypress="return noenter(event);" />
				<span style="padding-left:5px">
					<apex:commandButton id="btnSearch" value="Search" action="{!searchGFPM}" rerender="searchResults"/>
				    <apex:actionStatus id="status" startText="requesting..."/>
				</span>
			</apex:outputPanel>
			
			<apex:outputPanel id="pnlSearchResults" style="margin:10px;height:350px;overflow-Y:auto;" layout="block">
				<apex:pageBlock id="searchResults"> 
					<apex:pageBlockTable value="{!results}" var="result" id="tblResults">
						<apex:column headerValue="Go Forward PM System">
							<apex:outputLink value="javascript&colon;top.window.opener.lookupPick2('{!FormTag}','{!TextBox}_lkid','{!TextBox}','{!result.Id}','{!result.Name}', false)" rendered="{!NOT(ISNULL(result.Id))}">{!result.Name}</apex:outputLink>
						</apex:column>					
				    	<apex:column headerValue="Vendor Account" value="{!result.Vendor_Account__r.Name}"/>
				    	<apex:column headerValue="Status" value="{!result.Status__c}"/>
					</apex:pageBlockTable>
				</apex:pageBlock>
			</apex:outputPanel>			
		</apex:actionRegion>			
	</apex:outputPanel>
	</apex:form>
	
	<script type='text/javascript'>
		//This function allows the user to press enter to search
		function noenter(ev) {
			if (window.event && window.event.keyCode == 13 || ev.which == 13) {
				doSearchAF();
				return false;
			} else {
				return true;
			}
		}
	</script>	
</apex:page>

 

Best Answer chosen by Admin (Salesforce Developers) 
Kelly KKelly K

I finally got this working. Here's my code if anyone is interested.

 

Detail page override:

<apex:page standardController="Account">
     <script type="text/javascript"> 
   	
		function openLookup(baseURL, width, modified, searchParam) {
			//Example from acct lookup: https://c.cs15.visual.force.com/_ui/common/data/LookupPage?lknm=acc3j_id0_detail&lktp=001
			//If https://na13.salesforce.com/_ui/common/data/LookupPage?lknm=CF00Na000000A8hD5&lktp=a1i&lksrch=eClinicalWorks is a default URL			
			//then lknm=CF00Na000000A8hD5j_id0_detail&lktp=a1i is considered the BaseURL
			
			var lktp = baseURL.substr(baseURL.length-3,3); //This is the value for lktp (lookup type)
			
			if(lktp == "a1i") {
				var urlArr = baseURL.split("&"); //Results are lknm=CF00Na000000A8hD5j_id0_detail,lktp=a1i			
				var lknm = ''; //lookup name (ie field name)
				var frm = ''; //form tag
				if(urlArr.length > 1) { //if the urlArr array is greater than 1 element then
					urlArr = urlArr[0].split('='); //take the first element and split it - results are lknm,CF00Na000000A8hD5j_id0_detail
					lknm = urlArr[1]; //then take the 2nd element of that split
					frm = urlArr[1].substr(urlArr[1].length-12,12);
				}

				baseURL = "/apex/GFPMCustomLookupSearch?lktp=" + lktp + "&lknm=" + lknm + "&frm=" + frm;		
			}
			
			openPopup(baseURL, "lookup", 350, 480, "width="+width+",height=480,toolbar=no,status=no,directories=no,menubar=no,resizable=yes,scrollable=no", true);
		}		
    </script>     
    <apex:detail id="detail" inlineEdit="true"/>
</apex:page>

 

Lookup Page Override:

<apex:page controller="GFPMCustomLookupSearchController" title="Search" showHeader="false" sideBar="false" tabStyle="Go_Forward_PM_System__c" id="pg">
	<apex:form id="form">
	<apex:actionFunction name="doSearchAF" action="{!searchGFPM}"/>
	
	<apex:outputPanel id="outputPanel" layout="block" style="margin:5px;padding:10px;padding-top:2px;">
		<apex:actionRegion id="actionRegion">
			<apex:outputPanel id="top" layout="block" style="margin:5px;padding:10px;padding-top:2px;">
				<apex:outputLabel id="txtSearchLabel" value="Search" style="font-weight:Bold;padding-right:10px;" for="txtSearch" />
				<apex:inputText id="txtSearch" value="{!searchText}" onkeypress="return noenter(event);"/>
				<span style="padding-left:5px">
					<apex:commandButton id="btnSearch" value="Search" action="{!searchGFPM}" rerender="searchResults"/>
				    <apex:actionStatus id="status" startText="requesting..."/>
				</span>
			</apex:outputPanel>
			
			<apex:outputPanel id="pnlSearchResults" style="margin:10px;height:350px;overflow-Y:auto;" layout="block">
				<apex:pageBlock id="searchResults"> 
					<apex:pageBlockTable value="{!results}" var="result" id="tblResults">
						<apex:column headerValue="Go Forward PM System">
							<apex:outputLink value="javascript&colon;top.window.opener.lookupPick2('{!FormTag}','{!TextBox}_lkid','{!TextBox}','{!result.Id}','{!result.Name}', false)" rendered="{!NOT(ISNULL(result.Id))}">{!result.Name}</apex:outputLink>
						</apex:column>					
				    	<apex:column headerValue="Vendor Account" value="{!result.Vendor_Account__r.Name}"/>
				    	<apex:column headerValue="Status" value="{!result.Status__c}"/>
					</apex:pageBlockTable>
				</apex:pageBlock>
			</apex:outputPanel>	
					
		</apex:actionRegion>			
	</apex:outputPanel>
	</apex:form>

	<script type='text/javascript'>
		//This function allows the user to press enter to search
		function noenter(ev) {
			if (window.event && window.event.keyCode == 13 || ev.which == 13) {
				doSearchAF();
				return false;
			} else {
				return true;
			}
		}
	</script>	
</apex:page>

 

Relevant Controller Code:

public with sharing class GFPMCustomLookupSearchController {

 	// used by the visualforce page to send the link to the right dom element
  	public string getFormTag() {
    	return System.currentPageReference().getParameters().get('frm');
  	}
 
  	// used by the visualforce page to send the link to the right dom element for the text box
  	public string getTextBox() {
    	return System.currentPageReference().getParameters().get('lknm');
  	}	
}

 

 

 

All Answers

pinoytechiepinoytechie

the default lookup carries the target field Id as parameter. that's lknm (or lkfield? can't remember but should be one of them)

 

what you could do is parse that from salesforce 'baseURL' (basing on your code), add it as parameter (as well) to your vf page URL, and assign it to a property in your controller.

Kelly KKelly K

I tried switching it out to use lknm (identified as the txtId param) and lktp (identified as the frm param) as the parameters - which worked fine for the overriding of the popup. However, as far as the passback after a selection, I would need to modify this:

<apex:outputLink value="javascript&colon;top.window.opener.lookupPick2('{!FormTag}','{!TextBox}_lkid','{!TextBox}','{!result.Id}','{!result.Name}', false)" rendered="{!NOT(ISNULL(result.Id))}">{!result.Name}</apex:outputLink>

 

I don't understand how the .lookupPick2 function works and I cannot find any documentation on it. I also don't understand how the controller methods are passing the parameters back to the lookupPick2 considering the parameters in the function are not calling the controller (unless this is something in javascript that I'm not aware of). 

 	// used by the visualforce page to send the link to the right dom element
  	public string getFormTag() {
    	return System.currentPageReference().getParameters().get('frm');
  	}
 
  	// used by the visualforce page to send the link to the right dom element for the text box
  	public string getTextBox() {
    	return System.currentPageReference().getParameters().get('txt');
  	}

 

I did a comparison if I had a <inputField> from the detail page explicitly listed versus if I had the field selected from the input and this is what I found - when the popup generated from an input field, the URL looked like this (this worked on passback):

https://c.cs15.visual.force.com/apex/GFPMCustomLookupSearch?txt=j_id0%3Aj_id2%3Aj_id3&frm=j_id0%3Adetail

 

If I had it generate from the detail page, I it looked like this (this did not work on passback - I would expect urlArr is < 2):

https://c.cs15.visual.force.com/apex/GFPMCustomLookupSearch?txt=&frm=j_id0%3Adetail

 

I suspect the problem actually lies within originalBaseURL itself and how it's split out.

 

So all of this leaves me with a few questions -

1. Is there a way for me to inspect what the base URL is that is being generated prior to it being manipulated with Javascript? How do I do this? 

2. Is there a sandbox or some sort of dev area where I can play around with javascript to be come more familiar with it? Example, I'm curious to see what the results are for each step of this so I can understand why it failed for the URL mentioned above.

				var urlArr = baseURL.split("&");				
				var txtId = '';
				if(urlArr.length > 2) {
					urlArr = urlArr[1].split('=');
					txtId = urlArr[1];
				}

 

Appreciat you help!

Kelly KKelly K

I finally got this working. Here's my code if anyone is interested.

 

Detail page override:

<apex:page standardController="Account">
     <script type="text/javascript"> 
   	
		function openLookup(baseURL, width, modified, searchParam) {
			//Example from acct lookup: https://c.cs15.visual.force.com/_ui/common/data/LookupPage?lknm=acc3j_id0_detail&lktp=001
			//If https://na13.salesforce.com/_ui/common/data/LookupPage?lknm=CF00Na000000A8hD5&lktp=a1i&lksrch=eClinicalWorks is a default URL			
			//then lknm=CF00Na000000A8hD5j_id0_detail&lktp=a1i is considered the BaseURL
			
			var lktp = baseURL.substr(baseURL.length-3,3); //This is the value for lktp (lookup type)
			
			if(lktp == "a1i") {
				var urlArr = baseURL.split("&"); //Results are lknm=CF00Na000000A8hD5j_id0_detail,lktp=a1i			
				var lknm = ''; //lookup name (ie field name)
				var frm = ''; //form tag
				if(urlArr.length > 1) { //if the urlArr array is greater than 1 element then
					urlArr = urlArr[0].split('='); //take the first element and split it - results are lknm,CF00Na000000A8hD5j_id0_detail
					lknm = urlArr[1]; //then take the 2nd element of that split
					frm = urlArr[1].substr(urlArr[1].length-12,12);
				}

				baseURL = "/apex/GFPMCustomLookupSearch?lktp=" + lktp + "&lknm=" + lknm + "&frm=" + frm;		
			}
			
			openPopup(baseURL, "lookup", 350, 480, "width="+width+",height=480,toolbar=no,status=no,directories=no,menubar=no,resizable=yes,scrollable=no", true);
		}		
    </script>     
    <apex:detail id="detail" inlineEdit="true"/>
</apex:page>

 

Lookup Page Override:

<apex:page controller="GFPMCustomLookupSearchController" title="Search" showHeader="false" sideBar="false" tabStyle="Go_Forward_PM_System__c" id="pg">
	<apex:form id="form">
	<apex:actionFunction name="doSearchAF" action="{!searchGFPM}"/>
	
	<apex:outputPanel id="outputPanel" layout="block" style="margin:5px;padding:10px;padding-top:2px;">
		<apex:actionRegion id="actionRegion">
			<apex:outputPanel id="top" layout="block" style="margin:5px;padding:10px;padding-top:2px;">
				<apex:outputLabel id="txtSearchLabel" value="Search" style="font-weight:Bold;padding-right:10px;" for="txtSearch" />
				<apex:inputText id="txtSearch" value="{!searchText}" onkeypress="return noenter(event);"/>
				<span style="padding-left:5px">
					<apex:commandButton id="btnSearch" value="Search" action="{!searchGFPM}" rerender="searchResults"/>
				    <apex:actionStatus id="status" startText="requesting..."/>
				</span>
			</apex:outputPanel>
			
			<apex:outputPanel id="pnlSearchResults" style="margin:10px;height:350px;overflow-Y:auto;" layout="block">
				<apex:pageBlock id="searchResults"> 
					<apex:pageBlockTable value="{!results}" var="result" id="tblResults">
						<apex:column headerValue="Go Forward PM System">
							<apex:outputLink value="javascript&colon;top.window.opener.lookupPick2('{!FormTag}','{!TextBox}_lkid','{!TextBox}','{!result.Id}','{!result.Name}', false)" rendered="{!NOT(ISNULL(result.Id))}">{!result.Name}</apex:outputLink>
						</apex:column>					
				    	<apex:column headerValue="Vendor Account" value="{!result.Vendor_Account__r.Name}"/>
				    	<apex:column headerValue="Status" value="{!result.Status__c}"/>
					</apex:pageBlockTable>
				</apex:pageBlock>
			</apex:outputPanel>	
					
		</apex:actionRegion>			
	</apex:outputPanel>
	</apex:form>

	<script type='text/javascript'>
		//This function allows the user to press enter to search
		function noenter(ev) {
			if (window.event && window.event.keyCode == 13 || ev.which == 13) {
				doSearchAF();
				return false;
			} else {
				return true;
			}
		}
	</script>	
</apex:page>

 

Relevant Controller Code:

public with sharing class GFPMCustomLookupSearchController {

 	// used by the visualforce page to send the link to the right dom element
  	public string getFormTag() {
    	return System.currentPageReference().getParameters().get('frm');
  	}
 
  	// used by the visualforce page to send the link to the right dom element for the text box
  	public string getTextBox() {
    	return System.currentPageReference().getParameters().get('lknm');
  	}	
}

 

 

 

This was selected as the best answer