# HG changeset patch
# Parent 493f15eaa1c89e39510e90129042d52f40ef57f0
# Date 1330285022 18000
# User gpaddock
Correct the issue described in #1293166 where HS callbacks for the "Create" and "Cancel" buttons trigger full form submission. The cause is that the buttons are not part of the form when it is being processed, so FAPI assumes that the "Save" button was clicked.

diff --git a/hierarchical_select.module b/hierarchical_select.module
--- a/hierarchical_select.module
+++ b/hierarchical_select.module
@@ -556,6 +556,50 @@
 
 function _hs_process_render_create_new_item($element, $hierarchy) {
   $creating_new_item = FALSE;
+
+  /* This container and the "Create" / "Cancel" buttons must always be part of
+   * the form, even when HS is not in create mode, in order for AJAX submit
+   * callbacks on the "Create" and "Cancel" buttons to be processed correctly.
+   *
+   * Basically, FAPI looks through each of the buttons in the form to determine
+   * which one was clicked. If it can't find the responsible button, it
+   * assumes it was the first button in the form. This is problematic when the
+   * user clicks on the "Create" or "Cancel" buttons because we only want them
+   * to show up when HS is in create mode. To fix this, we always render the
+   * buttons as part of the form, then disable access to them in an
+   * "#after_build" callback.
+   *
+   * This might not be necessary if we used D7's native AJAX callback function,
+   * ajax_form_callback().
+   */
+  $element['hierarchical_select']['create_new_item'] = array(
+    '#prefix'       => '<div class="create-new-item">',
+    '#suffix'  	    => '</div>',
+
+    '#after_build'	=> array('hierarchical_select_create_new_item_after_build'),
+  );
+
+  // TODO: Port to use built-in D7 AJAX callback?
+  $element['hierarchical_select']['create_new_item']['create'] = array(
+    '#type'                     => 'submit',
+    '#value'	                  => t('Create'),
+    '#attributes'               => array('class' => array('create-new-item-create')),
+
+    '#limit_validation_errors'	=> array($element['#parents']),
+    '#validate'								  => array(),
+    '#submit'									  => array('hierarchical_select_ajax_update_submit'),
+  );
+
+  $element['hierarchical_select']['create_new_item']['cancel'] = array(
+    '#type'	                    => 'button',
+    '#value'                    => t('Cancel'),
+    '#attributes'	              => array('class' => array('create-new-item-cancel')),
+    
+    '#limit_validation_errors'	=> array($element['#parents']),
+    '#validate'								  => array(),
+    '#submit'									  => array('hierarchical_select_ajax_update_submit'),
+  );
+
   if (isset($element['#value']['hierarchical_select']['selects'])) {
     foreach ($element['#value']['hierarchical_select']['selects'] as $depth => $value) {
       if (($value == 'create_new_item') && _hierarchical_select_create_new_item_is_allowed($element['#config'], $depth)) {
@@ -573,11 +617,6 @@
           }
         }
 
-        $element['hierarchical_select']['create_new_item'] = array(
-          '#prefix' => '<div class="create-new-item">',
-          '#suffix' => '</div>',
-        );
-
         $item_type_depth = ($value == 'create_new_item') ? $depth : $depth + 1;
         $item_type = (!empty($config['editability']['item_types'][$item_type_depth])) ? t($config['editability']['item_types'][$item_type_depth]) : t('item');
 
@@ -593,26 +632,36 @@
           // Prevent the textfield from being wrapped in a div. This
           // simplifies the CSS and JS code.
           '#theme_wrappers' => array(),
-        );
-
-        $element['hierarchical_select']['create_new_item']['create'] = array(
-          '#type' => 'button',
-          '#value' => t('Create'),
-          '#attributes' => array('class' => array('create-new-item-create')),
-        );
-
-        $element['hierarchical_select']['create_new_item']['cancel'] = array(
-          '#type' => 'button',
-          '#value' => t('Cancel'),
-          '#attributes' => array('class' => array('create-new-item-cancel')),
+          
+          // Place above "Create" / "Cancel" buttons
+          '#weight' => -1,
         );
       }
     }
   }
 
+  $element['hierarchical_select']['create_new_item']['#creating_new_item'] = $creating_new_item;
+
   return array($element, $creating_new_item);
 }
 
+/**
+ * <p>After-build callback for the "create_new_item" element of HS forms.</p>
+ *
+ * <p>This disables access to the add element form unless the HS widget is in
+ * create mode.
+ *
+ * @param		array	$element
+ * 								The "create_new_item" form element.
+ *
+ * @return 	array	The modified form element, with appropriate access set.
+ */
+function hierarchical_select_create_new_item_after_build(array $element) {
+  $element['#access']  = $element['#creating_new_item'];
+
+  return $element;
+}
+
 function _hs_process_render_dropbox($element, $hsid, $creating_new_item, $dropbox, $form_state) {
   $config = $element['#config'];
 
