? ___form_builder___js___3bWSwY
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	30 Dec 2010 21:48:47 -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.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	30 Dec 2010 21:48:47 -0000
@@ -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);
-  }
 };
 
 /**
@@ -227,10 +221,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);
     });
   }
 };
@@ -487,6 +500,22 @@ Drupal.formBuilder.addElement = function
   $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;
 
@@ -537,18 +566,27 @@ 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,
@@ -558,16 +596,21 @@ Drupal.formBuilder.stopDrag = function(e
       success: Drupal.formBuilder.addElement
     });
 
-    $(element).replaceWith($ajaxPlaceholder);
-
     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);
   }
 
   Drupal.formBuilder.activeDragUi = false;
+  $('#form-builder .form-builder-placeholder').remove();
+  
+  // Update empty fieldsets
+  Drupal.formBuilder.checkFieldsets();
 
   // Scroll the palette into view.
   $(window).scroll();
@@ -581,11 +624,85 @@ 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,13 +714,19 @@ 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) {
+  // 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')) {
@@ -614,35 +737,24 @@ Drupal.formBuilder.stopPaletteDrag = fun
 };
 
 /**
- * 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.helper.outerHeight(true));
+  }
+  $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');
 };
 
 /**
