Browse Source

Got properties form elements behaving correctly on anlaysis module

Stephen Ficklin 11 years ago
parent
commit
31f2204ff6

+ 289 - 187
tripal_analysis/includes/tripal_analysis.form.inc

@@ -7,25 +7,45 @@
  */
 function chado_analysis_form($node, &$form_state) {
   $form = array();
-
-  // if the organism is part of the node object then we are editing. If not we are inserting
+  
+  // Default values can come in the following ways:
+  //
+  // 1) as elements of the $node object.  This occurs when editing an existing analysis
+  // 2) in the $form_state['values'] array which occurs on a failed validation or 
+  //    ajax callbacks from non submit form elements
+  // 3) in the $form_state['input'[ array which occurs on ajax callbacks from submit 
+  //    form elements and the form is being rebuilt
+  //
+  // set form field defaults
   $analysis_id = null;
+  $analysisname   = '';
+  $program        = '';
+  $programversion = '';
+  $algorithm      = '';
+  $sourcename     = '';
+  $sourceversion  = '';
+  $sourceuri      = '';
+  $timeexecuted   = '';
+  $description    = '';
+  $d_removed      = array(); // lists removed properties
+  $num_new        = 0;  // the number of new rows
+  
+  // if we are editing an existing node then the analysis is already part of the node
   if (property_exists($node, 'analysis')) {
-
     $analysis = $node->analysis;
     $analysis = tripal_core_expand_chado_vars($analysis, 'field', 'analysis.description');
     $analysis_id = $analysis->analysis_id;
 
     // get form defaults
-    $analysisname   = property_exists($node, 'analysisname')   ? property_exists($node, 'analysisname')   : $analysis->analysisname;
-    $program        = property_exists($node, 'program')        ? property_exists($node, 'program')        : $analysis->program;
-    $programversion = property_exists($node, 'programversion') ? property_exists($node, 'programversion') : $analysis->programversion;
-    $algorithm      = property_exists($node, 'algorithm')      ? property_exists($node, 'algorithm')      : $analysis->algorithm;
-    $sourcename     = property_exists($node, 'sourcename')     ? property_exists($node, 'sourcename')     : $analysis->sourcename;
-    $sourceversion  = property_exists($node, 'sourceversion')  ? property_exists($node, 'sourceversion')  : $analysis->sourceversion;
-    $sourceuri      = property_exists($node, 'sourceuri')      ? property_exists($node, 'sourceuri')      : $analysis->sourceuri;
-    $timeexecuted   = property_exists($node, 'timeexecuted')   ? property_exists($node, 'timeexecuted')   : $analysis->timeexecuted;
-    $description    = property_exists($node, 'description')    ? property_exists($node, 'description')    : $analysis->description;
+    $analysisname   = $analysis->analysisname;
+    $program        = $analysis->program;
+    $programversion = $analysis->programversion;
+    $algorithm      = $analysis->algorithm;
+    $sourcename     = $analysis->sourcename;
+    $sourceversion  = $analysis->sourceversion;
+    $sourceuri      = $analysis->sourceuri;
+    $timeexecuted   = $analysis->timeexecuted;
+    $description    = $analysis->description;
      
     // set the organism_id in the form
     $form['analysis_id'] = array(
@@ -33,18 +53,37 @@ function chado_analysis_form($node, &$form_state) {
       '#value' => $analysis->analysis_id,
     );
   }
-  else {
-    $analysisname   = property_exists($node, 'analysisname')   ? property_exists($node, 'analysisname')   : '';
-    $program        = property_exists($node, 'program')        ? property_exists($node, 'program')        : '';
-    $programversion = property_exists($node, 'programversion') ? property_exists($node, 'programversion') : '';
-    $algorithm      = property_exists($node, 'algorithm')      ? property_exists($node, 'algorithm')      : '';
-    $sourcename     = property_exists($node, 'sourcename')     ? property_exists($node, 'sourcename')     : '';
-    $sourceversion  = property_exists($node, 'sourceversion')  ? property_exists($node, 'sourceversion')  : '';
-    $sourceuri      = property_exists($node, 'sourceuri')      ? property_exists($node, 'sourceuri')      : '';
-    $timeexecuted   = property_exists($node, 'timeexecuted')   ? property_exists($node, 'timeexecuted')   : '';
-    $description    = property_exists($node, 'description')    ? property_exists($node, 'description')    : '';
+  // if we are re constructing the form from a failed validation or ajax callback 
+  // then use the $form_state['values'] values
+  if (array_key_exists('values', $form_state)) {
+    $analysisname   = $form_state['values']['analysisname'];
+    $program        = $form_state['values']['program'];
+    $programversion = $form_state['values']['programversion'];
+    $algorithm      = $form_state['values']['algorithm'];
+    $sourcename     = $form_state['values']['sourcename'];
+    $sourceversion  = $form_state['values']['sourceversion'];
+    $sourceuri      = $form_state['values']['sourceuri'];
+    $timeexecuted   = $form_state['values']['timeexecuted'];
+    $description    = $form_state['values']['description'];
+    $d_removed      = $form_state['values']['removed'];
+    $num_new        = $form_state['values']['num_new'] ? $form_state['values']['num_new'] : 0;
   }
-  
+  // if we are re building the form from after submission (from ajax call) then
+  // the values are in the $form_state['input'] array
+  if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
+    $analysisname   = $form_state['input']['analysisname'];
+    $program        = $form_state['input']['program'];
+    $programversion = $form_state['input']['programversion'];
+    $algorithm      = $form_state['input']['algorithm'];
+    $sourcename     = $form_state['input']['sourcename'];
+    $sourceversion  = $form_state['input']['sourceversion'];
+    $sourceuri      = $form_state['input']['sourceuri'];
+    $timeexecuted   = $form_state['input']['timeexecuted'];
+    $description    = $form_state['input']['description'];
+    $d_removed      = $form_state['input']['removed'];
+    $num_new        = $form_state['input']['num_new'] ? $form_state['input']['num_new'] : 0;
+  }
+
   $form['title']= array(
     '#type' => 'value',
     '#default_value' => $node->title,
@@ -171,26 +210,17 @@ function chado_analysis_form($node, &$form_state) {
     $properties_list[$prop->cvterm_id] = $prop;
   }
   
-  // initialize our arrays of properties and properties removed
-  $d_properties = array();
-  $d_removed = array();
+  // this array keeps track of all properties we have and allows the functions
+  // below to select the next rank if a property is dupliated
+  $ranks = array();
  
-  // on AJAX callbacks we want to keep a list of all the properties that have been removed
-  // we'll store this info in a hidden field and retrieve it here
-  if (array_key_exists('values', $form_state) and array_key_exists('removed', $form_state['values'])) {
-    // add the removed item to our array and get the number of new fields that have been added
-    $d_removed = $form_state['values']['removed'];
-    $num_new = $form_state['values']['num_new'] ? $form_state['values']['num_new'] : 0;
-  }
-  
   // add in the properties from the Chado analysisprop table (only pertains to existing analyses)
-  $num_properties = 0;
   if ($analysis_id) {
-    $num_properties += chado_analysis_node_form_add_analysisprop_table_props($form, $form_state, $analysis_id, $d_properties, $d_removed);
+    chado_analysis_node_form_add_analysisprop_table_props($form, $form_state, $analysis_id, $ranks, $d_removed);
   }
   
   // add in any new properties that have been added by the user through an AHAH callback
-  $num_new = chado_analysis_node_form_add_new_props($form, $form_state, $d_properties, $d_removed);
+  chado_analysis_node_form_add_new_props($form, $form_state, $ranks, $d_removed);
 
   // add an empty row of field to allow for addition of a new property
   chado_analysis_node_form_add_new_empty_props($form, $form_state, $properties_select);
@@ -198,30 +228,37 @@ function chado_analysis_form($node, &$form_state) {
   $form['#theme'] = 'chado_analysis_form';
   return $form;
 }
-
 /**
- *
- *
+ * This function is responsible for adding a blank row to the properties table for
+ * adding a new property.
  */
 function chado_analysis_node_form_add_new_empty_props(&$form, &$form_state, $properties_select) {
-  
+
+  // get the field defaults either from $form_state['values'] or $form_state['input']
   $description = '';
-  if (array_key_exists('values', $form_state) and 
-      array_key_exists('new_id', $form_state['values'])) {
-    
+  $text = '';
+  $id = 0;
+  if (array_key_exists('values', $form_state)) {
     $id = $form_state['values']['new_id'];
+    $text = $form_state['values']['new_value'];
+  }
+  
+  // if we have a property ID then get it's definition to display to the user
+  if($id) { 
     $values = array('cvterm_id' => $id);
     $cvterm = tripal_core_chado_select('cvterm', array('definition'), $values);
-    
+  
     if ($cvterm[0]->definition) {
       $description = $cvterm[0]->definition;
     }
   }
+  $rows = 1;
   
   // add one more blank set of property fields
   $form['properties']['table']['new']["new_id"] = array(
     '#type'          => 'select',
     '#options'       => $properties_select,
+    '#value'         => $id,
     '#ajax' => array(
       'callback' => "tripal_analysis_property_get_description",
       'wrapper'  => 'tripal-analysis-new_value',
@@ -230,116 +267,162 @@ function chado_analysis_node_form_add_new_empty_props(&$form, &$form_state, $pro
     ),
   );
   $form['properties']['table']['new']["new_value"] = array(
-    '#type'          => 'textarea',
-    '#default_value' => '',
-    '#cols'          => 5,
-    '#rows'          => 2,
-    '#prefix'        => '<div id="tripal-analysis-new_value">',
-    '#description'   => $description,
-    '#sffix'          => '</div>',
+    '#type'           => 'textarea',
+    '#value'          => $text,
+    '#cols'           => 50,
+    '#rows'           => $rows,
+    '#prefix'         => '<div id="tripal-analysis-new_value">',
+    '#description'    => $description,
+    '#suffix'         => '</div>',
   );
   
   $form['properties']['table']['new']["add"] = array(
-    '#type'           => 'image_button',
-    '#default_value'  => t('Add'),
-    '#src'            => drupal_get_path('module', 'tripal_core') . '/theme/images/add.png',
-    '#ajax' => array(
-      'callback' => "tripal_analysis_property_add",
+    '#type'    => 'button',
+    '#value'   => t('Add'),
+    '#name'    => 'add',
+    '#ajax'      => array(
+      'callback' => "tripal_analysis_property_ajax_update",
       'wrapper'  => 'tripal-analysis-edit-properties-table',
       'effect'   => 'fade',
-      'event'    => 'click',
       'method'   => 'replace',
+      'prevent'  => 'click'
     ),
-    '#attributes' => array('onClick' => 'return false;'),
+    // When this button is clicked, the form will be validated and submitted. 
+    // Therefore, we set custom submit and validate functions to override the
+    // default form submit.  In the validate function we set the form_state
+    // to rebuild the form so the submit function never actually gets called,
+    // but we need it or Drupal will run the default validate anyway.
+    // we also set #limit_validation_errors to empty so fields that
+    // are required that don't have values won't generate warnings. 
+    '#submit'   => array('chado_anslysis_node_form_props_button_submit'),
+    '#validate' => array('chado_anslysis_node_form_props_button_validate'),
+    '#limit_validation_errors' => array(array('new_id')),
   );
-  
 }
-/*
- *
-*/
-function chado_analysis_node_form_add_new_props(&$form, &$form_state, &$d_properties, &$d_removed) {
+/**
+ * This function is used to rebuild the form if an ajax call is made vai a button.
+ * The button causes the form to be submitted. We don't want this so we override
+ * the validate and submit routines on the form button. Therefore, this function
+ * only needs to tell Drupal to rebuild the form
+ */
+function chado_anslysis_node_form_props_button_validate($form, &$form_state){
+  if (array_key_exists('triggering_element', $form_state) and 
+      $form_state['triggering_element']['#name'] == 'add' and
+      $form_state['input']['new_id'] == 0 ){
+    form_set_error('new_id', "Please specify a property type");
+    return;
+  }
+  $form_state['rebuild'] = TRUE; 
+}
+/**
+ * This function is just a dummy to override the default form submit on ajax calls for buttons
+ */
+function chado_anslysis_node_form_props_button_submit($form, &$form_state){
+  // do nothing
+}
+/**
+ * This adds 
+ */
+function chado_analysis_node_form_add_new_props(&$form, &$form_state, &$ranks, &$d_removed) {
    
-  // first, add in all of the new properties that were added through a previous AHAH callback
+  // set some default values
   $j = 0;
   $num_properties = 0;
-
-  // we need to find the
+  
+  $values = array();
   if (array_key_exists('values', $form_state)) {
-    foreach ($form_state['values'] as $element_name => $value) {
-      if (preg_match('/new_value-(\d+)-(\d+)/', $element_name, $matches)) {
-        $new_id = $matches[1];
-        $rank = $matches[2];
-
-        // skip any properties that the user requested to delete through a previous
-        // AHAH callback or through the current AHAH callback
-        if ($d_removed["$new_id-$rank"]) {
-          continue;
-        }
-        if ($form_state['post']['remove-' . $new_id . '-' . $rank]) {
-          $d_removed["$new_id-$rank"] = 1;
-          continue;
-        }
-
-        // get this new_id information
-        $cvterm = tripal_core_chado_select('cvterm', array('name', 'definition'), array('cvterm_id' => $new_id));
-
-        // add it to the $d_properties array
-        $d_properties[$new_id][$rank]['name']  = $cvterm->name;
-        $d_properties[$new_id][$rank]['id']    = $new_id;
-        $d_properties[$new_id][$rank]['value'] = $value;
-        $d_properties[$new_id][$rank]['definition']  = $cvterm->definition;
-        $num_properties++;
-
-        // determine how many rows we need in the textarea
-        $rows = 1;
-
-        // add the new fields
-        $form['properties']['table']['new'][$new_id][$rank]["new_id-$new_id-$rank"] = array(
-          '#type'          => 'item',
-          '#value'         => $cvterm[0]->name
-        );
-        $form['properties']['table']['new'][$new_id][$rank]["new_value-$new_id-$rank"] = array(
-          '#type'          => 'textarea',
-          '#default_value' => $value,
-          '#cols'          => 50,
-          '#rows'          => $rows,
-          '#description'   => $cvterm->definition,
-        );
-
-        $form['properties']['table']['new'][$new_id][$rank]["remove-$new_id-$rank"] = array(
-          '#type'         => 'image_button',
-          '#value'        => t('Remove'),
-          '#src'          => drupal_get_path('theme', 'tripal') . '/images/minus.png',          
-          '#ajax' => array(
-            'callback' => "tripal_analysis/properties/minus/$new_id/$rank",
-            'wrapper'  => 'tripal-analysis-edit-properties-table',
-            'effect'   => 'fade',
-            'event'    => 'click',
-            'method'   => 'replace',
-          ),
-          '#attributes' => array('onClick' => 'return false;'),
-        );
+    $values = $form_state['values'];
+  }
+  if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
+    $values = $form_state['input'];
+  }
+  
+  // first, add in all of the new properties that were added previously via this form
+  foreach ($values as $element_name => $value) {
+    if (preg_match('/new_value-(\d+)-(\d+)/', $element_name, $matches)) {
+      $new_id = $matches[1];
+      $rank = $matches[2];
+  
+      // skip any properties that the user requested to delete through a previous
+      // ajax callback or through the current ajax callback
+      if (array_key_exists("$new_id-$rank", $d_removed)) {
+        continue;
+      }
+      if (array_key_exists('triggering_element', $form_state) and 
+         $form_state['triggering_element']['#name'] == 'remove-' . $new_id . '-' . $rank) {
+        $d_removed["$new_id-$rank"] = 1;
+        continue;
       }
+  
+      // get this new_id information
+      $args = array('cvterm_id' => $new_id);
+      $cvterm = tripal_core_chado_select('cvterm', array('name', 'definition'), $args);
+
+      // add it to the $ranks array
+      $ranks[$new_id][$rank]['name']  = $cvterm[0]->name;
+      $ranks[$new_id][$rank]['id']    = $new_id;
+      $ranks[$new_id][$rank]['value'] = $value;
+      $ranks[$new_id][$rank]['definition']  = $cvterm[0]->definition;
+      $num_properties++;
+  
+      // determine how many rows we need in the textarea
+      $rows = 1;
+      // add the new fields
+      $form['properties']['table']['new'][$new_id][$rank]["new_id-$new_id-$rank"] = array(
+        '#markup' => $cvterm[0]->name
+      );
+      $form['properties']['table']['new'][$new_id][$rank]["new_value-$new_id-$rank"] = array(
+        '#type'          => 'textarea',
+        '#default_value' => $value,
+        '#cols'          => 50,
+        '#rows'          => $rows,
+        '#description'   => $cvterm[0]->definition,
+      );
+  
+      $form['properties']['table']['new'][$new_id][$rank]["remove-$new_id-$rank"] = array(
+        '#type'         => 'button',
+        '#value'        => t('Remove'),
+        '#name'         => "remove-$new_id-$rank",
+        '#ajax' => array(
+          'callback' => "tripal_analysis_property_ajax_update",
+          'wrapper'  => 'tripal-analysis-edit-properties-table',
+          'effect'   => 'fade',
+          'event'    => 'mousedown',
+          'method'   => 'replace',
+          'prevent'  => 'click'
+        ),
+        // When this button is clicked, the form will be validated and submitted.
+        // Therefore, we set custom submit and validate functions to override the
+        // default form submit.  In the validate function we set the form_state
+        // to rebuild the form so the submit function never actually gets called,
+        // but we need it or Drupal will run the default validate anyway.
+        // we also set #limit_validation_errors to empty so fields that
+        // are required that don't have values won't generate warnings.
+        '#submit'   => array('chado_anslysis_node_form_props_button_submit'),
+        '#validate' => array('chado_anslysis_node_form_props_button_validate'),
+        '#limit_validation_errors' => array(),
+      );
     }
   }
 
-
-  // second add in any new properties added during this callback
-  if (array_key_exists('post', $form_state) and array_key_exists('add', $form_state['post'])) {
-    $new_id = $form_state['values']['new_id'];
-    $new_value = $form_state['values']['new_value'];
+  // second add in any new properties added during this callback 
+  if (array_key_exists('triggering_element', $form_state) and 
+      $form_state['triggering_element']['#name'] == 'add' and
+      $form_state['input']['new_id'] != 0) {
+    $new_id    = $form_state['input']['new_id'];
+    $new_value = $form_state['input']['new_value'];    
 
     // get the rank by counting the number of entries
-    $rank = count($d_properties[$new_id]);
+    $rank = count($ranks[$new_id]);
 
     // get this new_id information
     $cvterm = tripal_core_chado_select('cvterm', array('name', 'definition'), array('cvterm_id' => $new_id));
 
-    // add it to the $d_properties array
-    $d_properties[$new_id][$rank]['name']  = $cvterm->name;
-    $d_properties[$new_id][$rank]['id']    = $new_id;
-    $d_properties[$new_id][$rank]['value'] = $value;
-    $d_properties[$new_id][$rank]['definition']  = $cvterm->definition;
+    // add it to the $ranks array
+    $ranks[$new_id][$rank]['name']  = $cvterm[0]->name;
+    $ranks[$new_id][$rank]['id']    = $new_id;
+    $ranks[$new_id][$rank]['value'] = $value;
+    $ranks[$new_id][$rank]['definition']  = $cvterm[0]->definition;
     $num_properties++;
 
     // determine how many rows we need in the textarea
@@ -347,28 +430,38 @@ function chado_analysis_node_form_add_new_props(&$form, &$form_state, &$d_proper
 
     // add the new fields
     $form['properties']['table']['new'][$new_id][$rank]["new_id-$new_id-$rank"] = array(
-      '#type'          => 'item',
-      '#value'         => $cvterm[0]->name
+      '#markup' => $cvterm[0]->name
     );
     $form['properties']['table']['new'][$new_id][$rank]["new_value-$new_id-$rank"] = array(
       '#type'          => 'textarea',
       '#default_value' => $new_value,
       '#cols'          => 50,
       '#rows'          => $rows,
-      '#description'   => $cvterm->definition,
+      '#description'   => $cvterm[0]->definition,
     );
 
     $form['properties']['table']['new'][$new_id][$rank]["remove-$new_id-$rank"] = array(
-      '#type'         => 'image_button',
+      '#type'         => 'button',
       '#value'        => t('Remove'),
-      '#src'          => drupal_get_path('theme', 'tripal') . '/images/minus.png',
-      '#ahah' => array(
-        'path'    => "tripal_analysis/properties/minus/$new_id/$rank",
-        'wrapper' => 'tripal-analysis-edit-properties-table',
-        'event'   => 'click',
-        'method'  => 'replace',
+      '#name'         => "remove-$new_id-$rank",
+      '#ajax' => array(
+        'callback' => "tripal_analysis_property_ajax_update",
+        'wrapper'  => 'tripal-analysis-edit-properties-table',
+        'effect'   => 'fade',
+        'event'    => 'mousedown',
+        'method'   => 'replace',
+        'prevent'  => 'click'
       ),
-      '#attributes' => array('onClick' => 'return false;'),
+      // When this button is clicked, the form will be validated and submitted.
+      // Therefore, we set custom submit and validate functions to override the
+      // default form submit.  In the validate function we set the form_state
+      // to rebuild the form so the submit function never actually gets called,
+      // but we need it or Drupal will run the default validate anyway.
+      // we also set #limit_validation_errors to empty so fields that
+      // are required that don't have values won't generate warnings.
+      '#submit'   => array('chado_anslysis_node_form_props_button_submit'),
+      '#validate' => array('chado_anslysis_node_form_props_button_validate'),
+      '#limit_validation_errors' => array(),
     );
 
   }
@@ -378,7 +471,7 @@ function chado_analysis_node_form_add_new_props(&$form, &$form_state, &$d_proper
 /*
  *
 */
-function chado_analysis_node_form_add_analysisprop_table_props(&$form, $form_state, $analysis_id, &$d_properties, &$d_removed) {
+function chado_analysis_node_form_add_analysisprop_table_props(&$form, $form_state, $analysis_id, &$ranks, &$d_removed) {
 
   // get the properties for this analysis
   $num_properties = 0;
@@ -399,22 +492,23 @@ function chado_analysis_node_form_add_analysisprop_table_props(&$form, $form_sta
   while ($prop = $analysis_props->fetchObject()) {
 
     $type_id = $prop->cvterm_id;
-    $rank = count($d_properties[$type_id]);
+    $rank = count($ranks[$type_id]);
 
     // skip any properties that the user requested to delete through a previous
     // AHAH callback or through the current AHAH callback
-    if ($d_removed["$type_id-$rank"]) {
+    if (array_key_exists("$type_id-$rank", $d_removed)) {
       continue;
     }
-    if ($form_state['post']['remove-' . $type_id . '-' . $rank]) {
+    if (array_key_exists('triggering_element', $form_state) and 
+        $form_state['triggering_element']['#name'] == 'remove-' . $type_id . '-' . $rank) {
       $d_removed["$type_id-$rank"] = 1;
       continue;
     }
 
-    $d_properties[$type_id][$rank]['name']  = $prop->name;
-    $d_properties[$type_id][$rank]['id']    = $type_id;
-    $d_properties[$type_id][$rank]['value'] = $prop->value;
-    $d_properties[$type_id][$rank]['definition']  = $prop->definition;
+    $ranks[$type_id][$rank]['name']  = $prop->name;
+    $ranks[$type_id][$rank]['id']    = $type_id;
+    $ranks[$type_id][$rank]['value'] = $prop->value;
+    $ranks[$type_id][$rank]['definition']  = $prop->definition;
     $num_properties++;
 
     $form['properties']['table'][$type_id][$rank]["prop_id-$type_id-$rank"] = array(
@@ -430,16 +524,27 @@ function chado_analysis_node_form_add_analysisprop_table_props(&$form, $form_sta
     );
 
     $form['properties']['table'][$type_id][$rank]["remove-$type_id-$rank"] = array(
-      '#type'         => 'image_button',
+      '#type'         => 'button',
       '#value'        => t('Remove'),
-      '#src'          => drupal_get_path('theme', 'tripal') . '/images/minus.png',
-      '#ahah' => array(
-        'path'    => "tripal_analysis/properties/minus/$type_id/$rank",
-        'wrapper' => 'tripal-analysis-edit-properties-table',
-        'event'   => 'click',
-        'method'  => 'replace',
+      '#name'         => "remove-$type_id-$rank",
+      '#ajax' => array(
+        'callback' => "tripal_analysis_property_ajax_update",
+        'wrapper'  => 'tripal-analysis-edit-properties-table',
+        'effect'   => 'fade',
+        'event'    => 'mousedown',
+        'method'   => 'replace',
+        'prevent'  => 'click'
       ),
-      '#attributes' => array('onClick' => 'return false;'),
+      // When this button is clicked, the form will be validated and submitted.
+      // Therefore, we set custom submit and validate functions to override the
+      // default form submit.  In the validate function we set the form_state
+      // to rebuild the form so the submit function never actually gets called,
+      // but we need it or Drupal will run the default validate anyway.
+      // we also set #limit_validation_errors to empty so fields that
+      // are required that don't have values won't generate warnings.
+      '#submit'   => array('chado_anslysis_node_form_props_button_submit'),
+      '#validate' => array('chado_anslysis_node_form_props_button_validate'),
+      '#limit_validation_errors' => array(),
     );
   }
   return $num_properties;
@@ -451,7 +556,7 @@ function chado_analysis_node_form_add_analysisprop_table_props(&$form, $form_sta
  * @ingroup tripal_analysis
  */
 function chado_analysis_validate($node, &$form) {
-   // use the analysis parent to validate the node
+  // use the analysis parent to validate the node
   tripal_analysis_validate($node, $form);
 }
 
@@ -463,7 +568,8 @@ function chado_analysis_validate($node, &$form) {
  *
  * @ingroup tripal_analysis
  */
-function tripal_analysis_validate($node, &$form) {
+function tripal_analysis_validate($node, $form, &$form_state) {
+  
   $node->analysisname = trim($node->analysisname);
   $node->description = trim($node->description);
   $node->program = trim($node->program);
@@ -572,9 +678,9 @@ function tripal_analysis_theme_node_form_properties($form) {
         foreach ($elements as $rank => $element) {
           if (is_numeric($rank)) {
             $rows[] = array(
-            drupal_render($element["prop_id-$type_id-$rank"]),
-            drupal_render($element["prop_value-$type_id-$rank"]),
-            drupal_render($element["remove-$type_id-$rank"]),
+              drupal_render($element["prop_id-$type_id-$rank"]),
+              drupal_render($element["prop_value-$type_id-$rank"]),
+              drupal_render($element["remove-$type_id-$rank"]),
             );
           }
         }
@@ -589,9 +695,9 @@ function tripal_analysis_theme_node_form_properties($form) {
         foreach ($elements as $rank => $element) {
           if (is_numeric($rank)) {
             $rows[] = array(
-            drupal_render($element["new_id-$type_id-$rank"]),
-            drupal_render($element["new_value-$type_id-$rank"]),
-            drupal_render($element["remove-$type_id-$rank"]),
+              drupal_render($element["new_id-$type_id-$rank"]),
+              drupal_render($element["new_value-$type_id-$rank"]),
+              drupal_render($element["remove-$type_id-$rank"]),
             );
           }
         }
@@ -600,22 +706,19 @@ function tripal_analysis_theme_node_form_properties($form) {
 
     // finally add in a set of blank field for adding a new property
     $rows[] = array(
-    drupal_render($form['properties']['table']['new']['new_id']),
-    array(
-      'data' => drupal_render($form['properties']['table']['new']['new_value']),
-      'width' => '60%',
-    ),
-    drupal_render($form['properties']['table']['new']['add']),
+      drupal_render($form['properties']['table']['new']['new_id']),
+      array(
+        'data' => drupal_render($form['properties']['table']['new']['new_value']),
+        'width' => '60%',
+      ),
+      drupal_render($form['properties']['table']['new']['add']),
     );
   }
-
-  $headers = array('Property Type', 'Value', '');
+  $headers = array('Property Type', 'Value', 'Actions');
   $table = array(
     'header' => $headers,
     'rows' => $rows,
-    'attributes' => array(
-      'id' => 'tripal_analysis-edit-properties-table',
-    ),
+    'attributes' => array(),
     'sticky' => TRUE,
     'caption' => '',
     'colgroups' => array(),
@@ -630,15 +733,14 @@ function tripal_analysis_theme_node_form_properties($form) {
  * 
  * We only want to return the properties as that's all we'll replace with this callback
  */
-function tripal_analysis_property_add($form, $form_state) {
-  return tripal_analysis_theme_node_form_properties($form);
-}
-/**
- * Form AJAX callback for deleting properties
- *
- */
-function tripal_analysis_property_delete($form, $form_state) {
-  return tripal_analysis_theme_node_form_properties($form);
+function tripal_analysis_property_ajax_update($form, $form_state) {
+  $properties_html = tripal_analysis_theme_node_form_properties($form); 
+  $form['properties']['table'] = array(
+    '#markup' => $properties_html,
+    '#prefix' => '<div id="tripal-analysis-edit-properties-table">',
+    '#suffix' => '</div>',
+  );
+  return $form['properties']['table'];
 }
 /**
  * Form AJAX callback for updating a property description. This 

+ 2 - 2
tripal_core/api/tripal_core_chado.api.inc

@@ -899,9 +899,9 @@ function tripal_core_chado_delete($table, $match, $options = NULL) {
  *     (when using the -statement_name option).
  *
  * @return
- *  A database query result resource, FALSE if the query was not executed
+ *  An array of results, FALSE if the query was not executed
  *  correctly, an empty array if no records were matched, or the number of records
- *  in the dataset if $has_record is set.
+ *  in the dataset if $has_record is set. 
  *  If the option 'is_duplicate' is provided and the record is a duplicate it
  *  will return the duplicated record.  If the 'has_record' option is provided
  *  a value of TRUE will be returned if a record exists and FALSE will bee

BIN
tripal_core/theme/images/add.png