? drupal_ahah2.patch
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.227
diff -u -p -r1.227 form.inc
--- includes/form.inc	25 Sep 2007 15:14:37 -0000	1.227
+++ includes/form.inc	1 Oct 2007 12:30:35 -0000
@@ -1575,7 +1575,7 @@ function expand_radios($element) {
 
 /**
  * Add AHAH information about a form element to the page to communicate with
- * javascript. If #ahah_path is set on an element, this additional javascript is
+ * javascript. If #ahah[path] is set on an element, this additional javascript is
  * added to the page header to attach the AHAH behaviors. See ahah.js for more
  * information.
  *
@@ -1590,24 +1590,43 @@ function expand_radios($element) {
 function form_expand_ahah($element) {
   static $js_added = array();
 
+  // Add a reasonable default event handler if none specified.
+  if (isset($element['#ahah']['path']) && !isset($element['#ahah']['event'])) {
+    switch ($element['#type']) {
+      case 'submit':
+      case 'button':
+      case 'image_button':
+        $element['#ahah']['event'] = 'click';
+        break;
+      case 'password':
+      case 'textfield':
+      case 'textarea':
+        $element['#ahah']['event'] = 'blur';
+        break;
+      case 'radio':
+      case 'checkbox':
+      case 'select':
+        $element['#ahah']['event'] = 'change';
+        break;
+    }
+  }
+
   // Adding the same javascript settings twice will cause a recursion error,
   // we avoid the problem by checking if the javascript has already been added.
-  if (!isset($js_added[$element['#id']]) && isset($element['#ahah_event']) && isset($element['#ahah_path'])) {
+  if (isset($element['#ahah']['path']) && isset($element['#ahah']['event']) && !isset($js_added[$element['#id']])) {
+    drupal_add_js('misc/jquery.form.js');
     drupal_add_js('misc/ahah.js');
     drupal_add_js('misc/progress.js');
 
     $ahah_binding = array(
-      'id' => $element['#id'],
-      'uri' => url($element['#ahah_path']),
-      'event' => $element['#ahah_event'],
-      'effect' => empty($element['#ahah_effect']) ? 'none' : $element['#ahah_effect'],
-      'method' => empty($element['#ahah_method']) ? 'replace' : $element['#ahah_method'],
+      'url'   => url($element['#ahah']['path']),
+      'event' => $element['#ahah']['event'],
+      'wrapper' => empty($element['#ahah']['wrapper']) ? NULL : $element['#ahah']['wrapper'],
+      'selector' => empty($element['#ahah']['selector']) ? '#'. $element['#id'] : $element['#ahah']['selector'],
+      'effect'   => empty($element['#ahah']['effect']) ? 'none' : $element['#ahah']['effect'],
+      'method'   => empty($element['#ahah']['method']) ? 'replace' : $element['#ahah']['method'],
     );
 
-    if (!empty($element['#ahah_wrapper'])) {
-      $ahah_binding['wrapper'] = $element['#ahah_wrapper'];
-    }
-
     drupal_add_js(array('ahah' => array($element['#id'] => $ahah_binding)), 'setting');
 
     $js_added[$element['#id']] = TRUE;
Index: misc/ahah.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/ahah.js,v
retrieving revision 1.2
diff -u -p -r1.2 ahah.js
--- misc/ahah.js	12 Sep 2007 18:29:31 -0000	1.2
+++ misc/ahah.js	1 Oct 2007 12:30:35 -0000
@@ -7,8 +7,8 @@
  * page. The request returns a small chunk of HTML, which is then directly
  * injected into the page.
  *
- * Drupal uses this file to enhance form elements with #ahah_path and
- * #ahah_wrapper properties. If set, this file will automatically be included
+ * Drupal uses this file to enhance form elements with #ahah[path] and
+ * #ahah[wrapper] properties. If set, this file will automatically be included
  * to provide AHAH capabilities.
  */
 
@@ -18,8 +18,13 @@
 Drupal.behaviors.ahah = function(context) {
   for (var base in Drupal.settings.ahah) {
     if (!$('#'+ base + '.ahah-processed').size()) {
-      var element = Drupal.settings.ahah[base];
-      var ahah = new Drupal.ahah(base, element);
+      var element_settings = Drupal.settings.ahah[base];
+
+      $(element_settings.selector).each(function() {
+        element_settings.element = this;
+        var ahah = new Drupal.ahah(base, element_settings);
+      });
+
       $('#'+ base).addClass('ahah-processed');
     }
   }
@@ -28,95 +33,147 @@ Drupal.behaviors.ahah = function(context
 /**
  * AHAH object.
  */
-Drupal.ahah = function(base, element) {
+Drupal.ahah = function(base, element_settings) {
   // Set the properties for this object.
-  this.id = '#' + base;
-  this.event = element.event;
-  this.uri = element.uri;
-  this.wrapper = '#'+ element.wrapper;
-  this.effect = element.effect;
-  this.method = element.method;
+  this.element = element_settings.element;
+  this.selector = element_settings.selector;
+  this.event = element_settings.event;
+  this.url = element_settings.url;
+  this.wrapper = '#'+ element_settings.wrapper;
+  this.effect = element_settings.effect;
+  this.method = element_settings.method;
   if (this.effect == 'none') {
     this.showEffect = 'show';
     this.hideEffect = 'hide';
+    this.showSpeed = '';
   }
   else if (this.effect == 'fade') {
     this.showEffect = 'fadeIn';
     this.hideEffect = 'fadeOut';
+    this.showSpeed = 'slow';
   }
   else {
     this.showEffect = this.effect + 'Toggle';
     this.hideEffect = this.effect + 'Toggle';
+    this.showSpeed = 'slow';
   }
-  Drupal.redirectFormButton(this.uri, $(this.id).get(0), this);
+
+  // Record the form action and target, needed for iFrame file uploads.
+  var form = $(this.element).parents('form');
+  this.form_action = form.attr('action');
+  this.form_target = form.attr('target');
+  this.form_encattr = form.attr('encattr');
+
+  // Set the options for the ajaxSubmit function.
+  // The 'this' variable will not persist inside of the options object.
+  var ahah = this;
+  var options = {
+    url: ahah.url,
+    beforeSubmit: function(form_values, element_settings, options) {
+      return ahah.beforeSubmit(form_values, element_settings, options);
+    },
+    success: function(response, status) {
+      // Sanity check for browser support (object expected).
+      // When using iFrame uploads, responses must be returned as a string.
+      if (typeof(response) == 'string') {
+        response = Drupal.parseJson(response);
+      }
+      return ahah.success(response, status);
+    },
+    complete: function(response, status) {
+      if (status == 'error') {
+        return ahah.error(response.responseText);
+      }
+    },
+    dataType: 'json',
+    type: 'POST'
+  };
+
+  // Bind the ajaxSubmit function to the element event.
+  $(element_settings.element).bind(element_settings.event, function() {
+    $(element_settings.element).parents('form').ajaxSubmit(options);
+    return false;
+  });
 };
 
 /**
  * Handler for the form redirection submission.
  */
-Drupal.ahah.prototype.onsubmit = function () {
+Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) {
   // Insert progressbar and stretch to take the same space.
   this.progress = new Drupal.progressBar('ahah_progress');
   this.progress.setProgress(-1, Drupal.t('Please wait...'));
 
-  var wrapper = $(this.wrapper);
-  var button = $(this.id);
-  var progress_element = $(this.progress.element);
-
-  progress_element.css('float', 'left').css({
-    display: 'none',
-    width: '10em',
-    margin: '0 0 0 20px'
-  });
-  button.css('float', 'left').attr('disabled', true).after(progress_element);
-  if (progress_element[this.showEffect]) {
-    progress_element[this.showEffect]();
-  }
+  var progress_element = $(this.progress.element).addClass('ahah-progress');
+  $(this.element).addClass('progress-disabled').attr('disabled', true).after(progress_element);
 };
 
 /**
  * Handler for the form redirection completion.
  */
-Drupal.ahah.prototype.oncomplete = function (data) {
+Drupal.ahah.prototype.success = function (response, status) {
   var wrapper = $(this.wrapper);
-  var button = $(this.id);
+  var form = $(this.element).parents('form');
   var progress_element = $(this.progress.element);
-  var new_content = $('<div>' + data + '</div>');
-
-  Drupal.freezeHeight();
+  // Manually insert HTML into the jQuery object, using $() directly crashes
+  // Safari with long string lengths. http://dev.jquery.com/ticket/1152
+  var new_content = $('<div></div>').html(response.data);
+
+  // Restore the previous action and target to the form.
+  form.attr('action', this.form_action);
+  this.form_target ? form.attr('target', this.form_target) : form.removeAttr('target');
+  this.form_encattr ? form.attr('target', this.form_encattr) : form.removeAttr('encattr');
 
   // Remove the progress element.
   progress_element.remove();
+  $(this.element).removeClass('progess-disabled').attr('disabled', false);
 
   // Hide the new content before adding to page.
-  new_content.hide();
+  if (this.showEffect != 'show') {
+    new_content.hide();
+  }
 
-  // Add the form and re-attach behavior.
+  // Add the new content to the page.
+  Drupal.freezeHeight();
   if (this.method == 'replace') {
     wrapper.empty().append(new_content);
   }
-  else if (wrapper[this.method]) {
+  else {
     wrapper[this.method](new_content);
   }
-  if (new_content[this.showEffect]) {
-    new_content[this.showEffect]();
+
+  // Determine what effect use and what content will receive the effect,
+  // then show the new content.
+  if ($('.ahah-new-content', new_content).size() > 0) {
+    $('.ahah-new-content', new_content).hide();
+    new_content.show();
+    $(".ahah-new-content", new_content)[this.showEffect](this.showSpeed);
+  }
+  else if (this.showEffect != 'show') {
+    new_content[this.showEffect](this.showSpeed);
+  }
+
+  // Attach all javascript behaviors to the new content, if it was successfully
+  // added to the page, this if statement allows #ahah[wrapper] to be optional.
+  if (new_content.parents('html').length > 0) {
+    Drupal.attachBehaviors(new_content);
   }
-  button.css('float', 'none').attr('disabled', false);
 
-  Drupal.attachBehaviors(new_content);
   Drupal.unfreezeHeight();
 };
 
 /**
  * Handler for the form redirection error.
  */
-Drupal.ahah.prototype.onerror = function (error) {
+Drupal.ahah.prototype.error = function (error) {
   alert(Drupal.t('An error occurred:\n\n@error', { '@error': error }));
+  // Resore the previous action and target to the form.
+  element.parent('form').attr( { action: this.form_action, target: this.form_target} );
   // Remove progressbar.
   $(this.progress.element).remove();
   this.progress = null;
   // Undo hide.
   $(this.wrapper).show();
   // Re-enable the element.
-  $(this.id).css('float', 'none').attr('disabled', false);
+  $(this.element).removeClass('progess-disabled').attr('disabled', false);
 };
Index: misc/drupal.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/drupal.js,v
retrieving revision 1.39
diff -u -p -r1.39 drupal.js
--- misc/drupal.js	25 Sep 2007 14:55:36 -0000	1.39
+++ misc/drupal.js	1 Oct 2007 12:30:36 -0000
@@ -181,103 +181,15 @@ Drupal.theme = function(func) {
 };
 
 /**
- * Redirects a button's form submission to a hidden iframe and displays the result
- * in a given wrapper. The iframe should contain a call to
- * window.parent.iframeHandler() after submission.
- */
-Drupal.redirectFormButton = function (uri, button, handler) {
-  // Trap the button
-  button.onmouseover = button.onfocus = function() {
-    button.onclick = function() {
-      // Create target iframe
-      Drupal.deleteIframe();
-      Drupal.createIframe();
-
-      // Prepare variables for use in anonymous function.
-      var button = this;
-      var action = button.form.action;
-      var target = button.form.target;
-
-      // Redirect form submission to iframe
-      this.form.action = uri;
-      this.form.target = 'redirect-target';
-      this.form.submit();
-
-      handler.onsubmit();
-
-      // Set iframe handler for later
-      window.iframeHandler = function () {
-        var iframe = $('#redirect-target').get(0);
-        // Restore form submission
-        button.form.action = action;
-        button.form.target = target;
-
-        // Get response from iframe body
-        try {
-          response = (iframe.contentWindow || iframe.contentDocument || iframe).document.body.innerHTML;
-          // Firefox 1.0.x hack: Remove (corrupted) control characters
-          response = response.replace(/[\f\n\r\t]/g, ' ');
-          if (window.opera) {
-            // Opera-hack: it returns innerHTML sanitized.
-            response = response.replace(/&quot;/g, '"');
-          }
-        }
-        catch (e) {
-          response = null;
-        }
-
-        response = eval('('+ response +');');
-        // Check response code
-        if (!response || response.status == 0) {
-          handler.onerror(response.data || Drupal.t('Error parsing response'));
-          return;
-        }
-        handler.oncomplete(response.data);
-
-        return true;
-      };
-
-      return true;
-    };
-  };
-  button.onmouseout = button.onblur = function() {
-    button.onclick = null;
-  };
-};
-
-/**
- * Create an invisible iframe for form submissions.
- */
-Drupal.createIframe = function () {
-  if ($('#redirect-holder').size()) {
-    return;
+ * Parse a JSON response.
+ *
+ * The result is either the JSON object, or an object with 'status' 0 and 'data' an error message.
+ */
+Drupal.parseJson = function (data) {
+  if ((data.substring(0, 1) != '{') && (data.substring(0, 1) != '[')) {
+    return { status: 0, data: data.length ? data : Drupal.t('Unspecified error') };
   }
-  // Note: some browsers require the literal name/id attributes on the tag,
-  // some want them set through JS. We do both.
-  window.iframeHandler = function () {};
-  var div = document.createElement('div');
-  div.id = 'redirect-holder';
-  $(div).html('<iframe name="redirect-target" id="redirect-target" class="redirect" onload="window.iframeHandler();"></iframe>');
-  var iframe = div.firstChild;
-  $(iframe)
-    .attr({
-      name: 'redirect-target',
-      id: 'redirect-target'
-    })
-    .css({
-      position: 'absolute',
-      height: '1px',
-      width: '1px',
-      visibility: 'hidden'
-    });
-  $('body').append(div);
-};
-
-/**
- * Delete the invisible iframe
- */
-Drupal.deleteIframe = function () {
-  $('#redirect-holder').remove();
+  return eval('(' + data + ');');
 };
 
 /**
Index: misc/jquery.form.js
===================================================================
RCS file: misc/jquery.form.js
diff -N misc/jquery.form.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ misc/jquery.form.js	1 Oct 2007 12:30:36 -0000
@@ -0,0 +1,14 @@
+// $Id$
+
+/*
+ * jQuery form plugin
+ * @requires jQuery v1.1 or later
+ *
+ * Examples at: http://malsup.com/jquery/form/
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Version: 1.0.3
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5($){$.7.1f=5(o){3(H o==\'5\')o={K:o};o=$.25({1b:4.R(\'1J\')||1i.2q,P:4.R(\'2b\')||\'27\'},o||{});2 a=4.1v(o.2V);3(o.1M&&o.1M(a,4,o)===F)6 4;2 p={};$.N.O(\'Y.G.2m\',[a,4,o,p]);3(p.3s)6 4;2 q=$.1A(a);3(o.P.3j()==\'27\'){o.1b+=(o.1b.3g(\'?\')>=0?\'&\':\'?\')+q;o.19=B}A o.19=q;2 r=4,M=[];3(o.1p)M.C(5(){r.1p()});3(o.1o)M.C(5(){r.1o()});3(!o.16&&o.15){2 u=o.K;M.C(5(a){$(o.15).R("1K",a).2I().Q(u,2C)})}A 3(o.K)M.C(o.K);o.K=5(a,b){J(2 i=0,D=M.E;i<D;i++)M[i](a,b,r)};2 v=$(\'12:2p\',4).11();2 w=F;J(2 j=0;j<v.E;j++)3(v[j])w=18;3(o.2h||w)2d();A $.3p(o);$.N.O(\'Y.G.3o\',[4,o]);6 4;5 2d(){2 d=r[0];2 f=$.25({},$.3i,o);2 h=\'3e\'+$.7.1f.1e++;2 i=$(\'<2h 3a="\'+h+\'" 8="\'+h+\'" />\');2 j=i[0];2 k=$.1w.1Z&&1i.1Z.32()<9;3($.1w.1W||k)j.2Z=\'2Y:F;1l.2X("");\';i.2W({2U:\'2T\',1Q:\'-1R\',1N:\'-1R\'});2 l={X:B,1d:B,2O:0,2N:\'n/a\',2J:5(){},2H:5(){},2F:5(){}};2 g=f.2E;3(g&&!$.2c++)$.N.O("2z");3(g)$.N.O("2y",[l,f]);2 m=0;2 n=0;1a(5(){i.2u(\'1j\');j.1I?j.1I(\'1H\',V):j.2t(\'1G\',V,F);2 a=d.1F?\'1F\':\'2s\';2 t=r.R(\'15\');r.R({15:h,2b:\'2r\',2o:\'2n/Y-19\',1J:f.1b});3(f.1h)1a(5(){n=18;V()},f.1h);d.G();r.R(\'15\',t)},10);5 V(){3(m++)6;j.1C?j.1C(\'1H\',V):j.2l(\'1G\',V,F);2 a=18;2k{3(n)2j\'1h\';2 b,I;I=j.2i?j.2i.1l:j.2g?j.2g:j.1l;l.X=I.1j?I.1j.1K:B;l.1d=I.2f?I.2f:I;3(f.16==\'2e\'||f.16==\'3r\'){2 c=I.1B(\'1z\')[0];b=c?c.z:l.X;3(f.16==\'2e\')3n("19 = "+b);A $.3k(b)}A 3(f.16==\'2a\'){b=l.1d;3(!b&&l.X!=B)b=29(l.X)}A{b=l.X}}3h(e){a=F;$.3f(f,l,\'26\',e)}3(a){f.K(b,\'K\');3(g)$.N.O("3d",[l,f])}3(g)$.N.O("3c",[l,f]);3(g&&!--$.2c)$.N.O("3b");3(f.24)f.24(l,a?\'K\':\'26\');1a(5(){i.39();l.1d=B},38)};5 29(s,a){3(1i.22){a=21 22(\'37.36\');a.35=\'F\';a.34(s)}A a=(21 33()).31(s,\'1u/2a\');6(a&&a.1X&&a.1X.1t!=\'30\')?a:B}}};$.7.1f.1e=0;$.7.T=5(a){6 4.1V().G(1s).Q(5(){4.1r=$.7.T.1e++;$.7.T.1q[4.1r]=a;$(":G,12:U",4).1U(1m)})};$.7.T.1e=1;$.7.T.1q={};5 1m(e){2 a=4.Y;a.L=4;3(4.P==\'U\'){3(e.1T!=17){a.S=e.1T;a.Z=e.2S}A 3(H $.7.1P==\'5\'){2 b=$(4).1P();a.S=e.1S-b.1N;a.Z=e.1O-b.1Q}A{a.S=e.1S-4.2R;a.Z=e.1O-4.2Q}}1a(5(){a.L=a.S=a.Z=B},10)};5 1s(){2 a=4.1r;2 b=$.7.T.1q[a];$(4).1f(b);6 F};$.7.1V=5(){4.1Y(\'G\',1s);6 4.Q(5(){$(":G,12:U",4).1Y(\'1U\',1m)})};$.7.1v=5(b){2 a=[];3(4.E==0)6 a;2 c=4[0];2 d=b?c.1B(\'*\'):c.2P;3(!d)6 a;J(2 i=0,D=d.E;i<D;i++){2 e=d[i];2 n=e.8;3(!n)1x;3(b&&c.L&&e.P=="U"){3(!e.1n&&c.L==e)a.C({8:n+\'.x\',z:c.S},{8:n+\'.y\',z:c.Z});1x}2 v=$.11(e,18);3(v&&v.1c==1g){J(2 j=0,1L=v.E;j<1L;j++)a.C({8:n,z:v[j]})}A 3(v!==B&&H v!=\'17\')a.C({8:n,z:v})}3(!b&&c.L){2 f=c.1B("12");J(2 i=0,D=f.E;i<D;i++){2 g=f[i];2 n=g.8;3(n&&!g.1n&&g.P=="U"&&c.L==g)a.C({8:n+\'.x\',z:c.S},{8:n+\'.y\',z:c.Z})}}6 a};$.7.2M=5(a){6 $.1A(4.1v(a))};$.7.2L=5(b){2 a=[];4.Q(5(){2 n=4.8;3(!n)6;2 v=$.11(4,b);3(v&&v.1c==1g){J(2 i=0,D=v.E;i<D;i++)a.C({8:n,z:v[i]})}A 3(v!==B&&H v!=\'17\')a.C({8:4.8,z:v})});6 $.1A(a)};$.7.11=5(a){J(2 b=[],i=0,D=4.E;i<D;i++){2 c=4[i];2 v=$.11(c,a);3(v===B||H v==\'17\'||(v.1c==1g&&!v.E))1x;v.1c==1g?$.2K(b,v):b.C(v)}6 b};$.11=5(b,c){2 n=b.8,t=b.P,W=b.1t.20();3(H c==\'17\')c=18;3(c&&(!n||b.1n||t==\'14\'||t==\'2G\'||(t==\'23\'||t==\'1E\')&&!b.1D||(t==\'G\'||t==\'U\')&&b.Y&&b.Y.L!=b||W==\'13\'&&b.1k==-1))6 B;3(W==\'13\'){2 d=b.1k;3(d<0)6 B;2 a=[],1y=b.2D;2 e=(t==\'13-2B\');2 f=(e?d+1:1y.E);J(2 i=(e?d:0);i<f;i++){2 g=1y[i];3(g.2A){2 v=$.1w.1W&&!(g.3l[\'z\'].3m)?g.1u:g.z;3(e)6 v;a.C(v)}}6 a}6 b.z};$.7.1o=5(){6 4.Q(5(){$(\'12,13,1z\',4).28()})};$.7.28=$.7.2x=5(){6 4.Q(5(){2 t=4.P,W=4.1t.20();3(t==\'1u\'||t==\'2w\'||W==\'1z\')4.z=\'\';A 3(t==\'23\'||t==\'1E\')4.1D=F;A 3(W==\'13\')4.1k=-1})};$.7.1p=5(){6 4.Q(5(){3(H 4.14==\'5\'||(H 4.14==\'3q\'&&!4.14.2v))4.14()})}})(3t);',62,216,'||var|if|this|function|return|fn|name|||||||||||||||||||||||||||value|else|null|push|max|length|false|submit|typeof|doc|for|success|clk|callbacks|event|trigger|type|each|attr|clk_x|ajaxForm|image|cb|tag|responseText|form|clk_y||fieldValue|input|select|reset|target|dataType|undefined|true|data|setTimeout|url|constructor|responseXML|counter|ajaxSubmit|Array|timeout|window|body|selectedIndex|document|clickHandler|disabled|clearForm|resetForm|optionHash|formPluginId|submitHandler|tagName|text|formToArray|browser|continue|ops|textarea|param|getElementsByTagName|detachEvent|checked|radio|encoding|load|onload|attachEvent|action|innerHTML|jmax|beforeSubmit|left|pageY|offset|top|1000px|pageX|offsetX|click|ajaxFormUnbind|msie|documentElement|unbind|opera|toLowerCase|new|ActiveXObject|checkbox|complete|extend|error|GET|clearFields|toXml|xml|method|active|fileUpload|json|XMLDocument|contentDocument|iframe|contentWindow|throw|try|removeEventListener|validate|multipart|encAttr|file|location|POST|enctype|addEventListener|appendTo|nodeType|password|clearInputs|ajaxSend|ajaxStart|selected|one|arguments|options|global|setRequestHeader|button|getResponseHeader|evalScripts|getAllResponseHeaders|merge|fieldSerialize|formSerialize|statusText|status|elements|offsetTop|offsetLeft|offsetY|absolute|position|semantic|css|write|javascript|src|parsererror|parseFromString|version|DOMParser|loadXML|async|XMLDOM|Microsoft|100|remove|id|ajaxStop|ajaxComplete|ajaxSuccess|jqFormIO|handleError|indexOf|catch|ajaxSettings|toUpperCase|globalEval|attributes|specified|eval|notify|ajax|object|script|veto|jQuery'.split('|'),0,{}))
Index: modules/block/block-admin-display-form.tpl.php
===================================================================
RCS file: modules/block/block-admin-display-form.tpl.php
diff -N modules/block/block-admin-display-form.tpl.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/block/block-admin-display-form.tpl.php	1 Oct 2007 12:30:36 -0000
@@ -0,0 +1,67 @@
+<?php
+// $Id: block-admin-display.tpl.php,v 1.2 2007/08/07 08:39:35 goba Exp $
+
+/**
+ * @file block-admin-display-form.tpl.php
+ * Default theme implementation to configure blocks.
+ *
+ * Available variables:
+ * - $block_listing: An array of block controls within regions.
+ * - $form_submit: Form submit button.
+ * - $throttle: TRUE or FALSE depending on throttle module being enabled.
+ *
+ * Each $data in $block_listing contains:
+ * - $data->is_region_first: TRUE or FALSE depending on the listed blocks
+ *   positioning. Used here to insert a region header.
+ * - $data->region_title: Region title for the listed block.
+ * - $data->block_title: Block title.
+ * - $data->region_select: Drop-down menu for assigning a region.
+ * - $data->weight_select: Drop-down menu for setting weights.
+ * - $data->throttle_check: Checkbox to enable throttling.
+ * - $data->configure_link: Block configuration link.
+ * - $data->delete_link: For deleting user added blocks.
+ *
+ * @see template_preprocess_block_admin_display_form()
+ * @see theme_block_admin_display()
+ */
+?>
+<?php drupal_add_js('misc/tableheader.js'); ?>
+<?php print $messages; ?>
+
+<table id="blocks">
+  <thead>
+    <tr>
+      <th><?php print t('Block'); ?></th>
+      <th><?php print t('Region'); ?></th>
+      <th><?php print t('Weight'); ?></th>
+      <?php if ($throttle): ?>
+        <th><?php print t('Throttle'); ?></th>
+      <?php endif; ?>
+      <th colspan="2"><?php print t('Operations'); ?></th>
+    </tr>
+  </thead>
+  <tbody>
+    <?php $row = 0; ?>
+    <?php foreach ($block_listing as $data): ?>
+      <?php if ($data->is_region_first): ?>
+      <tr class="<?php print $row % 2 == 0 ? 'odd' : 'even'; ?>">
+        <td colspan="<?php print $throttle ? '7' : '6'; ?>" class="region"><?php print $data->region_title; ?></td>
+      </tr>
+      <?php $row++; ?>
+      <?php endif; ?>
+      <tr class="<?php print $row % 2 == 0 ? 'odd' : 'even'; ?><?php print $data->row_class ? ' '. $data->row_class : ''; ?>">
+        <td class="block"><?php print $data->block_title; ?></td>
+        <td><?php print $data->region_select; ?></td>
+        <td><?php print $data->weight_select; ?></td>
+        <?php if ($throttle): ?>
+          <td><?php print $data->throttle_check; ?></td>
+        <?php endif; ?>
+        <td><?php print $data->configure_link; ?></td>
+        <td><?php print $data->delete_link; ?></td>
+      </tr>
+      <?php $row++; ?>
+    <?php endforeach; ?>
+  </tbody>
+</table>
+
+<?php print $form_submit; ?>
Index: modules/block/block-admin-display.tpl.php
===================================================================
RCS file: modules/block/block-admin-display.tpl.php
diff -N modules/block/block-admin-display.tpl.php
--- modules/block/block-admin-display.tpl.php	7 Aug 2007 08:39:35 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,66 +0,0 @@
-<?php
-// $Id: block-admin-display.tpl.php,v 1.2 2007/08/07 08:39:35 goba Exp $
-
-/**
- * @file block-admin-display.tpl.php
- * Default theme implementation to configure blocks.
- *
- * Available variables:
- * - $block_listing: An array of block controls within regions.
- * - $form_submit: Form submit button.
- * - $throttle: TRUE or FALSE depending on throttle module being enabled.
- *
- * Each $data in $block_listing contains:
- * - $data->is_region_first: TRUE or FALSE depending on the listed blocks
- *   positioning. Used here to insert a region header.
- * - $data->region_title: Region title for the listed block.
- * - $data->block_title: Block title.
- * - $data->region_select: Drop-down menu for assigning a region.
- * - $data->weight_select: Drop-down menu for setting weights.
- * - $data->throttle_check: Checkbox to enable throttling.
- * - $data->configure_link: Block configuration link.
- * - $data->delete_link: For deleting user added blocks.
- *
- * @see template_preprocess_block_admin_display()
- * @see theme_block_admin_display()
- */
-?>
-<?php drupal_add_js('misc/tableheader.js'); ?>
-
-<table id="blocks">
-  <thead>
-    <tr>
-      <th><?php print t('Block'); ?></th>
-      <th><?php print t('Region'); ?></th>
-      <th><?php print t('Weight'); ?></th>
-      <?php if ($throttle): ?>
-        <th><?php print t('Throttle'); ?></th>
-      <?php endif; ?>
-      <th colspan="2"><?php print t('Operations'); ?></th>
-    </tr>
-  </thead>
-  <tbody>
-    <?php $row = 0; ?>
-    <?php foreach ($block_listing as $data): ?>
-      <?php if ($data->is_region_first): ?>
-      <tr class="<?php print $row % 2 == 0 ? 'odd' : 'even'; ?>">
-        <td colspan="<?php print $throttle ? '7' : '6'; ?>" class="region"><?php print $data->region_title; ?></td>
-      </tr>
-      <?php $row++; ?>
-      <?php endif; ?>
-      <tr class="<?php print $row % 2 == 0 ? 'odd' : 'even'; ?>">
-        <td class="block"><?php print $data->block_title; ?></td>
-        <td><?php print $data->region_select; ?></td>
-        <td><?php print $data->weight_select; ?></td>
-        <?php if ($throttle): ?>
-          <td><?php print $data->throttle_check; ?></td>
-        <?php endif; ?>
-        <td><?php print $data->configure_link; ?></td>
-        <td><?php print $data->delete_link; ?></td>
-      </tr>
-      <?php $row++; ?>
-    <?php endforeach; ?>
-  </tbody>
-</table>
-
-<?php print $form_submit; ?>
Index: modules/block/block-rtl.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block-rtl.css,v
retrieving revision 1.1
diff -u -p -r1.1 block-rtl.css
--- modules/block/block-rtl.css	27 May 2007 17:57:47 -0000	1.1
+++ modules/block/block-rtl.css	1 Oct 2007 12:30:36 -0000
@@ -4,3 +4,9 @@
   padding-left: inherit;
   padding-right: 1.5em;
 }
+#blocks select {
+  margin-left: 18px;
+}
+#blocks select.progress-disabled {
+  margin-left: 0px;
+}
\ No newline at end of file
Index: modules/block/block.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v
retrieving revision 1.8
diff -u -p -r1.8 block.admin.inc
--- modules/block/block.admin.inc	1 Sep 2007 05:31:09 -0000	1.8
+++ modules/block/block.admin.inc	1 Oct 2007 12:30:36 -0000
@@ -7,62 +7,102 @@
  */
 
 /**
+ * Menu callback for admin/build/block.
+ */
+function block_admin_display($theme = NULL) {
+  global $custom_theme;
+
+  // If non-default theme configuration has been selected, set the custom theme.
+  $custom_theme = isset($theme) ? $theme : variable_get('theme_default', 'garland');
+
+  // Fetch and sort blocks
+  $blocks = _block_rehash();
+  usort($blocks, '_block_compare');
+
+  return drupal_get_form('block_admin_display_form', $blocks, $theme);
+}
+
+/**
  * Generate main block administration form.
  */
-function block_admin_display(&$form_state, $theme = NULL) {
+function block_admin_display_form(&$form_state, $blocks, $theme = NULL) {
   global $theme_key, $custom_theme;
 
   // Add CSS
   drupal_add_css(drupal_get_path('module', 'block') .'/block.css', 'module', 'all', FALSE);
 
   // If non-default theme configuration has been selected, set the custom theme.
-  if ($theme) {
-    $custom_theme = $theme;
-  }
-  else {
-    $custom_theme = variable_get('theme_default', 'garland');
-  }
+  $custom_theme = isset($theme) ? $theme : variable_get('theme_default', 'garland');
   init_theme();
 
-  // Fetch and sort blocks
-  $blocks = _block_rehash();
-  usort($blocks, '_block_compare');
-
   $throttle = module_exists('throttle');
   $block_regions = array(BLOCK_REGION_NONE => '<'. t('none') .'>') + system_region_list($theme_key);
 
   // Build form tree
-  $form['#action'] = arg(3) ? url('admin/build/block/list/'. $theme_key) : url('admin/build/block');
-  $form['#tree'] = TRUE;
+  $form = array(
+    '#action' => arg(3) ? url('admin/build/block/list/'. $theme_key) : url('admin/build/block'),
+    '#tree' => TRUE,
+    '#cache' => TRUE,
+    '#prefix' => '<div id="block-admin-display-form-wrapper">',
+    '#suffix' => '</div>',
+  );
   foreach ($blocks as $i => $block) {
-    $form[$i]['module'] = array('#type' => 'value', '#value' => $block['module']);
-    $form[$i]['delta'] = array('#type' => 'value', '#value' => $block['delta']);
-    $form[$i]['info'] = array('#value' => check_plain($block['info']));
-    $form[$i]['theme'] = array('#type' => 'hidden', '#value' => $theme_key);
-    $form[$i]['weight'] = array('#type' => 'weight', '#default_value' => $block['weight']);
-    $form[$i]['region'] = array('#type' => 'select',
+    $key = $block['module'] .'_'. $block['delta'];
+    $form[$key]['module'] = array(
+      '#type' => 'value',
+      '#value' => $block['module'],
+    );
+    $form[$key]['delta'] = array(
+      '#type' => 'value',
+      '#value' => $block['delta'],
+    );
+    $form[$key]['info'] = array(
+      '#value' => check_plain($block['info'])
+    );
+    $form[$key]['theme'] = array(
+      '#type' => 'hidden',
+      '#value' => $theme_key
+    );
+    $form[$key]['weight'] = array(
+      '#type' => 'weight',
+      '#default_value' => $block['weight'],
+    );
+    $form[$key]['region'] = array(
+      '#type' => 'select',
       '#default_value' => $block['status'] ? (isset($block['region']) ? $block['region'] : system_default_region($theme_key)) : BLOCK_REGION_NONE,
       '#options' => $block_regions,
     );
 
     if ($throttle) {
-      $form[$i]['throttle'] = array('#type' => 'checkbox', '#default_value' => isset($block['throttle']) ? $block['throttle'] : FALSE);
+      $form[$key]['throttle'] = array('#type' => 'checkbox', '#default_value' => isset($block['throttle']) ? $block['throttle'] : FALSE);
     }
-    $form[$i]['configure'] = array('#value' => l(t('configure'), 'admin/build/block/configure/'. $block['module'] .'/'. $block['delta']));
+    $form[$key]['configure'] = array('#value' => l(t('configure'), 'admin/build/block/configure/'. $block['module'] .'/'. $block['delta']));
     if ($block['module'] == 'block') {
-      $form[$i]['delete'] = array('#value' => l(t('delete'), 'admin/build/block/delete/'. $block['delta']));
+      $form[$key]['delete'] = array('#value' => l(t('delete'), 'admin/build/block/delete/'. $block['delta']));
     }
   }
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Save blocks'));
+
+  // Attach the AHAH events to the submit button. Set the form id as the wrapper
+  // and set the selector to every select item in the form.
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save blocks'),
+    '#ahah' => array(
+      'path' => 'admin/build/block/list/js/'. $theme_key,
+      'selector' => '#block-admin-display-form-wrapper select',
+      'wrapper' => 'block-admin-display-form-wrapper',
+      'event' => 'change',
+      'effect' => 'fade',
+    ),
+  );
 
   return $form;
 }
 
-
 /**
  * Process main block administration form submission.
  */
-function block_admin_display_submit($form, &$form_state) {
+function block_admin_display_form_submit($form, &$form_state) {
   foreach ($form_state['values'] as $block) {
     $block['status'] = $block['region'] != BLOCK_REGION_NONE;
     $block['region'] = $block['status'] ? $block['region'] : '';
@@ -73,6 +113,81 @@ function block_admin_display_submit($for
 }
 
 /**
+ * Javascript callback for AHAH replacement. Re-generate the form with the
+ * updated values and return necessary html.
+ */
+function block_admin_display_js($theme = NULL) {
+  // Load the cached form.
+  $form_cache = cache_get('form_'. $_POST['form_build_id'], 'cache_form');
+
+  // Set the new weights and regions for each block.
+  $blocks = array();
+  foreach (element_children($form_cache->data) as $key) {
+    $field = $form_cache->data[$key];
+    if (isset($field['info'])) {
+      $block = array(
+        'module'   => $field['module']['#value'],
+        'delta'    => $field['delta']['#value'],
+        'info'     => html_entity_decode($field['info']['#value'], ENT_QUOTES),
+        'region'   => $_POST[$key]['region'],
+        'weight'   => $_POST[$key]['weight'],
+        'status'   => $_POST[$key]['region'] == BLOCK_REGION_NONE ? 0 : 1,
+      );
+
+      $throttle = module_exists('throttle');
+      if ($throttle) {
+        $block['throttle'] = $_POST[$key]['throttle'];
+      }
+
+      if ($block['weight'] != $form_cache->data[$key]['weight']['#default_value'] || $block['region'] != $form_cache->data[$key]['region']['#default_value']) {
+        $changed_block = $block['module'] .'_'. $block['delta'];
+      }
+
+      $blocks[] = $block;
+    }
+  }
+
+  // Resort the blocks with the new weights.
+  usort($blocks, '_block_compare');
+
+  // Create a form in the new order.
+  $form_state = array('submitted' => FALSE);
+  $form = block_admin_display_form($form_state, $blocks, $theme);
+
+  // Preserve the order of the new form while merging the previous data.
+  $form_order = array_flip(array_keys($form)); // Save the form order.
+  $form = array_merge($form_cache->data, $form);  // Merge the data.
+  $form = array_merge($form_order, $form); // Put back into the correct order.
+
+  cache_set('form_'. $_POST['form_build_id'], $form, 'cache_form', $form_cache->expire);
+
+  // Add a class to mark the new AHAH content.
+  $form[$changed_block]['#attributes']['class'] = empty($form[$changed_block]['attributes']['class']) ? 'ahah-new-content' : ' ahah-new-content';
+  $form['js_modified'] = array(
+    '#type' => 'value',
+    '#value' => TRUE,
+  );
+
+  $form['#post'] = $_POST;
+  $form['#theme'] = 'block_admin_display_form';
+
+  // Add messages to our output.
+  drupal_set_message(t('Your settings will not be saved until you click the <em>Save blocks</em> button.'), 'warning');
+
+  // Render the form.
+  drupal_alter('form', $form, array(), 'block_admin_display_form');
+  $form = form_builder('block_admin_display_form', $form, $form_state);
+
+  // Remove the wrapper from the form to prevent duplicate div IDs.
+  unset($form['#prefix'], $form['#suffix']);
+
+  $output = drupal_render($form);
+
+  // Return the output in JSON format.
+  drupal_json(array('status' => TRUE, 'data' => $output));
+}
+
+/**
  * Helper function for sorting blocks on admin/build/block.
  *
  * Active blocks are sorted by region, then by weight.
@@ -84,12 +199,19 @@ function _block_compare($a, $b) {
   if ($status) {
     return $status;
   }
-  // Enabled blocks
+  // Enabled blocks.
   if ($a['status']) {
     $place = strcmp($a['region'], $b['region']);
-    return $place ? $place : ($a['weight'] - $b['weight']);
+    if ($place) {
+      return $place;
+    }
+    $weight = $a['weight'] - $b['weight'];
+    if ($weight) {
+      return $weight;
+    }
+    return strcmp($a['info'], $b['info']);
   }
-  // Disabled blocks
+  // Disabled blocks.
   else {
     return strcmp($a['info'], $b['info']);
   }
@@ -309,7 +431,7 @@ function block_box_delete_submit($form, 
  * @see block-admin-display.tpl.php
  * @see theme_block_admin_display()
  */
-function template_preprocess_block_admin_display(&$variables) {
+function template_preprocess_block_admin_display_form(&$variables) {
   global $theme_key;
 
   $variables['throttle'] = module_exists('throttle');
@@ -344,6 +466,7 @@ function template_preprocess_block_admin
       }
 
       $variables['block_listing'][$i]->is_region_first = $is_region_first;
+      $variables['block_listing'][$i]->row_class = isset($block['#attributes']['class']) ? $block['#attributes']['class'] : '';
       $variables['block_listing'][$i]->region_title = $region_title;
       $variables['block_listing'][$i]->block_title =  drupal_render($block['info']);
       $variables['block_listing'][$i]->region_select = drupal_render($block['region']) . drupal_render($block['theme']);
@@ -356,5 +479,6 @@ function template_preprocess_block_admin
     }
   }
 
+  $variables['messages'] = isset($variables['form']['js_modified']) ? theme('status_messages') : '';
   $variables['form_submit'] = drupal_render($variables['form']);
 }
Index: modules/block/block.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.css,v
retrieving revision 1.3
diff -u -p -r1.3 block.css
--- modules/block/block.css	27 May 2007 17:57:47 -0000	1.3
+++ modules/block/block.css	1 Oct 2007 12:30:36 -0000
@@ -12,3 +12,18 @@
   margin-bottom: 4px;
   padding: 3px;
 }
+#blocks select {
+  margin-right: 18px; /* LTR */
+}
+#blocks select.progress-disabled {
+  margin-right: 0px; /* LTR */
+}
+#blocks .progress .bar {
+  width: 15px;
+  height: 15px;
+  background: transparent url(../../misc/throbber.gif) no-repeat 0px -18px;
+  border: none;
+}
+#blocks .progress .message {
+  display: none;
+}
Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.278
diff -u -p -r1.278 block.module
--- modules/block/block.module	27 Sep 2007 16:52:00 -0000	1.278
+++ modules/block/block.module	1 Oct 2007 12:30:36 -0000
@@ -102,8 +102,8 @@ function block_help($path, $arg) {
  */
 function block_theme() {
   return array(
-    'block_admin_display' => array(
-      'template' => 'block-admin-display',
+    'block_admin_display_form' => array(
+      'template' => 'block-admin-display-form',
       'file' => 'block.admin.inc',
       'arguments' => array('form' => NULL),
     ),
@@ -124,8 +124,7 @@ function block_menu() {
   $items['admin/build/block'] = array(
     'title' => 'Blocks',
     'description' => 'Configure what block content appears in your site\'s sidebars and other regions.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('block_admin_display'),
+    'page callback' => 'block_admin_display',
     'access arguments' => array('administer blocks'),
     'file' => 'block.admin.inc',
   );
@@ -134,6 +133,12 @@ function block_menu() {
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10,
   );
+  $items['admin/build/block/list/js'] = array(
+    'title' => 'Javascript List Form',
+    'page callback' => 'block_admin_display_js',
+    'type' => MENU_CALLBACK,
+    'file' => 'block.admin.inc',
+  );
   $items['admin/build/block/configure'] = array(
     'title' => 'Configure block',
     'page arguments' => array('block_admin_configure'),
@@ -148,6 +153,7 @@ function block_menu() {
   );
   $items['admin/build/block/add'] = array(
     'title' => 'Add block',
+    'page callback' => 'drupal_get_form',
     'page arguments' => array('block_add_block_form'),
     'type' => MENU_LOCAL_TASK,
     'file' => 'block.admin.inc',
@@ -156,7 +162,7 @@ function block_menu() {
   foreach (list_themes() as $key => $theme) {
     $items['admin/build/block/list/'. $key] = array(
       'title' => check_plain($theme->info['name']),
-      'page arguments' => array('block_admin_display', $key),
+      'page arguments' => array($key),
       'type' => $key == $default ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
       'weight' => $key == $default ? -10 : 0,
       'file' => 'block.admin.inc',
Index: modules/system/system-rtl.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system-rtl.css,v
retrieving revision 1.3
diff -u -p -r1.3 system-rtl.css
--- modules/system/system-rtl.css	8 Jun 2007 06:04:15 -0000	1.3
+++ modules/system/system-rtl.css	1 Oct 2007 12:30:36 -0000
@@ -83,6 +83,12 @@ div.teaser-button-wrapper {
 .progress .percentage {
   float: left;
 }
+.progess-disabled {
+  float: right;
+}
+.ahah-progress {
+  float: right;
+}
 input.password-field {
   margin-left: 10px;
   margin-right: inherit;
Index: modules/system/system.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.css,v
retrieving revision 1.34
diff -u -p -r1.34 system.css
--- modules/system/system.css	6 Sep 2007 13:06:13 -0000	1.34
+++ modules/system/system.css	1 Oct 2007 12:30:36 -0000
@@ -418,8 +418,9 @@ html.js .no-js {
 .progress .bar {
   background: #fff url(../../misc/progress.gif);
   border: 1px solid #00375a;
+  width: 5em;
   height: 1.5em;
-  margin-top: 0.2em;
+  margin: 0.2em 0 0 0.2em;
 }
 .progress .filled {
   background: #0072b9;
@@ -430,6 +431,12 @@ html.js .no-js {
 .progress .percentage {
   float: right; /* LTR */
 }
+.progress-disabled {
+  float: left; /* LTR */
+}
+.ahah-progress {
+  float: left; /* LTR */
+}
 
 /*
 ** Formatting for welcome page
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.534
diff -u -p -r1.534 system.module
--- modules/system/system.module	27 Sep 2007 13:12:26 -0000	1.534
+++ modules/system/system.module	1 Oct 2007 12:30:36 -0000
@@ -122,28 +122,28 @@ function system_elements() {
   $type['form'] = array('#method' => 'post', '#action' => request_uri());
 
   // Inputs
-  $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#ahah_event' => 'submit', '#process' => array('form_expand_ahah'));
-  $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE, '#ahah_event' => 'submit', '#process' => array('form_expand_ahah'));
-  $type['image_button'] = array('#input' => TRUE, '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#ahah_event' => 'submit', '#process' => array('form_expand_ahah'), '#return_value' => TRUE, '#has_garbage_value' => TRUE, '#src' => NULL);
-  $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE);
-  $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128);
+  $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#process' => array('form_expand_ahah'));
+  $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE, '#process' => array('form_expand_ahah'));
+  $type['image_button'] = array('#input' => TRUE, '#button_type' => 'submit','#executes_submit_callback' => TRUE, '#process' => array('form_expand_ahah'), '#return_value' => TRUE, '#has_garbage_value' => TRUE, '#src' => NULL);
+  $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE, '#process' => array('form_expand_ahah'));
+  $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#process' => array('form_expand_ahah'));
   $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm'));
-  $type['textarea'] = array('#input' => TRUE, '#cols' => 60, '#rows' => 5, '#resizable' => TRUE);
+  $type['textarea'] = array('#input' => TRUE, '#cols' => 60, '#rows' => 5, '#resizable' => TRUE, '#process' => array('form_expand_ahah'));
   $type['radios'] = array('#input' => TRUE, '#process' => array('expand_radios'));
-  $type['radio'] = array('#input' => TRUE, '#default_value' => NULL);
+  $type['radio'] = array('#input' => TRUE, '#default_value' => NULL, '#process' => array('form_expand_ahah'));
   $type['checkboxes'] = array('#input' => TRUE, '#process' => array('expand_checkboxes'), '#tree' => TRUE);
-  $type['checkbox'] = array('#input' => TRUE, '#return_value' => 1);
-  $type['select'] = array('#input' => TRUE, '#size' => 0, '#multiple' => FALSE);
-  $type['weight'] = array('#input' => TRUE, '#delta' => 10, '#default_value' => 0, '#process' => array('process_weight'));
+  $type['checkbox'] = array('#input' => TRUE, '#return_value' => 1, '#process' => array('form_expand_ahah'));
+  $type['select'] = array('#input' => TRUE, '#size' => 0, '#multiple' => FALSE, '#process' => array('form_expand_ahah'));
+  $type['weight'] = array('#input' => TRUE, '#delta' => 10, '#default_value' => 0, '#process' => array('process_weight', 'form_expand_ahah'));
   $type['date'] = array('#input' => TRUE, '#process' => array('expand_date'), '#element_validate' => array('date_validate'));
   $type['file'] = array('#input' => TRUE, '#size' => 60);
 
   // Form structure
   $type['item'] = array('#value' => '');
-  $type['hidden'] = array('#input' => TRUE);
+  $type['hidden'] = array('#input' => TRUE, '#process' => array('expand_ahah'));
   $type['value'] = array('#input' => TRUE);
   $type['markup'] = array('#prefix' => '', '#suffix' => '');
-  $type['fieldset'] = array('#collapsible' => FALSE, '#collapsed' => FALSE, '#value' => NULL);
+  $type['fieldset'] = array('#collapsible' => FALSE, '#collapsed' => FALSE, '#value' => NULL, '#process' => array('expand_ahah'));
   $type['token'] = array('#input' => TRUE);
   return $type;
 }
Index: modules/upload/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v
retrieving revision 1.182
diff -u -p -r1.182 upload.module
--- modules/upload/upload.module	12 Sep 2007 18:29:32 -0000	1.182
+++ modules/upload/upload.module	1 Oct 2007 12:30:36 -0000
@@ -499,8 +499,10 @@ function _upload_form($node) {
       '#type' => 'submit',
       '#value' => t('Attach'),
       '#name' => 'attach',
-      '#ahah_path' => 'upload/js',
-      '#ahah_wrapper' => 'attach-wrapper',
+      '#ahah' => array(
+        'path' => 'upload/js',
+        'wrapper' => 'attach-wrapper',
+      ),
       '#submit' => array('node_form_submit_build_node'),
     );
   }
