? .svn
? examples/.svn
? images/.svn
? images/fields/.svn
? includes/.svn
? modules/.svn
? modules/node/.svn
? modules/webform/.svn
Index: form_builder.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/form_builder/form_builder.css,v
retrieving revision 1.13
diff -u -p -r1.13 form_builder.css
--- form_builder.css	29 Dec 2010 21:15:24 -0000	1.13
+++ form_builder.css	1 Feb 2011 16:02:09 -0000
@@ -78,6 +78,11 @@ div.form-builder-element .form-builder-d
   left: 0;
 }
 
+.form-builder-placeholder.over,
+.form-builder-empty-placeholder.over {
+  background: #f0f0f0;
+}
+
 /* Empty fieldsets */
 #form-builder fieldset {
   padding-bottom: 20px;
@@ -109,11 +114,11 @@ div.form-builder-title-bar {
   border-bottom: none;
 }
 
-div.ui-sortable div.form-builder-title-bar {
+div.form-builder-title-bar {
   display: none;
 }
 
-div.ui-sortable div.form-builder-title-bar {
+div.form-builder-title-bar {
   cursor: move;
 }
 
@@ -123,16 +128,11 @@ span.form-builder-links {
   z-index: 40;
 }
 
-div.form-builder-hover div.form-builder-title-bar,
-div.form-builder-active div.form-builder-title-bar {
+div.form-builder-hover > div.form-builder-title-bar,
+div.form-builder-active > div.form-builder-title-bar {
   display: block;
 }
 
-div.ui-sortable div.form-builder-hover div.form-builder-wrapper div.form-builder-title-bar,
-div.ui-sortable div.form-builder-active div.form-builder-wrapper div.form-builder-title-bar {
-  display: none;
-}
-
 span.form-builder-links a.remove,
 span.form-builder-links a.configure {
   float: right;
@@ -244,7 +244,8 @@ div.form-builder-new-field span.progress
   padding: 0;
 }
 
-#form-builder-field-palette ul li {
+#form-builder-field-palette ul li,
+#form-builder-wrapper > li {
   list-style-type: none;
   background: white none no-repeat 6px center;
   padding: 2px 2px 2px 28px;
@@ -259,65 +260,85 @@ div.form-builder-new-field span.progress
 #form-builder-field-palette ul li a,
 #form-builder-field-palette ul li a:hover,
 #form-builder-field-palette ul li a:active,
-#form-builder-field-palette ul li a:visited {
+#form-builder-field-palette ul li a:visited,
+#form-builder-wrapper > li a {
   text-decoration: none;
   cursor: move;
   color: black;
 }
 
-#form-builder-field-palette ul li.field-body_field {
+#form-builder-field-palette ul li.field-body_field,
+#form-builder-wrapper > li.field-body_field {
   background-image: url(images/fields/body.png);
 }
-#form-builder-field-palette ul li.field-checkboxes {
+#form-builder-field-palette ul li.field-checkboxes,
+#form-builder-wrapper > li.field-checkboxes {
   background-image: url(images/fields/checkboxes.png);
 }
-#form-builder-field-palette ul li.field-email {
+#form-builder-field-palette ul li.field-email,
+#form-builder-wrapper > li.field-email {
   background-image: url(images/fields/email.png);
 }
-#form-builder-field-palette ul li.field-fieldset {
+#form-builder-field-palette ul li.field-fieldset,
+#form-builder-wrapper > li.field-fieldset {
   background-image: url(images/fields/fieldset.png);
 }
 #form-builder-field-palette ul li.field-file,
-#form-builder-field-palette ul li.field-upload_settings {
+#form-builder-field-palette ul li.field-upload_settings,
+#form-builder-wrapper > li.field-file,
+#form-builder-wrapper > li.field-upload_settings {
   background-image: url(images/fields/file.png);
 }
-#form-builder-field-palette ul li.field-hidden {
+#form-builder-field-palette ul li.field-hidden,
+#form-builder-wrapper > li.field-hidden {
   background-image: url(images/fields/hidden.png);
 }
-#form-builder-field-palette ul li.field-image {
+#form-builder-field-palette ul li.field-image,
+#form-builder-wrapper > li.field-image {
   background-image: url(images/fields/image.png);
 }
-#form-builder-field-palette ul li.field-markup {
+#form-builder-field-palette ul li.field-markup,
+#form-builder-wrapper > li.field-markup {
   background-image: url(images/fields/markup.png);
 }
-#form-builder-field-palette ul li.field-menu_settings {
+#form-builder-field-palette ul li.field-menu_settings,
+#form-builder-wrapper > li.field-menu_settings {
   background-image: url(images/fields/menu.png);
 }
-#form-builder-field-palette ul li.field-number {
+#form-builder-field-palette ul li.field-number,
+#form-builder-wrapper > li.field-number {
   background-image: url(images/fields/number.png);
 }
-#form-builder-field-palette ul li.field-path_settings {
+#form-builder-field-palette ul li.field-path_settings,
+#form-builder-wrapper > li.field-path_settings {
   background-image: url(images/fields/path.png);
 }
-#form-builder-field-palette ul li.field-radios {
+#form-builder-field-palette ul li.field-radios,
+#form-builder-wrapper > li.field-radios {
   background-image: url(images/fields/radios.png);
 }
-#form-builder-field-palette ul li.field-revision_information {
+#form-builder-field-palette ul li.field-revision_information,
+#form-builder-wrapper > li.field-revision_information {
   background-image: url(images/fields/revisions.png);
 }
-#form-builder-field-palette ul li.field-select {
+#form-builder-field-palette ul li.field-select,
+#form-builder-wrapper > li.field-select {
   background-image: url(images/fields/select.png);
 }
-#form-builder-field-palette ul li.field-taxonomy {
+#form-builder-field-palette ul li.field-taxonomy,
+#form-builder-wrapper > li.field-taxonomy {
   background-image: url(images/fields/taxonomy.png);
 }
-#form-builder-field-palette ul li.field-textarea {
+#form-builder-field-palette ul li.field-textarea,
+#form-builder-wrapper > li.field-textarea {
   background-image: url(images/fields/textarea.png);
 }
-#form-builder-field-palette ul li.field-textfield {
+#form-builder-field-palette ul li.field-textfield,
+#form-builder-wrapper > li.field-textfield {
   background-image: url(images/fields/textfield.png);
 }
-#form-builder-field-palette ul li.field-title {
+#form-builder-field-palette ul li.field-title,
+#form-builder-wrapper > li.field-title {
   background-image: url(images/fields/title.png);
 }
 
Index: form_builder.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/form_builder/form_builder.install,v
retrieving revision 1.2
diff -u -p -r1.2 form_builder.install
--- form_builder.install	29 Dec 2010 21:15:24 -0000	1.2
+++ form_builder.install	1 Feb 2011 16:02:09 -0000
@@ -62,6 +62,7 @@ function form_builder_schema() {
       'data' => array(
         'type' => 'blob',
         'not null' => FALSE,
+        'size' => 'big',
       ),
     ),
     'indexes' => array(
@@ -73,3 +74,15 @@ function form_builder_schema() {
 
   return $schema;
 }
+
+/**
+ * Change the {form_builder_cache} table to use a 'longblob' data column.
+ */
+function form_builder_update_7000() {
+  $spec = array(
+    'type' => 'blob',
+    'not null' => FALSE,
+    'size' => 'big',
+  );
+  db_change_field('form_builder_cache', 'data', 'data', $spec);
+}
Index: form_builder.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/form_builder/form_builder.js,v
retrieving revision 1.23
diff -u -p -r1.23 form_builder.js
--- form_builder.js	30 Dec 2010 17:09:05 -0000	1.23
+++ form_builder.js	1 Feb 2011 16:02:09 -0000
@@ -53,15 +53,15 @@ Drupal.behaviors.formBuilderElement.atta
 Drupal.behaviors.formBuilderFields = {};
 Drupal.behaviors.formBuilderFields.attach = function(context) {
   // Bind a function to all elements to update the preview on change.
-  var $configureForm = $('#form-builder-field-configure');
+  var $configureForm = $('#form-builder-field-configure', context);
 
   $configureForm.find('input, textarea, select')
-    .not('.form-builder-field-change)')
+    .not('.form-builder-field-change')
     .addClass('form-builder-field-change')
     .bind('change', Drupal.formBuilder.elementPendingChange);
 
   $configureForm.find('input.form-text, textarea')
-    .not('.form-builder-field-keyup)')
+    .not('.form-builder-field-keyup')
     .addClass('form-builder-field-keyup')
     .bind('keyup', Drupal.formBuilder.elementPendingChange);
 };
@@ -72,21 +72,20 @@ Drupal.behaviors.formBuilderFields.attac
 Drupal.behaviors.formBuilder = {};
 Drupal.behaviors.formBuilder.attach = function(context) {
   var formbuilder = $('#form-builder', context);
-  formbuilder.sortable({
-    items: 'div.form-builder-wrapper',
-    handle: 'div.form-builder-title-bar, div.form-builder-element',
-    axis: 'y',
+
+  $('.form-builder-wrapper:not(.ui-draggable)', formbuilder).draggable({
     opacity: 0.8,
-    forcePlaceholderSize: true,
+    helper: 'clone',
     scroll: true,
     scrollSensitivity: 50,
-    distance: 4, // Pixels before dragging starts.
-    appendTo: 'body',
-    helper: createHelper,
-    sort: Drupal.formBuilder.elementIndent, // Called on drag.
+    containment: 'body',
     start: Drupal.formBuilder.startDrag,
     stop: Drupal.formBuilder.stopDrag,
-    change: Drupal.formBuilder.checkFieldsets
+    change: Drupal.formBuilder.checkFieldsets,
+    distance: 4,
+    scope: 'fields',
+    addClasses: false,
+    appendTo: '#form-builder-wrapper'
   });
 
   // This sets the height of the drag target to be at least as hight as the field
@@ -96,11 +95,6 @@ Drupal.behaviors.formBuilder.attach = fu
   // here.
   var property = $.browser.msie && $.browser.version < 7 ? 'height' : 'min-height';
   formbuilder.css(property, $('#form-builder-fields').height());
-
-  // This helper function is needed to make the appendTo option take effect.
-  function createHelper(e, $el) {
-    return $el.clone().get(0);
-  }
 };
 
 /**
@@ -126,7 +120,7 @@ Drupal.behaviors.formBuilderTabs.attach 
   $fieldsets.filter(':first').before($close).before($tabs);
 
   // Hide all the fieldsets except the first.
-  $fieldsets.not(':first)').css('display', 'none');
+  $fieldsets.not(':first').css('display', 'none');
   $tabs.find('li:first').addClass('active').click(Drupal.formBuilder.clickCancel);
 
   // Enable tab switching by clicking on each tab.
@@ -151,9 +145,29 @@ Drupal.behaviors.formBuilderTabs.attach 
  */
 Drupal.behaviors.formBuilderDeleteConfirmation = {};
 Drupal.behaviors.formBuilderDeleteConfirmation.attach = function(context) {
-  $confirmForm = $('form.confirmation');
+  var $confirmForm = $('form.confirmation', context);
   if ($confirmForm.length) {
-    $confirmForm.submit(Drupal.formBuilder.deleteField);
+    $confirmForm.find('input[type=submit]').bind('click', function(event) {
+      event.preventDefault();
+      // Store the form and the options
+      var form = $confirmForm;
+      Drupal.formBuilder.ajaxOptions = {
+        url: form.attr('action'),
+        success: Drupal.formBuilder.deleteField,
+        error: Drupal.formBuilder.ajaxError,
+        type: 'post',
+        dataType: 'json',
+        action: 'deleteConfirmation',
+        data: form.serialize(),
+        tryCount: 0,
+        maxTry: 3
+      };
+      // Submit the form via ajax
+      $.ajax(Drupal.formBuilder.ajaxOptions);
+      // Bind this action to disable any submit buttons on the page.  It will be
+      // removed on success or after the retries have been exhausted.
+      $('form').submit(Drupal.formBuilder.preventSubmit);
+    });
     $confirmForm.find('a').click(Drupal.formBuilder.clickCancel);
   }
 };
@@ -176,7 +190,7 @@ Drupal.behaviors.formBuilderBlockScroll 
 Drupal.behaviors.formBuilderBlockScroll.attach = function(context) {
   var $list = $('ul.form-builder-fields', context);
 
-  if ($list.length) {
+  if ($list.length && $list.hasClass('block-scroll')) {
     var $block = $list.parents('div.block:first').css('position', 'relative');
     var blockScrollStart = $block.offset().top;
 
@@ -227,10 +241,29 @@ Drupal.behaviors.formBuilderNewField.att
       scroll: true,
       scrollSensitivity: 50,
       containment: 'body',
-      connectToSortable: '#form-builder',
-      start: Drupal.formBuilder.startPaletteDrag,
-      stop: Drupal.formBuilder.stopPaletteDrag,
-      change: Drupal.formBuilder.checkFieldsets
+      start: Drupal.formBuilder.startDrag,
+      stop: Drupal.formBuilder.stopDrag,
+      distance: 4,
+      scope: 'fields',
+      appendTo: '#form-builder-wrapper'
+    })
+    .bind('click', function(event) {
+      event.preventDefault();
+      event.stopPropagation();
+      var item = $(this).clone();
+      // Add a drop target at the bottom of the form to automatically drop the
+      // element onto.
+      var placeholder = $('<div class="form-builder-placeholder"></div>');
+      placeholder
+        .appendTo('#form-builder')
+        .droppable({
+          scope: 'fields',
+          drop: Drupal.formBuilder.drop
+        });
+      Drupal.formBuilder.drop({data: placeholder}, {draggable: item});
+      // Pass the element to the stopDrag method so that unique elements are
+      // properly hidden in the palette.
+      Drupal.formBuilder.stopDrag.apply(this);
     });
   }
 };
@@ -249,7 +282,9 @@ Drupal.formBuilder = {
   // replacing newer updates.
   lastUpdateTime: 0,
   // Status of mouse click.
-  mousePressed: 0
+  mousePressed: 0,
+  // Field configure form target
+  fieldConfigureHolder: false
 };
 
 /**
@@ -286,7 +321,11 @@ Drupal.formBuilder.clickField = function
     return;
   }
 
-  var link = $(this).parents('div.form-builder-wrapper:first').find('a.configure').get(0);
+  var wrapper = $(this).parents('.form-builder-wrapper:first');
+  // This will get the first configure link that does not belong to a nested form element
+  // inside this form element.
+  var link = wrapper.find('a.configure').not(wrapper.find('.form-builder-element .form-builder-element a')).get(0);
+  
   Drupal.formBuilder.editField.apply(link);
 
   return false;
@@ -302,39 +341,59 @@ Drupal.formBuilder.disableField = functi
 /**
  * Load the edit form from the server.
  */
-Drupal.formBuilder.editField = function() {
+Drupal.formBuilder.editField = function(event) {
+  if (event && $(event.target).is('a')) {
+    event.stopPropagation();
+  }
   var element = $(this).parents('div.form-builder-wrapper').get(0);
-  var link = this;
+  var link = $(this);
 
   // Prevent duplicate clicks from taking effect if already handling a click.
   if (Drupal.formBuilder.updatingElement) {
     return false;
   }
 
+  link.addClass('progress');
+
   // If clicking on the link a second time, close the form instead of open.
-  if (element == Drupal.formBuilder.activeElement && link == Drupal.formBuilder.activeLink) {
-    $(link).addClass('progress');
+  if (element == Drupal.formBuilder.activeElement && link.get(0) == Drupal.formBuilder.activeLink) {
     Drupal.formBuilder.closeActive(function() {
-      $(link).removeClass('progress');
+      link.removeClass('progress');
+      if (Drupal.formBuilder.fieldConfigureForm) {
+        Drupal.formBuilder.fieldConfigureForm.html($('<div class="field-settings-message">' + Drupal.t('No field selected') + '</div>'));
+      }
     });
     Drupal.formBuilder.unsetActive();
     return false;
   }
 
+  if (!Drupal.formBuilder.fieldConfigureForm) {
+    $('<div id="#form-builder-field-configure" class="form-builder-field-configure"><div class="field-settings-message">' + Drupal.t('Loading...') + '</div></div>').appendTo(element);
+  } else {
+    $('.field-settings-message').remove();
+    Drupal.formBuilder.fieldConfigureForm.append($('<div class="field-settings-message">' + Drupal.t('Loading...') + '</div>'));
+  }
+  
+
   var getForm = function() {
-    $.ajax({
-      url: link.href,
+    Drupal.formBuilder.ajaxOptions = {
+      url: link.attr('href'),
       type: 'GET',
       dataType: 'json',
       data: 'js=1',
-      success: Drupal.formBuilder.displayForm
-    });
+      success: Drupal.formBuilder.displayForm,
+      error: Drupal.formBuilder.ajaxError,
+      errorMessage: Drupal.t('Form could not be loaded at this time. Please try again later.'),
+      tryCount: 0,
+      maxTry: 3
+    }
+    
+    $.ajax(Drupal.formBuilder.ajaxOptions);
   };
 
-  $(link).addClass('progress');
   Drupal.formBuilder.updatingElement = true;
   Drupal.formBuilder.closeActive(getForm);
-  Drupal.formBuilder.setActive(element, link);
+  Drupal.formBuilder.setActive(element, link.get(0));
 
   return false;
 };
@@ -342,15 +401,24 @@ Drupal.formBuilder.editField = function(
 /**
  * Click handler for deleting a field.
  */
-Drupal.formBuilder.deleteField = function() {
-  $(this).parents('div.form-builder-wrapper:first').animate({ height: 'hide', opacity: 'hide' }, 'normal', function() {
+Drupal.formBuilder.deleteField = function(callback) {
+  var active = $(Drupal.formBuilder.activeElement);
+  // Renable form submission.
+  $('form').unbind('submit', Drupal.formBuilder.preventSubmit);
+  active.fadeOut(function() {
     // If this is a unique field, show the field in the palette again.
-    var elementId = $(this).find('div.form-builder-element').attr('id');
+    var elementId = active.find('.form-builder-element').attr('id');
     $('ul.form-builder-fields').find('li.' + elementId).show('slow');
     // Remove the field from the form.
-    $(this).remove();
+    active.remove();
+    // Close the form and unset the active element
+    Drupal.formBuilder.clickCancel();
     // Check for empty fieldsets.
     Drupal.formBuilder.checkFieldsets(null, null, true);
+
+    if (callback && $.isFunction(callback)) {
+      callback();
+    }
   });
 };
 
@@ -364,8 +432,19 @@ Drupal.formBuilder.clickCancel = functio
  * Display the edit form from the server.
  */
 Drupal.formBuilder.displayForm = function(response) {
+  if (response.settings) {
+    $.extend(true, Drupal.settings, response.settings);
+  }
   var $preview = $('#form-builder-element-' + response.elementId);
-  var $form = $(response.html).insertAfter($preview).css('display', 'none');
+  var $form = $(response.html)
+  if (!Drupal.formBuilder.fieldConfigureForm) {
+    $('.form-builder-field-configure').html($form);
+    $form.css('display', 'none');
+  } else {
+    Drupal.formBuilder.fieldConfigureForm.html($form);
+    $form.css('visibility: hidden');
+  }
+  $('.field-settings-message').remove();
   Drupal.attachBehaviors($form.parent().get(0));
 
   $form
@@ -377,10 +456,13 @@ Drupal.formBuilder.displayForm = functio
     // Add in any messages from the server.
     .find('fieldset:visible:first').prepend(response.messages);
 
+  $form.css({visibility: 'visible', display: 'none'});
   $form.slideDown(function() {
-    $form.parents('div.form-builder-wrapper:first').find('a.progress').removeClass('progress');
+    $preview.parents('.form-builder-wrapper:first').find('a.progress').removeClass('progress');
   });
-  //Drupal.unfreezeHeight();
+
+  // Give focus to the form
+  $form.find('input:visible:first').focus();
 
   Drupal.formBuilder.updatingElement = false;
 };
@@ -390,10 +472,25 @@ Drupal.formBuilder.displayForm = functio
  */
 Drupal.formBuilder.elementChange = function() {
   if (!Drupal.formBuilder.updatingElement) {
-    $(this).parents('form:first').ajaxSubmit({
+    // Store the form and the options
+    var form = $(this).parents('form:first');
+    Drupal.formBuilder.ajaxOptions = {
+      url: form.attr('action'),
       success: Drupal.formBuilder.updateElement,
-      dataType: 'json'
-    });
+      error: Drupal.formBuilder.ajaxError,
+      type: 'post',
+      dataType: 'json',
+      errorMessage: Drupal.t('Field could not be updated at this time. Please try again later.'),
+      data: form.serialize(),
+      tryCount: 0,
+      maxTry: 3
+    };
+    // Submit the form via ajax
+    $.ajax(Drupal.formBuilder.ajaxOptions);
+
+    // Bind this action to disable any submit buttons on the page.  It will be
+    // removed on success or after the retries have been exhausted.
+    $('form').submit(Drupal.formBuilder.preventSubmit);
   }
 
   // Clear any pending updates until further changes are made.
@@ -404,6 +501,23 @@ Drupal.formBuilder.elementChange = funct
   Drupal.formBuilder.updatingElement = true;
 };
 
+Drupal.formBuilder.ajaxError = function (XMLHttpRequest, textStatus, errorThrown) {
+  var options = Drupal.formBuilder.ajaxOptions;
+  var message = this.errorMessage ? this.errorMessage : 'Unable to reach server.  Please try again later.';
+
+  options.tryCount++;
+  if (options.tryCount <= options.maxTry) {
+    $.ajax(options);
+  } else {
+    $('form').unbind('submit', Drupal.formBuilder.preventSubmit);
+    alert(message);
+  }
+};
+
+Drupal.formBuilder.preventSubmit = function (event) {
+  event.preventDefault();
+}
+
 /**
  * Update a field after a delay.
  *
@@ -435,7 +549,7 @@ Drupal.formBuilder.elementPendingChange 
  * After submitting the change to the server, display the updated element.
  */
 Drupal.formBuilder.updateElement = function(response) {
-  var $configureForm = $('#form-builder-field-configure');
+  var $configureForm = $('.form-builder-field-configure');
 
   // Do not let older requests replace newer updates.
   if (response.time < Drupal.formBuilder.lastUpdateTime) {
@@ -445,6 +559,11 @@ Drupal.formBuilder.updateElement = funct
     Drupal.formBuilder.lastUpdateTime = response.time;
   }
 
+  // Update Drupal.settings.
+  if (response.settings) {
+    $.extend(true, Drupal.settings, response.settings);
+  }
+
   // Set the error class on fields.
   $configureForm.find('.error').removeClass('error');
   if (response.errors) {
@@ -463,7 +582,7 @@ Drupal.formBuilder.updateElement = funct
   // Do not update the element if errors were received.
   if (!response.errors) {
     var $exisiting = $('#form-builder-element-' + response.elementId);
-    var $new = $(response.html).find('div.form-builder-element:first');
+    var $new = $(response.html).find('.form-builder-element:first');
     $exisiting.replaceWith($new);
 
     // Expand root level fieldsets after updating to prevent them from closing
@@ -474,6 +593,7 @@ Drupal.formBuilder.updateElement = funct
 
   // Set the variable stating we're done updating.
   Drupal.formBuilder.updatingElement = false;
+  $('form').unbind('submit', Drupal.formBuilder.preventSubmit);
 };
 
 /**
@@ -482,11 +602,30 @@ Drupal.formBuilder.updateElement = funct
 Drupal.formBuilder.addElement = function(response) {
   // This is very similar to the update element callback, only we replace the
   // entire wrapper instead of just the element.
-  var $exisiting = $('#form-builder-element-' + response.elementId).parent();
-  var $new = $(response.html).find('div.form-builder-element:first').parent();
+  if (response.settings) {
+    $.extend(true, Drupal.settings, response.settings);
+  }
+  var $exisiting = $('.form-builder-new-field');
+  var $new = $(response.html);
   $exisiting.replaceWith($new);
   Drupal.attachBehaviors($new.get(0));
 
+  $new.draggable('destroy');
+  $new.draggable({
+    opacity: 0.8,
+    helper: 'clone',
+    scroll: true,
+    scrollSensitivity: 50,
+    containment: 'body',
+    start: Drupal.formBuilder.startDrag,
+    stop: Drupal.formBuilder.stopDrag,
+    change: Drupal.formBuilder.checkFieldsets,
+    distance: 4,
+    scope: 'fields',
+    addClasses: false,
+    appendTo: '#form-builder-wrapper'
+  });
+
   // Set the variable stating we're done updating.
   Drupal.formBuilder.updatingElement = false;
 
@@ -494,7 +633,7 @@ Drupal.formBuilder.addElement = function
   $('#form-builder-positions').replaceWith(response.positionForm);
 
   // Submit the new positions form to save the new element position.
-  Drupal.formBuilder.updateElementPosition($new.get(0));
+  Drupal.formBuilder.updateElementPosition($new);
 };
 
 /**
@@ -502,15 +641,15 @@ Drupal.formBuilder.addElement = function
  */
 Drupal.formBuilder.updateElementPosition = function(element) {
   // Update weights of all children within this element's parent.
-  $(element).parent().children('div.form-builder-wrapper').each(function(index) {
-    var child_id = $(this).children('div.form-builder-element:first').attr('id');
+  element.parent().children('.form-builder-wrapper').each(function(index) {
+    var child_id = $(this).children('.form-builder-element:first').attr('id');
     $('#form-builder-positions input.form-builder-weight').filter('.' + child_id).val(index);
   });
 
   // Update this element's parent.
-  var $parent = $(element).parents('div.form-builder-element:first');
+  var $parent = element.parents('.form-builder-element:first');
   var parent_id = $parent.length ? $parent.attr('id').replace(/form-builder-element-(.*)/, '$1') : 0;
-  var child_id = $(element).children('div.form-builder-element:first').attr('id');
+  var child_id = element.children('.form-builder-element:first').attr('id');
   $('#form-builder-positions input.form-builder-parent').filter('.' + child_id).val(parent_id);
 
   // Submit the position form via AJAX to save the new weights and parents.
@@ -518,18 +657,6 @@ Drupal.formBuilder.updateElementPosition
 };
 
 /**
- * Called when a field is about to be moved via Sortables.
- *
- * @param e
- *   The event object containing status information about the event.
- * @param ui
- *   The jQuery Sortables object containing information about the sortable.
- */
-Drupal.formBuilder.startDrag = function(e, ui) {
-  Drupal.formBuilder.activeDragUi = ui;
-};
-
-/**
  * Called when a field has been moved via Sortables.
  *
  * @param e
@@ -537,37 +664,59 @@ Drupal.formBuilder.startDrag = function(
  * @param ui
  *   The jQuery Sortables object containing information about the sortable.
  */
-Drupal.formBuilder.stopDrag = function(e, ui) {
-  var element = ui.item.get(0);
+Drupal.formBuilder.drop = function(e, ui) {
+  var element = ui.draggable;
+  var placeholder = e.data ? $(e.data) : $(this);
+  
+  // If no drop target is hit, add the component to the end of the form.
+  if (placeholder.is('#form-builder')) {
+    placeholder = placeholder.children(':last');
+  } else if (placeholder.is('.form-builder-wrapper:not(.form-builder-empty-placeholder)')) {
+    placeholder = placeholder.next('.form-builder-placeholder');
+  }
 
   // If the element is a new field from the palette, update it with a real field.
-  if ($(element).is('.ui-draggable')) {
+  if (element.is('.ui-draggable')) {
     var name = 'new_' + new Date().getTime();
     // If this is a "unique" element, its element ID is hard-coded.
-    if ($(element).is('.form-builder-unique')) {
+    if (element.is('.form-builder-unique')) {
       name = element.className.replace(/^.*?form-builder-element-([a-z0-9_]+).*?$/, '$1');
     }
 
     var $ajaxPlaceholder = $('<div class="form-builder-wrapper form-builder-new-field"><div id="form-builder-element-' + name + '" class="form-builder-element"><span class="progress">' + Drupal.t('Please wait...') + '</span></div></div>');
+    placeholder.replaceWith($ajaxPlaceholder);
 
-    $.ajax({
-      url: $(element).find('a').get(0).href,
+    Drupal.formBuilder.ajaxOptions = {
+      url: element.find('a').attr('href'),
       type: 'GET',
       dataType: 'json',
       data: 'js=1&element_id=' + name,
-      success: Drupal.formBuilder.addElement
-    });
-
-    $(element).replaceWith($ajaxPlaceholder);
+      success: Drupal.formBuilder.addElement,
+      error: Drupal.formBuilder.ajaxError,
+      errorMessage: Drupal.t('Element could not be added at this time. Please try again later.'),
+      tryCount: 0,
+      maxTry: 3
+    };
+    $.ajax(Drupal.formBuilder.ajaxOptions);
 
     Drupal.formBuilder.updatingElement = true;
   }
   // Update the positions (weights and parents) in the form cache.
   else {
+    placeholder.replaceWith(element);
+    element.removeClass('original').show();
+    ui.helper.remove();
     Drupal.formBuilder.updateElementPosition(element);
+
+    // Select the element
+    element.find('a.configure').click();
   }
 
   Drupal.formBuilder.activeDragUi = false;
+  $('#form-builder .form-builder-placeholder').remove();
+  
+  // Update empty fieldsets
+  Drupal.formBuilder.checkFieldsets();
 
   // Scroll the palette into view.
   $(window).scroll();
@@ -581,10 +730,84 @@ Drupal.formBuilder.stopDrag = function(e
  * @param ui
  *   The jQuery Sortables object containing information about the sortable.
  */
-Drupal.formBuilder.startPaletteDrag = function(e, ui) {
-  if ($(this).is('.form-builder-unique')) {
-    $(this).css('visibility', 'hidden');
+Drupal.formBuilder.startDrag = function(e, ui) {
+  var $this = $(this);
+  // Check to see if this has been pulled out of a fieldset.
+  Drupal.formBuilder.checkFieldsets();
+
+  ui.helper.width($(this).width());
+
+  if ($this.is('.form-builder-unique')) {
+    $this.css('visibility', 'hidden');
+  }
+  if ($this.is('.form-builder-wrapper')) {
+    $this.hide();
+  }
+  $this.addClass('original');
+
+  var isPagebreak = false;
+  if ($this.children('.form-builder-element-pagebreak').length > 0) {
+    isPagebreak = true;
   }
+  if ($this.is('.field-pagebreak')) {
+    isPagebreak = true;
+  }
+
+  // Grab the formbuilder and fields and store the placeholder markup.
+  var formbuilder = $('#form-builder');
+  var fields = $('#form-builder').find('.form-builder-wrapper')
+    .not(this)
+    .not('.form-builder-empty-placeholder')
+    .not($('.original *'));
+  var placeholder = '<div class="form-builder-placeholder"></div>';
+
+  // Add a drop target at the bottom of the form.
+  $(placeholder).appendTo(formbuilder);
+
+  if (fields.length) {
+    // Insert a drop target after each field.
+    $(placeholder).insertBefore(fields);
+    // If we're not dragging a page break, add a drop target at the bottom of each fieldset.
+    if (!isPagebreak) {
+      $(placeholder).appendTo('.fieldset-wrapper:not(:has(.form-builder-empty-placeholder))');
+    }
+  } else {
+    // The form is empty, so make the placeholder at least the size of the form.
+    formbuilder.find('.form-builder-placeholder').css('min-height', formbuilder.css('height'));
+  }
+
+  var height = formbuilder.height();
+  formbuilder.children(':visible:not(.form-builder-placeholder)').each(function() {
+    height = height - $(this).outerHeight(true);
+  });
+  if (height > 0) {
+    $('.form-builder-placeholder:last').css('min-height', height);
+  }
+
+  // Activate all the placeholders as drop targets.
+  var placeholders = $('.form-builder-placeholder, .form-builder-empty-placeholder');
+  if (isPagebreak) {
+    placeholders = placeholders.not('.fieldset-wrapper .form-builder-placeholder').not('.fieldset-wrapper .form-builder-empty-placeholder');
+  }
+  
+  placeholders.droppable({
+    scope: 'fields',
+    tolerance: 'touch',
+    over: Drupal.formBuilder.over,
+    out: Drupal.formBuilder.out,
+    drop: Drupal.formBuilder.drop
+  });
+
+  // Add droppable to form elements without the over / out methods
+  $('.form-builder-wrapper').droppable({
+    scope: 'fields',
+    tolerance: 'touch',
+    drop: Drupal.formBuilder.drop
+  });
+
+  // Retain the dimensions of the draggable
+  ui.helper.width($this.width());
+  ui.helper.height($this.height());
 
   Drupal.formBuilder.activeDragUi = ui;
 };
@@ -597,52 +820,49 @@ Drupal.formBuilder.startPaletteDrag = fu
  * @param ui
  *   The jQuery Sortables object containing information about the sortable.
  */
-Drupal.formBuilder.stopPaletteDrag = function(e, ui) {
+Drupal.formBuilder.stopDrag = function(e, ui) {
+  var $this = $(this);
+  // Remove the droppable from all elements within the form
+  $('#form-builder .ui-droppable').droppable('destroy');
+
   // If the activeDragUi is still set, we did not drop onto the form.
   if (Drupal.formBuilder.activeDragUi) {
     ui.helper.remove();
     Drupal.formBuilder.activeDragUi = false;
-    $(this).css('visibility', '');
+    $this.css('visibility', '').show().removeClass('original');
     $(window).scroll();
+    // Remove the placeholders
+    $('#form-builder .form-builder-placeholder').remove();
+    
+    Drupal.formBuilder.checkFieldsets();
   }
   // If dropped onto the form and a unique field, remove it from the palette.
-  else if ($(this).is('.form-builder-unique')) {
-    $(this).animate({ height: '0', width: '0' }, function() {
-      $(this).css({ visibility: '', height: '', width: '', display: 'none' });
+  else if ($this.is('.form-builder-unique')) {
+    $this.animate({height: '0', width: '0'}, function() {
+      $this.css({visibility: '', height: '', width: '', display: 'none'});
     });
   }
 };
 
 /**
- * Update the indentation and width of elements as they move over fieldsets.
- *
- * This function is called on every mouse movement during a Sortables drag.
- *
- * @param e
- *   The event object containing status information about the event.
- * @param ui
- *   The jQuery Sortables object containing information about the sortable.
+ * These functions add and remove a class to a drop target and adjust its height
+ * to the height of the item being dragged.
  */
-Drupal.formBuilder.elementIndent = function(e, ui) {
-  var placeholder = ui.placeholder.get(0);
-  var helper = ui.helper.get(0);
-  var item = ui.item.get(0);
-
-  // Do not affect the elements being dragged from the pallette.
-  if ($(item).is('li')) {
-    return;
+Drupal.formBuilder.over = function(e, ui) {
+  var $this = $(this);
+  if (!$this.is('.form-builder-empty-placeholder')) {
+    $this.height(ui.draggable.height());
+  }
+  $this.parent().find('.over').height(0);
+  $this.addClass('over');
+}
+
+Drupal.formBuilder.out = function(e, ui) {
+  var $this = $(this);
+  if (!$this.is('.form-builder-empty-placeholder')) {
+    $this.height(0);
   }
-
-  // Turn on the placeholder item (which is in the final location) to take some stats.
-  $(placeholder).css('visibility', 'visible');
-  var difference = $(helper).width() - $(placeholder).width();
-  var offset = $(placeholder).offset().left;
-  $(placeholder).css('visibility', 'hidden');
-
-  // Adjust the helper to match the location and width of the real item.
-  var newWidth = $(helper).width() - difference;
-  $(helper).css('width', newWidth + 'px');
-  $(helper).css('left', offset + 'px');
+  $this.removeClass('over');
 };
 
 /**
@@ -658,39 +878,17 @@ Drupal.formBuilder.elementIndent = funct
  * @param
  */
 Drupal.formBuilder.checkFieldsets = function(e, ui, expand) {
-  var $fieldsets = $('#form-builder').find('div.form-builder-element > fieldset.form-builder-fieldset');
-  var emptyFieldsets = [];
-
-  // Remove all current fieldset placeholders.
-  $fieldsets.find('.ui-sortable-placeholder').siblings('div.form-builder-empty-placeholder').remove();
+  var $fieldsets = $('#form-builder div.form-builder-element fieldset.form-builder-fieldset div.fieldset-wrapper');
 
   // Find all empty fieldsets.
   $fieldsets.each(function() {
-    // Check for empty collapsible fieldsets.
-    if ($(this).children('div.fieldset-wrapper').length) {
-      if ($(this).children('div.fieldset-wrapper').children(':not(.description):visible, .ui-sortable-placeholder').length == 0) {
-        emptyFieldsets.push(this);
+    // Remove placeholders.
+    $(this).children('.form-builder-empty-placeholder').remove();
+    // If there are no visible children after placeholders are removed, add a placeholder.
+    if ($(this).children(':not(.description):visible').length == 0) {
+      $(Drupal.settings.formBuilder.emptyFieldset).appendTo(this);
       }
-    }
-    // Check for empty normal fieldsets.
-    if ($(this).children(':not(legend, .description):visible, .ui-sortable-placeholder').length == 0) {
-      emptyFieldsets.push(this);
-    }
   });
-
-  // Add a placeholder DIV in the empty fieldsets.
-  $(emptyFieldsets).each(function() {
-    var wrapper = $(this).children('div.fieldset-wrapper').get(0) || this;
-    var $placeholder = $(Drupal.settings.formBuilder.emptyFieldset).css('display', 'none').appendTo(wrapper);
-    if (expand) {
-      $placeholder.slideDown();
-    }
-    else {
-      $placeholder.css('display', 'block');
-    }
-  });
-
-  $('#form-builder').sortable('refresh');
 };
 
 Drupal.formBuilder.setActive = function(element, link) {
@@ -710,13 +908,13 @@ Drupal.formBuilder.unsetActive = functio
 
 Drupal.formBuilder.closeActive = function(callback) {
   if (Drupal.formBuilder.activeElement) {
-    var $activeForm = $(Drupal.formBuilder.activeElement).find('form');
+    var $activeForm = Drupal.formBuilder.fieldConfigureForm ? Drupal.formBuilder.fieldConfigureForm.find('form') : $(Drupal.formBuilder.activeElement).find('form');
 
     if ($activeForm.length) {
       Drupal.freezeHeight();
       $activeForm.slideUp(function(){
         $(this).remove();
-        if (callback) {
+        if (callback && $.isFunction(callback)) {
           callback.call();
         }
       });
Index: form_builder.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/form_builder/form_builder.module,v
retrieving revision 1.16
diff -u -p -r1.16 form_builder.module
--- form_builder.module	12 Jan 2011 04:00:19 -0000	1.16
+++ form_builder.module	1 Feb 2011 16:02:09 -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',
     ),
   );
@@ -96,40 +88,37 @@ function form_builder_theme() {
 /**
  * Implementation of hook_block().
  */
-function form_builder_block($op = 'list', $delta = 0, $edit = array()) {
-  if ($op == 'list') {
-    $blocks['fields'] = array(
-      'info' => t('Form builder fields'),
-      'weight' => 0,
-    );
+function form_builder_block_info() {
+  $blocks['fields'] = array(
+    'info' => t('Form builder fields'),
+  );
 
-    return $blocks;
-  }
+  return $blocks;
+}
 
-  if ($op == 'view') {
-    switch($delta) {
-      case 'fields':
-        if ($active = form_builder_active_form()) {
-          $fields = form_builder_get_form_type($active['form_type']);
-          $groups = module_invoke_all('form_builder_palette_groups');
-          // TODO: We shouldn't have to clear the cache here.
-          $form = form_builder_cache_load($active['form_type'], $active['form_id'], NULL, TRUE);
-          $active_fields = form_builder_get_element_ids($form);
-          foreach ($fields as $key => $field) {
-            if ($field['unique'] && in_array($key, $active_fields)) {
-              $fields[$key]['in_use'] = TRUE;
-            }
-            if ($field['addable'] == FALSE) {
-              unset($fields[$key]);
-            }
+function form_builder_block_view($delta = '') {
+  $block = array();
+  switch($delta) {
+    case 'fields':
+      if ($active = form_builder_active_form()) {
+        $fields = form_builder_get_form_type($active['form_type']);
+        $groups = module_invoke_all('form_builder_palette_groups');
+        // TODO: We shouldn't have to clear the cache here.
+        $form = form_builder_cache_load($active['form_type'], $active['form_id'], NULL, TRUE);
+        $active_fields = form_builder_get_element_ids($form);
+        foreach ($fields as $key => $field) {
+          if ($field['unique'] && in_array($key, $active_fields)) {
+            $fields[$key]['in_use'] = TRUE;
+          }
+          if ($field['addable'] == FALSE) {
+            unset($fields[$key]);
           }
-          return array(
-            'content' => theme('form_builder_field_palette', $fields, $groups, $active['form_type'], $active['form_id']),
-          );
         }
-        break;
-    }
+        $block['content'] = theme('form_builder_field_palette', array('fields' => $fields, 'groups' => $groups, 'form_type' => $active['form_type'], 'form_id' => $active['form_id']));
+      }
+      break;
   }
+  return $block;
 }
 
 /**
Index: includes/form_builder.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/form_builder/includes/form_builder.admin.inc,v
retrieving revision 1.20
diff -u -p -r1.20 form_builder.admin.inc
--- includes/form_builder.admin.inc	12 Jan 2011 04:05:28 -0000	1.20
+++ includes/form_builder.admin.inc	1 Feb 2011 16:02:09 -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_render(drupal_get_form('form_builder_positions', $preview_form, $form_type, $form_id)),
-        'messages' => theme('status_messages'),
       );
 
-      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');
@@ -282,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()));
     }
@@ -343,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>';
@@ -426,25 +411,26 @@ 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 (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.
@@ -455,6 +441,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 ($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;
 }
 
@@ -542,16 +539,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) {
@@ -583,7 +576,7 @@ function theme_form_builder_field_config
     }
   }
 
-  return drupal_render_children($form);
+  return $form;
 }
 
 function form_builder_field_configure_submit(&$form, &$form_state) {
@@ -696,17 +689,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);
 }
 
 /**
@@ -723,10 +710,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);
+}
Index: includes/form_builder.properties.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/form_builder/includes/form_builder.properties.inc,v
retrieving revision 1.16
diff -u -p -r1.16 form_builder.properties.inc
--- includes/form_builder.properties.inc	12 Jan 2011 04:00:19 -0000	1.16
+++ includes/form_builder.properties.inc	1 Feb 2011 16:02:10 -0000
@@ -65,10 +65,10 @@ function form_builder_property_title_dis
     '#type' => 'select',
     '#default_value' => $element['#title_display'],
     '#options' => array(
-      'before' => t('Before'),
-      'after' => t('After'),
-      'invisible' => t('Invisible'),
-      'attribute' => t('Attribute'),
+      'before' => 'before',
+      'after' => 'after',
+      'invisible' => 'invisible',
+      'attribute' => 'attribute',
     ),
     '#required' => TRUE,
     '#weight' => -10,
