Saturday, 21 May 2011

Onload Handling

There's been a few posts around page onload handling on the Visualforce discussion board in the last couple of weeks, specifically around breaking existing Salesforce behaviour when adding a custom onload handler.

An example of this is adding a custom onload handler to a Visualforce page that contains a Date input field.

Here's my original page with no custom onload handler:

<apex:page standardController="Opportunity">
   <apex:form >
      <apex:pageBlock mode="detail">
         <apex:pageBlockSection columns="2">
            <apex:inputField value="{!Opportunity.Name}" />
            <apex:inputField value="{!Opportunity.AccountId}" />
            <apex:inputField value="{!Opportunity.CloseDate}" />
            <apex:inputField value="{!Opportunity.Amount}" />
         </apex:pageBlockSection>
      </apex:pageBlock>
   </apex:form>
</apex:page>

As expected, when I click into the Close Date field, the date picker appears and I can select the appropriate date:




However, if I add the following javascript to the bottom of the page, specifying my custom onload handler, things go awry:


<script>
      window.onload=function()
      {
         alert('My onload handler');
      };
</script>
The alert displays as expected:


However, once I've okayed the alert, I find that clicking into the Close Date field no longer displays a date picker.  It looks from this that the date picker is added through a javascript onload handler, which I have  overwritten with my onload function.

The solution is to check for an existing onload function before specifying my own, and if there is one already defined, append my function to that.

Here's the javascript to do exactly that:

function addLoadEvent(func) 
{ 
  var oldonload = window.onload; 
  if (typeof window.onload != 'function') 
  { 
     window.onload = func; 
  } 
  else 
  { 
      window.onload = function()  
      { 
        if (oldonload) 
        { 
           oldonload(); 
        } 
        func(); 
      } 
   } 
} 
  
addLoadEvent(function()  
{ 
   alert('My onload handler');
});

The addLoadEvent function checks if there is an onload handler specified, and if there isn't simply sets it to my function.  If there is one, a new function is created that invokes the existing onload handler followed my function and this is added as the onload handler.

Thus I end up with a chain of functions being executed when the page is loaded, starting with that defined by Salesforce.

6 comments:

  1. Absolutely fantastic!
    Thanks for sharing, I enjoyed the visit. :)

    ReplyDelete
  2. Truly, It makes a sense Bob..

    ReplyDelete
  3. Thank you !
    It helped me a lot..

    ReplyDelete
  4. Excellent, thank you very much!

    ReplyDelete
  5. Hi Bob,

    I have a unique requirement to change Case owner when user clicks on Case number (in list view) from service console.

    I have a embedded VF page on case detail page which when loaded changes the owner and refreshes the primary tab to reflect the change of owner.

    The issue I am facing is that the page refreshes in loop. Not able to stop the loop as every time the page refreshes it's a new context and all variables are initailised. Any help is highly appreciated

    ReplyDelete