Index: misc/collapse.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/collapse.js,v
retrieving revision 1.10
diff -u -F^f -r1.10 collapse.js
--- misc/collapse.js	11 Jan 2007 03:38:31 -0000	1.10
+++ misc/collapse.js	21 Jan 2007 05:57:27 -0000
@@ -11,12 +11,12 @@
       complete: function() {
         // Make sure we open to height auto
         $(this).css('height', 'auto');
-        Drupal.collapseScrollIntoView(this.parentNode);
+        Drupal.scrollIntoView(this.parentNode);
         this.parentNode.animating = false;
       },
       step: function() {
          // Scroll the fieldset into view
-        Drupal.collapseScrollIntoView(this.parentNode);
+        Drupal.scrollIntoView(this.parentNode);
       }
     });
     if (typeof Drupal.textareaAttach != 'undefined') {
@@ -32,23 +32,6 @@
   }
 }
 
-/**
- * Scroll a given fieldset into view as much as possible.
- */
-Drupal.collapseScrollIntoView = function (node) {
-  var h = self.innerHeight || document.documentElement.clientHeight || $('body')[0].clientHeight || 0;
-  var offset = self.pageYOffset || document.documentElement.scrollTop || $('body')[0].scrollTop || 0;
-  var pos = Drupal.absolutePosition(node);
-  var fudge = 55;
-  if (pos.y + node.offsetHeight + fudge > h + offset) {
-    if (node.offsetHeight > h) {
-      window.scrollTo(0, pos.y);
-    } else {
-      window.scrollTo(0, pos.y + node.offsetHeight - h + fudge);
-    }
-  }
-}
-
 // Global Killswitch
 if (Drupal.jsEnabled) {
   $(document).ready(function() {
Index: misc/drupal.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/drupal.js,v
retrieving revision 1.29
diff -u -F^f -r1.29 drupal.js
--- misc/drupal.js	14 Oct 2006 02:39:48 -0000	1.29
+++ misc/drupal.js	21 Jan 2007 05:57:27 -0000
@@ -200,6 +200,39 @@
   return uri.indexOf('?q=') ? item : item.replace('%26', '%2526').replace('%23', '%2523');
 };
 
+/**
+ * Equivalent of check_plain().
+ */
+Drupal.checkPlain = function (text) {
+	var entities = {
+		'&':'&amp;',
+		'<':'&lt;',
+		'>':'&gt;',
+		'"':'&quot;'
+	};
+	for (i in entities) {
+		text = text.replace(new RegExp(i, 'g'), entities[i]);
+	}
+	return text;
+}
+
+/**
+ * Scroll a given element into view as much as possible.
+ */
+Drupal.scrollIntoView = function (node) {
+  var h = self.innerHeight || document.documentElement.clientHeight || $('body')[0].clientHeight || 0;
+  var offset = self.pageYOffset || document.documentElement.scrollTop || $('body')[0].scrollTop || 0;
+  var pos = Drupal.absolutePosition(node);
+  var fudge = 55;
+  if (pos.y + node.offsetHeight + fudge > h + offset) {
+    if (node.offsetHeight > h) {
+      window.scrollTo(0, pos.y - 20);
+    } else {
+      window.scrollTo(0, pos.y - 20 + node.offsetHeight - h + fudge);
+    }
+  }
+}
+
 // Global Killswitch on the <html> element
 if (Drupal.jsEnabled) {
   document.documentElement.className = 'js';
Index: misc/textarea.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/textarea.js,v
retrieving revision 1.11
diff -u -F^f -r1.11 textarea.js
--- misc/textarea.js	7 Sep 2006 08:05:31 -0000	1.11
+++ misc/textarea.js	21 Jan 2007 05:57:27 -0000
@@ -1,15 +1,25 @@
 // $Id: textarea.js,v 1.11 2006/09/07 08:05:31 dries Exp $
 
+// Auto-expand based on "Interface Elements for jQuery" by Stefan Petre.
+
 Drupal.textareaAttach = function() {
+  var i = 0;
+  // Attach to all unprocessed textareas.
   $('textarea.resizable:not(.processed)').each(function() {
     var textarea = $(this).addClass('processed'), staticOffset = null;
 
+    // We use a helper div to measure text. We wrap it an overflow: hidden
+    // container to avoid lengthening the page scrollbar.
+    $('body').append('<div style="position: absolute; top: 0; left: 0; width: 100px; height: 100px; overflow: hidden; visibility: hidden;"><div id="expanderHelper'+ ++i +'" style="position: absolute; top: 0; left: 0;"></div></div>');
+    var helper = $('#expanderHelper'+ i);
+
+    // Wrap textarea and add grippie.
     $(this).wrap('<div class="resizable-textarea"></div>')
       .parent().append($('<div class="grippie"></div>').mousedown(startDrag));
-
     var grippie = $('div.grippie', $(this).parent())[0];
     grippie.style.marginRight = (grippie.offsetWidth - $(this)[0].offsetWidth) +'px';
 
+    // Clicking down on the grippie
     function startDrag(e) {
       staticOffset = textarea.height() - Drupal.mousePosition(e).y;
       textarea.css('opacity', 0.25);
@@ -17,15 +27,87 @@
       return false;
     }
 
+    // Moving the mouse during a drag.
     function performDrag(e) {
       textarea.height(Math.max(32, staticOffset + Drupal.mousePosition(e).y) + 'px');
       return false;
     }
 
+    // Letting go of the button during drag.
     function endDrag(e) {
       $(document).unmousemove(performDrag).unmouseup(endDrag);
       textarea.css('opacity', 1);
     }
+
+    // Get text styles and apply them to the helper.
+    var style = {
+      fontFamily: $(this).css('fontFamily')||'',
+      fontSize: $(this).css('fontSize')||'',
+      fontWeight: $(this).css('fontWeight')||'',
+      fontStyle: $(this).css('fontStyle')||'',
+      fontStretch: $(this).css('fontStretch')||'',
+      fontVariant: $(this).css('fontVariant')||'',
+      letterSpacing: $(this).css('letterSpacing')||'',
+      wordSpacing: $(this).css('wordSpacing')||'',
+      lineHeight: $(this).css('lineHeight')||'',
+      textWrap: 'unrestricted'
+    };
+    helper.css(style);
+
+    // Measure the text and some extra padding.
+    helper.html('DruP');
+    var spacer = helper[0].offsetWidth;
+
+    // Add auto-expand event handler and fire it once.
+    $(this).blur(expand).keyup(expand).keypress(expand);
+    var last = this.value;
+    expand.apply(this);
+
+    var time = (new Date()).getTime();
+    
+    // Auto-expand a textarea.
+    function expand() {
+      var e = this;
+
+      // Don't expand more than once every 250ms.
+      var now = (new Date()).getTime();
+      if (now - time < 250) {
+        return;
+      }
+      time = now;
+
+      // Force a tiny delay to ensure we get the entire value including the
+      // change this event causes.
+      window.setTimeout(function () {
+        // Get contents
+        if (!e.value || last == e.value) {
+          return;
+        }
+        var text = (last = e.value);
+
+        // Don't expand for extremely large textareas where we are sure to be
+        // at full size already.
+        if (e.value.length > 10000) {
+          return;
+        }
+
+        // Convert text to HTML and size it.
+        var html = Drupal.checkPlain(text);
+        html = html.replace(new RegExp("\\n", "g"), "<br />");
+        helper.css('width', ($(e).width() - ($.browser.safari && 12 || 2)) + 'px').html(html);
+
+        // Calculate page height, minus some padding.
+        var limit = (self.innerHeight || document.documentElement.clientHeight || $('body')[0].clientHeight) - 55;
+
+        // Calculate desired height.
+        var height = Math.min(limit, Math.max($(e).height(), helper[0].offsetHeight + spacer));
+        e.style.height = height + 'px';
+
+        // Scroll into view.
+        Drupal.scrollIntoView(e.parentNode);
+      }, 1);
+    }
+
   });
 }
 
