diff --git a/CRM/Contribute/Form/Contribution/Main.php b/CRM/Contribute/Form/Contribution/Main.php
index 59bd4a8739a37a295f4760170733f849c134fe3c..50155b9ce51891ac748cd5386ee5eae15bddccb0 100644
--- a/CRM/Contribute/Form/Contribution/Main.php
+++ b/CRM/Contribute/Form/Contribution/Main.php
@@ -47,8 +47,8 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
 
   public $_relatedOrganizationFound;
 
-  public $_onBehalfRequired = 0;
-  public $_onbehalf = 0;
+  public $_onBehalfRequired = FALSE;
+  public $_onbehalf = FALSE;
   public $_paymentProcessors;
   protected $_defaults;
 
@@ -57,6 +57,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
   public $_useForMember;
 
   protected $_ppType;
+  protected $_snippet;
 
   /**
    * Function to set variables up before form is built
@@ -67,23 +68,9 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
   public function preProcess() {
     parent::preProcess();
 
-    $this->_ppType = CRM_Utils_Array::value('type', $_GET);
-    $this->assign('ppType', FALSE);
-    if ($this->_ppType) {
-      $this->assign('ppType', TRUE);
-      return CRM_Core_Payment_ProcessorForm::preProcess($this);
-    }
-
-    //get payPal express id and make it available to template
-    $paymentProcessors = $this->get('paymentProcessors');
-    if (!empty($paymentProcessors)) {
-      foreach ($paymentProcessors as $ppId => $values) {
-        $payPalExpressId = ($values['payment_processor_type'] == 'PayPal_Express') ? $values['id'] : 0;
-        $this->assign('payPalExpressId', $payPalExpressId);
-        if ($payPalExpressId) {
-          break;
-        }
-      }
+    self::preProcessPaymentOptions($this);
+    if ($this->_snippet) {
+      return;
     }
 
     // Make the contributionPageID avilable to the template
@@ -112,38 +99,43 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $this->assign('mainDisplay', $mainDisplay);
     }
 
+    // Possible values for 'is_for_organization':
+    // * 0 - org profile disabled
+    // * 1 - org profile optional
+    // * 2 - org profile required
     $this->_onbehalf = FALSE;
-    if (CRM_Utils_Array::value('is_for_organization', $this->_values)) {
-      $urlParams = "&id={$this->_id}&qfKey={$this->controller->_key}";
-      $this->assign('urlParams', $urlParams);
-      $this->_onbehalf = CRM_Utils_Array::value('onbehalf', $_GET);
-
-      CRM_Contribute_Form_Contribution_OnBehalfOf::preProcess($this);
-      if (CRM_Utils_Array::value('hidden_onbehalf_profile', $_POST) &&
-        (CRM_Utils_Array::value('is_for_organization', $_POST) ||
-          CRM_Utils_Array::value('is_for_organization', $this->_values) == 2
-        )
+    if (!empty($this->_values['is_for_organization'])) {
+      if ($this->_values['is_for_organization'] == 2) {
+        $this->_onBehalfRequired = TRUE;
+      }
+      // Add organization profile if 1 of the following are true:
+      // If the org profile is required
+      if ($this->_onBehalfRequired ||
+        // Or we are building the form for the first time
+        empty($_POST) ||
+        // Or the user has submitted the form and checked the "On Behalf" checkbox
+        !empty($_POST['is_for_organization'])
       ) {
-        CRM_Contribute_Form_Contribution_OnBehalfOf::buildQuickForm($this);
+        $this->_onbehalf = TRUE;
+        CRM_Contribute_Form_Contribution_OnBehalfOf::preProcess($this);
       }
     }
+    $this->assign('onBehalfRequired', $this->_onBehalfRequired);
 
-    if (CRM_Utils_Array::value('id', $this->_pcpInfo) &&
-      CRM_Utils_Array::value('intro_text', $this->_pcpInfo)
-    ) {
+    if (!empty($this->_pcpInfo['id']) && !empty($this->_pcpInfo['intro_text'])) {
       $this->assign('intro_text', $this->_pcpInfo['intro_text']);
     }
-    elseif (CRM_Utils_Array::value('intro_text', $this->_values)) {
+    elseif (!empty($this->_values['intro_text'])) {
       $this->assign('intro_text', $this->_values['intro_text']);
     }
 
     $qParams = "reset=1&id={$this->_id}";
-    if ( $pcpId = CRM_Utils_Array::value( 'pcp_id', $this->_pcpInfo ) ) {
+    if ($pcpId = CRM_Utils_Array::value('pcp_id', $this->_pcpInfo)) {
       $qParams .= "&pcpId={$pcpId}";
     }
-    $this->assign( 'qParams' , $qParams );
+    $this->assign('qParams', $qParams);
 
-    if (CRM_Utils_Array::value('footer_text', $this->_values)) {
+    if (!empty($this->_values['footer_text'])) {
       $this->assign('footer_text', $this->_values['footer_text']);
     }
 
@@ -190,10 +182,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
   }
 
   function setDefaultValues() {
-    if ($this->_onbehalf) {
-      return;
-    }
-
     // check if the user is registered and we have a contact ID
     $contactID = $this->_userID;
 
@@ -386,18 +374,19 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
    * @access public
    */
   public function buildQuickForm() {
+    // Build payment processor form
     if ($this->_ppType) {
-      return CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
+      CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
+      // Return if we are in an ajax callback
+      if ($this->_snippet) {
+        return;
+      }
     }
 
     $config = CRM_Core_Config::singleton();
-    if (CRM_Utils_Array::value('is_for_organization', $this->_values) == 2) {
-      $this->assign('onBehalfRequired', TRUE);
-      $this->_onBehalfRequired = 1;
-    }
+
     if ($this->_onbehalf) {
-      $this->assign('onbehalf', TRUE);
-      return CRM_Contribute_Form_Contribution_OnBehalfOf::buildQuickForm($this);
+      CRM_Contribute_Form_Contribution_OnBehalfOf::buildQuickForm($this);
     }
 
     $this->applyFilter('__ALL__', 'trim');
@@ -648,16 +637,12 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       CRM_Core_BAO_Location::getValues($entityBlock, $this->_defaults);
     }
 
-    if ($this->_values['is_for_organization'] != 2) {
+    if (!$this->_onBehalfRequired) {
       $this->addElement('checkbox', 'is_for_organization',
         $this->_values['for_organization'],
         NULL, array('onclick' => "showOnBehalf( );")
       );
     }
-    else {
-      $this->assign('onBehalfRequired', TRUE);
-      $this->_onBehalfRequired = 1;
-    }
 
     $this->assign('is_for_organization', TRUE);
     $this->assign('urlPath', 'civicrm/contribute/transact');
@@ -1367,5 +1352,45 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact', "_qf_ThankYou_display=1&qfKey=$qfKey", TRUE, NULL, FALSE));
     }
   }
+
+  /**
+   * Handle Payment Processor switching
+   * For contribution and event registration forms
+   */
+  static function preProcessPaymentOptions(&$form) {
+    $form->_snippet = CRM_Utils_Array::value('snippet', $_GET);
+    $form->assign('snippet', $form->_snippet);
+
+    $paymentProcessors = $form->get('paymentProcessors');
+    $form->assign('ppType', FALSE);
+    $form->_ppType = NULL;
+    if (!empty($paymentProcessors)) {
+      // Fetch type during ajax request
+      if (isset($_GET['type']) && $form->_snippet) {
+        $form->_ppType = $_GET['type'];
+      }
+      // Set default payment processor
+      else {
+        foreach ($paymentProcessors as $values) {
+          if (!empty($values['is_default']) || count($paymentProcessors) == 1) {
+            $form->_ppType = $values['id'];
+          }
+        }
+      }
+      if ($form->_ppType) {
+        $form->assign('ppType', TRUE);
+        CRM_Core_Payment_ProcessorForm::preProcess($form);
+      }
+
+      //get payPal express id and make it available to template
+      foreach ($paymentProcessors as $ppId => $values) {
+        $payPalExpressId = ($values['payment_processor_type'] == 'PayPal_Express') ? $values['id'] : 0;
+        $form->assign('payPalExpressId', $payPalExpressId);
+        if ($payPalExpressId) {
+          break;
+        }
+      }
+    }
+  }
 }
 
diff --git a/CRM/Core/Payment/ProcessorForm.php b/CRM/Core/Payment/ProcessorForm.php
index 2fa9e329439b3bbca9c14908956b9767003c5cc6..eb51b452b890c97cc4706eb80a97dbedb4910889 100644
--- a/CRM/Core/Payment/ProcessorForm.php
+++ b/CRM/Core/Payment/ProcessorForm.php
@@ -102,13 +102,14 @@ class CRM_Core_Payment_ProcessorForm {
 
       CRM_Core_Error::fatal(ts('This contribution page is configured to support separate contribution and membership payments. This %1 plugin does not currently support multiple simultaneous payments, or the option to "Execute real-time monetary transactions" is disabled. Please contact the site administrator and notify them of this error',
           array(1 => $form->_paymentProcessor['payment_processor_type'])
-        ));
+        )
+      );
     }
 
     $profileAddressFields = $form->get('profileAddressFields');
-    if (!empty( $profileAddressFields)){
+    if (!empty( $profileAddressFields)) {
       $form->assign('profileAddressFields', $profileAddressFields);
-  }
+    }
   }
 
   static function buildQuickform(&$form) {
diff --git a/CRM/Event/Form/Registration/Register.php b/CRM/Event/Form/Registration/Register.php
index edf0ca45e4980e3ae571770d44b152657deac17f..2bdd91f75fc4f7b3f8e7129e3ce4aafb0c4f128e 100644
--- a/CRM/Event/Form/Registration/Register.php
+++ b/CRM/Event/Form/Registration/Register.php
@@ -68,7 +68,8 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
    */
   public $_skipDupeRegistrationCheck = FALSE;
 
-  protected $_ppType;
+  public $_ppType;
+  public $_snippet;
 
   /**
    * Function to set variables up before form is built
@@ -78,24 +79,10 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
    */
   function preProcess() {
     parent::preProcess();
-    $this->_ppType = CRM_Utils_Array::value('type', $_GET);
-    $this->assign('ppType', FALSE);
-    if ($this->_ppType) {
-      $this->assign('ppType', TRUE);
-      return CRM_Core_Payment_ProcessorForm::preProcess($this);
-    }
-
-    //get payPal express id and make it available to template
-    $paymentProcessors = $this->get('paymentProcessors');
-    $this->assign('payPalExpressId', 0);
-    if (!empty($paymentProcessors)) {
-      foreach ($paymentProcessors as $ppId => $values) {
-        $payPalExpressId = ($values['payment_processor_type'] == 'PayPal_Express') ? $values['id'] : 0;
-        $this->assign('payPalExpressId', $payPalExpressId);
-        if ($payPalExpressId) {
-          break;
-        }
-      }
+
+    CRM_Contribute_Form_Contribution_Main::preProcessPaymentOptions($this);
+    if ($this->_snippet) {
+      return;
     }
 
     //CRM-4320.
@@ -156,7 +143,7 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
    * @return None
    */
   function setDefaultValues() {
-    if ($this->_ppType && !($this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_FORM)) {
+    if ($this->_ppType && $this->_snippet && !($this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_FORM)) {
       // see function comment block for explanation of this
       return;
     }
@@ -353,8 +340,13 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
    * @access public
    */
   public function buildQuickForm() {
+    // Build payment processor form
     if ($this->_ppType) {
-      return CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
+      CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
+      // Return if we are in an ajax callback
+      if ($this->_snippet) {
+        return;
+      }
     }
 
     $contactID = parent::getContactID();
@@ -563,7 +555,7 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
    */
   static public function buildAmount(&$form, $required = TRUE, $discountId = NULL) {
     //if payment done, no need to build the fee block.
-    if (isset($form->_paymentId) && $form->_paymentId) {
+    if (!empty($form->_paymentId)) {
       //fix to diaplay line item in update mode.
       $form->assign('priceSet', isset($form->_priceSet) ? $form->_priceSet : NULL);
       return;
diff --git a/templates/CRM/Contribute/Form/Contribution/Main.tpl b/templates/CRM/Contribute/Form/Contribution/Main.tpl
index 7c560f0d53e4d6e4de21d6695ee19953e9675069..502dcfca8cba90ec757b48c67d45d0ff02d33a37 100644
--- a/templates/CRM/Contribute/Form/Contribution/Main.tpl
+++ b/templates/CRM/Contribute/Form/Contribution/Main.tpl
@@ -23,7 +23,8 @@
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
 *}
-{if $ppType}
+{* Callback snippet: Load payment processor *}
+{if $ppType and $snippet}
 {include file="CRM/Core/BillingBlock.tpl" context="front-end"}
   {if $is_monetary}
   {* Put PayPal Express button after customPost block since it's the submit button in this case. *}
@@ -51,8 +52,7 @@
     {/if}
   {/if}
 
-{elseif $onbehalf}
-  {include file=CRM/Contribute/Form/Contribution/OnBehalfOf.tpl}
+{* Main Form *}  
 {else}
   {literal}
   <script type="text/javascript">
@@ -179,8 +179,9 @@
   {/if}
 
   {if $is_for_organization}
-  <div id='onBehalfOfOrg' class="crm-section"></div>
-  {include file=CRM/Contribute/Form/Contribution/OnBehalfOf.tpl}
+  <div id='onBehalfOfOrg' class="crm-section">
+    {include file=CRM/Contribute/Form/Contribution/OnBehalfOf.tpl}
+  </div>
   {/if}
 
   {* User account registration option. Displays if enabled for one of the profiles on this page. *}
@@ -271,7 +272,8 @@
   {/if}
 
   {if $form.payment_processor.label}
-  <fieldset class="crm-group payment_options-group">
+  {* PP selection only works with JS enabled, so we hide it initially *}
+  <fieldset class="crm-group payment_options-group" style="display:none;">
     <legend>{ts}Payment Options{/ts}</legend>
     <div class="crm-section payment_processor-section">
       <div class="label">{$form.payment_processor.label}</div>
@@ -294,7 +296,12 @@
   </fieldset>
   {/if}
 
-  <div id="billing-payment-block"></div>
+  <div id="billing-payment-block">
+    {* If we have a payment processor, load it - otherwise it happens via ajax *}
+    {if $ppType}
+      {include file="CRM/Contribute/Form/Contribution/Main.tpl" snippet=4}
+    {/if}
+  </div>
   {include file="CRM/common/paymentBlock.tpl"}
 
   <div class="crm-group custom_post_profile-group">
diff --git a/templates/CRM/Contribute/Form/Contribution/OnBehalfOf.tpl b/templates/CRM/Contribute/Form/Contribution/OnBehalfOf.tpl
index b50b698f24e50ec73c98cfe0efe925975de02092..a3aece0358cac10a5ad73ce39c23c0f28414ebf0 100644
--- a/templates/CRM/Contribute/Form/Contribution/OnBehalfOf.tpl
+++ b/templates/CRM/Contribute/Form/Contribution/OnBehalfOf.tpl
@@ -23,7 +23,13 @@
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
 *}
-{* This file provides the HTML for the on-behalf-of form. Can also be used for related contact edit form. *}
+{**
+ * This file provides the HTML for the on-behalf-of form. 
+ * Also used for related contact edit form.
+ * FIXME: This is way more complex than it needs to be
+ * FIXME: About 1% of this javascript is needed for contribution forms
+ * FIXME: Why are we not just using the dynamic form tpl to display this profile?
+ *}
 
 {if $buildOnBehalfForm or $onBehalfRequired}
 <fieldset id="for_organization" class="for_organization-group">
@@ -127,19 +133,13 @@
 
 {literal}
 <script type="text/javascript">
-  var reset            = {/literal}"{$reset}"{literal};
-  var onBehalfRequired = {/literal}"{$onBehalfRequired}"{literal};
-  var mainDisplay      = {/literal}"{$mainDisplay}"{literal};
-  var mode             = {/literal}"{$mode}"{literal};
   cj( "div#id-onbehalf-orgname-help").hide( );
 
-  if (mainDisplay) {
-    showOnBehalf(false);
-  }
+  showOnBehalf({/literal}"{$onBehalfRequired}"{literal});
 
   cj( "#mode" ).hide( );
   cj( "#mode" ).attr( 'checked', 'checked' );
-  if ( cj( "#mode" ).attr( 'checked' ) && !reset ) {
+  if ( cj( "#mode" ).attr( 'checked' ) && !{/literal}"{$reset}"{literal} ) {
     $text = ' {/literal}{ts escape="js"}Use existing organization{/ts}{literal} ';
     cj( "#createNewOrg" ).text( $text );
     cj( "#mode" ).removeAttr( 'checked' );
@@ -147,29 +147,28 @@
 
 function showOnBehalf(onBehalfRequired) {
   if ( cj( "#is_for_organization" ).attr( 'checked' ) || onBehalfRequired ) {
-    cj( "#for_organization" ).html( '' );
-    var urlPath = {/literal}"{crmURL p=$urlPath h=0 q='snippet=4&onbehalf=1'}"{literal};
-    urlPath     = urlPath  + {/literal}"{$urlParams}"{literal};
-    if ( mode == 'test' ) {
-      urlPath = urlPath  + '&action=preview';
-    }
-    if ( reset ) {
-      urlPath = urlPath + '&reset=' + reset;
+    var urlPath = {/literal}"{crmURL p=$urlPath h=0 q='snippet=4&onbehalf=1'}";
+    urlPath += "{$urlParams}";
+    {if $mode eq 'test'}
+      urlPath += '&action=preview';
+    {/if}
+    {if $reset}
+      urlPath += '&reset={$reset}';
+    {/if}{literal}
+    cj("#onBehalfOfOrg").show();
+    if (cj("#onBehalfOfOrg *").length < 1) {
+      cj.ajax({
+        url     : urlPath,
+        global  : false,
+        async   : false,
+        success : function ( content ) {
+          cj( "#onBehalfOfOrg" ).html( content );
+        }
+      });
     }
-
-    cj.ajax({
-      url     : urlPath,
-      async   : false,
-      global  : false,
-      success : function ( content ) {
-        cj( "#onBehalfOfOrg" ).html( content );
-      }
-    });
   }
   else {
-    cj( "#onBehalfOfOrg" ).html('');
-    cj( "#for_organization" ).html( '' );
-    return;
+    cj("#onBehalfOfOrg").hide();
   }
 }
 
@@ -193,14 +192,13 @@ function resetValues( filter ) {
 
 function createNew( ) {
   if (cj("#mode").attr('checked')) {
-    textMessage = ' {/literal}{ts escape="js"}Use existing organization{/ts}{literal} ';
+    var textMessage = ' {/literal}{ts escape="js"}Use existing organization{/ts}{literal} ';
     cj("#onbehalf_organization_name").removeAttr('readonly');
     cj("#mode").removeAttr('checked');
-
     resetValues( false );
   }
   else {
-    textMessage = ' {/literal}{ts escape="js"}Enter a new organization{/ts}{literal} ';
+    var textMessage = ' {/literal}{ts escape="js"}Enter a new organization{/ts}{literal} ';
     cj("#mode").attr('checked', 'checked');
     setOrgName( );
   }
diff --git a/templates/CRM/Event/Form/Registration/Register.tpl b/templates/CRM/Event/Form/Registration/Register.tpl
index 74366a5997bc1b11db48bd4d916487476ab17238..059bdbc4d3b0ef4adfeee0e687fa6506a71f8bc1 100644
--- a/templates/CRM/Event/Form/Registration/Register.tpl
+++ b/templates/CRM/Event/Form/Registration/Register.tpl
@@ -23,7 +23,8 @@
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
 *}
-{if $ppType}
+{* Callback snippet: Load payment processor *}
+{if $ppType and $snippet}
   {include file="CRM/Core/BillingBlock.tpl" context="front-end"}
 
 <div id="paypalExpress">
@@ -144,7 +145,7 @@
 {include file="CRM/UF/Form/Block.tpl" fields=$customPre}
 
 {if $form.payment_processor.label}
-<fieldset class="crm-group payment_options-group">
+<fieldset class="crm-group payment_options-group" style="display:none;">
   <legend>{ts}Payment Options{/ts}</legend>
   <div class="crm-section payment_processor-section">
     <div class="label">{$form.payment_processor.label}</div>
@@ -154,7 +155,12 @@
 </fieldset>
 {/if}
 
-<div id="billing-payment-block"></div>
+<div id="billing-payment-block">
+  {* If we have a payment processor, load it - otherwise it happens via ajax *}
+  {if $ppType}
+    {include file="CRM/Event/Form/Registration/Register.tpl" snippet=4}
+  {/if}
+</div>
 {include file="CRM/common/paymentBlock.tpl"}
 
 {include file="CRM/UF/Form/Block.tpl" fields=$customPost}
diff --git a/templates/CRM/common/paymentBlock.tpl b/templates/CRM/common/paymentBlock.tpl
index f1792d34507e68d6ecec9c023c044f1aba241ca6..6d75285acbbae4fe638f50276e738584fcfe3f01 100644
--- a/templates/CRM/common/paymentBlock.tpl
+++ b/templates/CRM/common/paymentBlock.tpl
@@ -60,17 +60,7 @@ function buildPaymentBlock( type ) {
 }
 
 cj( function() {
-    var processorTypeObj = cj('input[name="payment_processor"]');
-
-    if ( processorTypeObj.attr('type') == 'hidden' ) {
-        var processorTypeValue = processorTypeObj.val( );
-    } else {
-        var processorTypeValue = processorTypeObj.filter(':checked').val();
-    }
-
-    if ( processorTypeValue ) {
-        buildPaymentBlock( processorTypeValue );
-    }
+    cj('.crm-group.payment_options-group').show();
 
     cj('input[name="payment_processor"]').change( function() {
         buildPaymentBlock( cj(this).val() );