diff --git a/misc/ahah.js b/misc/ahah.js
index a098addb9db946f3cd20e624064e8471c5f7eb9e..ca5580a46be63bcc0fd05143d3868869deecbae5 100644
--- a/misc/ahah.js
+++ b/misc/ahah.js
@@ -15,17 +15,19 @@
 /**
  * Attaches the ahah behavior to each ahah form element.
  */
-Drupal.behaviors.ahah = function(context) {
-  for (var base in Drupal.settings.ahah) {
-    if (!$('#'+ base + '.ahah-processed').size()) {
-      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');
+Drupal.behaviors.ahah = {
+  attach: function(context) {
+    for (var base in Drupal.settings.ahah) {
+      if (!$('#'+ base + '.ahah-processed').size()) {
+        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');
+      }
     }
   }
 };
diff --git a/misc/autocomplete.js b/misc/autocomplete.js
index 6efcf1e2606458fde8bef4622c8b623623585de2..da76380c450c531d100726f4f4bd2926ee7f3dc5 100644
--- a/misc/autocomplete.js
+++ b/misc/autocomplete.js
@@ -3,19 +3,21 @@
 /**
  * Attaches the autocomplete behavior to all required fields.
  */
-Drupal.behaviors.autocomplete = function (context) {
-  var acdb = [];
-  $('input.autocomplete:not(.autocomplete-processed)', context).each(function () {
-    var uri = this.value;
-    if (!acdb[uri]) {
-      acdb[uri] = new Drupal.ACDB(uri);
-    }
-    var input = $('#' + this.id.substr(0, this.id.length - 13))
-      .attr('autocomplete', 'OFF')[0];
-    $(input.form).submit(Drupal.autocompleteSubmit);
-    new Drupal.jsAC(input, acdb[uri]);
-    $(this).addClass('autocomplete-processed');
-  });
+Drupal.behaviors.autocomplete = {
+  attach: function(context) {
+    var acdb = [];
+    $('input.autocomplete:not(.autocomplete-processed)', context).each(function () {
+      var uri = this.value;
+      if (!acdb[uri]) {
+        acdb[uri] = new Drupal.ACDB(uri);
+      }
+      var input = $('#' + this.id.substr(0, this.id.length - 13))
+        .attr('autocomplete', 'OFF')[0];
+      $(input.form).submit(Drupal.autocompleteSubmit);
+      new Drupal.jsAC(input, acdb[uri]);
+      $(this).addClass('autocomplete-processed');
+    });
+  }
 };
 
 /**
diff --git a/misc/batch.js b/misc/batch.js
index 5a5587ad8aec0955f232283349072099fd7a6646..4d1a4d551fbd4c4ce100d5b5f7739db3f113062e 100644
--- a/misc/batch.js
+++ b/misc/batch.js
@@ -3,36 +3,38 @@
 /**
  * Attaches the batch behavior to progress bars.
  */
-Drupal.behaviors.batch = function (context) {
-  // This behavior attaches by ID, so is only valid once on a page.
-  if ($('#progress.batch-processed').size()) {
-    return;
-  }
-  $('#progress', context).addClass('batch-processed').each(function () {
-    var holder = this;
-    var uri = Drupal.settings.batch.uri;
-    var initMessage = Drupal.settings.batch.initMessage;
-    var errorMessage = Drupal.settings.batch.errorMessage;
+Drupal.behaviors.batch = {
+  attach: function(context) {
+    // This behavior attaches by ID, so is only valid once on a page.
+    if ($('#progress.batch-processed').size()) {
+      return;
+    }
+    $('#progress', context).addClass('batch-processed').each(function () {
+      var holder = this;
+      var uri = Drupal.settings.batch.uri;
+      var initMessage = Drupal.settings.batch.initMessage;
+      var errorMessage = Drupal.settings.batch.errorMessage;
 
-    // Success: redirect to the summary.
-    var updateCallback = function (progress, status, pb) {
-      if (progress == 100) {
-        pb.stopMonitoring();
-        window.location = uri+'&op=finished';
-      }
-    };
+      // Success: redirect to the summary.
+      var updateCallback = function (progress, status, pb) {
+        if (progress == 100) {
+          pb.stopMonitoring();
+          window.location = uri+'&op=finished';
+        }
+      };
 
-    var errorCallback = function (pb) {
-      var div = document.createElement('p');
-      div.className = 'error';
-      $(div).html(errorMessage);
-      $(holder).prepend(div);
-      $('#wait').hide();
-    };
+      var errorCallback = function (pb) {
+        var div = document.createElement('p');
+        div.className = 'error';
+        $(div).html(errorMessage);
+        $(holder).prepend(div);
+        $('#wait').hide();
+      };
 
-    var progress = new Drupal.progressBar('updateprogress', updateCallback, "POST", errorCallback);
-    progress.setProgress(-1, initMessage);
-    $(holder).append(progress.element);
-    progress.startMonitoring(uri+'&op=do', 10);
-  });
+      var progress = new Drupal.progressBar('updateprogress', updateCallback, "POST", errorCallback);
+      progress.setProgress(-1, initMessage);
+      $(holder).append(progress.element);
+      progress.startMonitoring(uri+'&op=do', 10);
+    });
+  }
 };
diff --git a/misc/collapse.js b/misc/collapse.js
index 5628c4b9ad10d4d25339fcec60b1de45e96331e3..4626b4519683d90f65b7787e3cbb15baf4a99ee6 100644
--- a/misc/collapse.js
+++ b/misc/collapse.js
@@ -50,28 +50,30 @@ Drupal.collapseScrollIntoView = function (node) {
   }
 };
 
-Drupal.behaviors.collapse = function (context) {
-  $('fieldset.collapsible > legend:not(.collapse-processed)', context).each(function() {
-    var fieldset = $(this.parentNode);
-    // Expand if there are errors inside
-    if ($('input.error, textarea.error, select.error', fieldset).size() > 0) {
-      fieldset.removeClass('collapsed');
-    }
+Drupal.behaviors.collapse = {
+  attach: function(context) {
+    $('fieldset.collapsible > legend:not(.collapse-processed)', context).each(function() {
+      var fieldset = $(this.parentNode);
+      // Expand if there are errors inside
+      if ($('input.error, textarea.error, select.error', fieldset).size() > 0) {
+        fieldset.removeClass('collapsed');
+      }
 
-    // Turn the legend into a clickable link and wrap the contents of the fieldset
-    // in a div for easier animation
-    var text = this.innerHTML;
-      $(this).empty().append($('<a href="#">'+ text +'</a>').click(function() {
-        var fieldset = $(this).parents('fieldset:first')[0];
-        // Don't animate multiple times
-        if (!fieldset.animating) {
-          fieldset.animating = true;
-          Drupal.toggleFieldset(fieldset);
-        }
-        return false;
-      }))
-      .after($('<div class="fieldset-wrapper"></div>')
-      .append(fieldset.children(':not(legend):not(.action)')))
-      .addClass('collapse-processed');
-  });
+      // Turn the legend into a clickable link and wrap the contents of the fieldset
+      // in a div for easier animation
+      var text = this.innerHTML;
+        $(this).empty().append($('<a href="#">'+ text +'</a>').click(function() {
+          var fieldset = $(this).parents('fieldset:first')[0];
+          // Don't animate multiple times
+          if (!fieldset.animating) {
+            fieldset.animating = true;
+            Drupal.toggleFieldset(fieldset);
+          }
+          return false;
+        }))
+        .after($('<div class="fieldset-wrapper"></div>')
+        .append(fieldset.children(':not(legend):not(.action)')))
+        .addClass('collapse-processed');
+    });
+  }
 };
diff --git a/misc/drupal.js b/misc/drupal.js
index 4cb99bd9991b8d90fe94b7e1d432314f170aa264..157a20fea12ee8b35ee9770e276892eba20bd32b 100644
--- a/misc/drupal.js
+++ b/misc/drupal.js
@@ -12,10 +12,15 @@ Drupal.jsEnabled = document.getElementsByTagName && document.createElement && do
  *
  * Behaviors are event-triggered actions that attach to page elements, enhancing
  * default non-Javascript UIs. Behaviors are registered in the Drupal.behaviors
- * object as follows:
+ * object using the method 'attach' and optionally also 'detach' as follows:
  * @code
- *    Drupal.behaviors.behaviorName = function () {
- *      ...
+ *    Drupal.behaviors.behaviorName = {
+ *      attach: function(context) {
+ *        ...
+ *      },
+ *      detach: function(context) {
+ *        ...
+ *      }
  *    };
  * @endcode
  *
@@ -38,7 +43,38 @@ Drupal.attachBehaviors = function(context) {
   context = context || document;
   // Execute all of them.
   jQuery.each(Drupal.behaviors, function() {
-    this(context);
+    if (jQuery.isFunction(this.attach)) {
+      this.attach(context);
+    }
+  });
+};
+
+/**
+ * Detach registered behaviors from a page element.
+ *
+ * Developers implementing AHAH/AJAX in their solutions should call this
+ * function before page content is about to be removed, feeding in an element
+ * to be processed, in order to allow special behaviors to detach from the
+ * content.
+ *
+ * Such implementations should look for the class name that was added in their
+ * corresponding Drupal.behaviors.behaviorName.attach implementation, i.e.
+ * behaviorName-processed, to ensure the behavior is detached only from
+ * previously processed elements.
+ *
+ * @param context
+ *   An element to detach behaviors from. If none is given, the document element
+ *   is used.
+ *
+ * @see Drupal.attachBehaviors
+ */
+Drupal.detachBehaviors = function(context) {
+  context = context || document;
+  // Execute all of them.
+  jQuery.each(Drupal.behaviors, function() {
+    if (jQuery.isFunction(this.detach)) {
+      this.detach(context);
+    }
   });
 };
 
diff --git a/misc/form.js b/misc/form.js
index f5e3e6846b0c18352ba8daaa46f43a4b1814a146..d3a9f692fbf9ef201c17426c3c5c24f20ab0fa06 100644
--- a/misc/form.js
+++ b/misc/form.js
@@ -1,10 +1,12 @@
 // $Id$
 
-Drupal.behaviors.multiselectSelector = function() {
-  // Automatically selects the right radio button in a multiselect control.
-  $('.multiselect select:not(.multiselectSelector-processed)')
-    .addClass('multiselectSelector-processed').change(function() {
-      $('.multiselect input:radio[value="'+ this.id.substr(5) +'"]')
-        .attr('checked', true);
-  });
+Drupal.behaviors.multiselectSelector = {
+  attach: function(context) {
+    // Automatically selects the right radio button in a multiselect control.
+    $('.multiselect select:not(.multiselectSelector-processed)', context)
+      .addClass('multiselectSelector-processed').change(function() {
+        $('.multiselect input:radio[value="'+ this.id.substr(5) +'"]')
+          .attr('checked', true);
+    });
+  }
 };
diff --git a/misc/tabledrag.js b/misc/tabledrag.js
index d8c1e6e9a0b01981581e69641ee1183c1a1234fe..7d11cd39e56e7eb1bbad5568a2800b4db7ffc7bc 100644
--- a/misc/tabledrag.js
+++ b/misc/tabledrag.js
@@ -11,18 +11,20 @@
  * overriding the .onDrag, .onDrop, .row.onSwap, and .row.onIndent methods.
  * See blocks.js for an example of adding additional functionality to tableDrag.
  */
-Drupal.behaviors.tableDrag = function(context) {
-  for (var base in Drupal.settings.tableDrag) {
-    if (!$('#' + base + '.tabledrag-processed', context).size()) {
-      var tableSettings = Drupal.settings.tableDrag[base];
-
-      $('#' + base).filter(':not(.tabledrag-processed)').each(function() {
-        // Create the new tableDrag instance. Save in the Drupal variable
-        // to allow other scripts access to the object.
-        Drupal.tableDrag[base] = new Drupal.tableDrag(this, tableSettings);
-      });
+Drupal.behaviors.tableDrag = {
+  attach: function(context) {
+    for (var base in Drupal.settings.tableDrag) {
+      if (!$('#' + base + '.tabledrag-processed', context).size()) {
+        var tableSettings = Drupal.settings.tableDrag[base];
+
+        $('#' + base).filter(':not(.tabledrag-processed)').each(function() {
+          // Create the new tableDrag instance. Save in the Drupal variable
+          // to allow other scripts access to the object.
+          Drupal.tableDrag[base] = new Drupal.tableDrag(this, tableSettings);
+        });
 
-      $('#' + base).addClass('tabledrag-processed');
+        $('#' + base).addClass('tabledrag-processed');
+      }
     }
   }
 };
diff --git a/misc/tableheader.js b/misc/tableheader.js
index 3127464d820bdebda68624c09b091bc09be78b0e..9fa58ce5d7bfdd305679d3dfcd41add38887c407 100644
--- a/misc/tableheader.js
+++ b/misc/tableheader.js
@@ -6,108 +6,110 @@ Drupal.tableHeaderDoScroll = function() {
   }
 };
 
-Drupal.behaviors.tableHeader = function (context) {
-  // This breaks in anything less than IE 7. Prevent it from running.
-  if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 7) {
-    return;
-  }
+Drupal.behaviors.tableHeader = {
+  attach: function(context) {
+    // This breaks in anything less than IE 7. Prevent it from running.
+    if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 7) {
+      return;
+    }
 
-  // Keep track of all cloned table headers.
-  var headers = [];
+    // Keep track of all cloned table headers.
+    var headers = [];
 
-  $('table.sticky-enabled thead:not(.tableHeader-processed)', context).each(function () {
-    // Clone thead so it inherits original jQuery properties.
-    var headerClone = $(this).clone(true).insertBefore(this.parentNode).wrap('<table class="sticky-header"></table>').parent().css({
-      position: 'fixed',
-      top: '0px'
-    });
+    $('table.sticky-enabled thead:not(.tableHeader-processed)', context).each(function () {
+      // Clone thead so it inherits original jQuery properties.
+      var headerClone = $(this).clone(true).insertBefore(this.parentNode).wrap('<table class="sticky-header"></table>').parent().css({
+        position: 'fixed',
+        top: '0px'
+      });
 
-    headerClone = $(headerClone)[0];
-    headers.push(headerClone);
+      headerClone = $(headerClone)[0];
+      headers.push(headerClone);
 
-    // Store parent table.
-    var table = $(this).parent('table')[0];
-    headerClone.table = table;
-    // Finish initialzing header positioning.
-    tracker(headerClone);
+      // Store parent table.
+      var table = $(this).parent('table')[0];
+      headerClone.table = table;
+      // Finish initialzing header positioning.
+      tracker(headerClone);
 
-    $(table).addClass('sticky-table');
-    $(this).addClass('tableHeader-processed');
-  });
+      $(table).addClass('sticky-table');
+      $(this).addClass('tableHeader-processed');
+    });
 
-  // Define the anchor holding var.
-  var prevAnchor = '';
+    // Define the anchor holding var.
+    var prevAnchor = '';
 
-  // Track positioning and visibility.
-  function tracker(e) {
-    // Save positioning data.
-    var viewHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
-    if (e.viewHeight != viewHeight) {
-      e.viewHeight = viewHeight;
-      e.vPosition = $(e.table).offset().top - 4;
-      e.hPosition = $(e.table).offset().left;
-      e.vLength = e.table.clientHeight - 100;
-      // Resize header and its cell widths.
-      var parentCell = $('th', e.table);
-      $('th', e).each(function(index) {
-        var cellWidth = parentCell.eq(index).css('width');
-        // Exception for IE7.
-        if (cellWidth == 'auto') {
-          cellWidth = parentCell.get(index).clientWidth +'px';
-        }
-        $(this).css('width', cellWidth);
-      });
-      $(e).css('width', $(e.table).css('width'));
-    }
+    // Track positioning and visibility.
+    function tracker(e) {
+      // Save positioning data.
+      var viewHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
+      if (e.viewHeight != viewHeight) {
+        e.viewHeight = viewHeight;
+        e.vPosition = $(e.table).offset().top - 4;
+        e.hPosition = $(e.table).offset().left;
+        e.vLength = e.table.clientHeight - 100;
+        // Resize header and its cell widths.
+        var parentCell = $('th', e.table);
+        $('th', e).each(function(index) {
+          var cellWidth = parentCell.eq(index).css('width');
+          // Exception for IE7.
+          if (cellWidth == 'auto') {
+            cellWidth = parentCell.get(index).clientWidth +'px';
+          }
+          $(this).css('width', cellWidth);
+        });
+        $(e).css('width', $(e.table).css('width'));
+      }
 
-    // Track horizontal positioning relative to the viewport and set visibility.
-    var hScroll = document.documentElement.scrollLeft || document.body.scrollLeft;
-    var vOffset = (document.documentElement.scrollTop || document.body.scrollTop) - e.vPosition;
-    var visState = (vOffset > 0 && vOffset < e.vLength) ? 'visible' : 'hidden';
-    $(e).css({left: -hScroll + e.hPosition +'px', visibility: visState});
+      // Track horizontal positioning relative to the viewport and set visibility.
+      var hScroll = document.documentElement.scrollLeft || document.body.scrollLeft;
+      var vOffset = (document.documentElement.scrollTop || document.body.scrollTop) - e.vPosition;
+      var visState = (vOffset > 0 && vOffset < e.vLength) ? 'visible' : 'hidden';
+      $(e).css({left: -hScroll + e.hPosition +'px', visibility: visState});
 
-    // Check the previous anchor to see if we need to scroll to make room for the header.
-    // Get the height of the header table and scroll up that amount.
-    if (prevAnchor != location.hash) {
-      if (location.hash != '') {
-        var scrollLocation = $('td' + location.hash).offset().top - $(e).height();
-        $('body, html').scrollTop(scrollLocation);
+      // Check the previous anchor to see if we need to scroll to make room for the header.
+      // Get the height of the header table and scroll up that amount.
+      if (prevAnchor != location.hash) {
+        if (location.hash != '') {
+          var scrollLocation = $('td' + location.hash).offset().top - $(e).height();
+          $('body, html').scrollTop(scrollLocation);
+        }
+        prevAnchor = location.hash;
       }
-      prevAnchor = location.hash;
     }
-  }
-
-  // Only attach to scrollbars once, even if Drupal.attachBehaviors is called
-  //  multiple times.
-  if (!$('body').hasClass('tableHeader-processed')) {
-    $('body').addClass('tableHeader-processed');
-    $(window).scroll(Drupal.tableHeaderDoScroll);
-    $(document.documentElement).scroll(Drupal.tableHeaderDoScroll);
-  }
-
-  // Track scrolling.
-  Drupal.tableHeaderOnScroll = function() {
-    $(headers).each(function () {
-      tracker(this);
-    });
-  };
 
-  // Track resizing.
-  var time = null;
-  var resize = function () {
-    // Ensure minimum time between adjustments.
-    if (time) {
-      return;
+    // Only attach to scrollbars once, even if Drupal.attachBehaviors is called
+    //  multiple times.
+    if (!$('body').hasClass('tableHeader-processed')) {
+      $('body').addClass('tableHeader-processed');
+      $(window).scroll(Drupal.tableHeaderDoScroll);
+      $(document.documentElement).scroll(Drupal.tableHeaderDoScroll);
     }
-    time = setTimeout(function () {
-      $('table.sticky-header').each(function () {
-        // Force cell width calculation.
-        this.viewHeight = 0;
+
+    // Track scrolling.
+    Drupal.tableHeaderOnScroll = function() {
+      $(headers).each(function () {
         tracker(this);
       });
-      // Reset timer.
-      time = null;
-    }, 250);
-  };
-  $(window).resize(resize);
+    };
+
+    // Track resizing.
+    var time = null;
+    var resize = function () {
+      // Ensure minimum time between adjustments.
+      if (time) {
+        return;
+      }
+      time = setTimeout(function () {
+        $('table.sticky-header').each(function () {
+          // Force cell width calculation.
+          this.viewHeight = 0;
+          tracker(this);
+        });
+        // Reset timer.
+        time = null;
+      }, 250);
+    };
+    $(window).resize(resize);
+  }
 };
diff --git a/misc/tableselect.js b/misc/tableselect.js
index 65eb7efbc5390bccd24a016d11bca849e735ace0..36a209f3ca19725c3b34296ef6ae7e17fd653a81 100644
--- a/misc/tableselect.js
+++ b/misc/tableselect.js
@@ -1,7 +1,9 @@
 // $Id$
 
-Drupal.behaviors.tableSelect = function (context) {
-  $('form table:has(th.select-all):not(.tableSelect-processed)', context).each(Drupal.tableSelect);
+Drupal.behaviors.tableSelect = {
+  attach: function(context) {
+    $('form table:has(th.select-all):not(.tableSelect-processed)', context).each(Drupal.tableSelect);
+  }
 };
 
 Drupal.tableSelect = function() {
diff --git a/misc/teaser.js b/misc/teaser.js
index 590dad5820bbedc70be4253a93a123664258af6c..e303aa963e15d097056182426ad5d60e7ae53e06 100644
--- a/misc/teaser.js
+++ b/misc/teaser.js
@@ -5,92 +5,94 @@
  *
  * Note: depends on resizable textareas.
  */
-Drupal.behaviors.teaser = function(context) {
-  // This breaks in Konqueror. Prevent it from running.
-  if (/KDE/.test(navigator.vendor)) {
-    return;
-  }
+Drupal.behaviors.teaser = {
+  attach: function(context) {
+    // This breaks in Konqueror. Prevent it from running.
+    if (/KDE/.test(navigator.vendor)) {
+      return;
+    }
 
-  $('textarea.teaser:not(.teaser-processed)', context).each(function() {
-    var teaser = $(this).addClass('teaser-processed');
+    $('textarea.teaser:not(.teaser-processed)', context).each(function() {
+      var teaser = $(this).addClass('teaser-processed');
 
-    // Move teaser textarea before body, and remove its form-item wrapper.
-    var body = $('#'+ Drupal.settings.teaser[this.id]);
-    var checkbox = $('#'+ Drupal.settings.teaserCheckbox[this.id]).parent();
-    var checked = $(checkbox).children('input').attr('checked') ? true : false;
-    var parent = teaser[0].parentNode;
-    $(body).before(teaser);
-    $(parent).remove();
+      // Move teaser textarea before body, and remove its form-item wrapper.
+      var body = $('#'+ Drupal.settings.teaser[this.id]);
+      var checkbox = $('#'+ Drupal.settings.teaserCheckbox[this.id]).parent();
+      var checked = $(checkbox).children('input').attr('checked') ? true : false;
+      var parent = teaser[0].parentNode;
+      $(body).before(teaser);
+      $(parent).remove();
 
-    function trim(text) {
-      return text.replace(/^\s+/g, '').replace(/\s+$/g, '');
-    }
+      function trim(text) {
+        return text.replace(/^\s+/g, '').replace(/\s+$/g, '');
+      }
 
-    // Join the teaser back to the body.
-    function join_teaser() {
-      if (teaser.val()) {
-        body.val(trim(teaser.val()) +'\r\n\r\n'+ trim(body.val()));
+      // Join the teaser back to the body.
+      function join_teaser() {
+        if (teaser.val()) {
+          body.val(trim(teaser.val()) +'\r\n\r\n'+ trim(body.val()));
+        }
+        // Empty, hide and disable teaser.
+        teaser[0].value = '';
+        $(teaser).attr('disabled', 'disabled');
+        $(teaser).parent().slideUp('fast');
+        // Change label.
+        $(this).val(Drupal.t('Split summary at cursor'));
+        // Hide separate teaser checkbox.
+        $(checkbox).hide();
+        // Force a hidden checkbox to be checked (to ensure that the body is
+        // correctly processed on form submit when teaser/body are in joined
+        // state), and remember the current checked status.
+        checked = $(checkbox).children('input').attr('checked') ? true : false;
+        $(checkbox).children('input').attr('checked', true);
       }
-      // Empty, hide and disable teaser.
-      teaser[0].value = '';
-      $(teaser).attr('disabled', 'disabled');
-      $(teaser).parent().slideUp('fast');
-      // Change label.
-      $(this).val(Drupal.t('Split summary at cursor'));
-      // Hide separate teaser checkbox.
-      $(checkbox).hide();
-      // Force a hidden checkbox to be checked (to ensure that the body is
-      // correctly processed on form submit when teaser/body are in joined
-      // state), and remember the current checked status.
-      checked = $(checkbox).children('input').attr('checked') ? true : false;
-      $(checkbox).children('input').attr('checked', true);
-    }
 
-    // Split the teaser from the body.
-    function split_teaser() {
-      body[0].focus();
-      var selection = Drupal.getSelection(body[0]);
-      var split = selection.start;
-      var text = body.val();
+      // Split the teaser from the body.
+      function split_teaser() {
+        body[0].focus();
+        var selection = Drupal.getSelection(body[0]);
+        var split = selection.start;
+        var text = body.val();
 
-      // Note: using val() fails sometimes. jQuery bug?
-      teaser[0].value = trim(text.slice(0, split));
-      body[0].value = trim(text.slice(split));
-      // Reveal and enable teaser.
-      $(teaser).attr('disabled', '');
-      $(teaser).parent().slideDown('fast');
-      // Change label.
-      $(this).val(Drupal.t('Join summary'));
-      // Show separate teaser checkbox, restore checked value.
-      $(checkbox).show().children('input').attr('checked', checked);
-    }
+        // Note: using val() fails sometimes. jQuery bug?
+        teaser[0].value = trim(text.slice(0, split));
+        body[0].value = trim(text.slice(split));
+        // Reveal and enable teaser.
+        $(teaser).attr('disabled', '');
+        $(teaser).parent().slideDown('fast');
+        // Change label.
+        $(this).val(Drupal.t('Join summary'));
+        // Show separate teaser checkbox, restore checked value.
+        $(checkbox).show().children('input').attr('checked', checked);
+      }
 
-    // Add split/join button.
-    var button = $('<div class="teaser-button-wrapper"><input type="button" class="teaser-button" /></div>');
-    var include = $('#'+ this.id.substring(0, this.id.length - 2) +'include');
-    $(include).parent().parent().before(button);
+      // Add split/join button.
+      var button = $('<div class="teaser-button-wrapper"><input type="button" class="teaser-button" /></div>');
+      var include = $('#'+ this.id.substring(0, this.id.length - 2) +'include');
+      $(include).parent().parent().before(button);
 
-    // Extract the teaser from the body, if set. Otherwise, stay in joined mode.
-    var text = body.val().split('<!--break-->', 2);
-    if (text.length == 2) {
-      teaser[0].value = trim(text[0]);
-      body[0].value = trim(text[1]);
-      $(teaser).attr('disabled', '');
-      $('input', button).val(Drupal.t('Join summary')).toggle(join_teaser, split_teaser);
-    }
-    else {
-      $('input', button).val(Drupal.t('Split summary at cursor')).toggle(split_teaser, join_teaser);
-      $(checkbox).hide().children('input').attr('checked', true);
-    }
+      // Extract the teaser from the body, if set. Otherwise, stay in joined mode.
+      var text = body.val().split('<!--break-->', 2);
+      if (text.length == 2) {
+        teaser[0].value = trim(text[0]);
+        body[0].value = trim(text[1]);
+        $(teaser).attr('disabled', '');
+        $('input', button).val(Drupal.t('Join summary')).toggle(join_teaser, split_teaser);
+      }
+      else {
+        $('input', button).val(Drupal.t('Split summary at cursor')).toggle(split_teaser, join_teaser);
+        $(checkbox).hide().children('input').attr('checked', true);
+      }
 
-    // Make sure that textarea.js has done its magic to ensure proper visibility state.
-    if (Drupal.behaviors.textarea && teaser.is(('.form-textarea:not(.textarea-processed)'))) {
-      Drupal.behaviors.textarea(teaser.parentNode);
-    }
-    // Set initial visibility.
-    if ($(teaser).is('[@disabled]')) {
-      $(teaser).parent().hide();
-    }
+      // Make sure that textarea.js has done its magic to ensure proper visibility state.
+      if (Drupal.behaviors.textarea && teaser.is(('.form-textarea:not(.textarea-processed)'))) {
+        Drupal.behaviors.textarea.attach(teaser.parentNode);
+      }
+      // Set initial visibility.
+      if ($(teaser).is('[@disabled]')) {
+        $(teaser).parent().hide();
+      }
 
-  });
+    });
+  }
 };
diff --git a/misc/textarea.js b/misc/textarea.js
index 75fb3f5200b574157d2d2bee6b2f0e3040058120..a1860c6c80179bb73f1a415088fec5f9f685b69c 100644
--- a/misc/textarea.js
+++ b/misc/textarea.js
@@ -1,36 +1,38 @@
 // $Id$
 
-Drupal.behaviors.textarea = function(context) {
-  $('textarea.resizable:not(.textarea-processed)', context).each(function() {
-    // Avoid non-processed teasers.
-    if ($(this).is(('textarea.teaser:not(.teaser-processed)'))) {
-      return false;
-    }
-    var textarea = $(this).addClass('textarea-processed'), staticOffset = null;
+Drupal.behaviors.textarea = {
+  attach: function(context) {
+    $('textarea.resizable:not(.textarea-processed)', context).each(function() {
+      // Avoid non-processed teasers.
+      if ($(this).is(('textarea.teaser:not(.teaser-processed)'))) {
+        return false;
+      }
+      var textarea = $(this).addClass('textarea-processed'), staticOffset = null;
 
-    // When wrapping the text area, work around an IE margin bug.  See:
-    // http://jaspan.com/ie-inherited-margin-bug-form-elements-and-haslayout
-    $(this).wrap('<div class="resizable-textarea"><span></span></div>')
-      .parent().append($('<div class="grippie"></div>').mousedown(startDrag));
+      // When wrapping the text area, work around an IE margin bug.  See:
+      // http://jaspan.com/ie-inherited-margin-bug-form-elements-and-haslayout
+      $(this).wrap('<div class="resizable-textarea"><span></span></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';
+      var grippie = $('div.grippie', $(this).parent())[0];
+      grippie.style.marginRight = (grippie.offsetWidth - $(this)[0].offsetWidth) +'px';
 
-    function startDrag(e) {
-      staticOffset = textarea.height() - e.pageY;
-      textarea.css('opacity', 0.25);
-      $(document).mousemove(performDrag).mouseup(endDrag);
-      return false;
-    }
+      function startDrag(e) {
+        staticOffset = textarea.height() - e.pageY;
+        textarea.css('opacity', 0.25);
+        $(document).mousemove(performDrag).mouseup(endDrag);
+        return false;
+      }
 
-    function performDrag(e) {
-      textarea.height(Math.max(32, staticOffset + e.pageY) + 'px');
-      return false;
-    }
+      function performDrag(e) {
+        textarea.height(Math.max(32, staticOffset + e.pageY) + 'px');
+        return false;
+      }
 
-    function endDrag(e) {
-      $(document).unbind("mousemove", performDrag).unbind("mouseup", endDrag);
-      textarea.css('opacity', 1);
-    }
-  });
+      function endDrag(e) {
+        $(document).unbind("mousemove", performDrag).unbind("mouseup", endDrag);
+        textarea.css('opacity', 1);
+      }
+    });
+  }
 };
diff --git a/modules/block/block.js b/modules/block/block.js
index 802f25666c1b0e402119d04b319f146b20d1bfbb..eeb9306e03cd36da686c8147e9f9a92381907c18 100644
--- a/modules/block/block.js
+++ b/modules/block/block.js
@@ -6,90 +6,92 @@
  * This behavior is dependent on the tableDrag behavior, since it uses the
  * objects initialized in that behavior to update the row.
  */
-Drupal.behaviors.blockDrag = function(context) {
-  var table = $('table#blocks');
-  var tableDrag = Drupal.tableDrag.blocks; // Get the blocks tableDrag object.
+Drupal.behaviors.blockDrag = {
+  attach: function(context) {
+    var table = $('table#blocks');
+    var tableDrag = Drupal.tableDrag.blocks; // Get the blocks tableDrag object.
 
-  // Add a handler for when a row is swapped, update empty regions.
-  tableDrag.row.prototype.onSwap = function(swappedRow) {
-    checkEmptyRegions(table, this);
-  };
+    // Add a handler for when a row is swapped, update empty regions.
+    tableDrag.row.prototype.onSwap = function(swappedRow) {
+      checkEmptyRegions(table, this);
+    };
 
-  // A custom message for the blocks page specifically.
-  Drupal.theme.tableDragChangedWarning = function () {
-    return '<div class="warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t("The changes to these blocks will not be saved until the <em>Save blocks</em> button is clicked.") + '</div>';
-  };
+    // A custom message for the blocks page specifically.
+    Drupal.theme.tableDragChangedWarning = function () {
+      return '<div class="warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t("The changes to these blocks will not be saved until the <em>Save blocks</em> button is clicked.") + '</div>';
+    };
 
-  // Add a handler so when a row is dropped, update fields dropped into new regions.
-  tableDrag.onDrop = function() {
-    dragObject = this;
-    if ($(dragObject.rowObject.element).prev('tr').is('.region-message')) {
-      var regionRow = $(dragObject.rowObject.element).prev('tr').get(0);
-      var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
-      var regionField = $('select.block-region-select', dragObject.rowObject.element);
-      var weightField = $('select.block-weight', dragObject.rowObject.element);
-      var oldRegionName = weightField[0].className.replace(/([^ ]+[ ]+)*block-weight-([^ ]+)([ ]+[^ ]+)*/, '$2');
+    // Add a handler so when a row is dropped, update fields dropped into new regions.
+    tableDrag.onDrop = function() {
+      dragObject = this;
+      if ($(dragObject.rowObject.element).prev('tr').is('.region-message')) {
+        var regionRow = $(dragObject.rowObject.element).prev('tr').get(0);
+        var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
+        var regionField = $('select.block-region-select', dragObject.rowObject.element);
+        var weightField = $('select.block-weight', dragObject.rowObject.element);
+        var oldRegionName = weightField[0].className.replace(/([^ ]+[ ]+)*block-weight-([^ ]+)([ ]+[^ ]+)*/, '$2');
 
-      if (!regionField.is('.block-region-'+ regionName)) {
-        regionField.removeClass('block-region-' + oldRegionName).addClass('block-region-' + regionName);
-        weightField.removeClass('block-weight-' + oldRegionName).addClass('block-weight-' + regionName);
-        regionField.val(regionName);
+        if (!regionField.is('.block-region-'+ regionName)) {
+          regionField.removeClass('block-region-' + oldRegionName).addClass('block-region-' + regionName);
+          weightField.removeClass('block-weight-' + oldRegionName).addClass('block-weight-' + regionName);
+          regionField.val(regionName);
+        }
       }
-    }
-  };
+    };
 
-  // Add the behavior to each region select list.
-  $('select.block-region-select:not(.blockregionselect-processed)', context).each(function() {
-    $(this).change(function(event) {
-      // Make our new row and select field.
-      var row = $(this).parents('tr:first');
-      var select = $(this);
-      tableDrag.rowObject = new tableDrag.row(row);
+    // Add the behavior to each region select list.
+    $('select.block-region-select:not(.blockregionselect-processed)', context).each(function() {
+      $(this).change(function(event) {
+        // Make our new row and select field.
+        var row = $(this).parents('tr:first');
+        var select = $(this);
+        tableDrag.rowObject = new tableDrag.row(row);
 
-      // Find the correct region and insert the row as the first in the region.
-      $('tr.region-message', table).each(function() {
-        if ($(this).is('.region-' + select[0].value + '-message')) {
-          // Add the new row and remove the old one.
-          $(this).after(row);
-          // Manually update weights and restripe.
-          tableDrag.updateFields(row.get(0));
-          tableDrag.rowObject.changed = true;
-          if (tableDrag.oldRowElement) {
-            $(tableDrag.oldRowElement).removeClass('drag-previous');
+        // Find the correct region and insert the row as the first in the region.
+        $('tr.region-message', table).each(function() {
+          if ($(this).is('.region-' + select[0].value + '-message')) {
+            // Add the new row and remove the old one.
+            $(this).after(row);
+            // Manually update weights and restripe.
+            tableDrag.updateFields(row.get(0));
+            tableDrag.rowObject.changed = true;
+            if (tableDrag.oldRowElement) {
+              $(tableDrag.oldRowElement).removeClass('drag-previous');
+            }
+            tableDrag.oldRowElement = row.get(0);
+            tableDrag.restripeTable();
+            tableDrag.rowObject.markChanged();
+            tableDrag.oldRowElement = row;
+            $(row).addClass('drag-previous');
           }
-          tableDrag.oldRowElement = row.get(0);
-          tableDrag.restripeTable();
-          tableDrag.rowObject.markChanged();
-          tableDrag.oldRowElement = row;
-          $(row).addClass('drag-previous');
-        }
-      });
+        });
 
-      // Modify empty regions with added or removed fields.
-      checkEmptyRegions(table, row);
-      // Remove focus from selectbox.
-      select.get(0).blur();
+        // Modify empty regions with added or removed fields.
+        checkEmptyRegions(table, row);
+        // Remove focus from selectbox.
+        select.get(0).blur();
+      });
+      $(this).addClass('blockregionselect-processed');
     });
-    $(this).addClass('blockregionselect-processed');
-  });
 
-  var checkEmptyRegions = function(table, rowObject) {
-    $('tr.region-message', table).each(function() {
-      // If the dragged row is in this region, but above the message row, swap it down one space.
-      if ($(this).prev('tr').get(0) == rowObject.element) {
-        // Prevent a recursion problem when using the keyboard to move rows up.
-        if ((rowObject.method != 'keyboard' || rowObject.direction == 'down')) {
-          rowObject.swap('after', this);
+    var checkEmptyRegions = function(table, rowObject) {
+      $('tr.region-message', table).each(function() {
+        // If the dragged row is in this region, but above the message row, swap it down one space.
+        if ($(this).prev('tr').get(0) == rowObject.element) {
+          // Prevent a recursion problem when using the keyboard to move rows up.
+          if ((rowObject.method != 'keyboard' || rowObject.direction == 'down')) {
+            rowObject.swap('after', this);
+          }
         }
-      }
-      // This region has become empty.
-      if ($(this).next('tr').is(':not(.draggable)') || $(this).next('tr').size() == 0) {
-        $(this).removeClass('region-populated').addClass('region-empty');
-      }
-      // This region has become populated.
-      else if ($(this).is('.region-empty')) {
-        $(this).removeClass('region-empty').addClass('region-populated');
-      }
-    });
-  };
+        // This region has become empty.
+        if ($(this).next('tr').is(':not(.draggable)') || $(this).next('tr').size() == 0) {
+          $(this).removeClass('region-populated').addClass('region-empty');
+        }
+        // This region has become populated.
+        else if ($(this).is('.region-empty')) {
+          $(this).removeClass('region-empty').addClass('region-populated');
+        }
+      });
+    };
+  }
 };
diff --git a/modules/color/color.js b/modules/color/color.js
index c04c419f8abed8cd33c40d9fbc2f76dc0ddf2228..89c94dc37b97b3bf1c62994620ac1be362c76bc6 100644
--- a/modules/color/color.js
+++ b/modules/color/color.js
@@ -1,251 +1,253 @@
 // $Id$
 
-Drupal.behaviors.color = function (context) {
-  // This behavior attaches by ID, so is only valid once on a page.
-  if ($('#color_scheme_form .color-form.color-processed').size()) {
-    return;
-  }
-  var form = $('#color_scheme_form .color-form', context);
-  var inputs = [];
-  var hooks = [];
-  var locks = [];
-  var focused = null;
-
-  // Add Farbtastic.
-  $(form).prepend('<div id="placeholder"></div>').addClass('color-processed');
-  var farb = $.farbtastic('#placeholder');
-
-  // Decode reference colors to HSL.
-  var reference = Drupal.settings.color.reference;
-  for (i in reference) {
-    reference[i] = farb.RGBToHSL(farb.unpack(reference[i]));
-  }
-
-  // Build a preview.
-  $('#preview:not(.color-processed)')
-    .append('<div id="gradient"></div>')
-    .addClass('color-processed');
-  var gradient = $('#preview #gradient');
-  var h = parseInt(gradient.css('height')) / 10;
-  for (i = 0; i < h; ++i) {
-    gradient.append('<div class="gradient-line"></div>');
-  }
+Drupal.behaviors.color = {
+  attach: function(context) {
+    // This behavior attaches by ID, so is only valid once on a page.
+    if ($('#color_scheme_form .color-form.color-processed').size()) {
+      return;
+    }
+    var form = $('#color_scheme_form .color-form', context);
+    var inputs = [];
+    var hooks = [];
+    var locks = [];
+    var focused = null;
+
+    // Add Farbtastic.
+    $(form).prepend('<div id="placeholder"></div>').addClass('color-processed');
+    var farb = $.farbtastic('#placeholder');
+
+    // Decode reference colors to HSL.
+    var reference = Drupal.settings.color.reference;
+    for (i in reference) {
+      reference[i] = farb.RGBToHSL(farb.unpack(reference[i]));
+    }
 
-  // Fix preview background in IE6.
-  if (navigator.appVersion.match(/MSIE [0-6]\./)) {
-    var e = $('#preview #img')[0];
-    var image = e.currentStyle.backgroundImage;
-    e.style.backgroundImage = 'none';
-    e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image.substring(5, image.length - 2) + "')";
-  }
+    // Build a preview.
+    $('#preview:not(.color-processed)')
+      .append('<div id="gradient"></div>')
+      .addClass('color-processed');
+    var gradient = $('#preview #gradient');
+    var h = parseInt(gradient.css('height')) / 10;
+    for (i = 0; i < h; ++i) {
+      gradient.append('<div class="gradient-line"></div>');
+    }
 
-  // Set up colorscheme selector.
-  $('#edit-scheme', form).change(function () {
-    var colors = this.options[this.selectedIndex].value;
-    if (colors != '') {
-      colors = colors.split(',');
-      for (i in colors) {
-        callback(inputs[i], colors[i], false, true);
-      }
-      preview();
+    // Fix preview background in IE6.
+    if (navigator.appVersion.match(/MSIE [0-6]\./)) {
+      var e = $('#preview #img')[0];
+      var image = e.currentStyle.backgroundImage;
+      e.style.backgroundImage = 'none';
+      e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image.substring(5, image.length - 2) + "')";
     }
-  });
-
-  /**
-   * Render the preview.
-   */
-  function preview() {
-    // Solid background.
-    $('#preview', form).css('backgroundColor', inputs[0].value);
-
-    // Text preview
-    $('#text', form).css('color', inputs[4].value);
-    $('#text a, #text h2', form).css('color', inputs[1].value);
-
-    // Set up gradient.
-    var top = farb.unpack(inputs[2].value);
-    var bottom = farb.unpack(inputs[3].value);
-    if (top && bottom) {
-      var delta = [];
-      for (i in top) {
-        delta[i] = (bottom[i] - top[i]) / h;
+
+    // Set up colorscheme selector.
+    $('#edit-scheme', form).change(function () {
+      var colors = this.options[this.selectedIndex].value;
+      if (colors != '') {
+        colors = colors.split(',');
+        for (i in colors) {
+          callback(inputs[i], colors[i], false, true);
+        }
+        preview();
       }
-      var accum = top;
+    });
 
-      // Render gradient lines.
-      $('#gradient > div', form).each(function () {
-        for (i in accum) {
-          accum[i] += delta[i];
+    /**
+     * Render the preview.
+     */
+    function preview() {
+      // Solid background.
+      $('#preview', form).css('backgroundColor', inputs[0].value);
+
+      // Text preview
+      $('#text', form).css('color', inputs[4].value);
+      $('#text a, #text h2', form).css('color', inputs[1].value);
+
+      // Set up gradient.
+      var top = farb.unpack(inputs[2].value);
+      var bottom = farb.unpack(inputs[3].value);
+      if (top && bottom) {
+        var delta = [];
+        for (i in top) {
+          delta[i] = (bottom[i] - top[i]) / h;
         }
-        this.style.backgroundColor = farb.pack(accum);
-      });
+        var accum = top;
+
+        // Render gradient lines.
+        $('#gradient > div', form).each(function () {
+          for (i in accum) {
+            accum[i] += delta[i];
+          }
+          this.style.backgroundColor = farb.pack(accum);
+        });
+      }
     }
-  }
 
-  /**
-   * Shift a given color, using a reference pair (ref in HSL).
-   *
-   * This algorithm ensures relative ordering on the saturation and luminance
-   * axes is preserved, and performs a simple hue shift.
-   *
-   * It is also symmetrical. If: shift_color(c, a, b) == d,
-   *                        then shift_color(d, b, a) == c.
-   */
-  function shift_color(given, ref1, ref2) {
-    // Convert to HSL.
-    given = farb.RGBToHSL(farb.unpack(given));
-
-    // Hue: apply delta.
-    given[0] += ref2[0] - ref1[0];
-
-    // Saturation: interpolate.
-    if (ref1[1] == 0 || ref2[1] == 0) {
-      given[1] = ref2[1];
-    }
-    else {
-      var d = ref1[1] / ref2[1];
-      if (d > 1) {
-        given[1] /= d;
+    /**
+     * Shift a given color, using a reference pair (ref in HSL).
+     *
+     * This algorithm ensures relative ordering on the saturation and luminance
+     * axes is preserved, and performs a simple hue shift.
+     *
+     * It is also symmetrical. If: shift_color(c, a, b) == d,
+     *                        then shift_color(d, b, a) == c.
+     */
+    function shift_color(given, ref1, ref2) {
+      // Convert to HSL.
+      given = farb.RGBToHSL(farb.unpack(given));
+
+      // Hue: apply delta.
+      given[0] += ref2[0] - ref1[0];
+
+      // Saturation: interpolate.
+      if (ref1[1] == 0 || ref2[1] == 0) {
+        given[1] = ref2[1];
       }
       else {
-        given[1] = 1 - (1 - given[1]) * d;
+        var d = ref1[1] / ref2[1];
+        if (d > 1) {
+          given[1] /= d;
+        }
+        else {
+          given[1] = 1 - (1 - given[1]) * d;
+        }
       }
-    }
 
-    // Luminance: interpolate.
-    if (ref1[2] == 0 || ref2[2] == 0) {
-      given[2] = ref2[2];
-    }
-    else {
-      var d = ref1[2] / ref2[2];
-      if (d > 1) {
-        given[2] /= d;
+      // Luminance: interpolate.
+      if (ref1[2] == 0 || ref2[2] == 0) {
+        given[2] = ref2[2];
       }
       else {
-        given[2] = 1 - (1 - given[2]) * d;
-      }
-    }
-
-    return farb.pack(farb.HSLToRGB(given));
-  }
-
-  /**
-   * Callback for Farbtastic when a new color is chosen.
-   */
-  function callback(input, color, propagate, colorscheme) {
-    // Set background/foreground colors.
-    $(input).css({
-      backgroundColor: color,
-      'color': farb.RGBToHSL(farb.unpack(color))[2] > 0.5 ? '#000' : '#fff'
-    });
-
-    // Change input value.
-    if (input.value && input.value != color) {
-      input.value = color;
-
-      // Update locked values.
-      if (propagate) {
-        var i = input.i;
-        for (j = i + 1; ; ++j) {
-          if (!locks[j - 1] || $(locks[j - 1]).is('.unlocked')) break;
-          var matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
-          callback(inputs[j], matched, false);
+        var d = ref1[2] / ref2[2];
+        if (d > 1) {
+          given[2] /= d;
         }
-        for (j = i - 1; ; --j) {
-          if (!locks[j] || $(locks[j]).is('.unlocked')) break;
-          var matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
-          callback(inputs[j], matched, false);
+        else {
+          given[2] = 1 - (1 - given[2]) * d;
         }
-
-        // Update preview.
-        preview();
       }
 
-      // Reset colorscheme selector.
-      if (!colorscheme) {
-        resetScheme();
-      }
+      return farb.pack(farb.HSLToRGB(given));
     }
 
-  }
-
-  /**
-   * Reset the color scheme selector.
-   */
-  function resetScheme() {
-    $('#edit-scheme', form).each(function () {
-      this.selectedIndex = this.options.length - 1;
-    });
-  }
-
-  // Focus the Farbtastic on a particular field.
-  function focus() {
-    var input = this;
-    // Remove old bindings.
-    focused && $(focused).unbind('keyup', farb.updateValue)
-        .unbind('keyup', preview).unbind('keyup', resetScheme)
-        .parent().removeClass('item-selected');
-
-    // Add new bindings.
-    focused = this;
-    farb.linkTo(function (color) { callback(input, color, true, false); });
-    farb.setColor(this.value);
-    $(focused).keyup(farb.updateValue).keyup(preview).keyup(resetScheme)
-      .parent().addClass('item-selected');
-  }
+    /**
+     * Callback for Farbtastic when a new color is chosen.
+     */
+    function callback(input, color, propagate, colorscheme) {
+      // Set background/foreground colors.
+      $(input).css({
+        backgroundColor: color,
+        'color': farb.RGBToHSL(farb.unpack(color))[2] > 0.5 ? '#000' : '#fff'
+      });
 
-  // Initialize color fields.
-  $('#palette input.form-text', form)
-  .each(function () {
-    // Extract palette field name
-    this.key = this.id.substring(13);
-
-    // Link to color picker temporarily to initialize.
-    farb.linkTo(function () {}).setColor('#000').linkTo(this);
-
-    // Add lock.
-    var i = inputs.length;
-    if (inputs.length) {
-      var lock = $('<div class="lock"></div>').toggle(
-        function () {
-          $(this).addClass('unlocked');
-          $(hooks[i - 1]).attr('class',
-            locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook up' : 'hook'
-          );
-          $(hooks[i]).attr('class',
-            locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook down' : 'hook'
-          );
-        },
-        function () {
-          $(this).removeClass('unlocked');
-          $(hooks[i - 1]).attr('class',
-            locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook both' : 'hook down'
-          );
-          $(hooks[i]).attr('class',
-            locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook both' : 'hook up'
-          );
+      // Change input value.
+      if (input.value && input.value != color) {
+        input.value = color;
+
+        // Update locked values.
+        if (propagate) {
+          var i = input.i;
+          for (j = i + 1; ; ++j) {
+            if (!locks[j - 1] || $(locks[j - 1]).is('.unlocked')) break;
+            var matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
+            callback(inputs[j], matched, false);
+          }
+          for (j = i - 1; ; --j) {
+            if (!locks[j] || $(locks[j]).is('.unlocked')) break;
+            var matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
+            callback(inputs[j], matched, false);
+          }
+
+          // Update preview.
+          preview();
         }
-      );
-      $(this).after(lock);
-      locks.push(lock);
-    };
 
-    // Add hook.
-    var hook = $('<div class="hook"></div>');
-    $(this).after(hook);
-    hooks.push(hook);
+        // Reset colorscheme selector.
+        if (!colorscheme) {
+          resetScheme();
+        }
+      }
 
-    $(this).parent().find('.lock').click();
-    this.i = i;
-    inputs.push(this);
-  })
-  .focus(focus);
+    }
 
-  $('#palette label', form);
+    /**
+     * Reset the color scheme selector.
+     */
+    function resetScheme() {
+      $('#edit-scheme', form).each(function () {
+        this.selectedIndex = this.options.length - 1;
+      });
+    }
 
-  // Focus first color.
-  focus.call(inputs[0]);
+    // Focus the Farbtastic on a particular field.
+    function focus() {
+      var input = this;
+      // Remove old bindings.
+      focused && $(focused).unbind('keyup', farb.updateValue)
+          .unbind('keyup', preview).unbind('keyup', resetScheme)
+          .parent().removeClass('item-selected');
+
+      // Add new bindings.
+      focused = this;
+      farb.linkTo(function (color) { callback(input, color, true, false); });
+      farb.setColor(this.value);
+      $(focused).keyup(farb.updateValue).keyup(preview).keyup(resetScheme)
+        .parent().addClass('item-selected');
+    }
 
-  // Render preview.
-  preview();
+    // Initialize color fields.
+    $('#palette input.form-text', form)
+    .each(function () {
+      // Extract palette field name
+      this.key = this.id.substring(13);
+
+      // Link to color picker temporarily to initialize.
+      farb.linkTo(function () {}).setColor('#000').linkTo(this);
+
+      // Add lock.
+      var i = inputs.length;
+      if (inputs.length) {
+        var lock = $('<div class="lock"></div>').toggle(
+          function () {
+            $(this).addClass('unlocked');
+            $(hooks[i - 1]).attr('class',
+              locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook up' : 'hook'
+            );
+            $(hooks[i]).attr('class',
+              locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook down' : 'hook'
+            );
+          },
+          function () {
+            $(this).removeClass('unlocked');
+            $(hooks[i - 1]).attr('class',
+              locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook both' : 'hook down'
+            );
+            $(hooks[i]).attr('class',
+              locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook both' : 'hook up'
+            );
+          }
+        );
+        $(this).after(lock);
+        locks.push(lock);
+      };
+
+      // Add hook.
+      var hook = $('<div class="hook"></div>');
+      $(this).after(hook);
+      hooks.push(hook);
+
+      $(this).parent().find('.lock').click();
+      this.i = i;
+      inputs.push(this);
+    })
+    .focus(focus);
+
+    $('#palette label', form);
+
+    // Focus first color.
+    focus.call(inputs[0]);
+
+    // Render preview.
+    preview();
+  }
 };
diff --git a/modules/comment/comment.js b/modules/comment/comment.js
index d639a4abd7c1eac04a347af2c5dd6dc7dce25dbb..b951f4211839a4942551dcb01e540624de905e05 100644
--- a/modules/comment/comment.js
+++ b/modules/comment/comment.js
@@ -1,14 +1,16 @@
 // $Id$
 
-Drupal.behaviors.comment = function(context) {
-  var parts = new Array("name", "homepage", "mail");
-  var cookie = '';
-  for (i=0;i<3;i++) {
-    cookie = Drupal.comment.getCookie('comment_info_' + parts[i]);
-    if (cookie != '') {
-      $("#comment-form input[name=" + parts[i] + "]:not(.comment-processed)", context)
-        .val(cookie)
-        .addClass('comment-processed');
+Drupal.behaviors.comment = {
+  attach: function(context) {
+    var parts = new Array("name", "homepage", "mail");
+    var cookie = '';
+    for (i=0;i<3;i++) {
+      cookie = Drupal.comment.getCookie('comment_info_' + parts[i]);
+      if (cookie != '') {
+        $("#comment-form input[name=" + parts[i] + "]:not(.comment-processed)", context)
+          .val(cookie)
+          .addClass('comment-processed');
+      }
     }
   }
 };
diff --git a/modules/openid/openid.js b/modules/openid/openid.js
index bd2948dc96230c893209c8d65ce7e98e2a9b294d..eeb84300d80173a5358bebd89b90d2912b6894f5 100644
--- a/modules/openid/openid.js
+++ b/modules/openid/openid.js
@@ -1,38 +1,40 @@
 // $Id$
 
-Drupal.behaviors.openid = function (context) {
-  var $loginElements = $("#edit-name-wrapper, #edit-pass-wrapper, li.openid-link");
-  var $openidElements = $("#edit-openid-identifier-wrapper, li.user-link");
+Drupal.behaviors.openid = {
+  attach: function(context) {
+    var $loginElements = $("#edit-name-wrapper, #edit-pass-wrapper, li.openid-link");
+    var $openidElements = $("#edit-openid-identifier-wrapper, li.user-link");
 
-  // This behavior attaches by ID, so is only valid once on a page.
-  if (!$("#edit-openid-identifier.openid-processed").size() && $("#edit-openid-identifier").val()) {
-    $("#edit-openid-identifier").addClass('openid-processed');
-    $loginElements.hide();
-    // Use .css("display", "block") instead of .show() to be Konqueror friendly.
-    $openidElements.css("display", "block");
+    // This behavior attaches by ID, so is only valid once on a page.
+    if (!$("#edit-openid-identifier.openid-processed").size() && $("#edit-openid-identifier").val()) {
+      $("#edit-openid-identifier").addClass('openid-processed');
+      $loginElements.hide();
+      // Use .css("display", "block") instead of .show() to be Konqueror friendly.
+      $openidElements.css("display", "block");
+    }
+    $("li.openid-link:not(.openid-processed)", context)
+      .addClass('openid-processed')
+      .click( function() {
+         $loginElements.hide();
+         $openidElements.css("display", "block");
+        // Remove possible error message.
+        $("#edit-name, #edit-pass").removeClass("error");
+        $("div.messages.error").hide();
+        // Set focus on OpenID Identifier field.
+        $("#edit-openid-identifier")[0].focus();
+        return false;
+      });
+    $("li.user-link:not(.openid-processed)", context)
+      .addClass('openid-processed')
+      .click(function() {
+         $openidElements.hide();
+         $loginElements.css("display", "block");
+        // Clear OpenID Identifier field and remove possible error message.
+        $("#edit-openid-identifier").val('').removeClass("error");
+        $("div.messages.error").css("display", "block");
+        // Set focus on username field.
+        $("#edit-name")[0].focus();
+        return false;
+      });
   }
-  $("li.openid-link:not(.openid-processed)", context)
-    .addClass('openid-processed')
-    .click( function() {
-       $loginElements.hide();
-       $openidElements.css("display", "block");
-      // Remove possible error message.
-      $("#edit-name, #edit-pass").removeClass("error");
-      $("div.messages.error").hide();
-      // Set focus on OpenID Identifier field.
-      $("#edit-openid-identifier")[0].focus();
-      return false;
-    });
-  $("li.user-link:not(.openid-processed)", context)
-    .addClass('openid-processed')
-    .click(function() {
-       $openidElements.hide();
-       $loginElements.css("display", "block");
-      // Clear OpenID Identifier field and remove possible error message.
-      $("#edit-openid-identifier").val('').removeClass("error");
-      $("div.messages.error").css("display", "block");
-      // Set focus on username field.
-      $("#edit-name")[0].focus();
-      return false;
-    });
 };
diff --git a/modules/profile/profile.js b/modules/profile/profile.js
index 2d84d27e057a0226186704a88902dd4504880979..d14be4b7d0d324c47c6c978396c706f49d1450de 100644
--- a/modules/profile/profile.js
+++ b/modules/profile/profile.js
@@ -7,48 +7,50 @@
  * objects initialized in that behavior to update the row. It shows and hides
  * a warning message when removing the last field from a profile category.
  */
-Drupal.behaviors.profileDrag = function(context) {
-  var table = $('#profile-fields');
-  var tableDrag = Drupal.tableDrag['profile-fields']; // Get the profile tableDrag object.
+Drupal.behaviors.profileDrag = {
+  attach: function(context) {
+    var table = $('#profile-fields');
+    var tableDrag = Drupal.tableDrag['profile-fields']; // Get the profile tableDrag object.
 
-  // Add a handler for when a row is swapped, update empty categories.
-  tableDrag.row.prototype.onSwap = function(swappedRow) {
-    var rowObject = this;
-    $('tr.category-message', table).each(function() {
-      // If the dragged row is in this category, but above the message row, swap it down one space.
-      if ($(this).prev('tr').get(0) == rowObject.element) {
-        // Prevent a recursion problem when using the keyboard to move rows up.
-        if ((rowObject.method != 'keyboard' || rowObject.direction == 'down')) {
-          rowObject.swap('after', this);
+    // Add a handler for when a row is swapped, update empty categories.
+    tableDrag.row.prototype.onSwap = function(swappedRow) {
+      var rowObject = this;
+      $('tr.category-message', table).each(function() {
+        // If the dragged row is in this category, but above the message row, swap it down one space.
+        if ($(this).prev('tr').get(0) == rowObject.element) {
+          // Prevent a recursion problem when using the keyboard to move rows up.
+          if ((rowObject.method != 'keyboard' || rowObject.direction == 'down')) {
+            rowObject.swap('after', this);
+          }
         }
-      }
-      // This category has become empty
-      if ($(this).next('tr').is(':not(.draggable)') || $(this).next('tr').size() == 0) {
-        $(this).removeClass('category-populated').addClass('category-empty');
-      }
-      // This category has become populated.
-      else if ($(this).is('.category-empty')) {
-        $(this).removeClass('category-empty').addClass('category-populated');
-      }
-    });
-  };
+        // This category has become empty
+        if ($(this).next('tr').is(':not(.draggable)') || $(this).next('tr').size() == 0) {
+          $(this).removeClass('category-populated').addClass('category-empty');
+        }
+        // This category has become populated.
+        else if ($(this).is('.category-empty')) {
+          $(this).removeClass('category-empty').addClass('category-populated');
+        }
+      });
+    };
 
-  // Add a handler so when a row is dropped, update fields dropped into new categories.
-  tableDrag.onDrop = function() {
-    dragObject = this;
-    if ($(dragObject.rowObject.element).prev('tr').is('.category-message')) {
-      var categoryRow = $(dragObject.rowObject.element).prev('tr').get(0);
-      var categoryNum = categoryRow.className.replace(/([^ ]+[ ]+)*category-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
-      var categoryField = $('select.profile-category', dragObject.rowObject.element);
-      var weightField = $('select.profile-weight', dragObject.rowObject.element);
-      var oldcategoryNum = weightField[0].className.replace(/([^ ]+[ ]+)*profile-weight-([^ ]+)([ ]+[^ ]+)*/, '$2');
+    // Add a handler so when a row is dropped, update fields dropped into new categories.
+    tableDrag.onDrop = function() {
+      dragObject = this;
+      if ($(dragObject.rowObject.element).prev('tr').is('.category-message')) {
+        var categoryRow = $(dragObject.rowObject.element).prev('tr').get(0);
+        var categoryNum = categoryRow.className.replace(/([^ ]+[ ]+)*category-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
+        var categoryField = $('select.profile-category', dragObject.rowObject.element);
+        var weightField = $('select.profile-weight', dragObject.rowObject.element);
+        var oldcategoryNum = weightField[0].className.replace(/([^ ]+[ ]+)*profile-weight-([^ ]+)([ ]+[^ ]+)*/, '$2');
 
-      if (!categoryField.is('.profile-category-'+ categoryNum)) {
-        categoryField.removeClass('profile-category-' + oldcategoryNum).addClass('profile-category-' + categoryNum);
-        weightField.removeClass('profile-weight-' + oldcategoryNum).addClass('profile-weight-' + categoryNum);
+        if (!categoryField.is('.profile-category-'+ categoryNum)) {
+          categoryField.removeClass('profile-category-' + oldcategoryNum).addClass('profile-category-' + categoryNum);
+          weightField.removeClass('profile-weight-' + oldcategoryNum).addClass('profile-weight-' + categoryNum);
 
-        categoryField.val(categoryField[0].options[categoryNum].value);
+          categoryField.val(categoryField[0].options[categoryNum].value);
+        }
       }
-    }
-  };
+    };
+  }
 };
diff --git a/modules/simpletest/simpletest.js b/modules/simpletest/simpletest.js
index a3f4a5e75fd8d7dc2733d4bce971b15e8c1d127a..6ae86a2aebce1f93b64628dbd52e77af64784d7e 100644
--- a/modules/simpletest/simpletest.js
+++ b/modules/simpletest/simpletest.js
@@ -3,73 +3,77 @@
 /**
  * Add the cool table collapsing on the testing overview page.
  */
-Drupal.behaviors.simpleTestMenuCollapse = function() {
-  // Adds expand-collapse functionality.
-  $('div.simpletest-image').each(function() {
-    direction = Drupal.settings.simpleTest[$(this).attr('id')].imageDirection;
-    $(this).html(Drupal.settings.simpleTest.images[direction]);
-  });
-  $('div.simpletest-image').click(function() {
-    // Toggle all of the trs.
-    if (!Drupal.settings.simpleTest[$(this).attr('id')].clickActive) {
-      Drupal.settings.simpleTest[$(this).attr('id')].clickActive = true;
-      var trs = $(this).parents('tbody').children().filter('.' + Drupal.settings.simpleTest[$(this).attr('id')].testClass), trs_formatted = [], direction = Drupal.settings.simpleTest[$(this).attr('id')].imageDirection, self = $(this);
-      for (var i = 0; i < trs.length; i++) {
-        trs_formatted.push(trs[i]);
-      }
-      var toggleTrs = function(trs, action, action2) {
-        tr = trs[action]();
-        if (tr) {
-          $(tr)[action2](1, function() {
-            toggleTrs(trs, action, action2);
-          });
+Drupal.behaviors.simpleTestMenuCollapse = {
+  attach: function() {
+    // Adds expand-collapse functionality.
+    $('div.simpletest-image').each(function() {
+      direction = Drupal.settings.simpleTest[$(this).attr('id')].imageDirection;
+      $(this).html(Drupal.settings.simpleTest.images[direction]);
+    });
+    $('div.simpletest-image').click(function() {
+      // Toggle all of the trs.
+      if (!Drupal.settings.simpleTest[$(this).attr('id')].clickActive) {
+        Drupal.settings.simpleTest[$(this).attr('id')].clickActive = true;
+        var trs = $(this).parents('tbody').children().filter('.' + Drupal.settings.simpleTest[$(this).attr('id')].testClass), trs_formatted = [], direction = Drupal.settings.simpleTest[$(this).attr('id')].imageDirection, self = $(this);
+        for (var i = 0; i < trs.length; i++) {
+          trs_formatted.push(trs[i]);
         }
-        else {
-          Drupal.settings.simpleTest[self.attr('id')].clickActive = false;
+        var toggleTrs = function(trs, action, action2) {
+          tr = trs[action]();
+          if (tr) {
+            $(tr)[action2](1, function() {
+              toggleTrs(trs, action, action2);
+            });
+          }
+          else {
+            Drupal.settings.simpleTest[self.attr('id')].clickActive = false;
+          }
         }
+        toggleTrs(trs_formatted, (direction ? 'pop' : 'shift'), (direction ? 'fadeOut' : 'fadeIn'));
+        Drupal.settings.simpleTest[$(this).attr('id')].imageDirection = !direction;
+        $(this).html(Drupal.settings.simpleTest.images[(direction? 0 : 1)]);
       }
-      toggleTrs(trs_formatted, (direction ? 'pop' : 'shift'), (direction ? 'fadeOut' : 'fadeIn'));
-      Drupal.settings.simpleTest[$(this).attr('id')].imageDirection = !direction;
-      $(this).html(Drupal.settings.simpleTest.images[(direction? 0 : 1)]);
-    }
-  });
-}
+    });
+  }
+};
 
 /**
  * Select/deselect all the inner checkboxes when the outer checkboxes are
  * selected/deselected.
  */
-Drupal.behaviors.simpleTestSelectAll = function() {
-  $('td.simpletest-select-all').each(function() {
-    var checkboxes = Drupal.settings.simpleTest['simpletest-test-group-'+ $(this).attr('id')].testNames, totalCheckboxes = 0,
-      checkbox = $('<input type="checkbox" class="form-checkbox" id="'+ $(this).attr('id') +'-select-all" />').change(function() {
-      var checked = !!($(this).attr('checked'));
-      for (var i = 0; i < checkboxes.length; i++) {
-        $('#'+ checkboxes[i]).attr('checked', checked);
-      }
-      self.data('simpletest-checked-tests', (checked ? checkboxes.length : 0));
-    }).data('simpletest-checked-tests', 0);
-    var self = $(this);
-    for (var i = 0; i < checkboxes.length; i++) {
-      if ($('#' + checkboxes[i]).change(function() {
-        if (checkbox.attr('checked') == 'checked') {
-          checkbox.attr('checked', '');
+Drupal.behaviors.simpleTestSelectAll = {
+  attach: function() {
+    $('td.simpletest-select-all').each(function() {
+      var checkboxes = Drupal.settings.simpleTest['simpletest-test-group-'+ $(this).attr('id')].testNames, totalCheckboxes = 0,
+        checkbox = $('<input type="checkbox" class="form-checkbox" id="'+ $(this).attr('id') +'-select-all" />').change(function() {
+        var checked = !!($(this).attr('checked'));
+        for (var i = 0; i < checkboxes.length; i++) {
+          $('#'+ checkboxes[i]).attr('checked', checked);
         }
-        var data = (!self.data('simpletest-checked-tests') ? 0 : self.data('simpletest-checked-tests')) + (!!($(this).attr('checked')) ? 1 : -1);
-        self.data('simpletest-checked-tests', data);
-        if (data == checkboxes.length) {
-          checkbox.attr('checked', 'checked');
-        }
-        else {
-          checkbox.removeAttr('checked');
+        self.data('simpletest-checked-tests', (checked ? checkboxes.length : 0));
+      }).data('simpletest-checked-tests', 0);
+      var self = $(this);
+      for (var i = 0; i < checkboxes.length; i++) {
+        if ($('#' + checkboxes[i]).change(function() {
+          if (checkbox.attr('checked') == 'checked') {
+            checkbox.attr('checked', '');
+          }
+          var data = (!self.data('simpletest-checked-tests') ? 0 : self.data('simpletest-checked-tests')) + (!!($(this).attr('checked')) ? 1 : -1);
+          self.data('simpletest-checked-tests', data);
+          if (data == checkboxes.length) {
+            checkbox.attr('checked', 'checked');
+          }
+          else {
+            checkbox.removeAttr('checked');
+          }
+        }).attr('checked') == 'checked') {
+          totalCheckboxes++;
         }
-      }).attr('checked') == 'checked') {
-        totalCheckboxes++;
       }
-    }
-    if (totalCheckboxes == checkboxes.length) {
-      $(checkbox).attr('checked', 'checked');
-    }
-    $(this).append(checkbox);
-  });
-};
\ No newline at end of file
+      if (totalCheckboxes == checkboxes.length) {
+        $(checkbox).attr('checked', 'checked');
+      }
+      $(this).append(checkbox);
+    });
+  }
+};
diff --git a/modules/system/system.js b/modules/system/system.js
index c2abc8a8999cceca7f308a1bde86a1b6dd2bccb5..3b477739e7c6e2d22fa25195a0ce10dd4b4b85b8 100644
--- a/modules/system/system.js
+++ b/modules/system/system.js
@@ -7,32 +7,34 @@
  * This function is not used to verify whether or not clean URLs
  * are currently enabled.
  */
-Drupal.behaviors.cleanURLsSettingsCheck = function(context) {
-  // This behavior attaches by ID, so is only valid once on a page.
-  // Also skip if we are on an install page, as Drupal.cleanURLsInstallCheck will handle
-  // the processing.
-  if ($("#clean-url.clean-url-processed, #clean-url.install").size()) {
-    return;
-  }
-  var url = Drupal.settings.basePath +"admin/settings/clean-urls/check";
-  $("#clean-url .description span").html('<div id="testing">'+ Drupal.t('Testing clean URLs...') +"</div>");
-  $("#clean-url p").hide();
-  $.ajax({
-    url: location.protocol +"//"+ location.host + url,
-    dataType: 'json',
-    success: function () {
-      // Check was successful.
-      $("#clean-url input.form-radio").attr("disabled", false);
-      $("#clean-url .description span").append('<div class="ok">'+ Drupal.t('Your server has been successfully tested to support this feature.') +"</div>");
-      $("#testing").hide();
-    },
-    error: function() {
-      // Check failed.
-      $("#clean-url .description span").append('<div class="warning">'+ Drupal.t('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.') +"</div>");
-      $("#testing").hide();
+Drupal.behaviors.cleanURLsSettingsCheck = {
+  attach: function(context) {
+    // This behavior attaches by ID, so is only valid once on a page.
+    // Also skip if we are on an install page, as Drupal.cleanURLsInstallCheck will handle
+    // the processing.
+    if ($("#clean-url.clean-url-processed, #clean-url.install").size()) {
+      return;
     }
-  });
-  $("#clean-url").addClass('clean-url-processed');
+    var url = Drupal.settings.basePath +"admin/settings/clean-urls/check";
+    $("#clean-url .description span").html('<div id="testing">'+ Drupal.t('Testing clean URLs...') +"</div>");
+    $("#clean-url p").hide();
+    $.ajax({
+      url: location.protocol +"//"+ location.host + url,
+      dataType: 'json',
+      success: function () {
+        // Check was successful.
+        $("#clean-url input.form-radio").attr("disabled", false);
+        $("#clean-url .description span").append('<div class="ok">'+ Drupal.t('Your server has been successfully tested to support this feature.') +"</div>");
+        $("#testing").hide();
+      },
+      error: function() {
+        // Check failed.
+        $("#clean-url .description span").append('<div class="warning">'+ Drupal.t('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.') +"</div>");
+        $("#testing").hide();
+      }
+    });
+    $("#clean-url").addClass('clean-url-processed');
+  }
 };
 
 /**
@@ -70,22 +72,24 @@ Drupal.cleanURLsInstallCheck = function() {
  * use the same value. In the installer this is used to populate the
  * administrator e-mail address with the same value as the site e-mail address.
  */
-Drupal.behaviors.copyFieldValue = function (context) {
-  for (var sourceId in Drupal.settings.copyFieldValue) {
-    // Get the list of target fields.
-    targetIds = Drupal.settings.copyFieldValue[sourceId];
-    if (!$('#'+ sourceId + '.copy-field-values-processed').size(), context) {
-      // Add the behavior to update target fields on blur of the primary field.
-      sourceField = $('#' + sourceId);
-      sourceField.bind('blur', function() {
-        for (var delta in targetIds) {
-          var targetField = $('#'+ targetIds[delta]);
-          if (targetField.val() == '') {
-            targetField.val(this.value);
+Drupal.behaviors.copyFieldValue = {
+  attach: function(context) {
+    for (var sourceId in Drupal.settings.copyFieldValue) {
+      // Get the list of target fields.
+      targetIds = Drupal.settings.copyFieldValue[sourceId];
+      if (!$('#'+ sourceId + '.copy-field-values-processed').size(), context) {
+        // Add the behavior to update target fields on blur of the primary field.
+        sourceField = $('#' + sourceId);
+        sourceField.bind('blur', function() {
+          for (var delta in targetIds) {
+            var targetField = $('#'+ targetIds[delta]);
+            if (targetField.val() == '') {
+              targetField.val(this.value);
+            }
           }
-        }
-      });
-      sourceField.addClass('copy-field-values-processed');
+        });
+        sourceField.addClass('copy-field-values-processed');
+      }
     }
   }
 };
@@ -93,21 +97,23 @@ Drupal.behaviors.copyFieldValue = function (context) {
 /**
  * Show/hide custom format sections on the date-time settings page.
  */
-Drupal.behaviors.dateTime = function(context) {
-  // Show/hide custom format depending on the select's value.
-  $('select.date-format:not(.date-time-processed)', context).change(function() {
-    $(this).addClass('date-time-processed').parents("div.date-container").children("div.custom-container")[$(this).val() == "custom" ? "show" : "hide"]();
-  });
+Drupal.behaviors.dateTime = {
+  attach: function(context) {
+    // Show/hide custom format depending on the select's value.
+    $('select.date-format:not(.date-time-processed)', context).change(function() {
+      $(this).addClass('date-time-processed').parents("div.date-container").children("div.custom-container")[$(this).val() == "custom" ? "show" : "hide"]();
+    });
 
-  // Attach keyup handler to custom format inputs.
-  $('input.custom-format:not(.date-time-processed)', context).addClass('date-time-processed').keyup(function() {
-    var input = $(this);
-    var url = Drupal.settings.dateTime.lookup +(Drupal.settings.dateTime.lookup.match(/\?q=/) ? "&format=" : "?format=") + Drupal.encodeURIComponent(input.val());
-    $.getJSON(url, function(data) {
-      $("div.description span", input.parent()).html(data);
+    // Attach keyup handler to custom format inputs.
+    $('input.custom-format:not(.date-time-processed)', context).addClass('date-time-processed').keyup(function() {
+      var input = $(this);
+      var url = Drupal.settings.dateTime.lookup +(Drupal.settings.dateTime.lookup.match(/\?q=/) ? "&format=" : "?format=") + Drupal.encodeURIComponent(input.val());
+      $.getJSON(url, function(data) {
+        $("div.description span", input.parent()).html(data);
+      });
     });
-  });
 
-  // Trigger the event handler to show the form input if necessary.
-  $('select.date-format', context).trigger('change');
+    // Trigger the event handler to show the form input if necessary.
+    $('select.date-format', context).trigger('change');
+  }
 };
diff --git a/modules/taxonomy/taxonomy.js b/modules/taxonomy/taxonomy.js
index 0631ebd99088ce54639ac88642ff7d7f4effdc5a..bbf1f5c47113fef22a66ed8bb4f8af7cde34d6ad 100644
--- a/modules/taxonomy/taxonomy.js
+++ b/modules/taxonomy/taxonomy.js
@@ -6,31 +6,33 @@
  * This behavior is dependent on the tableDrag behavior, since it uses the
  * objects initialized in that behavior to update the row.
  */
-Drupal.behaviors.termDrag = function(context) {
-  var table = $('#taxonomy', context);
-  var tableDrag = Drupal.tableDrag.taxonomy; // Get the blocks tableDrag object.
-  var rows = $('tr', table).size();
+Drupal.behaviors.termDrag = {
+  attach: function(context) {
+    var table = $('#taxonomy', context);
+    var tableDrag = Drupal.tableDrag.taxonomy; // Get the blocks tableDrag object.
+    var rows = $('tr', table).size();
 
-  // When a row is swapped, keep previous and next page classes set.
-  tableDrag.row.prototype.onSwap = function(swappedRow) {
-    $('tr.taxonomy-term-preview', table).removeClass('taxonomy-term-preview');
-    $('tr.taxonomy-term-divider-top', table).removeClass('taxonomy-term-divider-top');
-    $('tr.taxonomy-term-divider-bottom', table).removeClass('taxonomy-term-divider-bottom');
+    // When a row is swapped, keep previous and next page classes set.
+    tableDrag.row.prototype.onSwap = function(swappedRow) {
+      $('tr.taxonomy-term-preview', table).removeClass('taxonomy-term-preview');
+      $('tr.taxonomy-term-divider-top', table).removeClass('taxonomy-term-divider-top');
+      $('tr.taxonomy-term-divider-bottom', table).removeClass('taxonomy-term-divider-bottom');
 
-    if (Drupal.settings.taxonomy.backPeddle) {
-      for (var n = 0; n < Drupal.settings.taxonomy.backPeddle; n++) {
-        $(table[0].tBodies[0].rows[n]).addClass('taxonomy-term-preview');
+      if (Drupal.settings.taxonomy.backPeddle) {
+        for (var n = 0; n < Drupal.settings.taxonomy.backPeddle; n++) {
+          $(table[0].tBodies[0].rows[n]).addClass('taxonomy-term-preview');
+        }
+        $(table[0].tBodies[0].rows[Drupal.settings.taxonomy.backPeddle - 1]).addClass('taxonomy-term-divider-top');
+        $(table[0].tBodies[0].rows[Drupal.settings.taxonomy.backPeddle]).addClass('taxonomy-term-divider-bottom');
       }
-      $(table[0].tBodies[0].rows[Drupal.settings.taxonomy.backPeddle - 1]).addClass('taxonomy-term-divider-top');
-      $(table[0].tBodies[0].rows[Drupal.settings.taxonomy.backPeddle]).addClass('taxonomy-term-divider-bottom');
-    }
 
-    if (Drupal.settings.taxonomy.forwardPeddle) {
-      for (var n = rows - Drupal.settings.taxonomy.forwardPeddle - 1; n < rows - 1; n++) {
-        $(table[0].tBodies[0].rows[n]).addClass('taxonomy-term-preview');
+      if (Drupal.settings.taxonomy.forwardPeddle) {
+        for (var n = rows - Drupal.settings.taxonomy.forwardPeddle - 1; n < rows - 1; n++) {
+          $(table[0].tBodies[0].rows[n]).addClass('taxonomy-term-preview');
+        }
+        $(table[0].tBodies[0].rows[rows - Drupal.settings.taxonomy.forwardPeddle - 2]).addClass('taxonomy-term-divider-top');
+        $(table[0].tBodies[0].rows[rows - Drupal.settings.taxonomy.forwardPeddle - 1]).addClass('taxonomy-term-divider-bottom');
       }
-      $(table[0].tBodies[0].rows[rows - Drupal.settings.taxonomy.forwardPeddle - 2]).addClass('taxonomy-term-divider-top');
-      $(table[0].tBodies[0].rows[rows - Drupal.settings.taxonomy.forwardPeddle - 1]).addClass('taxonomy-term-divider-bottom');
-    }
-  };
+    };
+  }
 };
diff --git a/modules/user/user.js b/modules/user/user.js
index 504db3246fd9dcd3afc4d1e523f44600c17d365d..173a4879b27da9a410c2222164c202e60280eaa1 100644
--- a/modules/user/user.js
+++ b/modules/user/user.js
@@ -4,85 +4,86 @@
  * Attach handlers to evaluate the strength of any password fields and to check
  * that its confirmation is correct.
  */
-Drupal.behaviors.password = function(context) {
-
-  var translate = Drupal.settings.password;
-  $("input.password-field:not(.password-processed)", context).each(function() {
-    var passwordInput = $(this).addClass('password-processed');
-    var innerWrapper = $(this).parent();
-    var outerWrapper = $(this).parent().parent();
-
-    // Add the password strength layers.
-    var passwordStrength = $("span.password-strength", innerWrapper);
-    var passwordResult = $("span.password-result", passwordStrength);
-    innerWrapper.addClass("password-parent");
-
-    // Add the description box at the end.
-    var passwordMeter = '<div id="password-strength"><div class="password-strength-title">' + translate.strengthTitle + '</div><div id="password-indicator"><div id="indicator"></div></div></div>';
-    $("div.description", outerWrapper).prepend('<div class="password-suggestions"></div>');
-    $(innerWrapper).append(passwordMeter);
-    var passwordDescription = $("div.password-suggestions", outerWrapper).hide();
-
-    // Add the password confirmation layer.
-    $("input.password-confirm", outerWrapper).after('<div class="password-confirm">' + translate["confirmTitle"] + ' <span></span></div>').parent().addClass("confirm-parent");
-    var confirmInput = $("input.password-confirm", outerWrapper);
-    var confirmResult = $("div.password-confirm", outerWrapper);
-    var confirmChild = $("span", confirmResult);
-
-    // Check the password strength.
-    var passwordCheck = function () {
-
-      // Evaluate the password strength.
-      var result = Drupal.evaluatePasswordStrength(passwordInput.val());
-
-      // Update the suggestions for how to improve the password.
-      if (passwordDescription.html() != result.message) {
-        passwordDescription.html(result.message);
-      }
+Drupal.behaviors.password = {
+  attach: function(context) {
+    var translate = Drupal.settings.password;
+    $("input.password-field:not(.password-processed)", context).each(function() {
+      var passwordInput = $(this).addClass('password-processed');
+      var innerWrapper = $(this).parent();
+      var outerWrapper = $(this).parent().parent();
+
+      // Add the password strength layers.
+      var passwordStrength = $("span.password-strength", innerWrapper);
+      var passwordResult = $("span.password-result", passwordStrength);
+      innerWrapper.addClass("password-parent");
+
+      // Add the description box at the end.
+      var passwordMeter = '<div id="password-strength"><div class="password-strength-title">' + translate.strengthTitle + '</div><div id="password-indicator"><div id="indicator"></div></div></div>';
+      $("div.description", outerWrapper).prepend('<div class="password-suggestions"></div>');
+      $(innerWrapper).append(passwordMeter);
+      var passwordDescription = $("div.password-suggestions", outerWrapper).hide();
+
+      // Add the password confirmation layer.
+      $("input.password-confirm", outerWrapper).after('<div class="password-confirm">' + translate["confirmTitle"] + ' <span></span></div>').parent().addClass("confirm-parent");
+      var confirmInput = $("input.password-confirm", outerWrapper);
+      var confirmResult = $("div.password-confirm", outerWrapper);
+      var confirmChild = $("span", confirmResult);
+
+      // Check the password strength.
+      var passwordCheck = function () {
+
+        // Evaluate the password strength.
+        var result = Drupal.evaluatePasswordStrength(passwordInput.val());
+
+        // Update the suggestions for how to improve the password.
+        if (passwordDescription.html() != result.message) {
+          passwordDescription.html(result.message);
+        }
 
-      // Only show the description box if there is a weakness in the password.
-      if (result.strength == 100) {
-        passwordDescription.hide();
-      }
-      else {
-        passwordDescription.show();
-      }
+        // Only show the description box if there is a weakness in the password.
+        if (result.strength == 100) {
+          passwordDescription.hide();
+        }
+        else {
+          passwordDescription.show();
+        }
 
-      // Adjust the length of the strength indicator.
-      $("#indicator").css('width', result.strength + '%');
+        // Adjust the length of the strength indicator.
+        $("#indicator").css('width', result.strength + '%');
 
-      passwordCheckMatch();
-    };
+        passwordCheckMatch();
+      };
 
-    // Check that password and confirmation inputs match.
-    var passwordCheckMatch = function () {
+      // Check that password and confirmation inputs match.
+      var passwordCheckMatch = function () {
 
-      if (confirmInput.val()) {
-        var success = passwordInput.val() === confirmInput.val();
+        if (confirmInput.val()) {
+          var success = passwordInput.val() === confirmInput.val();
 
-        // Show the confirm result.
-        confirmResult.css({ visibility: "visible" });
+          // Show the confirm result.
+          confirmResult.css({ visibility: "visible" });
 
-        // Remove the previous styling if any exists.
-        if (this.confirmClass) {
-          confirmChild.removeClass(this.confirmClass);
-        }
+          // Remove the previous styling if any exists.
+          if (this.confirmClass) {
+            confirmChild.removeClass(this.confirmClass);
+          }
 
-        // Fill in the success message and set the class accordingly.
-        var confirmClass = success ? "ok" : 'error';
-        confirmChild.html(translate["confirm" + (success ? "Success" : "Failure")]).addClass(confirmClass);
-        this.confirmClass = confirmClass;
-      }
-      else {
-        confirmResult.css({ visibility: "hidden" });
+          // Fill in the success message and set the class accordingly.
+          var confirmClass = success ? "ok" : 'error';
+          confirmChild.html(translate["confirm" + (success ? "Success" : "Failure")]).addClass(confirmClass);
+          this.confirmClass = confirmClass;
+        }
+        else {
+          confirmResult.css({ visibility: "hidden" });
+        }
       }
-    }
 
-    // Monitor keyup and blur events.
-    // Blur must be used because a mouse paste does not trigger keyup.
-    passwordInput.keyup(passwordCheck).focus(passwordCheck).blur(passwordCheck);
-    confirmInput.keyup(passwordCheckMatch).blur(passwordCheckMatch);
-  });
+      // Monitor keyup and blur events.
+      // Blur must be used because a mouse paste does not trigger keyup.
+      passwordInput.keyup(passwordCheck).focus(passwordCheck).blur(passwordCheck);
+      confirmInput.keyup(passwordCheckMatch).blur(passwordCheckMatch);
+    });
+  }
 };
 
 /**
@@ -171,9 +172,10 @@ Drupal.setDefaultTimezone = function() {
  * picture-related form elements depending on the current value of the
  * "Picture support" radio buttons.
  */
-Drupal.behaviors.userSettings = function (context) {
-  $('div.user-admin-picture-radios input[type=radio]:not(.userSettings-processed)', context).addClass('userSettings-processed').click(function () {
-    $('div.user-admin-picture-settings', context)[['hide', 'show'][this.value]]();
-  });
+Drupal.behaviors.userSettings = {
+  attach: function(context) {
+    $('div.user-admin-picture-radios input[type=radio]:not(.userSettings-processed)', context).addClass('userSettings-processed').click(function () {
+      $('div.user-admin-picture-settings', context)[['hide', 'show'][this.value]]();
+    });
+  }
 };
-