Index: form_builder.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/form_builder/form_builder.module,v
retrieving revision 1.14
diff -u -p -r1.14 form_builder.module
--- form_builder.module	29 Dec 2010 20:28:57 -0000	1.14
+++ form_builder.module	29 Dec 2010 23:58:05 -0000
@@ -66,28 +66,20 @@ function form_builder_menu() {
  */
 function form_builder_theme() {
   return array(
-    'form_builder_preview' => array(
-      'arguments' => array('form' => NULL),
-      'file' => 'includes/form_builder.admin.inc',
-    ),
-    'form_builder_element_prefix' => array(
-      'arguments' => array('element' => NULL),
-      'file' => 'includes/form_builder.admin.inc',
-    ),
-    'form_builder_element_suffix' => array(
-      'arguments' => array('element' => NULL),
+    'form_builder_empty_fieldset' => array(
+      'variables' => array(),
       'file' => 'includes/form_builder.admin.inc',
     ),
-    'form_builder_empty_fieldset' => array(
-      'arguments' => array(),
+    'form_builder_field_palette' => array(
+      'variables' => array('fields' => NULL, 'groups' => NULL, 'form_type' => NULL, 'form_id' => NULL),
       'file' => 'includes/form_builder.admin.inc',
     ),
-    'form_builder_field_configure' => array(
-      'arguments' => array('form' => NULL),
+    'form_builder_element_wrapper' => array(
+      'render element' => 'element',
       'file' => 'includes/form_builder.admin.inc',
     ),
-    'form_builder_field_palette' => array(
-      'arguments' => array('fields' => NULL, 'groups' => NULL, 'form_type' => NULL, 'form_id' => NULL),
+    'form_builder_wrapper' => array(
+      'render element' => 'element',
       'file' => 'includes/form_builder.admin.inc',
     ),
   );
Index: includes/form_builder.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/form_builder/includes/form_builder.admin.inc,v
retrieving revision 1.17
diff -u -p -r1.17 form_builder.admin.inc
--- includes/form_builder.admin.inc	29 Dec 2010 20:28:57 -0000	1.17
+++ includes/form_builder.admin.inc	29 Dec 2010 23:58:05 -0000
@@ -69,17 +69,15 @@ function form_builder_add_page($form_typ
     if (isset($_REQUEST['js'])) {
       $element = form_builder_cache_field_load($form_type, $form_id, $element_id);
       $preview_form = form_builder_cache_load($form_type, $form_id);
-
       $data = array(
         'formType' => $form_type,
         'formId' => $form_id,
         'elementId' => $element_id,
         'html' => form_builder_field_render($form_type, $form_id, $element_id),
-        'positionForm' => drupal_get_form('form_builder_positions', $preview_form, $form_type, $form_id),
-        'messages' => theme('status_messages'),
+        'positionForm' => render(drupal_get_form('form_builder_positions', $preview_form, $form_type, $form_id)),
       );
 
-      drupal_json_output($data);
+      form_builder_render_json($data);
       exit();
     }
   }
@@ -107,10 +105,8 @@ function form_builder_configure_page($fo
         'elementId' => $element_id,
         'html' => drupal_render($output),
         'errors' => form_get_errors(),
-        'messages' => theme('status_messages'),
       );
-
-      drupal_json_output($data);
+      form_builder_render_json($data);
       exit();
     }
   }
@@ -131,10 +127,9 @@ function form_builder_remove_page($form_
       'formId' => $form_id,
       'elementId' => $element_id,
       'html' => drupal_render($output),
-      'messages' => theme('status_messages'),
     );
 
-    drupal_json_output($data);
+    form_builder_render_json($data);
     exit();
   }
 
@@ -160,12 +155,7 @@ function form_builder_preview($f, &$form
 
   // Add a pre_render to the entire form itself.
   $form['#pre_render'][] = 'form_builder_pre_render_form';
-
-  // Save the original form theming so that we can call it later.
-  if (!empty($form['#theme'])) {
-    $form['#theme-original'] = $form['#theme'];
-  }
-  $form['#theme'] = 'form_builder_preview';
+  $form['#theme_wrappers'] = array('form_builder_wrapper');
 
   // Add required jQuery UI elements.
   $form['#attached']['library'][] = array('system', 'ui.draggable');
@@ -177,8 +167,9 @@ function form_builder_preview($f, &$form
 
   // TODO: This JS file should be loaded dynamically as needed.
   $form['#attached']['js'][] = drupal_get_path('module', 'options_element') .'/options_element.js';
-  // @todo: no library for this?
+  // @todo: no library for this? see http://drupal.org/node/954804
   $form['#attached']['js'][] = 'misc/tabledrag.js';
+  $form['#attached']['js'][] = 'misc/jquery.cookie.js';
   $form['#attached']['library'][] = array('system', 'form');
   // @todo: no library for this?
   $form['#attached']['js'][] = 'misc/collapse.js';
@@ -281,58 +272,53 @@ function form_builder_positions_submit(&
   form_builder_cache_save($form_type, $form_id, $preview_form);
 }
 
-function theme_form_builder_preview($vars) {
-  global $theme;
-
-  // Pick out the form structure.
-  $form = array_shift($vars);
-
-  // Check if the Form Builder block is enabled.
-  // Otherwise make our own columns.
-  $block_enabled = db_query("SELECT status FROM {block} WHERE module = 'form_builder' AND theme = :theme", array(':theme' => $theme))->fetchField();
+/**
+ * Adds a wrapper around the form_builder preview and optionally will add the
+ * field palette if it is not already available as a block.
+ */
+function theme_form_builder_wrapper($vars) {
+  $element = $vars['element'];
 
-  if ($block_enabled && ($theme == 'garland' || $theme == 'minnelli')) {
-    // @todo: move this to an #attached
-    drupal_add_css(drupal_get_path('module', 'form_builder') .'/form_builder.garland.css', 'theme');
-  }
+  // Open the wrapper.
+  $output = '<div id="form-builder-wrapper" class="' . ($element['#block_enabled'] ? 'no-palette' : 'with-palette') . '">';
 
-  $output = '';
-  $output .= '<div id="form-builder-wrapper" class="' . ($block_enabled ? 'no-palette' : 'with-palette') . '">';
-  if (!$block_enabled) {
-    $fields = form_builder_get_form_type($form['#form_builder']['form_type']);
+  // If we need to add the field palette add it here.
+  if (!$element['#block_enabled']) {
+    $fields = form_builder_get_form_type($element['#form_builder']['form_type']);
     $groups = module_invoke_all('form_builder_palette_groups');
     $output .= '<div id="form-builder-fields">';
     $output .= '<div class="block">';
-    $output .= theme('form_builder_field_palette', array('fields' => $fields, 'groups' => $groups, 'form_type' => $form['#form_builder']['form_type'], 'form_id' => $form['#form_builder']['form_id']));
+    $output .= theme('form_builder_field_palette', array('fields' => $fields, 'groups' => $groups, 'form_type' => $element['#form_builder']['form_type'], 'form_id' => $element['#form_builder']['form_id']));
     $output .= '</div>';
     $output .= '</div>';
   }
+
   $output .= '<div id="form-builder">';
-  $output .= '<h3>' . t('Form preview') . '</h3>';
+  if (isset($element['#title'])) {
+    $output .= '<h3>' . $element['#title'] . '</h3>';
+  }
+
+  // Add the contents of the form and close the wrappers.
+  $output .= $element['#children'];
+  $output .= '</div></div>';
 
-  // Reset the original form theming, but allow form_builder implementations to
-  // alter the form output.
-  $form['#theme'] = isset($form['#theme-original']) ? $form['#theme-original'] : NULL;
-
-  // @todo: we cannot render ourselves again, so ideally this whole function with the
-  // above code would be in theme_wrappers, but I could not make that execute.
-  $output .= drupal_render_children($form);
-  $output .= '</div>';
-  $output .= '</div>';
   return $output;
 }
 
-function theme_form_builder_element_prefix($vars) {
+/**
+ * Theme the wrapper around a form_builder element and add configure and remove
+ * links as appropriate.
+ */
+function theme_form_builder_element_wrapper($vars) {
   $element = $vars['element'];
 
   $removable = isset($element['#form_builder']['removable']) ? $element['#form_builder']['removable'] : TRUE;
   $configurable  = isset($element['#form_builder']['configurable']) ? $element['#form_builder']['configurable'] : TRUE;
 
-  $output = '';
-  $output .= '<div class="form-builder-wrapper">';
-  $output .= '<div class="form-builder-title-bar">';
+  $output = '<div class="form-builder-wrapper">';
+
   if ($removable || $configurable) {
-    $output .= '<span class="form-builder-links">';
+    $output .= '<div class="form-builder-title-bar"><span class="form-builder-links">';
     if ($removable) {
       $output .= l('<span class="remove">'. t('Remove') .'</span>', 'admin/build/form-builder/remove/' . $element['#form_builder']['form_type'] . '/' . $element['#form_builder']['form_id'] . '/' . $element['#form_builder']['element_id'], array('html' => TRUE, 'attributes' => array('class' => array('remove'), 'title' => t('Remove')), 'query' => drupal_get_destination()));
     }
@@ -342,24 +328,24 @@ function theme_form_builder_element_pref
     if ($configurable) {
       $output .= l('<span class="configure">'. t('Configure') .'</span>', 'admin/build/form-builder/configure/' . $element['#form_builder']['form_type'] . '/' . $element['#form_builder']['form_id'] . '/' . $element['#form_builder']['element_id'], array('html' => TRUE, 'attributes' => array('class' => array('configure'), 'title' => t('Configure')), 'query' => drupal_get_destination()));
     }
-    $output .= '</span>';
+    $output .= '</span></div>';
   }
-  $output .= '</div>';
-  $output .= '<div class="form-builder-element" id="form-builder-element-' . $element['#form_builder']['element_id'] . '">';
+
+  $output .= '<div class="form-builder-element form-builder-element-' . $element['#type'] . '" id="form-builder-element-' . $element['#form_builder']['element_id'] . '">';
   // TODO: Overlay image: good idea or bad idea? Prevents any interaction with
   // form elements in the preview.
   //$output .= theme('image', drupal_get_path('module', 'form_builder') .'/images/blank.gif', '', '', array('width' => '1', 'height' => '1', 'class' => 'form-builder-disable'));
-  return $output;
-}
+  $output .= $element['#children'];
 
-function theme_form_builder_element_suffix($vars) {
-  return '</div></div>';
+  $output .= '</div></div>';
+
+  return $output;
 }
 
 /**
  * Placeholder for empty fieldsets during drag and drop.
  */
-function theme_form_builder_empty_fieldset($vars = array()) {
+function theme_form_builder_empty_fieldset($vars) {
   $output = '';
   $output .= '<div class="form-builder-wrapper form-builder-empty-placeholder">';
   $output .= '<span>' . t('This fieldset is empty. Drag a form element into it.') .'</span>';
@@ -425,25 +411,25 @@ function theme_form_builder_field_palett
  * Take a form structure and add a prebuild function to every element.
  */
 function form_builder_pre_render($element) {
-  // Allow modules to make modifications to this element.
-  drupal_alter('form_builder_preview', $element, $element['#form_builder']['form_type'], $element['#form_builder']['form_id']);
-
-  $element['#prefix'] = isset($element['#prefix']) ? theme('form_builder_element_prefix', array('element' => $element)) . $element['#prefix'] : theme('form_builder_element_prefix', array('element' => $element));
-  $element['#suffix'] = isset($element['#suffix']) ? $element['#suffix'] . theme('form_builder_element_suffix', array('element' => $element)) : theme('form_builder_element_suffix', array('element' => $element));
+  $element['#theme_wrappers'][] = 'form_builder_element_wrapper';
 
   if ($element['#form_builder']['element_type'] == 'fieldset') {
-    $element['#attributes']['class'] = array(isset($element['#attributes']['class']) ? $element['#attributes']['class'] . ' form-builder-fieldset' : 'form-builder-fieldset');
+    $element['#attributes']['class'][] = 'form-builder-fieldset';
+    if (count(element_children($element)) == 0) {
+      $element['#children'] = theme('form_builder_empty_fieldset');
+    }
   }
 
-  if (isset($element['#type']) && $element['#type'] == 'fieldset' && count(element_children($element)) == 0) {
-    $element['#children'] = theme('form_builder_empty_fieldset');
-  }
+  // Allow modules to make modifications to this element.
+  drupal_alter('form_builder_preview', $element, $element['#form_builder']['form_type'], $element['#form_builder']['form_id']);
 
   return $element;
 }
 
 /**
- * Change the type of the entire form to "markup" before rendering.
+ * This changes the type to markup before rendering.  Also sets a default title
+ * and sets a variable to indicate to the theme wrapper that the field palette
+ * should be added.
  */
 function form_builder_pre_render_form($form) {
   // We can't have forms inside of forms, so change this entire form a markup.
@@ -454,6 +440,17 @@ function form_builder_pre_render_form($f
   unset($form['form_token']);
   unset($form['form_builder_preview']);
 
+  global $theme;
+  // Check if the Form Builder block is enabled.
+  // Otherwise make our own columns.
+  $form['#block_enabled'] = db_query("SELECT status FROM {block} WHERE module = 'form_builder' AND theme = :theme", array(':theme' => $theme))->fetchField();
+
+  if ($form['#block_enabled'] && ($theme == 'garland' || $theme == 'minnelli')) {
+    $form['#attached']['css'][] = drupal_get_path('module', 'form_builder') .'/form_builder.garland.css';
+  }
+
+  $form['#title'] = t('Form preview');
+
   return $form;
 }
 
@@ -541,16 +538,12 @@ function form_builder_field_configure($f
     '#weight' => 100,
   );
 
+  $form['#pre_render'][] = 'form_builder_pre_render_field_configure';
+
   return $form;
 }
 
-/**
- * Theme function for the display of field configuration.
- */
-function theme_form_builder_field_configure($vars) {
-  $form = array_shift($vars);
-
-  // Group the properties into separate fieldsets (converted to tabs later).
+function form_builder_pre_render_field_configure($form) {
   $groups = module_invoke_all('form_builder_property_groups', $form['#form_type']);
 
   foreach (element_children($form) as $key) {
@@ -582,7 +575,7 @@ function theme_form_builder_field_config
     }
   }
 
-  return drupal_render_children($form);
+  return $form;
 }
 
 function form_builder_field_configure_submit(&$form, &$form_state) {
@@ -649,12 +642,12 @@ function form_builder_field_remove($form
   $form['#_edit_form_id'] = $form_id;
   $form['#_edit_element_id'] = $element_id;
 
-  $quesion = t('Remove the field %title?', array('%title' => $element['#title']));
+  $question = t('Remove the field %title?', array('%title' => $element['#title']));
   $path = isset($_GET['destination']) ? $_GET['destination'] : NULL;
   $description = t('Remove the field %title? This field will not be permanently removed until the form configuration is saved.', array('%title' => isset($element['#title']) ? $element['#title'] : $element['#form_builder']['element_id']));
   $yes = t('Remove');
 
-  return confirm_form($form, $quesion, $path, $description, $yes);
+  return confirm_form($form, $question, $path, $description, $yes);
 }
 
 function form_builder_field_remove_submit(&$form, &$form_state) {
@@ -695,17 +688,11 @@ function form_builder_field_render($form
   // Get only the element wanted and render it.
   $element = form_builder_get_element($form, $element_id);
 
-  $content = drupal_render($element);
-
-  $prefix = isset($element['#prefix']) ? $element['#prefix'] : '';
-  $suffix = isset($element['#suffix']) ? $element['#suffix'] : '';
-
   if ($wrapper) {
-    $prefix .= theme('form_builder_element_prefix', array('element' => $element));
-    $suffix .= theme('form_builder_element_suffix', array('element' => $element));
+    $element['#theme_wrappers'][] = 'form_builder_element_wrapper';
   }
 
-  return $suffix . $content . $suffix;
+  return drupal_render($element);
 }
 
 /**
@@ -722,10 +709,27 @@ function form_builder_field_json($form_t
     'elementId' => $element_id,
     'html' => form_builder_field_render($form_type, $form_id, $element_id),
     'errors' => form_get_errors(),
-    'messages' => theme('status_messages'),
-    'time' => time(),
   );
 
-  drupal_json_output($data);
+  form_builder_render_json($data);
   exit();
 }
+
+/**
+ * Adds status messages, settings, and timestamp to a form builder JSON response and outputs it.
+ */
+function form_builder_render_json($data) {
+  if (!isset($data['messages'])) {
+    $data['messages'] = theme('status_messages');
+  }
+  if (!isset($data['settings'])) {
+    $scripts = drupal_add_js();
+    if (!empty($scripts['settings'])) {
+      $data['settings'] = drupal_array_merge_deep_array($scripts['settings']['data']);
+    }
+  }
+  if (!isset($data['time'])) {
+    $data['time'] = time();
+  }
+  drupal_json_output($data);
+}
