diff --git a/core/misc/active-link.js b/core/misc/active-link.js
index 6054faa..5bd12eb 100644
--- a/core/misc/active-link.js
+++ b/core/misc/active-link.js
@@ -5,59 +5,59 @@
 
 (function (Drupal, drupalSettings) {
 
-"use strict";
+  "use strict";
+
+  /**
+   * Append active class.
+   *
+   * The link is only active if its path corresponds to the current path, the
+   * language of the linked path is equal to the current language, and if the
+   * query parameters of the link equal those of the current request, since the
+   * same request with different query parameters may yield a different page
+   * (e.g. pagers, exposed View filters).
+   *
+   * Does not discriminate based on element type, so allows you to set the active
+   * class on any element: a, li…
+   */
+  Drupal.behaviors.activeLinks = {
+    attach: function (context) {
+      // Start by finding all potentially active links.
+      var path = drupalSettings.path;
+      var queryString = JSON.stringify(path.currentQuery);
+      var querySelector = path.currentQuery ? "[data-drupal-link-query='" + queryString + "']" : ':not([data-drupal-link-query])';
+      var originalSelectors = ['[data-drupal-link-system-path="' + path.currentPath + '"]'];
+      var selectors;
+
+      // If this is the front page, we have to check for the <front> path as well.
+      if (path.isFront) {
+        originalSelectors.push('[data-drupal-link-system-path="<front>"]');
+      }
 
-/**
- * Append active class.
- *
- * The link is only active if its path corresponds to the current path, the
- * language of the linked path is equal to the current language, and if the
- * query parameters of the link equal those of the current request, since the
- * same request with different query parameters may yield a different page
- * (e.g. pagers, exposed View filters).
- *
- * Does not discriminate based on element type, so allows you to set the active
- * class on any element: a, li…
- */
-Drupal.behaviors.activeLinks = {
-  attach: function (context) {
-    // Start by finding all potentially active links.
-    var path = drupalSettings.path;
-    var queryString = JSON.stringify(path.currentQuery);
-    var querySelector = path.currentQuery ? "[data-drupal-link-query='" + queryString + "']" : ':not([data-drupal-link-query])';
-    var originalSelectors = ['[data-drupal-link-system-path="' + path.currentPath + '"]'];
-    var selectors;
-
-    // If this is the front page, we have to check for the <front> path as well.
-    if (path.isFront) {
-      originalSelectors.push('[data-drupal-link-system-path="<front>"]');
-    }
+      // Add language filtering.
+      selectors = [].concat(
+        // Links without any hreflang attributes (most of them).
+        originalSelectors.map(function (selector) { return selector + ':not([hreflang])'; }),
+        // Links with hreflang equals to the current language.
+        originalSelectors.map(function (selector) { return selector + '[hreflang="' + path.currentLanguage + '"]'; })
+      );
 
-    // Add language filtering.
-    selectors = [].concat(
-      // Links without any hreflang attributes (most of them).
-      originalSelectors.map(function (selector) { return selector + ':not([hreflang])';}),
-      // Links with hreflang equals to the current language.
-      originalSelectors.map(function (selector) { return selector + '[hreflang="' + path.currentLanguage + '"]';})
-    );
-
-    // Add query string selector for pagers, exposed filters.
-    selectors = selectors.map(function (current) { return current + querySelector; });
-
-    // Query the DOM.
-    var activeLinks = context.querySelectorAll(selectors.join(','));
-    for (var i = 0, il = activeLinks.length; i < il; i += 1) {
-      activeLinks[i].classList.add('active');
-    }
-  },
-  detach: function (context, settings, trigger) {
-    if (trigger === 'unload') {
-      var activeLinks = context.querySelectorAll('[data-drupal-link-system-path].active');
+      // Add query string selector for pagers, exposed filters.
+      selectors = selectors.map(function (current) { return current + querySelector; });
+
+      // Query the DOM.
+      var activeLinks = context.querySelectorAll(selectors.join(','));
       for (var i = 0, il = activeLinks.length; i < il; i += 1) {
-        activeLinks[i].classList.remove('active');
+        activeLinks[i].classList.add('active');
+      }
+    },
+    detach: function (context, settings, trigger) {
+      if (trigger === 'unload') {
+        var activeLinks = context.querySelectorAll('[data-drupal-link-system-path].active');
+        for (var i = 0, il = activeLinks.length; i < il; i += 1) {
+          activeLinks[i].classList.remove('active');
+        }
       }
     }
-  }
-};
+  };
 
 })(Drupal, drupalSettings);
diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index 4abb652..6fd9979 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -1,140 +1,140 @@
 (function ($, window, Drupal, drupalSettings) {
 
-"use strict";
-
-/**
- * Provides Ajax page updating via jQuery $.ajax (Asynchronous JavaScript and XML).
- *
- * Ajax is a method of making a request via JavaScript while viewing an HTML
- * page. The request returns an array of commands encoded in JSON, which is
- * then executed to make any changes that are necessary to the page.
- *
- * Drupal uses this file to enhance form elements with #ajax['path'] and
- * #ajax['wrapper'] properties. If set, this file will automatically be included
- * to provide Ajax capabilities.
- */
-
-Drupal.ajax = Drupal.ajax || {};
-
-/**
- * Attaches the Ajax behavior to each Ajax form element.
- */
-Drupal.behaviors.AJAX = {
-  attach: function (context, settings) {
-
-    function loadAjaxBehavior(base) {
-      var element_settings = settings.ajax[base];
-      if (typeof element_settings.selector === 'undefined') {
-        element_settings.selector = '#' + base;
+  "use strict";
+
+  /**
+   * Provides Ajax page updating via jQuery $.ajax (Asynchronous JavaScript and XML).
+   *
+   * Ajax is a method of making a request via JavaScript while viewing an HTML
+   * page. The request returns an array of commands encoded in JSON, which is
+   * then executed to make any changes that are necessary to the page.
+   *
+   * Drupal uses this file to enhance form elements with #ajax['path'] and
+   * #ajax['wrapper'] properties. If set, this file will automatically be included
+   * to provide Ajax capabilities.
+   */
+
+  Drupal.ajax = Drupal.ajax || {};
+
+  /**
+   * Attaches the Ajax behavior to each Ajax form element.
+   */
+  Drupal.behaviors.AJAX = {
+    attach: function (context, settings) {
+
+      function loadAjaxBehavior(base) {
+        var element_settings = settings.ajax[base];
+        if (typeof element_settings.selector === 'undefined') {
+          element_settings.selector = '#' + base;
+        }
+        $(element_settings.selector).once('drupal-ajax', function () {
+          element_settings.element = this;
+          Drupal.ajax[element_settings.selector] = new Drupal.ajax(base, this, element_settings);
+        });
+      }
+
+      // Load all Ajax behaviors specified in the settings.
+      for (var base in settings.ajax) {
+        if (settings.ajax.hasOwnProperty(base)) {
+          loadAjaxBehavior(base);
+        }
       }
-      $(element_settings.selector).once('drupal-ajax', function() {
-        element_settings.element = this;
-        Drupal.ajax[element_settings.selector] = new Drupal.ajax(base, this, element_settings);
+
+      // Bind Ajax behaviors to all items showing the class.
+      $('.use-ajax').once('ajax', function () {
+        var element_settings = {};
+        // Clicked links look better with the throbber than the progress bar.
+        element_settings.progress = { 'type': 'throbber' };
+
+        // For anchor tags, these will go to the target of the anchor rather
+        // than the usual location.
+        if ($(this).attr('href')) {
+          element_settings.url = $(this).attr('href');
+          element_settings.event = 'click';
+        }
+        element_settings.accepts = $(this).data('accepts');
+        element_settings.dialog = $(this).data('dialog-options');
+        var base = $(this).attr('id');
+        Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
+      });
+
+      // This class means to submit the form to the action using Ajax.
+      $('.use-ajax-submit').once('ajax', function () {
+        var element_settings = {};
+
+        // Ajax submits specified in this manner automatically submit to the
+        // normal form action.
+        element_settings.url = $(this.form).attr('action');
+        // Form submit button clicks need to tell the form what was clicked so
+        // it gets passed in the POST request.
+        element_settings.setClick = true;
+        // Form buttons use the 'click' event rather than mousedown.
+        element_settings.event = 'click';
+        // Clicked form buttons look better with the throbber than the progress bar.
+        element_settings.progress = { 'type': 'throbber' };
+
+        var base = $(this).attr('id');
+        Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
       });
     }
+  };
 
-    // Load all Ajax behaviors specified in the settings.
-    for (var base in settings.ajax) {
-      if (settings.ajax.hasOwnProperty(base)) {
-        loadAjaxBehavior(base);
-      }
+  /**
+   * Extends Error to provide handling for Errors in AJAX
+   */
+  Drupal.AjaxError = function (xmlhttp, uri) {
+
+    var statusCode, statusText, pathText, responseText, readyStateText;
+    if (xmlhttp.status) {
+      statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") + "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status});
+    }
+    else {
+      statusCode = "\n" + Drupal.t("An AJAX HTTP request terminated abnormally.");
     }
+    statusCode += "\n" + Drupal.t("Debugging information follows.");
+    pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri});
+    statusText = '';
+    // In some cases, when statusCode === 0, xmlhttp.statusText may not be defined.
+    // Unfortunately, testing for it with typeof, etc, doesn't seem to catch that
+    // and the test causes an exception. So we need to catch the exception here.
+    try {
+      statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)});
+    }
+    catch (e) {}
 
-    // Bind Ajax behaviors to all items showing the class.
-    $('.use-ajax').once('ajax', function () {
-      var element_settings = {};
-      // Clicked links look better with the throbber than the progress bar.
-      element_settings.progress = { 'type': 'throbber' };
+    responseText = '';
+    // Again, we don't have a way to know for sure whether accessing
+    // xmlhttp.responseText is going to throw an exception. So we'll catch it.
+    try {
+      responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) });
+    } catch (e) {}
 
-      // For anchor tags, these will go to the target of the anchor rather
-      // than the usual location.
-      if ($(this).attr('href')) {
-        element_settings.url = $(this).attr('href');
-        element_settings.event = 'click';
-      }
-      element_settings.accepts = $(this).data('accepts');
-      element_settings.dialog = $(this).data('dialog-options');
-      var base = $(this).attr('id');
-      Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
-    });
+    // Make the responseText more readable by stripping HTML tags and newlines.
+    responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi, "");
+    responseText = responseText.replace(/[\n]+\s+/g, "\n");
 
-    // This class means to submit the form to the action using Ajax.
-    $('.use-ajax-submit').once('ajax', function () {
-      var element_settings = {};
-
-      // Ajax submits specified in this manner automatically submit to the
-      // normal form action.
-      element_settings.url = $(this.form).attr('action');
-      // Form submit button clicks need to tell the form what was clicked so
-      // it gets passed in the POST request.
-      element_settings.setClick = true;
-      // Form buttons use the 'click' event rather than mousedown.
-      element_settings.event = 'click';
-      // Clicked form buttons look better with the throbber than the progress bar.
-      element_settings.progress = { 'type': 'throbber' };
-
-      var base = $(this).attr('id');
-      Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
-    });
-  }
-};
-
-/**
- * Extends Error to provide handling for Errors in AJAX
- */
-Drupal.AjaxError = function(xmlhttp, uri) {
-
-  var statusCode, statusText, pathText, responseText, readyStateText;
-  if (xmlhttp.status) {
-    statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") +  "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status});
-  }
-  else {
-    statusCode = "\n" + Drupal.t("An AJAX HTTP request terminated abnormally.");
-  }
-  statusCode += "\n" + Drupal.t("Debugging information follows.");
-  pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri} );
-  statusText = '';
-  // In some cases, when statusCode === 0, xmlhttp.statusText may not be defined.
-  // Unfortunately, testing for it with typeof, etc, doesn't seem to catch that
-  // and the test causes an exception. So we need to catch the exception here.
-  try {
-    statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)});
-  }
-  catch (e) {}
-
-  responseText = '';
-  // Again, we don't have a way to know for sure whether accessing
-  // xmlhttp.responseText is going to throw an exception. So we'll catch it.
-  try {
-    responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) } );
-  } catch (e) {}
-
-  // Make the responseText more readable by stripping HTML tags and newlines.
-  responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi,"");
-  responseText = responseText.replace(/[\n]+\s+/g,"\n");
-
-  // We don't need readyState except for status == 0.
-  readyStateText = xmlhttp.status === 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
-
-  this.message = statusCode + pathText + statusText + responseText + readyStateText;
-  this.name = 'AjaxError';
-};
-
-Drupal.AjaxError.prototype = new Error();
-Drupal.AjaxError.prototype.constructor = Drupal.AjaxError;
-
-/**
- * Ajax object.
- *
- * All Ajax objects on a page are accessible through the global Drupal.ajax
- * object and are keyed by the submit button's ID. You can access them from
- * your module's JavaScript file to override properties or functions.
- *
- * For example, if your Ajax enabled button has the ID 'edit-submit', you can
- * redefine the function that is called to insert the new content like this
- * (inside a Drupal.behaviors attach block):
- * @code
- *    Drupal.behaviors.myCustomAJAXStuff = {
+    // We don't need readyState except for status == 0.
+    readyStateText = xmlhttp.status === 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
+
+    this.message = statusCode + pathText + statusText + responseText + readyStateText;
+    this.name = 'AjaxError';
+  };
+
+  Drupal.AjaxError.prototype = new Error();
+  Drupal.AjaxError.prototype.constructor = Drupal.AjaxError;
+
+  /**
+   * Ajax object.
+   *
+   * All Ajax objects on a page are accessible through the global Drupal.ajax
+   * object and are keyed by the submit button's ID. You can access them from
+   * your module's JavaScript file to override properties or functions.
+   *
+   * For example, if your Ajax enabled button has the ID 'edit-submit', you can
+   * redefine the function that is called to insert the new content like this
+   * (inside a Drupal.behaviors attach block):
+   * @code
+   *    Drupal.behaviors.myCustomAJAXStuff = {
  *      attach: function (context, settings) {
  *        Drupal.ajax['edit-submit'].commands.insert = function (ajax, response, status) {
  *          new_content = $(response.data);
@@ -143,596 +143,596 @@ Drupal.AjaxError.prototype.constructor = Drupal.AjaxError;
  *        }
  *      }
  *    };
- * @endcode
- */
-Drupal.ajax = function (base, element, element_settings) {
-  var defaults = {
-    event: 'mousedown',
-    keypress: true,
-    selector: '#' + base,
-    effect: 'none',
-    speed: 'none',
-    method: 'replaceWith',
-    progress: {
-      type: 'throbber',
-      message: Drupal.t('Please wait...')
-    },
-    submit: {
-      'js': true
+   * @endcode
+   */
+  Drupal.ajax = function (base, element, element_settings) {
+    var defaults = {
+      event: 'mousedown',
+      keypress: true,
+      selector: '#' + base,
+      effect: 'none',
+      speed: 'none',
+      method: 'replaceWith',
+      progress: {
+        type: 'throbber',
+        message: Drupal.t('Please wait...')
+      },
+      submit: {
+        'js': true
+      }
+    };
+
+    $.extend(this, defaults, element_settings);
+
+    this.commands = new Drupal.AjaxCommands();
+
+    // @todo Remove this after refactoring the PHP code to:
+    //   - Call this 'selector'.
+    //   - Include the '#' for ID-based selectors.
+    //   - Support non-ID-based selectors.
+    if (this.wrapper) {
+      this.wrapper = '#' + this.wrapper;
     }
-  };
 
-  $.extend(this, defaults, element_settings);
-
-  this.commands = new Drupal.AjaxCommands();
-
-  // @todo Remove this after refactoring the PHP code to:
-  //   - Call this 'selector'.
-  //   - Include the '#' for ID-based selectors.
-  //   - Support non-ID-based selectors.
-  if (this.wrapper) {
-    this.wrapper = '#' + this.wrapper;
-  }
-
-  this.element = element;
-  this.element_settings = element_settings;
-
-  // If there isn't a form, jQuery.ajax() will be used instead, allowing us to
-  // bind Ajax to links as well.
-  if (this.element.form) {
-    this.$form = $(this.element.form);
-  }
-
-  // If no Ajax callback URL was given, use the link href or form action.
-  if (!this.url) {
-    if ($(element).is('a')) {
-      this.url = $(element).attr('href');
-    }
-    else if (element.form) {
-      this.url = this.$form.attr('action');
-
-      // @todo If there's a file input on this form, then jQuery will submit the
-      //   AJAX response with a hidden Iframe rather than the XHR object. If the
-      //   response to the submission is an HTTP redirect, then the Iframe will
-      //   follow it, but the server won't content negotiate it correctly,
-      //   because there won't be an ajax_iframe_upload POST variable. Until we
-      //   figure out a work around to this problem, we prevent AJAX-enabling
-      //   elements that submit to the same URL as the form when there's a file
-      //   input. For example, this means the Delete button on the edit form of
-      //   an Article node doesn't open its confirmation form in a dialog.
-      if (this.$form.find(':file').length) {
-        return;
-      }
+    this.element = element;
+    this.element_settings = element_settings;
+
+    // If there isn't a form, jQuery.ajax() will be used instead, allowing us to
+    // bind Ajax to links as well.
+    if (this.element.form) {
+      this.$form = $(this.element.form);
     }
-  }
-
-  // Replacing 'nojs' with 'ajax' in the URL allows for an easy method to let
-  // the server detect when it needs to degrade gracefully.
-  // There are four scenarios to check for:
-  // 1. /nojs/
-  // 2. /nojs$ - The end of a URL string.
-  // 3. /nojs? - Followed by a query (e.g. path/nojs?destination=foobar).
-  // 4. /nojs# - Followed by a fragment (e.g.: path/nojs#myfragment).
-  this.url = this.url.replace(/\/nojs(\/|$|\?|#)/g, '/ajax$1');
-
-  // Set the options for the ajaxSubmit function.
-  // The 'this' variable will not persist inside of the options object.
-  var ajax = this;
-  ajax.options = {
-    url: ajax.url,
-    data: ajax.submit,
-    beforeSerialize: function (element_settings, options) {
-      return ajax.beforeSerialize(element_settings, options);
-    },
-    beforeSubmit: function (form_values, element_settings, options) {
-      ajax.ajaxing = true;
-      return ajax.beforeSubmit(form_values, element_settings, options);
-    },
-    beforeSend: function (xmlhttprequest, options) {
-      ajax.ajaxing = true;
-      return ajax.beforeSend(xmlhttprequest, options);
-    },
-    success: function (response, status) {
-      // Sanity check for browser support (object expected).
-      // When using iFrame uploads, responses must be returned as a string.
-      if (typeof response === 'string') {
-        response = $.parseJSON(response);
+
+    // If no Ajax callback URL was given, use the link href or form action.
+    if (!this.url) {
+      if ($(element).is('a')) {
+        this.url = $(element).attr('href');
       }
-      return ajax.success(response, status);
-    },
-    complete: function (response, status) {
-      ajax.ajaxing = false;
-      if (status === 'error' || status === 'parsererror') {
-        return ajax.error(response, ajax.url);
+      else if (element.form) {
+        this.url = this.$form.attr('action');
+
+        // @todo If there's a file input on this form, then jQuery will submit the
+        //   AJAX response with a hidden Iframe rather than the XHR object. If the
+        //   response to the submission is an HTTP redirect, then the Iframe will
+        //   follow it, but the server won't content negotiate it correctly,
+        //   because there won't be an ajax_iframe_upload POST variable. Until we
+        //   figure out a work around to this problem, we prevent AJAX-enabling
+        //   elements that submit to the same URL as the form when there's a file
+        //   input. For example, this means the Delete button on the edit form of
+        //   an Article node doesn't open its confirmation form in a dialog.
+        if (this.$form.find(':file').length) {
+          return;
+        }
       }
-    },
-    dataType: 'json',
-    accepts: {
-      json: element_settings.accepts || 'application/vnd.drupal-ajax'
-    },
-    type: 'POST'
-  };
+    }
+
+    // Replacing 'nojs' with 'ajax' in the URL allows for an easy method to let
+    // the server detect when it needs to degrade gracefully.
+    // There are four scenarios to check for:
+    // 1. /nojs/
+    // 2. /nojs$ - The end of a URL string.
+    // 3. /nojs? - Followed by a query (e.g. path/nojs?destination=foobar).
+    // 4. /nojs# - Followed by a fragment (e.g.: path/nojs#myfragment).
+    this.url = this.url.replace(/\/nojs(\/|$|\?|#)/g, '/ajax$1');
+
+    // Set the options for the ajaxSubmit function.
+    // The 'this' variable will not persist inside of the options object.
+    var ajax = this;
+    ajax.options = {
+      url: ajax.url,
+      data: ajax.submit,
+      beforeSerialize: function (element_settings, options) {
+        return ajax.beforeSerialize(element_settings, options);
+      },
+      beforeSubmit: function (form_values, element_settings, options) {
+        ajax.ajaxing = true;
+        return ajax.beforeSubmit(form_values, element_settings, options);
+      },
+      beforeSend: function (xmlhttprequest, options) {
+        ajax.ajaxing = true;
+        return ajax.beforeSend(xmlhttprequest, options);
+      },
+      success: function (response, status) {
+        // Sanity check for browser support (object expected).
+        // When using iFrame uploads, responses must be returned as a string.
+        if (typeof response === 'string') {
+          response = $.parseJSON(response);
+        }
+        return ajax.success(response, status);
+      },
+      complete: function (response, status) {
+        ajax.ajaxing = false;
+        if (status === 'error' || status === 'parsererror') {
+          return ajax.error(response, ajax.url);
+        }
+      },
+      dataType: 'json',
+      accepts: {
+        json: element_settings.accepts || 'application/vnd.drupal-ajax'
+      },
+      type: 'POST'
+    };
+
+    if (element_settings.dialog) {
+      ajax.options.data.dialogOptions = element_settings.dialog;
+    }
 
-  if (element_settings.dialog) {
-    ajax.options.data.dialogOptions = element_settings.dialog;
-  }
-
-  // Bind the ajaxSubmit function to the element event.
-  $(ajax.element).on(element_settings.event, function (event) {
-    return ajax.eventResponse(this, event);
-  });
-
-  // If necessary, enable keyboard submission so that Ajax behaviors
-  // can be triggered through keyboard input as well as e.g. a mousedown
-  // action.
-  if (element_settings.keypress) {
-    $(ajax.element).on('keypress', function (event) {
-      return ajax.keypressResponse(this, event);
+    // Bind the ajaxSubmit function to the element event.
+    $(ajax.element).on(element_settings.event, function (event) {
+      return ajax.eventResponse(this, event);
     });
-  }
-
-  // If necessary, prevent the browser default action of an additional event.
-  // For example, prevent the browser default action of a click, even if the
-  // AJAX behavior binds to mousedown.
-  if (element_settings.prevent) {
-    $(ajax.element).on(element_settings.prevent, false);
-  }
-};
-
-/**
- * Handle a key press.
- *
- * The Ajax object will, if instructed, bind to a key press response. This
- * will test to see if the key press is valid to trigger this event and
- * if it is, trigger it for us and prevent other keypresses from triggering.
- * In this case we're handling RETURN and SPACEBAR keypresses (event codes 13
- * and 32. RETURN is often used to submit a form when in a textfield, and
- * SPACE is often used to activate an element without submitting.
- */
-Drupal.ajax.prototype.keypressResponse = function (element, event) {
-  // Create a synonym for this to reduce code confusion.
-  var ajax = this;
-
-  // Detect enter key and space bar and allow the standard response for them,
-  // except for form elements of type 'text', 'tel', 'number' and 'textarea',
-  // where the spacebar activation causes inappropriate activation if
-  // #ajax['keypress'] is TRUE. On a text-type widget a space should always be a
-  // space.
-  if (event.which === 13 || (event.which === 32 && element.type !== 'text' &&
-      element.type !== 'textarea' && element.type !== 'tel' && element.type !== 'number')) {
-    event.preventDefault();
-    event.stopPropagation();
-    $(ajax.element_settings.element).trigger(ajax.element_settings.event);
-  }
-};
-
-/**
- * Handle an event that triggers an Ajax response.
- *
- * When an event that triggers an Ajax response happens, this method will
- * perform the actual Ajax call. It is bound to the event using
- * bind() in the constructor, and it uses the options specified on the
- * ajax object.
- */
-Drupal.ajax.prototype.eventResponse = function (element, event) {
-  event.preventDefault();
-  event.stopPropagation();
-
-  // Create a synonym for this to reduce code confusion.
-  var ajax = this;
-
-  // Do not perform another ajax command if one is already in progress.
-  if (ajax.ajaxing) {
-    return;
-  }
-
-  try {
-    if (ajax.$form) {
-      // If setClick is set, we must set this to ensure that the button's
-      // value is passed.
-      if (ajax.setClick) {
-        // Mark the clicked button. 'form.clk' is a special variable for
-        // ajaxSubmit that tells the system which element got clicked to
-        // trigger the submit. Without it there would be no 'op' or
-        // equivalent.
-        element.form.clk = element;
-      }
 
-      ajax.$form.ajaxSubmit(ajax.options);
+    // If necessary, enable keyboard submission so that Ajax behaviors
+    // can be triggered through keyboard input as well as e.g. a mousedown
+    // action.
+    if (element_settings.keypress) {
+      $(ajax.element).on('keypress', function (event) {
+        return ajax.keypressResponse(this, event);
+      });
     }
-    else {
-      ajax.beforeSerialize(ajax.element, ajax.options);
-      $.ajax(ajax.options);
-    }
-  }
-  catch (e) {
-    // Unset the ajax.ajaxing flag here because it won't be unset during
-    // the complete response.
-    ajax.ajaxing = false;
-    window.alert("An error occurred while attempting to process " + ajax.options.url + ": " + e.message);
-  }
-};
-
-/**
- * Handler for the form serialization.
- *
- * Runs before the beforeSend() handler (see below), and unlike that one, runs
- * before field data is collected.
- */
-Drupal.ajax.prototype.beforeSerialize = function (element, options) {
-  // Allow detaching behaviors to update field values before collecting them.
-  // This is only needed when field values are added to the POST data, so only
-  // when there is a form such that this.$form.ajaxSubmit() is used instead of
-  // $.ajax(). When there is no form and $.ajax() is used, beforeSerialize()
-  // isn't called, but don't rely on that: explicitly check this.$form.
-  if (this.$form) {
-    var settings = this.settings || drupalSettings;
-    Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize');
-  }
-
-  // Prevent duplicate HTML ids in the returned markup.
-  // @see drupal_html_id()
-  var ids = document.querySelectorAll('[id]');
-  var ajaxHtmlIds = [];
-  for (var i = 0, il = ids.length; i < il; i++) {
-    ajaxHtmlIds.push(ids[i].id);
-  }
-  // Join IDs to minimize request size.
-  options.data.ajax_html_ids = ajaxHtmlIds.join(' ');
-
-  // Allow Drupal to return new JavaScript and CSS files to load without
-  // returning the ones already loaded.
-  // @see \Drupal\Core\Theme\AjaxBasePageNegotiator
-  // @see drupal_get_css()
-  // @see drupal_get_js()
-  var pageState = drupalSettings.ajaxPageState;
-  options.data['ajax_page_state[theme]'] = pageState.theme;
-  options.data['ajax_page_state[theme_token]'] = pageState.theme_token;
-  for (var cssFile in pageState.css) {
-    if (pageState.css.hasOwnProperty(cssFile)) {
-      options.data['ajax_page_state[css][' + cssFile + ']'] = 1;
-    }
-  }
-  for (var jsFile in pageState.js) {
-    if (pageState.js.hasOwnProperty(jsFile)) {
-      options.data['ajax_page_state[js][' + jsFile + ']'] = 1;
-    }
-  }
-};
-
-/**
- * Modify form values prior to form submission.
- */
-Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) {
-  // This function is left empty to make it simple to override for modules
-  // that wish to add functionality here.
-};
-
-/**
- * Prepare the Ajax request before it is sent.
- */
-Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) {
-  // For forms without file inputs, the jQuery Form plugin serializes the form
-  // values, and then calls jQuery's $.ajax() function, which invokes this
-  // handler. In this circumstance, options.extraData is never used. For forms
-  // with file inputs, the jQuery Form plugin uses the browser's normal form
-  // submission mechanism, but captures the response in a hidden IFRAME. In this
-  // circumstance, it calls this handler first, and then appends hidden fields
-  // to the form to submit the values in options.extraData. There is no simple
-  // way to know which submission mechanism will be used, so we add to extraData
-  // regardless, and allow it to be ignored in the former case.
-  if (this.$form) {
-    options.extraData = options.extraData || {};
-
-    // Let the server know when the IFRAME submission mechanism is used. The
-    // server can use this information to wrap the JSON response in a TEXTAREA,
-    // as per http://jquery.malsup.com/form/#file-upload.
-    options.extraData.ajax_iframe_upload = '1';
-
-    // The triggering element is about to be disabled (see below), but if it
-    // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that
-    // value is included in the submission. As per above, submissions that use
-    // $.ajax() are already serialized prior to the element being disabled, so
-    // this is only needed for IFRAME submissions.
-    var v = $.fieldValue(this.element);
-    if (v !== null) {
-      options.extraData[this.element.name] = v;
-    }
-  }
-
-  // Disable the element that received the change to prevent user interface
-  // interaction while the Ajax request is in progress. ajax.ajaxing prevents
-  // the element from triggering a new request, but does not prevent the user
-  // from changing its value.
-  $(this.element).addClass('progress-disabled').prop('disabled', true);
-
-  // Insert progressbar or throbber.
-  if (this.progress.type === 'bar') {
-    var progressBar = new Drupal.ProgressBar('ajax-progress-' + this.element.id, $.noop, this.progress.method, $.noop);
-    if (this.progress.message) {
-      progressBar.setProgress(-1, this.progress.message);
-    }
-    if (this.progress.url) {
-      progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
-    }
-    this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar');
-    this.progress.object = progressBar;
-    $(this.element).after(this.progress.element);
-  }
-  else if (this.progress.type === 'throbber') {
-    this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
-    if (this.progress.message) {
-      this.progress.element.find('.throbber').after('<div class="message">' + this.progress.message + '</div>');
-    }
-    $(this.element).after(this.progress.element);
-  }
-};
-
-/**
- * Handler for the form redirection completion.
- */
-Drupal.ajax.prototype.success = function (response, status) {
-  // Remove the progress element.
-  if (this.progress.element) {
-    $(this.progress.element).remove();
-  }
-  if (this.progress.object) {
-    this.progress.object.stopMonitoring();
-  }
-  $(this.element).removeClass('progress-disabled').prop('disabled', false);
-
-  for (var i in response) {
-    if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) {
-      this.commands[response[i].command](this, response[i], status);
-    }
-  }
-
-  // Reattach behaviors, if they were detached in beforeSerialize(). The
-  // attachBehaviors() called on the new content from processing the response
-  // commands is not sufficient, because behaviors from the entire form need
-  // to be reattached.
-  if (this.$form) {
-    var settings = this.settings || drupalSettings;
-    Drupal.attachBehaviors(this.$form.get(0), settings);
-  }
-
-  // Remove any response-specific settings so they don't get used on the next
-  // call by mistake.
-  this.settings = null;
-};
-
-/**
- * Build an effect object which tells us how to apply the effect when adding new HTML.
- */
-Drupal.ajax.prototype.getEffect = function (response) {
-  var type = response.effect || this.effect;
-  var speed = response.speed || this.speed;
-
-  var effect = {};
-  if (type === 'none') {
-    effect.showEffect = 'show';
-    effect.hideEffect = 'hide';
-    effect.showSpeed = '';
-  }
-  else if (type === 'fade') {
-    effect.showEffect = 'fadeIn';
-    effect.hideEffect = 'fadeOut';
-    effect.showSpeed = speed;
-  }
-  else {
-    effect.showEffect = type + 'Toggle';
-    effect.hideEffect = type + 'Toggle';
-    effect.showSpeed = speed;
-  }
-
-  return effect;
-};
-
-/**
- * Handler for the form redirection error.
- */
-Drupal.ajax.prototype.error = function (response, uri) {
-  // Remove the progress element.
-  if (this.progress.element) {
-    $(this.progress.element).remove();
-  }
-  if (this.progress.object) {
-    this.progress.object.stopMonitoring();
-  }
-  // Undo hide.
-  $(this.wrapper).show();
-  // Re-enable the element.
-  $(this.element).removeClass('progress-disabled').prop('disabled', false);
-  // Reattach behaviors, if they were detached in beforeSerialize().
-  if (this.$form) {
-    var settings = response.settings || this.settings || drupalSettings;
-    Drupal.attachBehaviors(this.$form.get(0), settings);
-  }
-  throw new Drupal.AjaxError(response, uri);
-};
-
-/**
- * Provide a series of commands that the server can request the client perform.
- */
-Drupal.AjaxCommands = function () {};
-Drupal.AjaxCommands.prototype = {
+
+    // If necessary, prevent the browser default action of an additional event.
+    // For example, prevent the browser default action of a click, even if the
+    // AJAX behavior binds to mousedown.
+    if (element_settings.prevent) {
+      $(ajax.element).on(element_settings.prevent, false);
+    }
+  };
+
   /**
-   * Command to insert new content into the DOM.
+   * Handle a key press.
+   *
+   * The Ajax object will, if instructed, bind to a key press response. This
+   * will test to see if the key press is valid to trigger this event and
+   * if it is, trigger it for us and prevent other keypresses from triggering.
+   * In this case we're handling RETURN and SPACEBAR keypresses (event codes 13
+   * and 32. RETURN is often used to submit a form when in a textfield, and
+   * SPACE is often used to activate an element without submitting.
    */
-  insert: function (ajax, response, status) {
-    // Get information from the response. If it is not there, default to
-    // our presets.
-    var wrapper = response.selector ? $(response.selector) : $(ajax.wrapper);
-    var method = response.method || ajax.method;
-    var effect = ajax.getEffect(response);
-    var settings;
-
-    // We don't know what response.data contains: it might be a string of text
-    // without HTML, so don't rely on jQuery correctly iterpreting
-    // $(response.data) as new HTML rather than a CSS selector. Also, if
-    // response.data contains top-level text nodes, they get lost with either
-    // $(response.data) or $('<div></div>').replaceWith(response.data).
-    var new_content_wrapped = $('<div></div>').html(response.data);
-    var new_content = new_content_wrapped.contents();
-
-    // For legacy reasons, the effects processing code assumes that new_content
-    // consists of a single top-level element. Also, it has not been
-    // sufficiently tested whether attachBehaviors() can be successfully called
-    // with a context object that includes top-level text nodes. However, to
-    // give developers full control of the HTML appearing in the page, and to
-    // enable Ajax content to be inserted in places where DIV elements are not
-    // allowed (e.g., within TABLE, TR, and SPAN parents), we check if the new
-    // content satisfies the requirement of a single top-level element, and
-    // only use the container DIV created above when it doesn't. For more
-    // information, please see http://drupal.org/node/736066.
-    if (new_content.length !== 1 || new_content.get(0).nodeType !== 1) {
-      new_content = new_content_wrapped;
-    }
-
-    // If removing content from the wrapper, detach behaviors first.
-    switch (method) {
-      case 'html':
-      case 'replaceWith':
-      case 'replaceAll':
-      case 'empty':
-      case 'remove':
-        settings = response.settings || ajax.settings || drupalSettings;
-        Drupal.detachBehaviors(wrapper.get(0), settings);
+  Drupal.ajax.prototype.keypressResponse = function (element, event) {
+    // Create a synonym for this to reduce code confusion.
+    var ajax = this;
+
+    // Detect enter key and space bar and allow the standard response for them,
+    // except for form elements of type 'text', 'tel', 'number' and 'textarea',
+    // where the spacebar activation causes inappropriate activation if
+    // #ajax['keypress'] is TRUE. On a text-type widget a space should always be a
+    // space.
+    if (event.which === 13 || (event.which === 32 && element.type !== 'text' &&
+      element.type !== 'textarea' && element.type !== 'tel' && element.type !== 'number')) {
+      event.preventDefault();
+      event.stopPropagation();
+      $(ajax.element_settings.element).trigger(ajax.element_settings.event);
     }
+  };
 
-    // Add the new content to the page.
-    wrapper[method](new_content);
+  /**
+   * Handle an event that triggers an Ajax response.
+   *
+   * When an event that triggers an Ajax response happens, this method will
+   * perform the actual Ajax call. It is bound to the event using
+   * bind() in the constructor, and it uses the options specified on the
+   * ajax object.
+   */
+  Drupal.ajax.prototype.eventResponse = function (element, event) {
+    event.preventDefault();
+    event.stopPropagation();
 
-    // Immediately hide the new content if we're using any effects.
-    if (effect.showEffect !== 'show') {
-      new_content.hide();
-    }
+    // Create a synonym for this to reduce code confusion.
+    var ajax = this;
 
-    // Determine which effect to use and what content will receive the
-    // effect, then show the new content.
-    if (new_content.find('.ajax-new-content').length > 0) {
-      new_content.find('.ajax-new-content').hide();
-      new_content.show();
-      new_content.find('.ajax-new-content')[effect.showEffect](effect.showSpeed);
-    }
-    else if (effect.showEffect !== 'show') {
-      new_content[effect.showEffect](effect.showSpeed);
+    // Do not perform another ajax command if one is already in progress.
+    if (ajax.ajaxing) {
+      return;
     }
 
-    // Attach all JavaScript behaviors to the new content, if it was successfully
-    // added to the page, this if statement allows #ajax['wrapper'] to be
-    // optional.
-    if (new_content.parents('html').length > 0) {
-      // Apply any settings from the returned JSON if available.
-      settings = response.settings || ajax.settings || drupalSettings;
-      Drupal.attachBehaviors(new_content.get(0), settings);
+    try {
+      if (ajax.$form) {
+        // If setClick is set, we must set this to ensure that the button's
+        // value is passed.
+        if (ajax.setClick) {
+          // Mark the clicked button. 'form.clk' is a special variable for
+          // ajaxSubmit that tells the system which element got clicked to
+          // trigger the submit. Without it there would be no 'op' or
+          // equivalent.
+          element.form.clk = element;
+        }
+
+        ajax.$form.ajaxSubmit(ajax.options);
+      }
+      else {
+        ajax.beforeSerialize(ajax.element, ajax.options);
+        $.ajax(ajax.options);
+      }
     }
-  },
+    catch (e) {
+      // Unset the ajax.ajaxing flag here because it won't be unset during
+      // the complete response.
+      ajax.ajaxing = false;
+      window.alert("An error occurred while attempting to process " + ajax.options.url + ": " + e.message);
+    }
+  };
 
   /**
-   * Command to remove a chunk from the page.
+   * Handler for the form serialization.
+   *
+   * Runs before the beforeSend() handler (see below), and unlike that one, runs
+   * before field data is collected.
    */
-  remove: function (ajax, response, status) {
-    var settings = response.settings || ajax.settings || drupalSettings;
-    $(response.selector).each(function() {
-      Drupal.detachBehaviors(this, settings);
-    })
-    .remove();
-  },
+  Drupal.ajax.prototype.beforeSerialize = function (element, options) {
+    // Allow detaching behaviors to update field values before collecting them.
+    // This is only needed when field values are added to the POST data, so only
+    // when there is a form such that this.$form.ajaxSubmit() is used instead of
+    // $.ajax(). When there is no form and $.ajax() is used, beforeSerialize()
+    // isn't called, but don't rely on that: explicitly check this.$form.
+    if (this.$form) {
+      var settings = this.settings || drupalSettings;
+      Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize');
+    }
 
-  /**
-   * Command to mark a chunk changed.
-   */
-  changed: function (ajax, response, status) {
-    if (!$(response.selector).hasClass('ajax-changed')) {
-      $(response.selector).addClass('ajax-changed');
-      if (response.asterisk) {
-        $(response.selector).find(response.asterisk).append(' <abbr class="ajax-changed" title="' + Drupal.t('Changed') + '">*</abbr> ');
+    // Prevent duplicate HTML ids in the returned markup.
+    // @see drupal_html_id()
+    var ids = document.querySelectorAll('[id]');
+    var ajaxHtmlIds = [];
+    for (var i = 0, il = ids.length; i < il; i++) {
+      ajaxHtmlIds.push(ids[i].id);
+    }
+    // Join IDs to minimize request size.
+    options.data.ajax_html_ids = ajaxHtmlIds.join(' ');
+
+    // Allow Drupal to return new JavaScript and CSS files to load without
+    // returning the ones already loaded.
+    // @see \Drupal\Core\Theme\AjaxBasePageNegotiator
+    // @see drupal_get_css()
+    // @see drupal_get_js()
+    var pageState = drupalSettings.ajaxPageState;
+    options.data['ajax_page_state[theme]'] = pageState.theme;
+    options.data['ajax_page_state[theme_token]'] = pageState.theme_token;
+    for (var cssFile in pageState.css) {
+      if (pageState.css.hasOwnProperty(cssFile)) {
+        options.data['ajax_page_state[css][' + cssFile + ']'] = 1;
+      }
+    }
+    for (var jsFile in pageState.js) {
+      if (pageState.js.hasOwnProperty(jsFile)) {
+        options.data['ajax_page_state[js][' + jsFile + ']'] = 1;
       }
     }
-  },
+  };
 
   /**
-   * Command to provide an alert.
+   * Modify form values prior to form submission.
    */
-  alert: function (ajax, response, status) {
-    window.alert(response.text, response.title);
-  },
+  Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) {
+    // This function is left empty to make it simple to override for modules
+    // that wish to add functionality here.
+  };
 
   /**
-   * Command to set the window.location, redirecting the browser.
+   * Prepare the Ajax request before it is sent.
    */
-  redirect: function (ajax, response, status) {
-    window.location = response.url;
-  },
+  Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) {
+    // For forms without file inputs, the jQuery Form plugin serializes the form
+    // values, and then calls jQuery's $.ajax() function, which invokes this
+    // handler. In this circumstance, options.extraData is never used. For forms
+    // with file inputs, the jQuery Form plugin uses the browser's normal form
+    // submission mechanism, but captures the response in a hidden IFRAME. In this
+    // circumstance, it calls this handler first, and then appends hidden fields
+    // to the form to submit the values in options.extraData. There is no simple
+    // way to know which submission mechanism will be used, so we add to extraData
+    // regardless, and allow it to be ignored in the former case.
+    if (this.$form) {
+      options.extraData = options.extraData || {};
+
+      // Let the server know when the IFRAME submission mechanism is used. The
+      // server can use this information to wrap the JSON response in a TEXTAREA,
+      // as per http://jquery.malsup.com/form/#file-upload.
+      options.extraData.ajax_iframe_upload = '1';
+
+      // The triggering element is about to be disabled (see below), but if it
+      // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that
+      // value is included in the submission. As per above, submissions that use
+      // $.ajax() are already serialized prior to the element being disabled, so
+      // this is only needed for IFRAME submissions.
+      var v = $.fieldValue(this.element);
+      if (v !== null) {
+        options.extraData[this.element.name] = v;
+      }
+    }
+
+    // Disable the element that received the change to prevent user interface
+    // interaction while the Ajax request is in progress. ajax.ajaxing prevents
+    // the element from triggering a new request, but does not prevent the user
+    // from changing its value.
+    $(this.element).addClass('progress-disabled').prop('disabled', true);
+
+    // Insert progressbar or throbber.
+    if (this.progress.type === 'bar') {
+      var progressBar = new Drupal.ProgressBar('ajax-progress-' + this.element.id, $.noop, this.progress.method, $.noop);
+      if (this.progress.message) {
+        progressBar.setProgress(-1, this.progress.message);
+      }
+      if (this.progress.url) {
+        progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
+      }
+      this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar');
+      this.progress.object = progressBar;
+      $(this.element).after(this.progress.element);
+    }
+    else if (this.progress.type === 'throbber') {
+      this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
+      if (this.progress.message) {
+        this.progress.element.find('.throbber').after('<div class="message">' + this.progress.message + '</div>');
+      }
+      $(this.element).after(this.progress.element);
+    }
+  };
 
   /**
-   * Command to provide the jQuery css() function.
+   * Handler for the form redirection completion.
    */
-  css: function (ajax, response, status) {
-    $(response.selector).css(response.argument);
-  },
+  Drupal.ajax.prototype.success = function (response, status) {
+    // Remove the progress element.
+    if (this.progress.element) {
+      $(this.progress.element).remove();
+    }
+    if (this.progress.object) {
+      this.progress.object.stopMonitoring();
+    }
+    $(this.element).removeClass('progress-disabled').prop('disabled', false);
+
+    for (var i in response) {
+      if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) {
+        this.commands[response[i].command](this, response[i], status);
+      }
+    }
+
+    // Reattach behaviors, if they were detached in beforeSerialize(). The
+    // attachBehaviors() called on the new content from processing the response
+    // commands is not sufficient, because behaviors from the entire form need
+    // to be reattached.
+    if (this.$form) {
+      var settings = this.settings || drupalSettings;
+      Drupal.attachBehaviors(this.$form.get(0), settings);
+    }
+
+    // Remove any response-specific settings so they don't get used on the next
+    // call by mistake.
+    this.settings = null;
+  };
 
   /**
-   * Command to set the settings that will be used for other commands in this response.
+   * Build an effect object which tells us how to apply the effect when adding new HTML.
    */
-  settings: function (ajax, response, status) {
-    if (response.merge) {
-      $.extend(true, drupalSettings, response.settings);
+  Drupal.ajax.prototype.getEffect = function (response) {
+    var type = response.effect || this.effect;
+    var speed = response.speed || this.speed;
+
+    var effect = {};
+    if (type === 'none') {
+      effect.showEffect = 'show';
+      effect.hideEffect = 'hide';
+      effect.showSpeed = '';
+    }
+    else if (type === 'fade') {
+      effect.showEffect = 'fadeIn';
+      effect.hideEffect = 'fadeOut';
+      effect.showSpeed = speed;
     }
     else {
-      ajax.settings = response.settings;
+      effect.showEffect = type + 'Toggle';
+      effect.hideEffect = type + 'Toggle';
+      effect.showSpeed = speed;
     }
-  },
 
-  /**
-   * Command to attach data using jQuery's data API.
-   */
-  data: function (ajax, response, status) {
-    $(response.selector).data(response.name, response.value);
-  },
+    return effect;
+  };
 
   /**
-   * Command to apply a jQuery method.
+   * Handler for the form redirection error.
    */
-  invoke: function (ajax, response, status) {
-    var $element = $(response.selector);
-    $element[response.method].apply($element, response.args);
-  },
+  Drupal.ajax.prototype.error = function (response, uri) {
+    // Remove the progress element.
+    if (this.progress.element) {
+      $(this.progress.element).remove();
+    }
+    if (this.progress.object) {
+      this.progress.object.stopMonitoring();
+    }
+    // Undo hide.
+    $(this.wrapper).show();
+    // Re-enable the element.
+    $(this.element).removeClass('progress-disabled').prop('disabled', false);
+    // Reattach behaviors, if they were detached in beforeSerialize().
+    if (this.$form) {
+      var settings = response.settings || this.settings || drupalSettings;
+      Drupal.attachBehaviors(this.$form.get(0), settings);
+    }
+    throw new Drupal.AjaxError(response, uri);
+  };
 
   /**
-   * Command to restripe a table.
+   * Provide a series of commands that the server can request the client perform.
    */
-  restripe: function (ajax, response, status) {
-    // :even and :odd are reversed because jQuery counts from 0 and
-    // we count from 1, so we're out of sync.
-    // Match immediate children of the parent element to allow nesting.
-    $(response.selector).find('> tbody > tr:visible, > tr:visible')
-      .removeClass('odd even')
-      .filter(':even').addClass('odd').end()
-      .filter(':odd').addClass('even');
-  },
+  Drupal.AjaxCommands = function () {};
+  Drupal.AjaxCommands.prototype = {
+    /**
+     * Command to insert new content into the DOM.
+     */
+    insert: function (ajax, response, status) {
+      // Get information from the response. If it is not there, default to
+      // our presets.
+      var wrapper = response.selector ? $(response.selector) : $(ajax.wrapper);
+      var method = response.method || ajax.method;
+      var effect = ajax.getEffect(response);
+      var settings;
+
+      // We don't know what response.data contains: it might be a string of text
+      // without HTML, so don't rely on jQuery correctly iterpreting
+      // $(response.data) as new HTML rather than a CSS selector. Also, if
+      // response.data contains top-level text nodes, they get lost with either
+      // $(response.data) or $('<div></div>').replaceWith(response.data).
+      var new_content_wrapped = $('<div></div>').html(response.data);
+      var new_content = new_content_wrapped.contents();
+
+      // For legacy reasons, the effects processing code assumes that new_content
+      // consists of a single top-level element. Also, it has not been
+      // sufficiently tested whether attachBehaviors() can be successfully called
+      // with a context object that includes top-level text nodes. However, to
+      // give developers full control of the HTML appearing in the page, and to
+      // enable Ajax content to be inserted in places where DIV elements are not
+      // allowed (e.g., within TABLE, TR, and SPAN parents), we check if the new
+      // content satisfies the requirement of a single top-level element, and
+      // only use the container DIV created above when it doesn't. For more
+      // information, please see http://drupal.org/node/736066.
+      if (new_content.length !== 1 || new_content.get(0).nodeType !== 1) {
+        new_content = new_content_wrapped;
+      }
 
-  /**
-   * Command to add css.
-   *
-   * Uses the proprietary addImport method if available as browsers which
-   * support that method ignore @import statements in dynamically added
-   * stylesheets.
-   */
-  add_css: function (ajax, response, status) {
-    // Add the styles in the normal way.
-    $('head').prepend(response.data);
-    // Add imports in the styles using the addImport method if available.
-    var match, importMatch = /^@import url\("(.*)"\);$/igm;
-    if (document.styleSheets[0].addImport && importMatch.test(response.data)) {
-      importMatch.lastIndex = 0;
-      do {
-        match = importMatch.exec(response.data);
-        document.styleSheets[0].addImport(match[1]);
-      } while (match);
-    }
-  }
-};
+      // If removing content from the wrapper, detach behaviors first.
+      switch (method) {
+        case 'html':
+        case 'replaceWith':
+        case 'replaceAll':
+        case 'empty':
+        case 'remove':
+          settings = response.settings || ajax.settings || drupalSettings;
+          Drupal.detachBehaviors(wrapper.get(0), settings);
+      }
+
+      // Add the new content to the page.
+      wrapper[method](new_content);
+
+      // Immediately hide the new content if we're using any effects.
+      if (effect.showEffect !== 'show') {
+        new_content.hide();
+      }
+
+      // Determine which effect to use and what content will receive the
+      // effect, then show the new content.
+      if (new_content.find('.ajax-new-content').length > 0) {
+        new_content.find('.ajax-new-content').hide();
+        new_content.show();
+        new_content.find('.ajax-new-content')[effect.showEffect](effect.showSpeed);
+      }
+      else if (effect.showEffect !== 'show') {
+        new_content[effect.showEffect](effect.showSpeed);
+      }
+
+      // Attach all JavaScript behaviors to the new content, if it was successfully
+      // added to the page, this if statement allows #ajax['wrapper'] to be
+      // optional.
+      if (new_content.parents('html').length > 0) {
+        // Apply any settings from the returned JSON if available.
+        settings = response.settings || ajax.settings || drupalSettings;
+        Drupal.attachBehaviors(new_content.get(0), settings);
+      }
+    },
+
+    /**
+     * Command to remove a chunk from the page.
+     */
+    remove: function (ajax, response, status) {
+      var settings = response.settings || ajax.settings || drupalSettings;
+      $(response.selector).each(function () {
+        Drupal.detachBehaviors(this, settings);
+      })
+        .remove();
+    },
+
+    /**
+     * Command to mark a chunk changed.
+     */
+    changed: function (ajax, response, status) {
+      if (!$(response.selector).hasClass('ajax-changed')) {
+        $(response.selector).addClass('ajax-changed');
+        if (response.asterisk) {
+          $(response.selector).find(response.asterisk).append(' <abbr class="ajax-changed" title="' + Drupal.t('Changed') + '">*</abbr> ');
+        }
+      }
+    },
+
+    /**
+     * Command to provide an alert.
+     */
+    alert: function (ajax, response, status) {
+      window.alert(response.text, response.title);
+    },
+
+    /**
+     * Command to set the window.location, redirecting the browser.
+     */
+    redirect: function (ajax, response, status) {
+      window.location = response.url;
+    },
+
+    /**
+     * Command to provide the jQuery css() function.
+     */
+    css: function (ajax, response, status) {
+      $(response.selector).css(response.argument);
+    },
+
+    /**
+     * Command to set the settings that will be used for other commands in this response.
+     */
+    settings: function (ajax, response, status) {
+      if (response.merge) {
+        $.extend(true, drupalSettings, response.settings);
+      }
+      else {
+        ajax.settings = response.settings;
+      }
+    },
+
+    /**
+     * Command to attach data using jQuery's data API.
+     */
+    data: function (ajax, response, status) {
+      $(response.selector).data(response.name, response.value);
+    },
+
+    /**
+     * Command to apply a jQuery method.
+     */
+    invoke: function (ajax, response, status) {
+      var $element = $(response.selector);
+      $element[response.method].apply($element, response.args);
+    },
+
+    /**
+     * Command to restripe a table.
+     */
+    restripe: function (ajax, response, status) {
+      // :even and :odd are reversed because jQuery counts from 0 and
+      // we count from 1, so we're out of sync.
+      // Match immediate children of the parent element to allow nesting.
+      $(response.selector).find('> tbody > tr:visible, > tr:visible')
+        .removeClass('odd even')
+        .filter(':even').addClass('odd').end()
+        .filter(':odd').addClass('even');
+    },
+
+    /**
+     * Command to add css.
+     *
+     * Uses the proprietary addImport method if available as browsers which
+     * support that method ignore @import statements in dynamically added
+     * stylesheets.
+     */
+    add_css: function (ajax, response, status) {
+      // Add the styles in the normal way.
+      $('head').prepend(response.data);
+      // Add imports in the styles using the addImport method if available.
+      var match, importMatch = /^@import url\("(.*)"\);$/igm;
+      if (document.styleSheets[0].addImport && importMatch.test(response.data)) {
+        importMatch.lastIndex = 0;
+        do {
+          match = importMatch.exec(response.data);
+          document.styleSheets[0].addImport(match[1]);
+        } while (match);
+      }
+    }
+  };
 
 })(jQuery, this, Drupal, drupalSettings);
diff --git a/core/misc/announce.js b/core/misc/announce.js
index dbefeb6..00ce14b 100644
--- a/core/misc/announce.js
+++ b/core/misc/announce.js
@@ -42,7 +42,7 @@
   /**
    * Concatenates announcements to a single string; appends to the live region.
    */
-  function announce () {
+  function announce() {
     var text = [];
     var priority = 'polite';
     var announcement;
diff --git a/core/misc/autocomplete.js b/core/misc/autocomplete.js
index 743e8d0..2181fda 100644
--- a/core/misc/autocomplete.js
+++ b/core/misc/autocomplete.js
@@ -1,201 +1,201 @@
 (function ($, Drupal) {
 
-"use strict";
-
-var autocomplete;
-
-/**
- * Helper splitting terms from the autocomplete value.
- *
- * @param {String} value
- *
- * @return {Array}
- */
-function autocompleteSplitValues (value) {
-  // We will match the value against comma-seperated terms.
-  var result = [];
-  var quote = false;
-  var current = '';
-  var valueLength = value.length;
-  var i, character;
-
-  for (i = 0; i < valueLength; i++) {
-    character = value.charAt(i);
-    if (character === '"') {
-      current += character;
-      quote = !quote;
-    }
-    else if (character === ',' && !quote) {
-      result.push(current.trim());
-      current = '';
+  "use strict";
+
+  var autocomplete;
+
+  /**
+   * Helper splitting terms from the autocomplete value.
+   *
+   * @param {String} value
+   *
+   * @return {Array}
+   */
+  function autocompleteSplitValues(value) {
+    // We will match the value against comma-seperated terms.
+    var result = [];
+    var quote = false;
+    var current = '';
+    var valueLength = value.length;
+    var i, character;
+
+    for (i = 0; i < valueLength; i++) {
+      character = value.charAt(i);
+      if (character === '"') {
+        current += character;
+        quote = !quote;
+      }
+      else if (character === ',' && !quote) {
+        result.push(current.trim());
+        current = '';
+      }
+      else {
+        current += character;
+      }
     }
-    else {
-      current += character;
+    if (value.length > 0) {
+      result.push($.trim(current));
     }
-  }
-  if (value.length > 0) {
-    result.push($.trim(current));
+
+    return result;
   }
 
-  return result;
-}
-
-/**
- * Returns the last value of an multi-value textfield.
- *
- * @param {String} terms
- *
- * @return {String}
- */
-function extractLastTerm (terms) {
-  return autocomplete.splitValues(terms).pop();
-}
-
-/**
- * The search handler is called before a search is performed.
- *
- * @param {Object} event
- *
- * @return {Boolean}
- */
-function searchHandler (event) {
-  // Only search when the term is two characters or larger.
-  var term = autocomplete.extractLastTerm(event.target.value);
-  return term.length >= autocomplete.minLength;
-}
-
-/**
- * jQuery UI autocomplete source callback.
- *
- * @param {Object} request
- * @param {Function} response
- */
-function sourceData (request, response) {
-  /*jshint validthis:true */
-  var elementId = this.element.attr('id');
-
-  if (!(elementId in autocomplete.cache)) {
-    autocomplete.cache[elementId] = {};
+  /**
+   * Returns the last value of an multi-value textfield.
+   *
+   * @param {String} terms
+   *
+   * @return {String}
+   */
+  function extractLastTerm(terms) {
+    return autocomplete.splitValues(terms).pop();
   }
 
   /**
-   * Filter through the suggestions removing all terms already tagged and
-   * display the available terms to the user.
+   * The search handler is called before a search is performed.
+   *
+   * @param {Object} event
    *
-   * @param {Object} suggestions
+   * @return {Boolean}
    */
-  function showSuggestions (suggestions) {
-    var tagged = autocomplete.splitValues(request.term);
-    for (var i = 0, il = tagged.length; i < il; i++) {
-      var index = suggestions.indexOf(tagged[i]);
-      if (index >= 0) {
-        suggestions.splice(index, 1);
-      }
-    }
-    response(suggestions);
+  function searchHandler(event) {
+    // Only search when the term is two characters or larger.
+    var term = autocomplete.extractLastTerm(event.target.value);
+    return term.length >= autocomplete.minLength;
   }
 
   /**
-   * Transforms the data object into an array and update autocomplete results.
+   * jQuery UI autocomplete source callback.
    *
-   * @param {Object} data
+   * @param {Object} request
+   * @param {Function} response
    */
-  function sourceCallbackHandler (data) {
-    autocomplete.cache[elementId][term] = data;
+  function sourceData(request, response) {
+    /*jshint validthis:true */
+    var elementId = this.element.attr('id');
 
-    // Send the new string array of terms to the jQuery UI list.
-    showSuggestions(data);
-  }
+    if (!(elementId in autocomplete.cache)) {
+      autocomplete.cache[elementId] = {};
+    }
 
-  // Get the desired term and construct the autocomplete URL for it.
-  var term = autocomplete.extractLastTerm(request.term);
+    /**
+     * Filter through the suggestions removing all terms already tagged and
+     * display the available terms to the user.
+     *
+     * @param {Object} suggestions
+     */
+    function showSuggestions(suggestions) {
+      var tagged = autocomplete.splitValues(request.term);
+      for (var i = 0, il = tagged.length; i < il; i++) {
+        var index = suggestions.indexOf(tagged[i]);
+        if (index >= 0) {
+          suggestions.splice(index, 1);
+        }
+      }
+      response(suggestions);
+    }
 
-  // Check if the term is already cached.
-  if (autocomplete.cache[elementId].hasOwnProperty(term)) {
-    showSuggestions(autocomplete.cache[elementId][term]);
-  }
-  else {
-    var options = $.extend({ success: sourceCallbackHandler, data: { q: term } }, autocomplete.ajax);
-    /*jshint validthis:true */
-    $.ajax(this.element.attr('data-autocomplete-path'), options);
-  }
-}
-
-/**
- * Handles an autocompletefocus event.
- *
- * @return {Boolean}
- */
-function focusHandler () {
-  return false;
-}
-
-/**
- * Handles an autocompleteselect event.
- *
- * @param {Object} event
- * @param {Object} ui
- *
- * @return {Boolean}
- */
-function selectHandler (event, ui) {
-  var terms = autocomplete.splitValues(event.target.value);
-  // Remove the current input.
-  terms.pop();
-  // Add the selected item.
-  if (ui.item.value.search(",") > 0) {
-    terms.push('"' + ui.item.value + '"');
+    /**
+     * Transforms the data object into an array and update autocomplete results.
+     *
+     * @param {Object} data
+     */
+    function sourceCallbackHandler(data) {
+      autocomplete.cache[elementId][term] = data;
+
+      // Send the new string array of terms to the jQuery UI list.
+      showSuggestions(data);
+    }
+
+    // Get the desired term and construct the autocomplete URL for it.
+    var term = autocomplete.extractLastTerm(request.term);
+
+    // Check if the term is already cached.
+    if (autocomplete.cache[elementId].hasOwnProperty(term)) {
+      showSuggestions(autocomplete.cache[elementId][term]);
+    }
+    else {
+      var options = $.extend({ success: sourceCallbackHandler, data: { q: term } }, autocomplete.ajax);
+      /*jshint validthis:true */
+      $.ajax(this.element.attr('data-autocomplete-path'), options);
+    }
   }
-  else {
-    terms.push(ui.item.value);
+
+  /**
+   * Handles an autocompletefocus event.
+   *
+   * @return {Boolean}
+   */
+  function focusHandler() {
+    return false;
   }
-  event.target.value = terms.join(', ');
-  // Return false to tell jQuery UI that we've filled in the value already.
-  return false;
-}
-
-/**
- * Attaches the autocomplete behavior to all required fields.
- */
-Drupal.behaviors.autocomplete = {
-  attach: function (context) {
-    // Act on textfields with the "form-autocomplete" class.
-    var $autocomplete = $(context).find('input.form-autocomplete').once('autocomplete');
-    if ($autocomplete.length) {
-      // Use jQuery UI Autocomplete on the textfield.
-      $autocomplete.autocomplete(autocomplete.options);
+
+  /**
+   * Handles an autocompleteselect event.
+   *
+   * @param {Object} event
+   * @param {Object} ui
+   *
+   * @return {Boolean}
+   */
+  function selectHandler(event, ui) {
+    var terms = autocomplete.splitValues(event.target.value);
+    // Remove the current input.
+    terms.pop();
+    // Add the selected item.
+    if (ui.item.value.search(",") > 0) {
+      terms.push('"' + ui.item.value + '"');
     }
-  },
-  detach: function (context, settings, trigger) {
-    if (trigger === 'unload') {
-      $(context).find('input.form-autocomplete')
-        .removeOnce('autocomplete')
-        .autocomplete('destroy');
+    else {
+      terms.push(ui.item.value);
     }
+    event.target.value = terms.join(', ');
+    // Return false to tell jQuery UI that we've filled in the value already.
+    return false;
   }
-};
-
-/**
- * Autocomplete object implementation.
- */
-autocomplete = {
-  cache: {},
-  // Exposes methods to allow overriding by contrib.
-  minLength: 1,
-  splitValues: autocompleteSplitValues,
-  extractLastTerm: extractLastTerm,
-  // jQuery UI autocomplete options.
-  options: {
-    source: sourceData,
-    focus: focusHandler,
-    search: searchHandler,
-    select: selectHandler
-  },
-  ajax: {
-    dataType: 'json'
-  }
-};
 
-Drupal.autocomplete = autocomplete;
+  /**
+   * Attaches the autocomplete behavior to all required fields.
+   */
+  Drupal.behaviors.autocomplete = {
+    attach: function (context) {
+      // Act on textfields with the "form-autocomplete" class.
+      var $autocomplete = $(context).find('input.form-autocomplete').once('autocomplete');
+      if ($autocomplete.length) {
+        // Use jQuery UI Autocomplete on the textfield.
+        $autocomplete.autocomplete(autocomplete.options);
+      }
+    },
+    detach: function (context, settings, trigger) {
+      if (trigger === 'unload') {
+        $(context).find('input.form-autocomplete')
+          .removeOnce('autocomplete')
+          .autocomplete('destroy');
+      }
+    }
+  };
+
+  /**
+   * Autocomplete object implementation.
+   */
+  autocomplete = {
+    cache: {},
+    // Exposes methods to allow overriding by contrib.
+    minLength: 1,
+    splitValues: autocompleteSplitValues,
+    extractLastTerm: extractLastTerm,
+    // jQuery UI autocomplete options.
+    options: {
+      source: sourceData,
+      focus: focusHandler,
+      search: searchHandler,
+      select: selectHandler
+    },
+    ajax: {
+      dataType: 'json'
+    }
+  };
+
+  Drupal.autocomplete = autocomplete;
 
 })(jQuery, Drupal);
diff --git a/core/misc/batch.js b/core/misc/batch.js
index b3013e5..82d6bce 100644
--- a/core/misc/batch.js
+++ b/core/misc/batch.js
@@ -1,39 +1,39 @@
 (function ($, Drupal) {
 
-"use strict";
+  "use strict";
 
-/**
- * Attaches the batch behavior to progress bars.
- */
-Drupal.behaviors.batch = {
-  attach: function (context, settings) {
-    var batch = settings.batch;
-    var $progress = $('#progress').once('batch');
-    var progressBar;
+  /**
+   * Attaches the batch behavior to progress bars.
+   */
+  Drupal.behaviors.batch = {
+    attach: function (context, settings) {
+      var batch = settings.batch;
+      var $progress = $('#progress').once('batch');
+      var progressBar;
 
-    // Success: redirect to the summary.
-    function updateCallback(progress, status, pb) {
-      if (progress === '100') {
-        pb.stopMonitoring();
-        window.location = batch.uri + '&op=finished';
+      // Success: redirect to the summary.
+      function updateCallback(progress, status, pb) {
+        if (progress === '100') {
+          pb.stopMonitoring();
+          window.location = batch.uri + '&op=finished';
+        }
       }
-    }
 
-    function errorCallback(pb) {
-      $progress.prepend($('<p class="error"></p>').html(batch.errorMessage));
-      $('#wait').hide();
-    }
+      function errorCallback(pb) {
+        $progress.prepend($('<p class="error"></p>').html(batch.errorMessage));
+        $('#wait').hide();
+      }
 
-    if ($progress.length) {
-      progressBar = new Drupal.ProgressBar('updateprogress', updateCallback, 'POST', errorCallback);
-      progressBar.setProgress(-1, batch.initMessage);
-      progressBar.startMonitoring(batch.uri + '&op=do', 10);
-      // Remove HTML from no-js progress bar.
-      $progress.empty();
-      // Append the JS progressbar element.
-      $progress.append(progressBar.element);
+      if ($progress.length) {
+        progressBar = new Drupal.ProgressBar('updateprogress', updateCallback, 'POST', errorCallback);
+        progressBar.setProgress(-1, batch.initMessage);
+        progressBar.startMonitoring(batch.uri + '&op=do', 10);
+        // Remove HTML from no-js progress bar.
+        $progress.empty();
+        // Append the JS progressbar element.
+        $progress.append(progressBar.element);
+      }
     }
-  }
-};
+  };
 
 })(jQuery, Drupal);
diff --git a/core/misc/collapse.js b/core/misc/collapse.js
index 84a803d..9dc4202 100644
--- a/core/misc/collapse.js
+++ b/core/misc/collapse.js
@@ -1,113 +1,113 @@
 (function ($, Modernizr, Drupal) {
 
-"use strict";
+  "use strict";
 
-/**
- * The collapsible details object represents a single collapsible details element.
- */
-function CollapsibleDetails (node) {
-  this.$node = $(node);
-  this.$node.data('details', this);
-  // Expand details if there are errors inside, or if it contains an
-  // element that is targeted by the URI fragment identifier.
-  var anchor = location.hash && location.hash !== '#' ? ', ' + location.hash : '';
-  if (this.$node.find('.error' + anchor).length) {
-    this.$node.attr('open', true);
-  }
-  // Initialize and setup the summary,
-  this.setupSummary();
-  // Initialize and setup the legend.
-  this.setupLegend();
-}
-
-/**
- * Extend CollapsibleDetails function.
- */
-$.extend(CollapsibleDetails, {
   /**
-   * Holds references to instantiated CollapsibleDetails objects.
+   * The collapsible details object represents a single collapsible details element.
    */
-  instances: []
-});
+  function CollapsibleDetails(node) {
+    this.$node = $(node);
+    this.$node.data('details', this);
+    // Expand details if there are errors inside, or if it contains an
+    // element that is targeted by the URI fragment identifier.
+    var anchor = location.hash && location.hash !== '#' ? ', ' + location.hash : '';
+    if (this.$node.find('.error' + anchor).length) {
+      this.$node.attr('open', true);
+    }
+    // Initialize and setup the summary,
+    this.setupSummary();
+    // Initialize and setup the legend.
+    this.setupLegend();
+  }
 
-/**
- * Extend CollapsibleDetails prototype.
- */
-$.extend(CollapsibleDetails.prototype, {
   /**
-   * Initialize and setup summary events and markup.
+   * Extend CollapsibleDetails function.
    */
-  setupSummary: function () {
-    this.$summary = $('<span class="summary"></span>');
-    this.$node
-      .on('summaryUpdated', $.proxy(this.onSummaryUpdated, this))
-      .trigger('summaryUpdated');
-  },
+  $.extend(CollapsibleDetails, {
+    /**
+     * Holds references to instantiated CollapsibleDetails objects.
+     */
+    instances: []
+  });
+
   /**
-   * Initialize and setup legend markup.
+   * Extend CollapsibleDetails prototype.
    */
-  setupLegend: function () {
-    // Turn the summary into a clickable link.
-    var $legend = this.$node.find('> summary');
+  $.extend(CollapsibleDetails.prototype, {
+    /**
+     * Initialize and setup summary events and markup.
+     */
+    setupSummary: function () {
+      this.$summary = $('<span class="summary"></span>');
+      this.$node
+        .on('summaryUpdated', $.proxy(this.onSummaryUpdated, this))
+        .trigger('summaryUpdated');
+    },
+    /**
+     * Initialize and setup legend markup.
+     */
+    setupLegend: function () {
+      // Turn the summary into a clickable link.
+      var $legend = this.$node.find('> summary');
 
-    $('<span class="details-summary-prefix visually-hidden"></span>')
-      .append(this.$node.attr('open') ? Drupal.t('Hide') : Drupal.t('Show'))
-      .prependTo($legend)
-      .after(document.createTextNode(' '));
+      $('<span class="details-summary-prefix visually-hidden"></span>')
+        .append(this.$node.attr('open') ? Drupal.t('Hide') : Drupal.t('Show'))
+        .prependTo($legend)
+        .after(document.createTextNode(' '));
 
-    // .wrapInner() does not retain bound events.
-    $('<a class="details-title"></a>')
-      .attr('href', '#' + this.$node.attr('id'))
-      .prepend($legend.contents())
-      .appendTo($legend)
-      .on('click', $.proxy(this.onLegendClick, this));
-    $legend.append(this.$summary);
-  },
-  /**
-   * Handle legend clicks
-   */
-  onLegendClick: function (e) {
-    this.toggle();
-    e.preventDefault();
-  },
-  /**
-   * Update summary
-   */
-  onSummaryUpdated: function () {
-    var text = $.trim(this.$node.drupalGetSummary());
-    this.$summary.html(text ? ' (' + text + ')' : '');
-  },
-  /**
-   * Toggle the visibility of a details element using smooth animations.
-   */
-  toggle: function () {
-    var isOpen = !!this.$node.attr('open');
-    var $summaryPrefix = this.$node.find('> summary span.details-summary-prefix');
-    if (isOpen) {
-      $summaryPrefix.html(Drupal.t('Show'));
-    }
-    else {
-      $summaryPrefix.html(Drupal.t('Hide'));
+      // .wrapInner() does not retain bound events.
+      $('<a class="details-title"></a>')
+        .attr('href', '#' + this.$node.attr('id'))
+        .prepend($legend.contents())
+        .appendTo($legend)
+        .on('click', $.proxy(this.onLegendClick, this));
+      $legend.append(this.$summary);
+    },
+    /**
+     * Handle legend clicks
+     */
+    onLegendClick: function (e) {
+      this.toggle();
+      e.preventDefault();
+    },
+    /**
+     * Update summary
+     */
+    onSummaryUpdated: function () {
+      var text = $.trim(this.$node.drupalGetSummary());
+      this.$summary.html(text ? ' (' + text + ')' : '');
+    },
+    /**
+     * Toggle the visibility of a details element using smooth animations.
+     */
+    toggle: function () {
+      var isOpen = !!this.$node.attr('open');
+      var $summaryPrefix = this.$node.find('> summary span.details-summary-prefix');
+      if (isOpen) {
+        $summaryPrefix.html(Drupal.t('Show'));
+      }
+      else {
+        $summaryPrefix.html(Drupal.t('Hide'));
+      }
+      this.$node.attr('open', !isOpen);
     }
-    this.$node.attr('open', !isOpen);
-  }
-});
+  });
 
-Drupal.behaviors.collapse = {
-  attach: function (context) {
-    if (Modernizr.details) {
-      return;
-    }
-    var $collapsibleDetails = $(context).find('details').once('collapse');
-    if ($collapsibleDetails.length) {
-      for (var i = 0; i < $collapsibleDetails.length; i++) {
-        CollapsibleDetails.instances.push(new CollapsibleDetails($collapsibleDetails[i]));
+  Drupal.behaviors.collapse = {
+    attach: function (context) {
+      if (Modernizr.details) {
+        return;
+      }
+      var $collapsibleDetails = $(context).find('details').once('collapse');
+      if ($collapsibleDetails.length) {
+        for (var i = 0; i < $collapsibleDetails.length; i++) {
+          CollapsibleDetails.instances.push(new CollapsibleDetails($collapsibleDetails[i]));
+        }
       }
     }
-  }
-};
+  };
 
 // Expose constructor in the public space.
-Drupal.CollapsibleDetails = CollapsibleDetails;
+  Drupal.CollapsibleDetails = CollapsibleDetails;
 
 })(jQuery, Modernizr, Drupal);
diff --git a/core/misc/dialog.ajax.js b/core/misc/dialog.ajax.js
index d2d8d3a..4845cbd 100644
--- a/core/misc/dialog.ajax.js
+++ b/core/misc/dialog.ajax.js
@@ -98,7 +98,7 @@
     }
 
     // Bind dialogButtonsChange
-    $dialog.on('dialogButtonsChange', function() {
+    $dialog.on('dialogButtonsChange', function () {
       var buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
       $dialog.dialog('option', 'buttons', buttons);
     });
diff --git a/core/misc/dialog.js b/core/misc/dialog.js
index 2bb3a32..789c37e 100644
--- a/core/misc/dialog.js
+++ b/core/misc/dialog.js
@@ -6,56 +6,56 @@
  */
 (function ($, Drupal, drupalSettings) {
 
-"use strict";
-
-drupalSettings.dialog = {
-  autoOpen: true,
-  dialogClass: '',
-  // When using this API directly (when generating dialogs on the client side),
-  // you may want to override this method and do
-  // @code
-  // jQuery(event.target).remove()
-  // @endcode
-  // as well, to remove the dialog on closing.
-  close: function (event) {
-    Drupal.detachBehaviors(event.target, null, 'unload');
-  }
-};
-
-Drupal.dialog = function (element, options) {
-
-  function openDialog (settings) {
-    settings = $.extend({}, drupalSettings.dialog, options, settings);
-    // Trigger a global event to allow scripts to bind events to the dialog.
-    $(window).trigger('dialog:beforecreate', [dialog, $element, settings]);
-    $element.dialog(settings);
-    dialog.open = true;
-    $(window).trigger('dialog:aftercreate', [dialog, $element, settings]);
-  }
-
-  function closeDialog (value) {
-    $(window).trigger('dialog:beforeclose', [dialog, $element]);
-    $element.dialog('close');
-    dialog.returnValue = value;
-    dialog.open = false;
-    $(window).trigger('dialog:afterclose', [dialog, $element]);
-  }
-
-  var undef;
-  var $element = $(element);
-  var dialog = {
-    open: false,
-    returnValue: undef,
-    show: function () {
-      openDialog({modal: false});
-    },
-    showModal: function () {
-      openDialog({modal: true});
-    },
-    close: closeDialog
+  "use strict";
+
+  drupalSettings.dialog = {
+    autoOpen: true,
+    dialogClass: '',
+    // When using this API directly (when generating dialogs on the client side),
+    // you may want to override this method and do
+    // @code
+    // jQuery(event.target).remove()
+    // @endcode
+    // as well, to remove the dialog on closing.
+    close: function (event) {
+      Drupal.detachBehaviors(event.target, null, 'unload');
+    }
   };
 
-  return dialog;
-};
+  Drupal.dialog = function (element, options) {
+
+    function openDialog(settings) {
+      settings = $.extend({}, drupalSettings.dialog, options, settings);
+      // Trigger a global event to allow scripts to bind events to the dialog.
+      $(window).trigger('dialog:beforecreate', [dialog, $element, settings]);
+      $element.dialog(settings);
+      dialog.open = true;
+      $(window).trigger('dialog:aftercreate', [dialog, $element, settings]);
+    }
+
+    function closeDialog(value) {
+      $(window).trigger('dialog:beforeclose', [dialog, $element]);
+      $element.dialog('close');
+      dialog.returnValue = value;
+      dialog.open = false;
+      $(window).trigger('dialog:afterclose', [dialog, $element]);
+    }
+
+    var undef;
+    var $element = $(element);
+    var dialog = {
+      open: false,
+      returnValue: undef,
+      show: function () {
+        openDialog({modal: false});
+      },
+      showModal: function () {
+        openDialog({modal: true});
+      },
+      close: closeDialog
+    };
+
+    return dialog;
+  };
 
 })(jQuery, Drupal, drupalSettings);
diff --git a/core/misc/dialog.position.js b/core/misc/dialog.position.js
index 7b12055..9d03f69 100644
--- a/core/misc/dialog.position.js
+++ b/core/misc/dialog.position.js
@@ -13,7 +13,7 @@
    * be disabled by setting autoResize: false in the options array when creating
    * a new Drupal.dialog().
    */
-  function resetSize (event) {
+  function resetSize(event) {
     var positionOptions = ['width', 'height', 'minWidth', 'minHeight', 'maxHeight', 'maxWidth', 'position'];
     var adjustedOptions = {};
     var windowHeight = $(window).height();
@@ -45,13 +45,13 @@
   /**
    * Position the dialog's center at the center of displace.offsets boundaries.
    */
-  function resetPosition (options) {
+  function resetPosition(options) {
     var offsets = displace.offsets;
     var left = offsets.left - offsets.right;
     var top = offsets.top - offsets.bottom;
 
-    var leftString = (left > 0 ? '+' : '-') + Math.abs(Math.round(left/2)) + 'px';
-    var topString = (top > 0 ? '+' : '-') + Math.abs(Math.round(top/2)) + 'px';
+    var leftString = (left > 0 ? '+' : '-') + Math.abs(Math.round(left / 2)) + 'px';
+    var topString = (top > 0 ? '+' : '-') + Math.abs(Math.round(top / 2)) + 'px';
     options.position = {
       my: 'center' + (left !== 0 ? leftString : '') + ' center' + (top !== 0 ? topString : '')
     };
diff --git a/core/misc/displace.js b/core/misc/displace.js
index c658694..9cc285a 100644
--- a/core/misc/displace.js
+++ b/core/misc/displace.js
@@ -39,7 +39,7 @@
    *   and left. The value of each key is the viewport displacement distance for
    *   that edge.
    */
-  function displace (broadcast) {
+  function displace(broadcast) {
     offsets = Drupal.displace.offsets = calculateOffsets();
     if (typeof broadcast === 'undefined' || broadcast) {
       $(document).trigger('drupalViewportOffsetChange', offsets);
@@ -55,7 +55,7 @@
    *   and left. The value of each key is the viewport displacement distance for
    *   that edge.
    */
-  function calculateOffsets () {
+  function calculateOffsets() {
     return {
       top: calculateOffset('top'),
       right: calculateOffset('right'),
@@ -79,7 +79,7 @@
    * @return {number}
    *   The viewport displacement distance for the requested edge.
    */
-  function calculateOffset (edge) {
+  function calculateOffset(edge) {
     var edgeOffset = 0;
     var displacingElements = document.querySelectorAll('[data-offset-' + edge + ']');
     for (var i = 0, n = displacingElements.length; i < n; i++) {
@@ -94,7 +94,7 @@
       // but is not a valid number then get the displacement
       // dimensions directly from the element.
       if (isNaN(displacement)) {
-          displacement = getRawOffset(el, edge);
+        displacement = getRawOffset(el, edge);
       }
       // If the displacement value is larger than the current value for this
       // edge, use the displacement value.
@@ -117,7 +117,7 @@
    * @return {number}
    *   The viewport displacement distance for the requested edge.
    */
-  function getRawOffset (el, edge) {
+  function getRawOffset(el, edge) {
     var $el = $(el);
     var documentElement = document.documentElement;
     var displacement = 0;
diff --git a/core/misc/form.js b/core/misc/form.js
index 9bb9379..f752f31 100644
--- a/core/misc/form.js
+++ b/core/misc/form.js
@@ -1,213 +1,213 @@
 (function ($, Drupal, debounce) {
 
-"use strict";
-
-/**
- * Retrieves the summary for the first element.
- */
-$.fn.drupalGetSummary = function () {
-  var callback = this.data('summaryCallback');
-  return (this[0] && callback) ? $.trim(callback(this[0])) : '';
-};
-
-/**
- * Sets the summary for all matched elements.
- *
- * @param callback
- *   Either a function that will be called each time the summary is
- *   retrieved or a string (which is returned each time).
- */
-$.fn.drupalSetSummary = function (callback) {
-  var self = this;
-
-  // To facilitate things, the callback should always be a function. If it's
-  // not, we wrap it into an anonymous function which just returns the value.
-  if (typeof callback !== 'function') {
-    var val = callback;
-    callback = function () { return val; };
-  }
+  "use strict";
+
+  /**
+   * Retrieves the summary for the first element.
+   */
+  $.fn.drupalGetSummary = function () {
+    var callback = this.data('summaryCallback');
+    return (this[0] && callback) ? $.trim(callback(this[0])) : '';
+  };
+
+  /**
+   * Sets the summary for all matched elements.
+   *
+   * @param callback
+   *   Either a function that will be called each time the summary is
+   *   retrieved or a string (which is returned each time).
+   */
+  $.fn.drupalSetSummary = function (callback) {
+    var self = this;
+
+    // To facilitate things, the callback should always be a function. If it's
+    // not, we wrap it into an anonymous function which just returns the value.
+    if (typeof callback !== 'function') {
+      var val = callback;
+      callback = function () { return val; };
+    }
 
-  return this
-    .data('summaryCallback', callback)
-    // To prevent duplicate events, the handlers are first removed and then
-    // (re-)added.
-    .off('formUpdated.summary')
-    .on('formUpdated.summary', function () {
-      self.trigger('summaryUpdated');
-    })
-    // The actual summaryUpdated handler doesn't fire when the callback is
-    // changed, so we have to do this manually.
-    .trigger('summaryUpdated');
-};
-
-/**
- * Sends a 'formUpdated' event each time a form element is modified.
- */
-Drupal.behaviors.formUpdated = {
-  attach: function (context) {
-    // These events are namespaced so that we can remove them later.
-    var events = 'change.formUpdated click.formUpdated blur.formUpdated keyup.formUpdated';
-    $(context)
-      // Since context could be an input element itself, it's added back to
-      // the jQuery object and filtered again.
-      .find(':input').addBack().filter(':input')
+    return this
+      .data('summaryCallback', callback)
       // To prevent duplicate events, the handlers are first removed and then
       // (re-)added.
-      .off(events).on(events, function () {
-        $(this).trigger('formUpdated');
-      });
-  }
-};
-
-/**
- * Prevents consecutive form submissions of identical form values.
- *
- * Repetitive form submissions that would submit the identical form values are
- * prevented, unless the form values are different to the previously submitted
- * values.
- *
- * This is a simplified re-implementation of a user-agent behavior that should
- * be natively supported by major web browsers, but at this time, only Firefox
- * has a built-in protection.
- *
- * A form value-based approach ensures that the constraint is triggered for
- * consecutive, identical form submissions only. Compared to that, a form
- * button-based approach would (1) rely on [visible] buttons to exist where
- * technically not required and (2) require more complex state management if
- * there are multiple buttons in a form.
- *
- * This implementation is based on form-level submit events only and relies on
- * jQuery's serialize() method to determine submitted form values. As such, the
- * following limitations exist:
- *
- * - Event handlers on form buttons that preventDefault() do not receive a
- *   double-submit protection. That is deemed to be fine, since such button
- *   events typically trigger reversible client-side or server-side operations
- *   that are local to the context of a form only.
- * - Changed values in advanced form controls, such as file inputs, are not part
- *   of the form values being compared between consecutive form submits (due to
- *   limitations of jQuery.serialize()). That is deemed to be acceptable,
- *   because if the user forgot to attach a file, then the size of HTTP payload
- *   will most likely be small enough to be fully passed to the server endpoint
- *   within (milli)seconds. If a user mistakenly attached a wrong file and is
- *   technically versed enough to cancel the form submission (and HTTP payload)
- *   in order to attach a different file, then that edge-case is not supported
- *   here.
- *
- * Lastly, all forms submitted via HTTP GET are idempotent by definition of HTTP
- * standards, so excluded in this implementation.
- */
-Drupal.behaviors.formSingleSubmit = {
-  attach: function () {
-    function onFormSubmit (e) {
-      var $form = $(e.currentTarget);
-      var formValues = $form.serialize();
-      var previousValues = $form.attr('data-drupal-form-submit-last');
-      if (previousValues === formValues) {
-        e.preventDefault();
-      }
-      else {
-        $form.attr('data-drupal-form-submit-last', formValues);
+      .off('formUpdated.summary')
+      .on('formUpdated.summary', function () {
+        self.trigger('summaryUpdated');
+      })
+      // The actual summaryUpdated handler doesn't fire when the callback is
+      // changed, so we have to do this manually.
+      .trigger('summaryUpdated');
+  };
+
+  /**
+   * Sends a 'formUpdated' event each time a form element is modified.
+   */
+  Drupal.behaviors.formUpdated = {
+    attach: function (context) {
+      // These events are namespaced so that we can remove them later.
+      var events = 'change.formUpdated click.formUpdated blur.formUpdated keyup.formUpdated';
+      $(context)
+        // Since context could be an input element itself, it's added back to
+        // the jQuery object and filtered again.
+        .find(':input').addBack().filter(':input')
+        // To prevent duplicate events, the handlers are first removed and then
+        // (re-)added.
+        .off(events).on(events, function () {
+          $(this).trigger('formUpdated');
+        });
+    }
+  };
+
+  /**
+   * Prevents consecutive form submissions of identical form values.
+   *
+   * Repetitive form submissions that would submit the identical form values are
+   * prevented, unless the form values are different to the previously submitted
+   * values.
+   *
+   * This is a simplified re-implementation of a user-agent behavior that should
+   * be natively supported by major web browsers, but at this time, only Firefox
+   * has a built-in protection.
+   *
+   * A form value-based approach ensures that the constraint is triggered for
+   * consecutive, identical form submissions only. Compared to that, a form
+   * button-based approach would (1) rely on [visible] buttons to exist where
+   * technically not required and (2) require more complex state management if
+   * there are multiple buttons in a form.
+   *
+   * This implementation is based on form-level submit events only and relies on
+   * jQuery's serialize() method to determine submitted form values. As such, the
+   * following limitations exist:
+   *
+   * - Event handlers on form buttons that preventDefault() do not receive a
+   *   double-submit protection. That is deemed to be fine, since such button
+   *   events typically trigger reversible client-side or server-side operations
+   *   that are local to the context of a form only.
+   * - Changed values in advanced form controls, such as file inputs, are not part
+   *   of the form values being compared between consecutive form submits (due to
+   *   limitations of jQuery.serialize()). That is deemed to be acceptable,
+   *   because if the user forgot to attach a file, then the size of HTTP payload
+   *   will most likely be small enough to be fully passed to the server endpoint
+   *   within (milli)seconds. If a user mistakenly attached a wrong file and is
+   *   technically versed enough to cancel the form submission (and HTTP payload)
+   *   in order to attach a different file, then that edge-case is not supported
+   *   here.
+   *
+   * Lastly, all forms submitted via HTTP GET are idempotent by definition of HTTP
+   * standards, so excluded in this implementation.
+   */
+  Drupal.behaviors.formSingleSubmit = {
+    attach: function () {
+      function onFormSubmit(e) {
+        var $form = $(e.currentTarget);
+        var formValues = $form.serialize();
+        var previousValues = $form.attr('data-drupal-form-submit-last');
+        if (previousValues === formValues) {
+          e.preventDefault();
+        }
+        else {
+          $form.attr('data-drupal-form-submit-last', formValues);
+        }
       }
+
+      $('body').once('form-single-submit')
+        .on('submit.singleSubmit', 'form:not([method~="GET"])', onFormSubmit);
     }
+  };
 
-    $('body').once('form-single-submit')
-      .on('submit.singleSubmit', 'form:not([method~="GET"])', onFormSubmit);
+
+  /**
+   * Sends a 'formUpdated' event each time a form element is modified.
+   */
+  function triggerFormUpdated(element) {
+    $(element).trigger('formUpdated');
   }
-};
-
-
-/**
- * Sends a 'formUpdated' event each time a form element is modified.
- */
-function triggerFormUpdated (element) {
- $(element).trigger('formUpdated');
-}
-
-/**
- * Collects the IDs of all form fields in the given form.
- *
- * @param {HTMLFormElement} form
- * @return {Array}
- */
-function fieldsList (form) {
-  var $fieldList = $(form).find('[name]').map(function (index, element) {
-    // We use id to avoid name duplicates on radio fields and filter out
-    // elements with a name but no id.
-    return element.getAttribute('id');
-  });
-  // Return a true array.
-  return $.makeArray($fieldList);
-}
-
-/**
- * Triggers the 'formUpdated' event on form elements when they are modified.
- */
-Drupal.behaviors.formUpdated = {
- attach: function (context) {
-   var $context = $(context);
-   var contextIsForm = $context.is('form');
-   var $forms = (contextIsForm ? $context : $context.find('form')).once('form-updated');
-
-
-   if ($forms.length) {
-     // Initialize form behaviors, use $.makeArray to be able to use native
-     // forEach array method and have the callback parameters in the right order.
-     $.makeArray($forms).forEach(function (form) {
-       var events = 'change.formUpdated keypress.formUpdated';
-       var eventHandler = debounce(function (event) { triggerFormUpdated(event.target); }, 300);
-       var formFields = fieldsList(form).join(',');
-
-       form.setAttribute('data-drupal-form-fields', formFields);
-       $(form).on(events, eventHandler);
-     });
-   }
-   // On ajax requests context is the form element.
-   if (contextIsForm) {
-    var formFields = fieldsList(context).join(',');
-    // @todo replace with form.getAttribute() when #1979468 is in.
-    var currentFields = $(context).attr('data-drupal-form-fields');
-    // if there has been a change in the fields or their order, trigger
-    // formUpdated.
-    if (formFields !== currentFields) {
-      triggerFormUpdated(context);
-    }
+
+  /**
+   * Collects the IDs of all form fields in the given form.
+   *
+   * @param {HTMLFormElement} form
+   * @return {Array}
+   */
+  function fieldsList(form) {
+    var $fieldList = $(form).find('[name]').map(function (index, element) {
+      // We use id to avoid name duplicates on radio fields and filter out
+      // elements with a name but no id.
+      return element.getAttribute('id');
+    });
+    // Return a true array.
+    return $.makeArray($fieldList);
   }
 
- },
- detach: function (context, settings, trigger) {
-   var $context = $(context);
-   var contextIsForm = $context.is('form');
-   if (trigger === 'unload') {
-     var $forms = (contextIsForm ? $context : $context.find('form')).removeOnce('form-updated');
-     if ($forms.length) {
-       $.makeArray($forms).forEach(function (form) {
-         form.removeAttribute('data-drupal-form-fields');
-         $(form).off('.formUpdated');
-       });
-     }
-   }
- }
-};
-
-/**
- * Prepopulate form fields with information from the visitor cookie.
- */
-Drupal.behaviors.fillUserInfoFromCookie = {
-  attach: function (context, settings) {
-    var userInfo = ['name', 'mail', 'homepage'];
-    $('form.user-info-from-cookie').once('user-info-from-cookie', function () {
-      var $formContext = $(this);
-      var i, il, $element, cookie;
-      for (i = 0, il = userInfo.length; i < il; i += 1) {
-        $element = $formContext.find('[name=' + userInfo[i] + ']');
-        cookie = $.cookie('Drupal.visitor.' + userInfo[i]);
-        if ($element.length && cookie) {
-          $element.val(cookie);
+  /**
+   * Triggers the 'formUpdated' event on form elements when they are modified.
+   */
+  Drupal.behaviors.formUpdated = {
+    attach: function (context) {
+      var $context = $(context);
+      var contextIsForm = $context.is('form');
+      var $forms = (contextIsForm ? $context : $context.find('form')).once('form-updated');
+
+
+      if ($forms.length) {
+        // Initialize form behaviors, use $.makeArray to be able to use native
+        // forEach array method and have the callback parameters in the right order.
+        $.makeArray($forms).forEach(function (form) {
+          var events = 'change.formUpdated keypress.formUpdated';
+          var eventHandler = debounce(function (event) { triggerFormUpdated(event.target); }, 300);
+          var formFields = fieldsList(form).join(',');
+
+          form.setAttribute('data-drupal-form-fields', formFields);
+          $(form).on(events, eventHandler);
+        });
+      }
+      // On ajax requests context is the form element.
+      if (contextIsForm) {
+        var formFields = fieldsList(context).join(',');
+        // @todo replace with form.getAttribute() when #1979468 is in.
+        var currentFields = $(context).attr('data-drupal-form-fields');
+        // if there has been a change in the fields or their order, trigger
+        // formUpdated.
+        if (formFields !== currentFields) {
+          triggerFormUpdated(context);
         }
       }
-    });
-  }
-};
+
+    },
+    detach: function (context, settings, trigger) {
+      var $context = $(context);
+      var contextIsForm = $context.is('form');
+      if (trigger === 'unload') {
+        var $forms = (contextIsForm ? $context : $context.find('form')).removeOnce('form-updated');
+        if ($forms.length) {
+          $.makeArray($forms).forEach(function (form) {
+            form.removeAttribute('data-drupal-form-fields');
+            $(form).off('.formUpdated');
+          });
+        }
+      }
+    }
+  };
+
+  /**
+   * Prepopulate form fields with information from the visitor cookie.
+   */
+  Drupal.behaviors.fillUserInfoFromCookie = {
+    attach: function (context, settings) {
+      var userInfo = ['name', 'mail', 'homepage'];
+      $('form.user-info-from-cookie').once('user-info-from-cookie', function () {
+        var $formContext = $(this);
+        var i, il, $element, cookie;
+        for (i = 0, il = userInfo.length; i < il; i += 1) {
+          $element = $formContext.find('[name=' + userInfo[i] + ']');
+          cookie = $.cookie('Drupal.visitor.' + userInfo[i]);
+          if ($element.length && cookie) {
+            $element.val(cookie);
+          }
+        }
+      });
+    }
+  };
 
 })(jQuery, Drupal, Drupal.debounce);
diff --git a/core/misc/machine-name.js b/core/misc/machine-name.js
index f399e20..3a9fa03 100644
--- a/core/misc/machine-name.js
+++ b/core/misc/machine-name.js
@@ -1,171 +1,171 @@
 (function ($, Drupal, drupalSettings) {
 
-"use strict";
+  "use strict";
 
-/**
- * Attach the machine-readable name form element behavior.
- */
-Drupal.behaviors.machineName = {
   /**
-   * Attaches the behavior.
-   *
-   * @param settings.machineName
-   *   A list of elements to process, keyed by the HTML ID of the form element
-   *   containing the human-readable value. Each element is an object defining
-   *   the following properties:
-   *   - target: The HTML ID of the machine name form element.
-   *   - suffix: The HTML ID of a container to show the machine name preview in
-   *     (usually a field suffix after the human-readable name form element).
-   *   - label: The label to show for the machine name preview.
-   *   - replace_pattern: A regular expression (without modifiers) matching
-   *     disallowed characters in the machine name; e.g., '[^a-z0-9]+'.
-   *   - replace: A character to replace disallowed characters with; e.g., '_'
-   *     or '-'.
-   *   - standalone: Whether the preview should stay in its own element rather
-   *     than the suffix of the source element.
-   *   - field_prefix: The #field_prefix of the form element.
-   *   - field_suffix: The #field_suffix of the form element.
+   * Attach the machine-readable name form element behavior.
    */
-  attach: function (context, settings) {
-    var self = this;
-    var $context = $(context);
-    var source_id, options, machine, eventData;
+  Drupal.behaviors.machineName = {
+    /**
+     * Attaches the behavior.
+     *
+     * @param settings.machineName
+     *   A list of elements to process, keyed by the HTML ID of the form element
+     *   containing the human-readable value. Each element is an object defining
+     *   the following properties:
+     *   - target: The HTML ID of the machine name form element.
+     *   - suffix: The HTML ID of a container to show the machine name preview in
+     *     (usually a field suffix after the human-readable name form element).
+     *   - label: The label to show for the machine name preview.
+     *   - replace_pattern: A regular expression (without modifiers) matching
+     *     disallowed characters in the machine name; e.g., '[^a-z0-9]+'.
+     *   - replace: A character to replace disallowed characters with; e.g., '_'
+     *     or '-'.
+     *   - standalone: Whether the preview should stay in its own element rather
+     *     than the suffix of the source element.
+     *   - field_prefix: The #field_prefix of the form element.
+     *   - field_suffix: The #field_suffix of the form element.
+     */
+    attach: function (context, settings) {
+      var self = this;
+      var $context = $(context);
+      var source_id, options, machine, eventData;
 
-    function clickEditHandler(e) {
-      var data = e.data;
-      e.preventDefault();
-      data.$wrapper.show();
-      data.$target.trigger('focus');
-      data.$suffix.hide();
-      data.$source.off('.machineName');
-    }
-
-    function machineNameHandler(e) {
-      var data = e.data;
-      var settings = data.options;
-      var baseValue = $(e.target).val();
-
-      var rx = new RegExp(settings.replace_pattern, 'g');
-      var expected = baseValue.toLowerCase().replace(rx, settings.replace).substr(0, settings.maxlength);
-
-      if(baseValue.toLowerCase() !== expected) {
-        self.transliterate(baseValue, settings).done(function (machine) {
-          self.showMachineName(machine.substr(0, settings.maxlength), data);
-        });
-      }
-      else {
-        self.showMachineName(expected, data);
+      function clickEditHandler(e) {
+        var data = e.data;
+        e.preventDefault();
+        data.$wrapper.show();
+        data.$target.trigger('focus');
+        data.$suffix.hide();
+        data.$source.off('.machineName');
       }
-    }
 
-    for (source_id in settings.machineName) {
-      if (settings.machineName.hasOwnProperty(source_id)) {
-        options =  settings.machineName[source_id];
+      function machineNameHandler(e) {
+        var data = e.data;
+        var settings = data.options;
+        var baseValue = $(e.target).val();
 
-        var $source = $context.find(source_id).addClass('machine-name-source').once('machine-name');
-        var $target = $context.find(options.target).addClass('machine-name-target');
-        var $suffix = $context.find(options.suffix);
-        var $wrapper = $target.closest('.form-item');
-        // All elements have to exist.
-        if (!$source.length || !$target.length || !$suffix.length || !$wrapper.length) {
-          return;
-        }
-        // Skip processing upon a form validation error on the machine name.
-        if ($target.hasClass('error')) {
-          return;
-        }
-        // Figure out the maximum length for the machine name.
-        options.maxlength = $target.attr('maxlength');
-        // Hide the form item container of the machine name form element.
-        $wrapper.hide();
-        // Determine the initial machine name value. Unless the machine name form
-        // element is disabled or not empty, the initial default value is based on
-        // the human-readable form element value.
-        if ($target.is(':disabled') || $target.val() !== '') {
-          machine = $target.val();
+        var rx = new RegExp(settings.replace_pattern, 'g');
+        var expected = baseValue.toLowerCase().replace(rx, settings.replace).substr(0, settings.maxlength);
+
+        if (baseValue.toLowerCase() !== expected) {
+          self.transliterate(baseValue, settings).done(function (machine) {
+            self.showMachineName(machine.substr(0, settings.maxlength), data);
+          });
         }
         else {
-          machine = self.transliterate($source.val(), options);
-        }
-        // Append the machine name preview to the source field.
-        var $preview = $('<span class="machine-name-value">' + options.field_prefix + Drupal.checkPlain(machine) + options.field_suffix + '</span>');
-        $suffix.empty();
-        if (options.label) {
-          $suffix.append(' ').append('<span class="machine-name-label">' + options.label + ':</span>');
+          self.showMachineName(expected, data);
         }
-        $suffix.append(' ').append($preview);
+      }
 
-        // If the machine name cannot be edited, stop further processing.
-        if ($target.is(':disabled')) {
-          return;
-        }
+      for (source_id in settings.machineName) {
+        if (settings.machineName.hasOwnProperty(source_id)) {
+          options = settings.machineName[source_id];
+
+          var $source = $context.find(source_id).addClass('machine-name-source').once('machine-name');
+          var $target = $context.find(options.target).addClass('machine-name-target');
+          var $suffix = $context.find(options.suffix);
+          var $wrapper = $target.closest('.form-item');
+          // All elements have to exist.
+          if (!$source.length || !$target.length || !$suffix.length || !$wrapper.length) {
+            return;
+          }
+          // Skip processing upon a form validation error on the machine name.
+          if ($target.hasClass('error')) {
+            return;
+          }
+          // Figure out the maximum length for the machine name.
+          options.maxlength = $target.attr('maxlength');
+          // Hide the form item container of the machine name form element.
+          $wrapper.hide();
+          // Determine the initial machine name value. Unless the machine name form
+          // element is disabled or not empty, the initial default value is based on
+          // the human-readable form element value.
+          if ($target.is(':disabled') || $target.val() !== '') {
+            machine = $target.val();
+          }
+          else {
+            machine = self.transliterate($source.val(), options);
+          }
+          // Append the machine name preview to the source field.
+          var $preview = $('<span class="machine-name-value">' + options.field_prefix + Drupal.checkPlain(machine) + options.field_suffix + '</span>');
+          $suffix.empty();
+          if (options.label) {
+            $suffix.append(' ').append('<span class="machine-name-label">' + options.label + ':</span>');
+          }
+          $suffix.append(' ').append($preview);
 
-        eventData = {
-          $source: $source,
-          $target: $target,
-          $suffix: $suffix,
-          $wrapper: $wrapper,
-          $preview: $preview,
-          options: options
-        };
-        // If it is editable, append an edit link.
-        var $link = $('<span class="admin-link"><button type="button" class="link">' + Drupal.t('Edit') + '</button></span>').on('click', eventData, clickEditHandler);
-        $suffix.append(' ').append($link);
+          // If the machine name cannot be edited, stop further processing.
+          if ($target.is(':disabled')) {
+            return;
+          }
 
-        // Preview the machine name in realtime when the human-readable name
-        // changes, but only if there is no machine name yet; i.e., only upon
-        // initial creation, not when editing.
-        if ($target.val() === '') {
-          $source.on('keyup.machineName change.machineName input.machineName', eventData, machineNameHandler)
-          // Initialize machine name preview.
-          .trigger('keyup');
+          eventData = {
+            $source: $source,
+            $target: $target,
+            $suffix: $suffix,
+            $wrapper: $wrapper,
+            $preview: $preview,
+            options: options
+          };
+          // If it is editable, append an edit link.
+          var $link = $('<span class="admin-link"><button type="button" class="link">' + Drupal.t('Edit') + '</button></span>').on('click', eventData, clickEditHandler);
+          $suffix.append(' ').append($link);
+
+          // Preview the machine name in realtime when the human-readable name
+          // changes, but only if there is no machine name yet; i.e., only upon
+          // initial creation, not when editing.
+          if ($target.val() === '') {
+            $source.on('keyup.machineName change.machineName input.machineName', eventData, machineNameHandler)
+              // Initialize machine name preview.
+              .trigger('keyup');
+          }
         }
       }
-    }
-  },
+    },
 
-  showMachineName: function (machine, data) {
-    var settings = data.options;
-    // Set the machine name to the transliterated value.
-    if (machine !== '') {
-      if (machine !== settings.replace) {
+    showMachineName: function (machine, data) {
+      var settings = data.options;
+      // Set the machine name to the transliterated value.
+      if (machine !== '') {
+        if (machine !== settings.replace) {
+          data.$target.val(machine);
+          data.$preview.html(settings.field_prefix + Drupal.checkPlain(machine) + settings.field_suffix);
+        }
+        data.$suffix.show();
+      }
+      else {
+        data.$suffix.hide();
         data.$target.val(machine);
-        data.$preview.html(settings.field_prefix + Drupal.checkPlain(machine) + settings.field_suffix);
+        data.$preview.empty();
       }
-      data.$suffix.show();
-    }
-    else {
-      data.$suffix.hide();
-      data.$target.val(machine);
-      data.$preview.empty();
-    }
-  },
+    },
 
-  /**
-   * Transliterate a human-readable name to a machine name.
-   *
-   * @param source
-   *   A string to transliterate.
-   * @param settings
-   *   The machine name settings for the corresponding field, containing:
-   *   - replace_pattern: A regular expression (without modifiers) matching
-   *     disallowed characters in the machine name; e.g., '[^a-z0-9]+'.
-   *   - replace: A character to replace disallowed characters with; e.g., '_'
-   *     or '-'.
-   *   - maxlength: The maximum length of the machine name.
-   *
-   * @return
-   *   The transliterated source string.
-   */
-  transliterate: function (source, settings) {
-    return $.get(drupalSettings.path.basePath + 'machine_name/transliterate', {
-      text: source,
-      langcode: drupalSettings.langcode,
-      replace_pattern: settings.replace_pattern,
-      replace: settings.replace,
-      lowercase: true
-    });
-  }
-};
+    /**
+     * Transliterate a human-readable name to a machine name.
+     *
+     * @param source
+     *   A string to transliterate.
+     * @param settings
+     *   The machine name settings for the corresponding field, containing:
+     *   - replace_pattern: A regular expression (without modifiers) matching
+     *     disallowed characters in the machine name; e.g., '[^a-z0-9]+'.
+     *   - replace: A character to replace disallowed characters with; e.g., '_'
+     *     or '-'.
+     *   - maxlength: The maximum length of the machine name.
+     *
+     * @return
+     *   The transliterated source string.
+     */
+    transliterate: function (source, settings) {
+      return $.get(drupalSettings.path.basePath + 'machine_name/transliterate', {
+        text: source,
+        langcode: drupalSettings.langcode,
+        replace_pattern: settings.replace_pattern,
+        replace: settings.replace,
+        lowercase: true
+      });
+    }
+  };
 
 })(jQuery, Drupal, drupalSettings);
diff --git a/core/misc/matchmedia.js b/core/misc/matchmedia.js
index a26723a..4d23bae 100644
--- a/core/misc/matchmedia.js
+++ b/core/misc/matchmedia.js
@@ -33,7 +33,7 @@ window.matchMedia = window.matchMedia || (function (doc, window, Drupal) {
    * @param {String} q
    *   A media query e.g. "screen" or "screen and (min-width: 28em)".
    */
-  function MediaQueryList (q) {
+  function MediaQueryList(q) {
     this.media = q;
     this.matches = false;
     this.check.call(this);
diff --git a/core/misc/progress.js b/core/misc/progress.js
index e3e000f..e54c26d 100644
--- a/core/misc/progress.js
+++ b/core/misc/progress.js
@@ -1,113 +1,113 @@
 (function ($) {
 
-"use strict";
+  "use strict";
 
-/**
- * A progressbar object. Initialized with the given id. Must be inserted into
- * the DOM afterwards through progressBar.element.
- *
- * method is the function which will perform the HTTP request to get the
- * progress bar state. Either "GET" or "POST".
- *
- * e.g. pb = new Drupal.ProgressBar('myProgressBar');
- *      some_element.appendChild(pb.element);
- */
-Drupal.ProgressBar = function (id, updateCallback, method, errorCallback) {
-  this.id = id;
-  this.method = method || 'GET';
-  this.updateCallback = updateCallback;
-  this.errorCallback = errorCallback;
-
-  // The WAI-ARIA setting aria-live="polite" will announce changes after users
-  // have completed their current activity and not interrupt the screen reader.
-  this.element = $('<div class="progress" aria-live="polite"></div>').attr('id', id);
-  this.element.html('<div class="progress__label">&nbsp;</div>' +
-                    '<div class="progress__track"><div class="progress__bar"></div></div>' +
-                    '<div class="progress__percentage"></div>' +
-                    '<div class="progress__description">&nbsp;</div>');
-};
-
-$.extend(Drupal.ProgressBar.prototype, {
   /**
-   * Set the percentage and status message for the progressbar.
+   * A progressbar object. Initialized with the given id. Must be inserted into
+   * the DOM afterwards through progressBar.element.
+   *
+   * method is the function which will perform the HTTP request to get the
+   * progress bar state. Either "GET" or "POST".
+   *
+   * e.g. pb = new Drupal.ProgressBar('myProgressBar');
+   *      some_element.appendChild(pb.element);
    */
-  setProgress: function (percentage, message, label) {
-    if (percentage >= 0 && percentage <= 100) {
-      $(this.element).find('div.progress__bar').css('width', percentage + '%');
-      $(this.element).find('div.progress__percentage').html(percentage + '%');
-    }
-    $('div.progress__description', this.element).html(message);
-    $('div.progress__label', this.element).html(label);
-    if (this.updateCallback) {
-      this.updateCallback(percentage, message, this);
-    }
-  },
+  Drupal.ProgressBar = function (id, updateCallback, method, errorCallback) {
+    this.id = id;
+    this.method = method || 'GET';
+    this.updateCallback = updateCallback;
+    this.errorCallback = errorCallback;
 
-  /**
-   * Start monitoring progress via Ajax.
-   */
-  startMonitoring: function (uri, delay) {
-    this.delay = delay;
-    this.uri = uri;
-    this.sendPing();
-  },
+    // The WAI-ARIA setting aria-live="polite" will announce changes after users
+    // have completed their current activity and not interrupt the screen reader.
+    this.element = $('<div class="progress" aria-live="polite"></div>').attr('id', id);
+    this.element.html('<div class="progress__label">&nbsp;</div>' +
+      '<div class="progress__track"><div class="progress__bar"></div></div>' +
+      '<div class="progress__percentage"></div>' +
+      '<div class="progress__description">&nbsp;</div>');
+  };
 
-  /**
-   * Stop monitoring progress via Ajax.
-   */
-  stopMonitoring: function () {
-    clearTimeout(this.timer);
-    // This allows monitoring to be stopped from within the callback.
-    this.uri = null;
-  },
+  $.extend(Drupal.ProgressBar.prototype, {
+    /**
+     * Set the percentage and status message for the progressbar.
+     */
+    setProgress: function (percentage, message, label) {
+      if (percentage >= 0 && percentage <= 100) {
+        $(this.element).find('div.progress__bar').css('width', percentage + '%');
+        $(this.element).find('div.progress__percentage').html(percentage + '%');
+      }
+      $('div.progress__description', this.element).html(message);
+      $('div.progress__label', this.element).html(label);
+      if (this.updateCallback) {
+        this.updateCallback(percentage, message, this);
+      }
+    },
 
-  /**
-   * Request progress data from server.
-   */
-  sendPing: function () {
-    if (this.timer) {
+    /**
+     * Start monitoring progress via Ajax.
+     */
+    startMonitoring: function (uri, delay) {
+      this.delay = delay;
+      this.uri = uri;
+      this.sendPing();
+    },
+
+    /**
+     * Stop monitoring progress via Ajax.
+     */
+    stopMonitoring: function () {
       clearTimeout(this.timer);
-    }
-    if (this.uri) {
-      var pb = this;
-      // When doing a post request, you need non-null data. Otherwise a
-      // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
-      $.ajax({
-        type: this.method,
-        url: this.uri,
-        data: '',
-        dataType: 'json',
-        success: function (progress) {
-          // Display errors.
-          if (progress.status === 0) {
-            pb.displayError(progress.data);
-            return;
+      // This allows monitoring to be stopped from within the callback.
+      this.uri = null;
+    },
+
+    /**
+     * Request progress data from server.
+     */
+    sendPing: function () {
+      if (this.timer) {
+        clearTimeout(this.timer);
+      }
+      if (this.uri) {
+        var pb = this;
+        // When doing a post request, you need non-null data. Otherwise a
+        // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
+        $.ajax({
+          type: this.method,
+          url: this.uri,
+          data: '',
+          dataType: 'json',
+          success: function (progress) {
+            // Display errors.
+            if (progress.status === 0) {
+              pb.displayError(progress.data);
+              return;
+            }
+            // Update display.
+            pb.setProgress(progress.percentage, progress.message, progress.label);
+            // Schedule next timer.
+            pb.timer = setTimeout(function () { pb.sendPing(); }, pb.delay);
+          },
+          error: function (xmlhttp) {
+            var e = new Drupal.AjaxError(xmlhttp, pb.uri);
+            pb.displayError('<pre>' + e.message + '</pre>');
           }
-          // Update display.
-          pb.setProgress(progress.percentage, progress.message, progress.label);
-          // Schedule next timer.
-          pb.timer = setTimeout(function () { pb.sendPing(); }, pb.delay);
-        },
-        error: function (xmlhttp) {
-          var e = new Drupal.AjaxError(xmlhttp, pb.uri);
-          pb.displayError('<pre>' + e.message + '</pre>');
-        }
-      });
-    }
-  },
+        });
+      }
+    },
 
-  /**
-   * Display errors on the page.
-   */
-  displayError: function (string) {
-    var error = $('<div class="messages messages--error"></div>').html(string);
-    $(this.element).before(error).hide();
+    /**
+     * Display errors on the page.
+     */
+    displayError: function (string) {
+      var error = $('<div class="messages messages--error"></div>').html(string);
+      $(this.element).before(error).hide();
 
-    if (this.errorCallback) {
-      this.errorCallback(this);
+      if (this.errorCallback) {
+        this.errorCallback(this);
+      }
     }
-  }
-});
+  });
 
 
 })(jQuery);
diff --git a/core/misc/states.js b/core/misc/states.js
index 206d521..8b640e8 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -1,579 +1,579 @@
 (function ($) {
 
-"use strict";
-
-/**
- * The base States namespace.
- *
- * Having the local states variable allows us to use the States namespace
- * without having to always declare "Drupal.states".
- */
-var states = Drupal.states = {
-  // An array of functions that should be postponed.
-  postponed: []
-};
-
-/**
- * Attaches the states.
- */
-Drupal.behaviors.states = {
-  attach: function (context, settings) {
-    var $states = $(context).find('[data-drupal-states]');
-    var config, state;
-    for (var i = 0, il = $states.length; i < il; i += 1) {
-      config = JSON.parse($states[i].getAttribute('data-drupal-states'));
-      for (state in config) {
-        if (config.hasOwnProperty(state)) {
-          new states.Dependent({
-            element: $($states[i]),
-            state: states.State.sanitize(state),
-            constraints: config[state]
-          });
+  "use strict";
+
+  /**
+   * The base States namespace.
+   *
+   * Having the local states variable allows us to use the States namespace
+   * without having to always declare "Drupal.states".
+   */
+  var states = Drupal.states = {
+    // An array of functions that should be postponed.
+    postponed: []
+  };
+
+  /**
+   * Attaches the states.
+   */
+  Drupal.behaviors.states = {
+    attach: function (context, settings) {
+      var $states = $(context).find('[data-drupal-states]');
+      var config, state;
+      for (var i = 0, il = $states.length; i < il; i += 1) {
+        config = JSON.parse($states[i].getAttribute('data-drupal-states'));
+        for (state in config) {
+          if (config.hasOwnProperty(state)) {
+            new states.Dependent({
+              element: $($states[i]),
+              state: states.State.sanitize(state),
+              constraints: config[state]
+            });
+          }
         }
       }
-    }
 
-    // Execute all postponed functions now.
-    while (states.postponed.length) {
-      (states.postponed.shift())();
-    }
-  }
-};
-
-/**
- * Object representing an element that depends on other elements.
- *
- * @param args
- *   Object with the following keys (all of which are required):
- *   - element: A jQuery object of the dependent element
- *   - state: A State object describing the state that is dependent
- *   - constraints: An object with dependency specifications. Lists all elements
- *     that this element depends on. It can be nested and can contain arbitrary
- *     AND and OR clauses.
- */
-states.Dependent = function (args) {
-  $.extend(this, { values: {}, oldValue: null }, args);
-
-  this.dependees = this.getDependees();
-  for (var selector in this.dependees) {
-    if (this.dependees.hasOwnProperty(selector)) {
-      this.initializeDependee(selector, this.dependees[selector]);
+      // Execute all postponed functions now.
+      while (states.postponed.length) {
+        (states.postponed.shift())();
+      }
     }
-  }
-};
-
-/**
- * Comparison functions for comparing the value of an element with the
- * specification from the dependency settings. If the object type can't be
- * found in this list, the === operator is used by default.
- */
-states.Dependent.comparisons = {
-  'RegExp': function (reference, value) {
-    return reference.test(value);
-  },
-  'Function': function (reference, value) {
-    // The "reference" variable is a comparison function.
-    return reference(value);
-  },
-  'Number': function (reference, value) {
-    // If "reference" is a number and "value" is a string, then cast reference
-    // as a string before applying the strict comparison in compare(). Otherwise
-    // numeric keys in the form's #states array fail to match string values
-    // returned from jQuery's val().
-    return (typeof value === 'string') ? compare(reference.toString(), value) : compare(reference, value);
-  }
-};
+  };
 
-states.Dependent.prototype = {
   /**
-   * Initializes one of the elements this dependent depends on.
+   * Object representing an element that depends on other elements.
    *
-   * @param selector
-   *   The CSS selector describing the dependee.
-   * @param dependeeStates
-   *   The list of states that have to be monitored for tracking the
-   *   dependee's compliance status.
+   * @param args
+   *   Object with the following keys (all of which are required):
+   *   - element: A jQuery object of the dependent element
+   *   - state: A State object describing the state that is dependent
+   *   - constraints: An object with dependency specifications. Lists all elements
+   *     that this element depends on. It can be nested and can contain arbitrary
+   *     AND and OR clauses.
    */
-  initializeDependee: function (selector, dependeeStates) {
-    var state, self = this;
+  states.Dependent = function (args) {
+    $.extend(this, { values: {}, oldValue: null }, args);
 
-    function stateEventHandler(e) {
-      self.update(e.data.selector, e.data.state, e.value);
+    this.dependees = this.getDependees();
+    for (var selector in this.dependees) {
+      if (this.dependees.hasOwnProperty(selector)) {
+        this.initializeDependee(selector, this.dependees[selector]);
+      }
     }
+  };
 
-    // Cache for the states of this dependee.
-    this.values[selector] = {};
+  /**
+   * Comparison functions for comparing the value of an element with the
+   * specification from the dependency settings. If the object type can't be
+   * found in this list, the === operator is used by default.
+   */
+  states.Dependent.comparisons = {
+    'RegExp': function (reference, value) {
+      return reference.test(value);
+    },
+    'Function': function (reference, value) {
+      // The "reference" variable is a comparison function.
+      return reference(value);
+    },
+    'Number': function (reference, value) {
+      // If "reference" is a number and "value" is a string, then cast reference
+      // as a string before applying the strict comparison in compare(). Otherwise
+      // numeric keys in the form's #states array fail to match string values
+      // returned from jQuery's val().
+      return (typeof value === 'string') ? compare(reference.toString(), value) : compare(reference, value);
+    }
+  };
+
+  states.Dependent.prototype = {
+    /**
+     * Initializes one of the elements this dependent depends on.
+     *
+     * @param selector
+     *   The CSS selector describing the dependee.
+     * @param dependeeStates
+     *   The list of states that have to be monitored for tracking the
+     *   dependee's compliance status.
+     */
+    initializeDependee: function (selector, dependeeStates) {
+      var state, self = this;
+
+      function stateEventHandler(e) {
+        self.update(e.data.selector, e.data.state, e.value);
+      }
 
-    for (var i in dependeeStates) {
-      if (dependeeStates.hasOwnProperty(i)) {
-        state = dependeeStates[i];
-        // Make sure we're not initializing this selector/state combination twice.
-        if ($.inArray(state, dependeeStates) === -1) {
-          continue;
-        }
+      // Cache for the states of this dependee.
+      this.values[selector] = {};
 
-        state = states.State.sanitize(state);
+      for (var i in dependeeStates) {
+        if (dependeeStates.hasOwnProperty(i)) {
+          state = dependeeStates[i];
+          // Make sure we're not initializing this selector/state combination twice.
+          if ($.inArray(state, dependeeStates) === -1) {
+            continue;
+          }
+
+          state = states.State.sanitize(state);
 
-        // Initialize the value of this state.
-        this.values[selector][state.name] = null;
+          // Initialize the value of this state.
+          this.values[selector][state.name] = null;
 
-        // Monitor state changes of the specified state for this dependee.
-        $(selector).on('state:' + state, {selector: selector, state: state}, stateEventHandler);
+          // Monitor state changes of the specified state for this dependee.
+          $(selector).on('state:' + state, {selector: selector, state: state}, stateEventHandler);
 
-        // Make sure the event we just bound ourselves to is actually fired.
-        new states.Trigger({ selector: selector, state: state });
+          // Make sure the event we just bound ourselves to is actually fired.
+          new states.Trigger({ selector: selector, state: state });
+        }
       }
-    }
-  },
+    },
 
-  /**
-   * Compares a value with a reference value.
-   *
-   * @param reference
-   *   The value used for reference.
-   * @param selector
-   *   CSS selector describing the dependee.
-   * @param state
-   *   A State object describing the dependee's updated state.
-   *
-   * @return
-   *   true or false.
-   */
-  compare: function (reference, selector, state) {
-    var value = this.values[selector][state.name];
-    if (reference.constructor.name in states.Dependent.comparisons) {
-      // Use a custom compare function for certain reference value types.
-      return states.Dependent.comparisons[reference.constructor.name](reference, value);
-    }
-    else {
-      // Do a plain comparison otherwise.
-      return compare(reference, value);
-    }
-  },
+    /**
+     * Compares a value with a reference value.
+     *
+     * @param reference
+     *   The value used for reference.
+     * @param selector
+     *   CSS selector describing the dependee.
+     * @param state
+     *   A State object describing the dependee's updated state.
+     *
+     * @return
+     *   true or false.
+     */
+    compare: function (reference, selector, state) {
+      var value = this.values[selector][state.name];
+      if (reference.constructor.name in states.Dependent.comparisons) {
+        // Use a custom compare function for certain reference value types.
+        return states.Dependent.comparisons[reference.constructor.name](reference, value);
+      }
+      else {
+        // Do a plain comparison otherwise.
+        return compare(reference, value);
+      }
+    },
 
-  /**
-   * Update the value of a dependee's state.
-   *
-   * @param selector
-   *   CSS selector describing the dependee.
-   * @param state
-   *   A State object describing the dependee's updated state.
-   * @param value
-   *   The new value for the dependee's updated state.
-   */
-  update: function (selector, state, value) {
-    // Only act when the 'new' value is actually new.
-    if (value !== this.values[selector][state.name]) {
-      this.values[selector][state.name] = value;
-      this.reevaluate();
-    }
-  },
+    /**
+     * Update the value of a dependee's state.
+     *
+     * @param selector
+     *   CSS selector describing the dependee.
+     * @param state
+     *   A State object describing the dependee's updated state.
+     * @param value
+     *   The new value for the dependee's updated state.
+     */
+    update: function (selector, state, value) {
+      // Only act when the 'new' value is actually new.
+      if (value !== this.values[selector][state.name]) {
+        this.values[selector][state.name] = value;
+        this.reevaluate();
+      }
+    },
 
-  /**
-   * Triggers change events in case a state changed.
-   */
-  reevaluate: function () {
-    // Check whether any constraint for this dependent state is satisifed.
-    var value = this.verifyConstraints(this.constraints);
-
-    // Only invoke a state change event when the value actually changed.
-    if (value !== this.oldValue) {
-      // Store the new value so that we can compare later whether the value
-      // actually changed.
-      this.oldValue = value;
-
-      // Normalize the value to match the normalized state name.
-      value = invert(value, this.state.invert);
-
-      // By adding "trigger: true", we ensure that state changes don't go into
-      // infinite loops.
-      this.element.trigger({ type: 'state:' + this.state, value: value, trigger: true });
-    }
-  },
+    /**
+     * Triggers change events in case a state changed.
+     */
+    reevaluate: function () {
+      // Check whether any constraint for this dependent state is satisifed.
+      var value = this.verifyConstraints(this.constraints);
+
+      // Only invoke a state change event when the value actually changed.
+      if (value !== this.oldValue) {
+        // Store the new value so that we can compare later whether the value
+        // actually changed.
+        this.oldValue = value;
+
+        // Normalize the value to match the normalized state name.
+        value = invert(value, this.state.invert);
+
+        // By adding "trigger: true", we ensure that state changes don't go into
+        // infinite loops.
+        this.element.trigger({ type: 'state:' + this.state, value: value, trigger: true });
+      }
+    },
 
-  /**
-   * Evaluates child constraints to determine if a constraint is satisfied.
-   *
-   * @param constraints
-   *   A constraint object or an array of constraints.
-   * @param selector
-   *   The selector for these constraints. If undefined, there isn't yet a
-   *   selector that these constraints apply to. In that case, the keys of the
-   *   object are interpreted as the selector if encountered.
-   *
-   * @return
-   *   true or false, depending on whether these constraints are satisfied.
-   */
-  verifyConstraints: function(constraints, selector) {
-    var result;
-    if ($.isArray(constraints)) {
-      // This constraint is an array (OR or XOR).
-      var hasXor = $.inArray('xor', constraints) === -1;
-      for (var i = 0, len = constraints.length; i < len; i++) {
-        if (constraints[i] !== 'xor') {
-          var constraint = this.checkConstraints(constraints[i], selector, i);
-          // Return if this is OR and we have a satisfied constraint or if this
-          // is XOR and we have a second satisfied constraint.
-          if (constraint && (hasXor || result)) {
-            return hasXor;
+    /**
+     * Evaluates child constraints to determine if a constraint is satisfied.
+     *
+     * @param constraints
+     *   A constraint object or an array of constraints.
+     * @param selector
+     *   The selector for these constraints. If undefined, there isn't yet a
+     *   selector that these constraints apply to. In that case, the keys of the
+     *   object are interpreted as the selector if encountered.
+     *
+     * @return
+     *   true or false, depending on whether these constraints are satisfied.
+     */
+    verifyConstraints: function (constraints, selector) {
+      var result;
+      if ($.isArray(constraints)) {
+        // This constraint is an array (OR or XOR).
+        var hasXor = $.inArray('xor', constraints) === -1;
+        for (var i = 0, len = constraints.length; i < len; i++) {
+          if (constraints[i] !== 'xor') {
+            var constraint = this.checkConstraints(constraints[i], selector, i);
+            // Return if this is OR and we have a satisfied constraint or if this
+            // is XOR and we have a second satisfied constraint.
+            if (constraint && (hasXor || result)) {
+              return hasXor;
+            }
+            result = result || constraint;
           }
-          result = result || constraint;
         }
       }
-    }
-    // Make sure we don't try to iterate over things other than objects. This
-    // shouldn't normally occur, but in case the condition definition is bogus,
-    // we don't want to end up with an infinite loop.
-    else if ($.isPlainObject(constraints)) {
-      // This constraint is an object (AND).
-      for (var n in constraints) {
-        if (constraints.hasOwnProperty(n)) {
-          result = ternary(result, this.checkConstraints(constraints[n], selector, n));
-          // False and anything else will evaluate to false, so return when any
-          // false condition is found.
-          if (result === false) { return false; }
+      // Make sure we don't try to iterate over things other than objects. This
+      // shouldn't normally occur, but in case the condition definition is bogus,
+      // we don't want to end up with an infinite loop.
+      else if ($.isPlainObject(constraints)) {
+        // This constraint is an object (AND).
+        for (var n in constraints) {
+          if (constraints.hasOwnProperty(n)) {
+            result = ternary(result, this.checkConstraints(constraints[n], selector, n));
+            // False and anything else will evaluate to false, so return when any
+            // false condition is found.
+            if (result === false) { return false; }
+          }
         }
       }
-    }
-    return result;
-  },
+      return result;
+    },
 
-  /**
-   * Checks whether the value matches the requirements for this constraint.
-   *
-   * @param value
-   *   Either the value of a state or an array/object of constraints. In the
-   *   latter case, resolving the constraint continues.
-   * @param selector
-   *   The selector for this constraint. If undefined, there isn't yet a
-   *   selector that this constraint applies to. In that case, the state key is
-   *   propagates to a selector and resolving continues.
-   * @param state
-   *   The state to check for this constraint. If undefined, resolving
-   *   continues.
-   *   If both selector and state aren't undefined and valid non-numeric
-   *   strings, a lookup for the actual value of that selector's state is
-   *   performed. This parameter is not a State object but a pristine state
-   *   string.
-   *
-   * @return
-   *   true or false, depending on whether this constraint is satisfied.
-   */
-  checkConstraints: function(value, selector, state) {
-    // Normalize the last parameter. If it's non-numeric, we treat it either as
-    // a selector (in case there isn't one yet) or as a trigger/state.
-    if (typeof state !== 'string' || (/[0-9]/).test(state[0])) {
-      state = null;
-    }
-    else if (typeof selector === 'undefined') {
-      // Propagate the state to the selector when there isn't one yet.
-      selector = state;
-      state = null;
-    }
+    /**
+     * Checks whether the value matches the requirements for this constraint.
+     *
+     * @param value
+     *   Either the value of a state or an array/object of constraints. In the
+     *   latter case, resolving the constraint continues.
+     * @param selector
+     *   The selector for this constraint. If undefined, there isn't yet a
+     *   selector that this constraint applies to. In that case, the state key is
+     *   propagates to a selector and resolving continues.
+     * @param state
+     *   The state to check for this constraint. If undefined, resolving
+     *   continues.
+     *   If both selector and state aren't undefined and valid non-numeric
+     *   strings, a lookup for the actual value of that selector's state is
+     *   performed. This parameter is not a State object but a pristine state
+     *   string.
+     *
+     * @return
+     *   true or false, depending on whether this constraint is satisfied.
+     */
+    checkConstraints: function (value, selector, state) {
+      // Normalize the last parameter. If it's non-numeric, we treat it either as
+      // a selector (in case there isn't one yet) or as a trigger/state.
+      if (typeof state !== 'string' || (/[0-9]/).test(state[0])) {
+        state = null;
+      }
+      else if (typeof selector === 'undefined') {
+        // Propagate the state to the selector when there isn't one yet.
+        selector = state;
+        state = null;
+      }
 
-    if (state !== null) {
-      // constraints is the actual constraints of an element to check for.
-      state = states.State.sanitize(state);
-      return invert(this.compare(value, selector, state), state.invert);
-    }
-    else {
-      // Resolve this constraint as an AND/OR operator.
-      return this.verifyConstraints(value, selector);
-    }
-  },
+      if (state !== null) {
+        // constraints is the actual constraints of an element to check for.
+        state = states.State.sanitize(state);
+        return invert(this.compare(value, selector, state), state.invert);
+      }
+      else {
+        // Resolve this constraint as an AND/OR operator.
+        return this.verifyConstraints(value, selector);
+      }
+    },
 
-  /**
-   * Gathers information about all required triggers.
-   */
-  getDependees: function() {
-    var cache = {};
-    // Swivel the lookup function so that we can record all available selector-
-    // state combinations for initialization.
-    var _compare = this.compare;
-    this.compare = function(reference, selector, state) {
-      (cache[selector] || (cache[selector] = [])).push(state.name);
-      // Return nothing (=== undefined) so that the constraint loops are not
-      // broken.
-    };
-
-    // This call doesn't actually verify anything but uses the resolving
-    // mechanism to go through the constraints array, trying to look up each
-    // value. Since we swivelled the compare function, this comparison returns
-    // undefined and lookup continues until the very end. Instead of lookup up
-    // the value, we record that combination of selector and state so that we
-    // can initialize all triggers.
-    this.verifyConstraints(this.constraints);
-    // Restore the original function.
-    this.compare = _compare;
-
-    return cache;
-  }
-};
+    /**
+     * Gathers information about all required triggers.
+     */
+    getDependees: function () {
+      var cache = {};
+      // Swivel the lookup function so that we can record all available selector-
+      // state combinations for initialization.
+      var _compare = this.compare;
+      this.compare = function (reference, selector, state) {
+        (cache[selector] || (cache[selector] = [])).push(state.name);
+        // Return nothing (=== undefined) so that the constraint loops are not
+        // broken.
+      };
+
+      // This call doesn't actually verify anything but uses the resolving
+      // mechanism to go through the constraints array, trying to look up each
+      // value. Since we swivelled the compare function, this comparison returns
+      // undefined and lookup continues until the very end. Instead of lookup up
+      // the value, we record that combination of selector and state so that we
+      // can initialize all triggers.
+      this.verifyConstraints(this.constraints);
+      // Restore the original function.
+      this.compare = _compare;
+
+      return cache;
+    }
+  };
 
-states.Trigger = function (args) {
-  $.extend(this, args);
+  states.Trigger = function (args) {
+    $.extend(this, args);
 
-  if (this.state in states.Trigger.states) {
-    this.element = $(this.selector);
+    if (this.state in states.Trigger.states) {
+      this.element = $(this.selector);
 
-    // Only call the trigger initializer when it wasn't yet attached to this
-    // element. Otherwise we'd end up with duplicate events.
-    if (!this.element.data('trigger:' + this.state)) {
-      this.initialize();
+      // Only call the trigger initializer when it wasn't yet attached to this
+      // element. Otherwise we'd end up with duplicate events.
+      if (!this.element.data('trigger:' + this.state)) {
+        this.initialize();
+      }
     }
-  }
-};
+  };
 
-states.Trigger.prototype = {
-  initialize: function () {
-    var trigger = states.Trigger.states[this.state];
+  states.Trigger.prototype = {
+    initialize: function () {
+      var trigger = states.Trigger.states[this.state];
 
-    if (typeof trigger === 'function') {
-      // We have a custom trigger initialization function.
-      trigger.call(window, this.element);
-    }
-    else {
-      for (var event in trigger) {
-        if (trigger.hasOwnProperty(event)) {
-          this.defaultTrigger(event, trigger[event]);
+      if (typeof trigger === 'function') {
+        // We have a custom trigger initialization function.
+        trigger.call(window, this.element);
+      }
+      else {
+        for (var event in trigger) {
+          if (trigger.hasOwnProperty(event)) {
+            this.defaultTrigger(event, trigger[event]);
+          }
         }
       }
-    }
 
-    // Mark this trigger as initialized for this element.
-    this.element.data('trigger:' + this.state, true);
-  },
+      // Mark this trigger as initialized for this element.
+      this.element.data('trigger:' + this.state, true);
+    },
 
-  defaultTrigger: function (event, valueFn) {
-    var oldValue = valueFn.call(this.element);
+    defaultTrigger: function (event, valueFn) {
+      var oldValue = valueFn.call(this.element);
 
-    // Attach the event callback.
-    this.element.on(event, $.proxy(function (e) {
-      var value = valueFn.call(this.element, e);
-      // Only trigger the event if the value has actually changed.
-      if (oldValue !== value) {
-        this.element.trigger({ type: 'state:' + this.state, value: value, oldValue: oldValue });
-        oldValue = value;
-      }
-    }, this));
+      // Attach the event callback.
+      this.element.on(event, $.proxy(function (e) {
+        var value = valueFn.call(this.element, e);
+        // Only trigger the event if the value has actually changed.
+        if (oldValue !== value) {
+          this.element.trigger({ type: 'state:' + this.state, value: value, oldValue: oldValue });
+          oldValue = value;
+        }
+      }, this));
 
-    states.postponed.push($.proxy(function () {
-      // Trigger the event once for initialization purposes.
-      this.element.trigger({ type: 'state:' + this.state, value: oldValue, oldValue: null });
-    }, this));
-  }
-};
-
-/**
- * This list of states contains functions that are used to monitor the state
- * of an element. Whenever an element depends on the state of another element,
- * one of these trigger functions is added to the dependee so that the
- * dependent element can be updated.
- */
-states.Trigger.states = {
-  // 'empty' describes the state to be monitored
-  empty: {
-    // 'keyup' is the (native DOM) event that we watch for.
-    'keyup': function () {
-      // The function associated to that trigger returns the new value for the
-      // state.
-      return this.val() === '';
-    }
-  },
-
-  checked: {
-    'change': function () {
-      // prop() and attr() only takes the first element into account. To support
-      // selectors matching multiple checkboxes, iterate over all and return
-      // whether any is checked.
-      var checked = false;
-      this.each(function () {
-        // Use prop() here as we want a boolean of the checkbox state.
-        // @see http://api.jquery.com/prop/
-        checked = $(this).prop('checked');
-        // Break the each() loop if this is checked.
-        return !checked;
-      });
-      return checked;
+      states.postponed.push($.proxy(function () {
+        // Trigger the event once for initialization purposes.
+        this.element.trigger({ type: 'state:' + this.state, value: oldValue, oldValue: null });
+      }, this));
     }
-  },
-
-  // For radio buttons, only return the value if the radio button is selected.
-  value: {
-    'keyup': function () {
-      // Radio buttons share the same :input[name="key"] selector.
-      if (this.length > 1) {
-        // Initial checked value of radios is undefined, so we return false.
-        return this.filter(':checked').val() || false;
+  };
+
+  /**
+   * This list of states contains functions that are used to monitor the state
+   * of an element. Whenever an element depends on the state of another element,
+   * one of these trigger functions is added to the dependee so that the
+   * dependent element can be updated.
+   */
+  states.Trigger.states = {
+    // 'empty' describes the state to be monitored
+    empty: {
+      // 'keyup' is the (native DOM) event that we watch for.
+      'keyup': function () {
+        // The function associated to that trigger returns the new value for the
+        // state.
+        return this.val() === '';
       }
-      return this.val();
     },
-    'change': function () {
-      // Radio buttons share the same :input[name="key"] selector.
-      if (this.length > 1) {
-        // Initial checked value of radios is undefined, so we return false.
-        return this.filter(':checked').val() || false;
+
+    checked: {
+      'change': function () {
+        // prop() and attr() only takes the first element into account. To support
+        // selectors matching multiple checkboxes, iterate over all and return
+        // whether any is checked.
+        var checked = false;
+        this.each(function () {
+          // Use prop() here as we want a boolean of the checkbox state.
+          // @see http://api.jquery.com/prop/
+          checked = $(this).prop('checked');
+          // Break the each() loop if this is checked.
+          return !checked;
+        });
+        return checked;
       }
-      return this.val();
-    }
-  },
+    },
 
-  collapsed: {
-    'collapsed': function(e) {
-      return (typeof e !== 'undefined' && 'value' in e) ? e.value : !this.is('[open]');
+    // For radio buttons, only return the value if the radio button is selected.
+    value: {
+      'keyup': function () {
+        // Radio buttons share the same :input[name="key"] selector.
+        if (this.length > 1) {
+          // Initial checked value of radios is undefined, so we return false.
+          return this.filter(':checked').val() || false;
+        }
+        return this.val();
+      },
+      'change': function () {
+        // Radio buttons share the same :input[name="key"] selector.
+        if (this.length > 1) {
+          // Initial checked value of radios is undefined, so we return false.
+          return this.filter(':checked').val() || false;
+        }
+        return this.val();
+      }
+    },
+
+    collapsed: {
+      'collapsed': function (e) {
+        return (typeof e !== 'undefined' && 'value' in e) ? e.value : !this.is('[open]');
+      }
     }
-  }
-};
-
-
-/**
- * A state object is used for describing the state and performing aliasing.
- */
-states.State = function(state) {
-  // We may need the original unresolved name later.
-  this.pristine = this.name = state;
-
-  // Normalize the state name.
-  while (true) {
-    // Iteratively remove exclamation marks and invert the value.
-    while (this.name.charAt(0) === '!') {
-      this.name = this.name.substring(1);
-      this.invert = !this.invert;
+  };
+
+
+  /**
+   * A state object is used for describing the state and performing aliasing.
+   */
+  states.State = function (state) {
+    // We may need the original unresolved name later.
+    this.pristine = this.name = state;
+
+    // Normalize the state name.
+    while (true) {
+      // Iteratively remove exclamation marks and invert the value.
+      while (this.name.charAt(0) === '!') {
+        this.name = this.name.substring(1);
+        this.invert = !this.invert;
+      }
+
+      // Replace the state with its normalized name.
+      if (this.name in states.State.aliases) {
+        this.name = states.State.aliases[this.name];
+      }
+      else {
+        break;
+      }
     }
+  };
 
-    // Replace the state with its normalized name.
-    if (this.name in states.State.aliases) {
-      this.name = states.State.aliases[this.name];
+  /**
+   * Creates a new State object by sanitizing the passed value.
+   */
+  states.State.sanitize = function (state) {
+    if (state instanceof states.State) {
+      return state;
     }
     else {
-      break;
+      return new states.State(state);
     }
-  }
-};
-
-/**
- * Creates a new State object by sanitizing the passed value.
- */
-states.State.sanitize = function (state) {
-  if (state instanceof states.State) {
-    return state;
-  }
-  else {
-    return new states.State(state);
-  }
-};
-
-/**
- * This list of aliases is used to normalize states and associates negated names
- * with their respective inverse state.
- */
-states.State.aliases = {
-  'enabled': '!disabled',
-  'invisible': '!visible',
-  'invalid': '!valid',
-  'untouched': '!touched',
-  'optional': '!required',
-  'filled': '!empty',
-  'unchecked': '!checked',
-  'irrelevant': '!relevant',
-  'expanded': '!collapsed',
-  'open': '!collapsed',
-  'closed': 'collapsed',
-  'readwrite': '!readonly'
-};
-
-states.State.prototype = {
-  invert: false,
+  };
 
   /**
-   * Ensures that just using the state object returns the name.
+   * This list of aliases is used to normalize states and associates negated names
+   * with their respective inverse state.
    */
-  toString: function() {
-    return this.name;
-  }
-};
-
-/**
- * Global state change handlers. These are bound to "document" to cover all
- * elements whose state changes. Events sent to elements within the page
- * bubble up to these handlers. We use this system so that themes and modules
- * can override these state change handlers for particular parts of a page.
- */
-
-$(document).on('state:disabled', function (e) {
-  // Only act when this change was triggered by a dependency and not by the
-  // element monitoring itself.
-  if (e.trigger) {
-    $(e.target)
-      .prop('disabled', e.value)
+  states.State.aliases = {
+    'enabled': '!disabled',
+    'invisible': '!visible',
+    'invalid': '!valid',
+    'untouched': '!touched',
+    'optional': '!required',
+    'filled': '!empty',
+    'unchecked': '!checked',
+    'irrelevant': '!relevant',
+    'expanded': '!collapsed',
+    'open': '!collapsed',
+    'closed': 'collapsed',
+    'readwrite': '!readonly'
+  };
+
+  states.State.prototype = {
+    invert: false,
+
+    /**
+     * Ensures that just using the state object returns the name.
+     */
+    toString: function () {
+      return this.name;
+    }
+  };
+
+  /**
+   * Global state change handlers. These are bound to "document" to cover all
+   * elements whose state changes. Events sent to elements within the page
+   * bubble up to these handlers. We use this system so that themes and modules
+   * can override these state change handlers for particular parts of a page.
+   */
+
+  $(document).on('state:disabled', function (e) {
+    // Only act when this change was triggered by a dependency and not by the
+    // element monitoring itself.
+    if (e.trigger) {
+      $(e.target)
+        .prop('disabled', e.value)
         .closest('.form-item, .form-submit, .form-wrapper').toggleClass('form-disabled', e.value)
         .find('select, input, textarea').prop('disabled', e.value);
 
-    // Note: WebKit nightlies don't reflect that change correctly.
-    // See https://bugs.webkit.org/show_bug.cgi?id=23789
-  }
-});
-
-$(document).on('state:required', function (e) {
-  if (e.trigger) {
-    if (e.value) {
-      var $label = $(e.target).attr({ 'required': 'required', 'aria-required': 'aria-required' }).closest('.form-item, .form-wrapper').find('label');
-      // Avoids duplicate required markers on initialization.
-      if (!$label.find('.form-required').length) {
-        $label.append(Drupal.theme('requiredMarker'));
-      }
+      // Note: WebKit nightlies don't reflect that change correctly.
+      // See https://bugs.webkit.org/show_bug.cgi?id=23789
     }
-    else {
-      $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label .form-required').remove();
+  });
+
+  $(document).on('state:required', function (e) {
+    if (e.trigger) {
+      if (e.value) {
+        var $label = $(e.target).attr({ 'required': 'required', 'aria-required': 'aria-required' }).closest('.form-item, .form-wrapper').find('label');
+        // Avoids duplicate required markers on initialization.
+        if (!$label.find('.form-required').length) {
+          $label.append(Drupal.theme('requiredMarker'));
+        }
+      }
+      else {
+        $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label .form-required').remove();
+      }
     }
-  }
-});
+  });
 
-$(document).on('state:visible', function (e) {
-  if (e.trigger) {
-    $(e.target).closest('.form-item, .form-submit, .form-wrapper').toggle(e.value);
-  }
-});
+  $(document).on('state:visible', function (e) {
+    if (e.trigger) {
+      $(e.target).closest('.form-item, .form-submit, .form-wrapper').toggle(e.value);
+    }
+  });
 
-$(document).on('state:checked', function (e) {
-  if (e.trigger) {
-    $(e.target).prop('checked', e.value);
-  }
-});
+  $(document).on('state:checked', function (e) {
+    if (e.trigger) {
+      $(e.target).prop('checked', e.value);
+    }
+  });
 
-$(document).on('state:collapsed', function (e) {
-  if (e.trigger) {
-    if ($(e.target).is('[open]') === e.value) {
-      $(e.target).find('> summary a').trigger('click');
+  $(document).on('state:collapsed', function (e) {
+    if (e.trigger) {
+      if ($(e.target).is('[open]') === e.value) {
+        $(e.target).find('> summary a').trigger('click');
+      }
     }
-  }
-});
+  });
 
 
-/**
- * These are helper functions implementing addition "operators" and don't
- * implement any logic that is particular to states.
- */
+  /**
+   * These are helper functions implementing addition "operators" and don't
+   * implement any logic that is particular to states.
+   */
 
 // Bitwise AND with a third undefined state.
-function ternary (a, b) {
-  return typeof a === 'undefined' ? b : (typeof b === 'undefined' ? a : a && b);
-}
+  function ternary(a, b) {
+    return typeof a === 'undefined' ? b : (typeof b === 'undefined' ? a : a && b);
+  }
 
 // Inverts a (if it's not undefined) when invertState is true.
-function invert (a, invertState) {
-  return (invertState && typeof a !== 'undefined') ? !a : a;
-}
+  function invert(a, invertState) {
+    return (invertState && typeof a !== 'undefined') ? !a : a;
+  }
 
 // Compares two values while ignoring undefined values.
-function compare (a, b) {
-  return (a === b) ? (typeof a === 'undefined' ? a : true) : (typeof a === 'undefined' || typeof b === 'undefined');
-}
-
-$.extend(Drupal.theme, {
-  requiredMarker: function () {
-    return '<abbr class="form-required" title="' + Drupal.t('This field is required.') + '">*</abbr>';
+  function compare(a, b) {
+    return (a === b) ? (typeof a === 'undefined' ? a : true) : (typeof a === 'undefined' || typeof b === 'undefined');
   }
-});
+
+  $.extend(Drupal.theme, {
+    requiredMarker: function () {
+      return '<abbr class="form-required" title="' + Drupal.t('This field is required.') + '">*</abbr>';
+    }
+  });
 
 })(jQuery);
diff --git a/core/misc/tabbingmanager.js b/core/misc/tabbingmanager.js
index 0507120..5b98dab 100644
--- a/core/misc/tabbingmanager.js
+++ b/core/misc/tabbingmanager.js
@@ -5,288 +5,288 @@
 
 (function ($, Drupal) {
 
-"use strict";
+  "use strict";
 
-/**
- * Provides an API for managing page tabbing order modifications.
- */
-function TabbingManager () {
-  // Tabbing sets are stored as a stack. The active set is at the top of the
-  // stack. We use a JavaScript array as if it were a stack; we consider the
-  // first element to be the bottom and the last element to be the top. This
-  // allows us to use JavaScript's built-in Array.push() and Array.pop()
-  // methods.
-  this.stack = [];
-}
+  /**
+   * Provides an API for managing page tabbing order modifications.
+   */
+  function TabbingManager() {
+    // Tabbing sets are stored as a stack. The active set is at the top of the
+    // stack. We use a JavaScript array as if it were a stack; we consider the
+    // first element to be the bottom and the last element to be the top. This
+    // allows us to use JavaScript's built-in Array.push() and Array.pop()
+    // methods.
+    this.stack = [];
+  }
 
-/**
- * Add public methods to the TabbingManager class.
- */
-$.extend(TabbingManager.prototype, {
   /**
-   * Constrain tabbing to the specified set of elements only.
-   *
-   * Makes elements outside of the specified set of elements unreachable via the
-   * tab key.
-   *
-   * @param jQuery elements
-   *   The set of elements to which tabbing should be constrained. Can also be
-   *   a jQuery-compatible selector string.
-   *
-   * @return TabbingContext
+   * Add public methods to the TabbingManager class.
    */
-  constrain: function (elements) {
-    // Deactivate all tabbingContexts to prepare for the new constraint. A
-    // tabbingContext instance will only be reactivated if the stack is unwound
-    // to it in the _unwindStack() method.
-    for (var i = 0, il = this.stack.length; i < il; i++) {
-      this.stack[i].deactivate();
-    }
+  $.extend(TabbingManager.prototype, {
+    /**
+     * Constrain tabbing to the specified set of elements only.
+     *
+     * Makes elements outside of the specified set of elements unreachable via the
+     * tab key.
+     *
+     * @param jQuery elements
+     *   The set of elements to which tabbing should be constrained. Can also be
+     *   a jQuery-compatible selector string.
+     *
+     * @return TabbingContext
+     */
+    constrain: function (elements) {
+      // Deactivate all tabbingContexts to prepare for the new constraint. A
+      // tabbingContext instance will only be reactivated if the stack is unwound
+      // to it in the _unwindStack() method.
+      for (var i = 0, il = this.stack.length; i < il; i++) {
+        this.stack[i].deactivate();
+      }
 
-    // The "active tabbing set" are the elements tabbing should be constrained
-    // to.
-    var $elements = $(elements).find(':tabbable').addBack(':tabbable');
+      // The "active tabbing set" are the elements tabbing should be constrained
+      // to.
+      var $elements = $(elements).find(':tabbable').addBack(':tabbable');
 
-    var tabbingContext = new TabbingContext({
-      // The level is the current height of the stack before this new
-      // tabbingContext is pushed on top of the stack.
-      level: this.stack.length,
-      $tabbableElements: $elements
-    });
+      var tabbingContext = new TabbingContext({
+        // The level is the current height of the stack before this new
+        // tabbingContext is pushed on top of the stack.
+        level: this.stack.length,
+        $tabbableElements: $elements
+      });
 
-    this.stack.push(tabbingContext);
+      this.stack.push(tabbingContext);
 
-    // Activates the tabbingContext; this will manipulate the DOM to constrain
-    // tabbing.
-    tabbingContext.activate();
+      // Activates the tabbingContext; this will manipulate the DOM to constrain
+      // tabbing.
+      tabbingContext.activate();
 
-    // Allow modules to respond to the constrain event.
-    $(document).trigger('drupalTabbingConstrained', tabbingContext);
+      // Allow modules to respond to the constrain event.
+      $(document).trigger('drupalTabbingConstrained', tabbingContext);
 
-    return tabbingContext;
-  },
+      return tabbingContext;
+    },
 
-  /**
-   * Restores a former tabbingContext when an active tabbingContext is released.
-   *
-   * The TabbingManager stack of tabbingContext instances will be unwound from
-   * the top-most released tabbingContext down to the first non-released
-   * tabbingContext instance. This non-released instance is then activated.
-   */
-  release: function () {
-    // Unwind as far as possible: find the topmost non-released tabbingContext.
-    var toActivate = this.stack.length - 1;
-    while (toActivate >= 0 && this.stack[toActivate].released) {
-      toActivate--;
-    }
+    /**
+     * Restores a former tabbingContext when an active tabbingContext is released.
+     *
+     * The TabbingManager stack of tabbingContext instances will be unwound from
+     * the top-most released tabbingContext down to the first non-released
+     * tabbingContext instance. This non-released instance is then activated.
+     */
+    release: function () {
+      // Unwind as far as possible: find the topmost non-released tabbingContext.
+      var toActivate = this.stack.length - 1;
+      while (toActivate >= 0 && this.stack[toActivate].released) {
+        toActivate--;
+      }
 
-    // Delete all tabbingContexts after the to be activated one. They have
-    // already been deactivated, so their effect on the DOM has been reversed.
-    this.stack.splice(toActivate + 1);
+      // Delete all tabbingContexts after the to be activated one. They have
+      // already been deactivated, so their effect on the DOM has been reversed.
+      this.stack.splice(toActivate + 1);
 
-    // Get topmost tabbingContext, if one exists, and activate it.
-    if (toActivate >= 0) {
-      this.stack[toActivate].activate();
-    }
-  },
+      // Get topmost tabbingContext, if one exists, and activate it.
+      if (toActivate >= 0) {
+        this.stack[toActivate].activate();
+      }
+    },
 
-  /**
-   * Makes all elements outside the of the tabbingContext's set untabbable.
-   *
-   * Elements made untabble have their original tabindex and autfocus values
-   * stored so that they might be restored later when this tabbingContext
-   * is deactivated.
-   *
-   * @param TabbingContext tabbingContext
-   *   The TabbingContext instance that has been activated.
-   */
-  activate: function (tabbingContext) {
-    var $set = tabbingContext.$tabbableElements;
-    var level = tabbingContext.level;
-    // Determine which elements are reachable via tabbing by default.
-    var $disabledSet = $(':tabbable')
-      // Exclude elements of the active tabbing set.
-      .not($set);
-    // Set the disabled set on the tabbingContext.
-    tabbingContext.$disabledElements = $disabledSet;
-    // Record the tabindex for each element, so we can restore it later.
-    for (var i = 0, il = $disabledSet.length; i < il; i++) {
-      this.recordTabindex($disabledSet.eq(i), level);
-    }
-    // Make all tabbable elements outside of the active tabbing set unreachable.
-    $disabledSet
-      .prop('tabindex', -1)
-      .prop('autofocus', false);
+    /**
+     * Makes all elements outside the of the tabbingContext's set untabbable.
+     *
+     * Elements made untabble have their original tabindex and autfocus values
+     * stored so that they might be restored later when this tabbingContext
+     * is deactivated.
+     *
+     * @param TabbingContext tabbingContext
+     *   The TabbingContext instance that has been activated.
+     */
+    activate: function (tabbingContext) {
+      var $set = tabbingContext.$tabbableElements;
+      var level = tabbingContext.level;
+      // Determine which elements are reachable via tabbing by default.
+      var $disabledSet = $(':tabbable')
+        // Exclude elements of the active tabbing set.
+        .not($set);
+      // Set the disabled set on the tabbingContext.
+      tabbingContext.$disabledElements = $disabledSet;
+      // Record the tabindex for each element, so we can restore it later.
+      for (var i = 0, il = $disabledSet.length; i < il; i++) {
+        this.recordTabindex($disabledSet.eq(i), level);
+      }
+      // Make all tabbable elements outside of the active tabbing set unreachable.
+      $disabledSet
+        .prop('tabindex', -1)
+        .prop('autofocus', false);
 
-    // Set focus on an element in the tabbingContext's set of tabbable elements.
-    // First, check if there is an element with an autofocus attribute. Select
-    // the last one from the DOM order.
-    var $hasFocus = $set.filter('[autofocus]').eq(-1);
-    // If no element in the tabbable set has an autofocus attribute, select the
-    // first element in the set.
-    if ($hasFocus.length === 0) {
-      $hasFocus = $set.eq(0);
-    }
-    $hasFocus.trigger('focus');
-  },
+      // Set focus on an element in the tabbingContext's set of tabbable elements.
+      // First, check if there is an element with an autofocus attribute. Select
+      // the last one from the DOM order.
+      var $hasFocus = $set.filter('[autofocus]').eq(-1);
+      // If no element in the tabbable set has an autofocus attribute, select the
+      // first element in the set.
+      if ($hasFocus.length === 0) {
+        $hasFocus = $set.eq(0);
+      }
+      $hasFocus.trigger('focus');
+    },
 
-  /**
-   * Restores that tabbable state of a tabbingContext's disabled elements.
-   *
-   * Elements that were made untabble have their original tabindex and autfocus
-   * values restored.
-   *
-   * @param TabbingContext tabbingContext
-   *   The TabbingContext instance that has been deactivated.
-   */
-  deactivate: function (tabbingContext) {
-    var $set = tabbingContext.$disabledElements;
-    var level = tabbingContext.level;
-    for (var i = 0, il = $set.length; i < il; i++) {
-      this.restoreTabindex($set.eq(i), level);
-    }
-  },
+    /**
+     * Restores that tabbable state of a tabbingContext's disabled elements.
+     *
+     * Elements that were made untabble have their original tabindex and autfocus
+     * values restored.
+     *
+     * @param TabbingContext tabbingContext
+     *   The TabbingContext instance that has been deactivated.
+     */
+    deactivate: function (tabbingContext) {
+      var $set = tabbingContext.$disabledElements;
+      var level = tabbingContext.level;
+      for (var i = 0, il = $set.length; i < il; i++) {
+        this.restoreTabindex($set.eq(i), level);
+      }
+    },
 
-  /**
-   * Records the tabindex and autofocus values of an untabbable element.
-   *
-   * @param jQuery $set
-   *   The set of elements that have been disabled.
-   * @param Number level
-   *   The stack level for which the tabindex attribute should be recorded.
-   */
-  recordTabindex: function ($el, level) {
-    var tabInfo = $el.data('drupalOriginalTabIndices') || {};
-    tabInfo[level] = {
-      tabindex: $el[0].getAttribute('tabindex'),
-      autofocus: $el[0].hasAttribute('autofocus')
-    };
-    $el.data('drupalOriginalTabIndices', tabInfo);
-  },
+    /**
+     * Records the tabindex and autofocus values of an untabbable element.
+     *
+     * @param jQuery $set
+     *   The set of elements that have been disabled.
+     * @param Number level
+     *   The stack level for which the tabindex attribute should be recorded.
+     */
+    recordTabindex: function ($el, level) {
+      var tabInfo = $el.data('drupalOriginalTabIndices') || {};
+      tabInfo[level] = {
+        tabindex: $el[0].getAttribute('tabindex'),
+        autofocus: $el[0].hasAttribute('autofocus')
+      };
+      $el.data('drupalOriginalTabIndices', tabInfo);
+    },
 
-  /**
-   * Restores the tabindex and autofocus values of a reactivated element.
-   *
-   * @param jQuery $el
-   *   The element that is being reactivated.
-   * @param Number level
-   *   The stack level for which the tabindex attribute should be restored.
-   */
-  restoreTabindex: function ($el, level) {
-    var tabInfo = $el.data('drupalOriginalTabIndices');
-    if (tabInfo && tabInfo[level]) {
-      var data = tabInfo[level];
-      if (data.tabindex) {
-        $el[0].setAttribute('tabindex', data.tabindex);
-      }
-      // If the element did not have a tabindex at this stack level then
-      // remove it.
-      else {
-        $el[0].removeAttribute('tabindex');
-      }
-      if (data.autofocus) {
-        $el[0].setAttribute('autofocus', 'autofocus');
-      }
+    /**
+     * Restores the tabindex and autofocus values of a reactivated element.
+     *
+     * @param jQuery $el
+     *   The element that is being reactivated.
+     * @param Number level
+     *   The stack level for which the tabindex attribute should be restored.
+     */
+    restoreTabindex: function ($el, level) {
+      var tabInfo = $el.data('drupalOriginalTabIndices');
+      if (tabInfo && tabInfo[level]) {
+        var data = tabInfo[level];
+        if (data.tabindex) {
+          $el[0].setAttribute('tabindex', data.tabindex);
+        }
+        // If the element did not have a tabindex at this stack level then
+        // remove it.
+        else {
+          $el[0].removeAttribute('tabindex');
+        }
+        if (data.autofocus) {
+          $el[0].setAttribute('autofocus', 'autofocus');
+        }
 
-      // Clean up $.data.
-      if (level === 0) {
-        // Remove all data.
-       $el.removeData('drupalOriginalTabIndices');
-      }
-      else {
-        // Remove the data for this stack level and higher.
-        var levelToDelete = level;
-        while (tabInfo.hasOwnProperty(levelToDelete)) {
-          delete tabInfo[levelToDelete];
-          levelToDelete++;
+        // Clean up $.data.
+        if (level === 0) {
+          // Remove all data.
+          $el.removeData('drupalOriginalTabIndices');
+        }
+        else {
+          // Remove the data for this stack level and higher.
+          var levelToDelete = level;
+          while (tabInfo.hasOwnProperty(levelToDelete)) {
+            delete tabInfo[levelToDelete];
+            levelToDelete++;
+          }
+          $el.data('drupalOriginalTabIndices', tabInfo);
         }
-        $el.data('drupalOriginalTabIndices', tabInfo);
       }
     }
-  }
-});
-
-/**
- * Stores a set of tabbable elements.
- *
- * This constraint can be removed with the release() method.
- *
- * @param Object options
- *   A set of initiating values that include:
- *   - Number level: The level in the TabbingManager's stack of this
- *   tabbingContext.
- *   - jQuery $tabbableElements: The DOM elements that should be reachable via
- *   the tab key when this tabbingContext is active.
- *   - jQuery $disabledElements: The DOM elements that should not be reachable
- *   via the tab key when this tabbingContext is active.
- *   - Boolean released: A released tabbingContext can never be activated again.
- *   It will be cleaned up when the TabbingManager unwinds its stack.
- *   - Boolean active: When true, the tabbable elements of this tabbingContext
- *   will be reachable via the tab key and the disabled elements will not. Only
- *   one tabbingContext can be active at a time.
- */
-function TabbingContext (options) {
-  $.extend(this, {
-    level: null,
-    $tabbableElements: $(),
-    $disabledElements: $(),
-    released: false,
-    active: false
-  }, options);
-}
+  });
 
-/**
- * Add public methods to the TabbingContext class.
- */
-$.extend(TabbingContext.prototype, {
   /**
-   * Releases this TabbingContext.
+   * Stores a set of tabbable elements.
    *
-   * Once a TabbingContext object is released, it can never be activated again.
+   * This constraint can be removed with the release() method.
+   *
+   * @param Object options
+   *   A set of initiating values that include:
+   *   - Number level: The level in the TabbingManager's stack of this
+   *   tabbingContext.
+   *   - jQuery $tabbableElements: The DOM elements that should be reachable via
+   *   the tab key when this tabbingContext is active.
+   *   - jQuery $disabledElements: The DOM elements that should not be reachable
+   *   via the tab key when this tabbingContext is active.
+   *   - Boolean released: A released tabbingContext can never be activated again.
+   *   It will be cleaned up when the TabbingManager unwinds its stack.
+   *   - Boolean active: When true, the tabbable elements of this tabbingContext
+   *   will be reachable via the tab key and the disabled elements will not. Only
+   *   one tabbingContext can be active at a time.
    */
-  release: function () {
-    if (!this.released) {
-      this.deactivate();
-      this.released = true;
-      Drupal.tabbingManager.release(this);
-      // Allow modules to respond to the tabbingContext release event.
-      $(document).trigger('drupalTabbingContextReleased', this);
-    }
-  },
+  function TabbingContext(options) {
+    $.extend(this, {
+      level: null,
+      $tabbableElements: $(),
+      $disabledElements: $(),
+      released: false,
+      active: false
+    }, options);
+  }
 
   /**
-   * Activates this TabbingContext.
+   * Add public methods to the TabbingContext class.
    */
-  activate: function () {
-    // A released TabbingContext object can never be activated again.
-    if (!this.active && !this.released) {
-      this.active = true;
-      Drupal.tabbingManager.activate(this);
-      // Allow modules to respond to the constrain event.
-      $(document).trigger('drupalTabbingContextActivated', this);
-    }
-  },
+  $.extend(TabbingContext.prototype, {
+    /**
+     * Releases this TabbingContext.
+     *
+     * Once a TabbingContext object is released, it can never be activated again.
+     */
+    release: function () {
+      if (!this.released) {
+        this.deactivate();
+        this.released = true;
+        Drupal.tabbingManager.release(this);
+        // Allow modules to respond to the tabbingContext release event.
+        $(document).trigger('drupalTabbingContextReleased', this);
+      }
+    },
 
-  /**
-   * Deactivates this TabbingContext.
-   */
-  deactivate: function () {
-    if (this.active) {
-      this.active = false;
-      Drupal.tabbingManager.deactivate(this);
-      // Allow modules to respond to the constrain event.
-      $(document).trigger('drupalTabbingContextDeactivated', this);
+    /**
+     * Activates this TabbingContext.
+     */
+    activate: function () {
+      // A released TabbingContext object can never be activated again.
+      if (!this.active && !this.released) {
+        this.active = true;
+        Drupal.tabbingManager.activate(this);
+        // Allow modules to respond to the constrain event.
+        $(document).trigger('drupalTabbingContextActivated', this);
+      }
+    },
+
+    /**
+     * Deactivates this TabbingContext.
+     */
+    deactivate: function () {
+      if (this.active) {
+        this.active = false;
+        Drupal.tabbingManager.deactivate(this);
+        // Allow modules to respond to the constrain event.
+        $(document).trigger('drupalTabbingContextDeactivated', this);
+      }
     }
-  }
-});
+  });
 
 
 // Mark this behavior as processed on the first pass and return if it is
 // already processed.
-if (Drupal.tabbingManager) {
-  return;
-}
-Drupal.tabbingManager = new TabbingManager();
+  if (Drupal.tabbingManager) {
+    return;
+  }
+  Drupal.tabbingManager = new TabbingManager();
 
 
 }(jQuery, Drupal));
diff --git a/core/misc/tabledrag.js b/core/misc/tabledrag.js
index 68be8f6..f3c6c9e 100644
--- a/core/misc/tabledrag.js
+++ b/core/misc/tabledrag.js
@@ -1,1266 +1,1266 @@
 (function ($, Drupal, drupalSettings) {
 
-"use strict";
-
-/**
- * Store the state of weight columns display for all tables.
- * Default value is to hide weight columns.
- */
-var showWeight = JSON.parse(localStorage.getItem('Drupal.tableDrag.showWeight'));
-
-/**
- * Drag and drop table rows with field manipulation.
- *
- * Using the drupal_attach_tabledrag() function, any table with weights or
- * parent relationships may be made into draggable tables. Columns containing a
- * field may optionally be hidden, providing a better user experience.
- *
- * Created tableDrag instances may be modified with custom behaviors by
- * 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 = {
-  attach: function (context, settings) {
-    function initTableDrag(table, base) {
-      if (table.length) {
-        // Create the new tableDrag instance. Save in the Drupal variable
-        // to allow other scripts access to the object.
-        Drupal.tableDrag[base] = new Drupal.tableDrag(table[0], settings.tableDrag[base]);
+  "use strict";
+
+  /**
+   * Store the state of weight columns display for all tables.
+   * Default value is to hide weight columns.
+   */
+  var showWeight = JSON.parse(localStorage.getItem('Drupal.tableDrag.showWeight'));
+
+  /**
+   * Drag and drop table rows with field manipulation.
+   *
+   * Using the drupal_attach_tabledrag() function, any table with weights or
+   * parent relationships may be made into draggable tables. Columns containing a
+   * field may optionally be hidden, providing a better user experience.
+   *
+   * Created tableDrag instances may be modified with custom behaviors by
+   * 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 = {
+    attach: function (context, settings) {
+      function initTableDrag(table, base) {
+        if (table.length) {
+          // Create the new tableDrag instance. Save in the Drupal variable
+          // to allow other scripts access to the object.
+          Drupal.tableDrag[base] = new Drupal.tableDrag(table[0], settings.tableDrag[base]);
+        }
       }
-    }
 
-    for (var base in settings.tableDrag) {
-      if (settings.tableDrag.hasOwnProperty(base)) {
-        initTableDrag($(context).find('#' + base).once('tabledrag'), base);
+      for (var base in settings.tableDrag) {
+        if (settings.tableDrag.hasOwnProperty(base)) {
+          initTableDrag($(context).find('#' + base).once('tabledrag'), base);
+        }
       }
     }
-  }
-};
-
-/**
- * Constructor for the tableDrag object. Provides table and field manipulation.
- *
- * @param table
- *   DOM object for the table to be made draggable.
- * @param tableSettings
- *   Settings for the table added via drupal_add_dragtable().
- */
-Drupal.tableDrag = function (table, tableSettings) {
-  var self = this;
-  var $table = $(table);
-
-  // Required object variables.
-  this.$table = $(table);
-  this.table = table;
-  this.tableSettings = tableSettings;
-  this.dragObject = null; // Used to hold information about a current drag operation.
-  this.rowObject = null; // Provides operations for row manipulation.
-  this.oldRowElement = null; // Remember the previous element.
-  this.oldY = 0; // Used to determine up or down direction from last mouse move.
-  this.changed = false; // Whether anything in the entire table has changed.
-  this.maxDepth = 0; // Maximum amount of allowed parenting.
-  this.rtl = $(this.table).css('direction') === 'rtl' ? -1 : 1; // Direction of the table.
-
-  // Configure the scroll settings.
-  this.scrollSettings = { amount: 4, interval: 50, trigger: 70 };
-  this.scrollInterval = null;
-  this.scrollY = 0;
-  this.windowHeight = 0;
-
-  // Check this table's settings to see if there are parent relationships in
-  // this table. For efficiency, large sections of code can be skipped if we
-  // don't need to track horizontal movement and indentations.
-  this.indentEnabled = false;
-  for (var group in tableSettings) {
-    if (tableSettings.hasOwnProperty(group)) {
-      for (var n in tableSettings[group]) {
-        if (tableSettings[group].hasOwnProperty(n)) {
-          if (tableSettings[group][n].relationship === 'parent') {
-            this.indentEnabled = true;
-          }
-          if (tableSettings[group][n].limit > 0) {
-            this.maxDepth = tableSettings[group][n].limit;
+  };
+
+  /**
+   * Constructor for the tableDrag object. Provides table and field manipulation.
+   *
+   * @param table
+   *   DOM object for the table to be made draggable.
+   * @param tableSettings
+   *   Settings for the table added via drupal_add_dragtable().
+   */
+  Drupal.tableDrag = function (table, tableSettings) {
+    var self = this;
+    var $table = $(table);
+
+    // Required object variables.
+    this.$table = $(table);
+    this.table = table;
+    this.tableSettings = tableSettings;
+    this.dragObject = null; // Used to hold information about a current drag operation.
+    this.rowObject = null; // Provides operations for row manipulation.
+    this.oldRowElement = null; // Remember the previous element.
+    this.oldY = 0; // Used to determine up or down direction from last mouse move.
+    this.changed = false; // Whether anything in the entire table has changed.
+    this.maxDepth = 0; // Maximum amount of allowed parenting.
+    this.rtl = $(this.table).css('direction') === 'rtl' ? -1 : 1; // Direction of the table.
+
+    // Configure the scroll settings.
+    this.scrollSettings = { amount: 4, interval: 50, trigger: 70 };
+    this.scrollInterval = null;
+    this.scrollY = 0;
+    this.windowHeight = 0;
+
+    // Check this table's settings to see if there are parent relationships in
+    // this table. For efficiency, large sections of code can be skipped if we
+    // don't need to track horizontal movement and indentations.
+    this.indentEnabled = false;
+    for (var group in tableSettings) {
+      if (tableSettings.hasOwnProperty(group)) {
+        for (var n in tableSettings[group]) {
+          if (tableSettings[group].hasOwnProperty(n)) {
+            if (tableSettings[group][n].relationship === 'parent') {
+              this.indentEnabled = true;
+            }
+            if (tableSettings[group][n].limit > 0) {
+              this.maxDepth = tableSettings[group][n].limit;
+            }
           }
         }
       }
     }
-  }
-  if (this.indentEnabled) {
-    this.indentCount = 1; // Total width of indents, set in makeDraggable.
-    // Find the width of indentations to measure mouse movements against.
-    // Because the table doesn't need to start with any indentations, we
-    // manually append 2 indentations in the first draggable row, measure
-    // the offset, then remove.
-    var indent = Drupal.theme('tableDragIndentation');
-    var testRow = $('<tr/>').addClass('draggable').appendTo(table);
-    var testCell = $('<td/>').appendTo(testRow).prepend(indent).prepend(indent);
-    var $indentation = testCell.find('.indentation');
-    this.indentAmount = $indentation.get(1).offsetLeft - $indentation.get(0).offsetLeft;
-    testRow.remove();
-  }
-
-  // Make each applicable row draggable.
-  // Match immediate children of the parent element to allow nesting.
-  $table.find('> tr.draggable, > tbody > tr.draggable').each(function () { self.makeDraggable(this); });
-
-  // Add a link before the table for users to show or hide weight columns.
-  $table.before($('<button type="button" class="link tabledrag-toggle-weight"></button>')
-    .attr('title', Drupal.t('Re-order rows by numerical weight instead of dragging.'))
-    .on('click', $.proxy(function (e) {
-      e.preventDefault();
-      this.toggleColumns();
-    }, this))
-    .wrap('<div class="tabledrag-toggle-weight-wrapper"></div>')
-    .parent()
-  );
-
-  // Initialize the specified columns (for example, weight or parent columns)
-  // to show or hide according to user preference. This aids accessibility
-  // so that, e.g., screen reader users can choose to enter weight values and
-  // manipulate form elements directly, rather than using drag-and-drop..
-  self.initColumns();
-
-  // Add event bindings to the document. The self variable is passed along
-  // as event handlers do not have direct access to the tableDrag object.
-  if (Modernizr.touch) {
-    $(document).on('touchmove', function (event) { return self.dragRow(event.originalEvent.touches[0], self); });
-    $(document).on('touchend', function (event) { return self.dropRow(event.originalEvent.touches[0], self); });
-  }
-  else {
-    $(document).on('mousemove', function (event) { return self.dragRow(event, self); });
-    $(document).on('mouseup', function (event) { return self.dropRow(event, self); });
-  }
-
-  // React to localStorage event showing or hiding weight columns.
-  $(window).on('storage', $.proxy(function (e) {
-    // Only react to 'Drupal.tableDrag.showWeight' value change.
-    if (e.originalEvent.key === 'Drupal.tableDrag.showWeight') {
-      // This was changed in another window, get the new value for this window.
-      showWeight = JSON.parse(e.originalEvent.newValue);
-      this.displayColumns(showWeight);
+    if (this.indentEnabled) {
+      this.indentCount = 1; // Total width of indents, set in makeDraggable.
+      // Find the width of indentations to measure mouse movements against.
+      // Because the table doesn't need to start with any indentations, we
+      // manually append 2 indentations in the first draggable row, measure
+      // the offset, then remove.
+      var indent = Drupal.theme('tableDragIndentation');
+      var testRow = $('<tr/>').addClass('draggable').appendTo(table);
+      var testCell = $('<td/>').appendTo(testRow).prepend(indent).prepend(indent);
+      var $indentation = testCell.find('.indentation');
+      this.indentAmount = $indentation.get(1).offsetLeft - $indentation.get(0).offsetLeft;
+      testRow.remove();
     }
-  }, this));
-};
-
-/**
- * Initialize columns containing form elements to be hidden by default,
- * according to the settings for this tableDrag instance.
- *
- * Identify and mark each cell with a CSS class so we can easily toggle
- * show/hide it. Finally, hide columns if user does not have a
- * 'Drupal.tableDrag.showWeight' localStorage value.
- */
-Drupal.tableDrag.prototype.initColumns = function () {
-  var $table = this.$table;
-  var hidden, cell, columnIndex;
-  for (var group in this.tableSettings) {
-    if (this.tableSettings.hasOwnProperty(group)) { // Find the first field in this group.
-      for (var d in this.tableSettings[group]) {
-        if (this.tableSettings[group].hasOwnProperty(d)) {
-          var field = $table.find('.' + this.tableSettings[group][d].target + ':first');
-          if (field.length && this.tableSettings[group][d].hidden) {
-            hidden = this.tableSettings[group][d].hidden;
-            cell = field.closest('td');
-            break;
-          }
-        }
-      }
 
-      // Mark the column containing this field so it can be hidden.
-      if (hidden && cell[0]) {
-        // Add 1 to our indexes. The nth-child selector is 1 based, not 0 based.
-        // Match immediate children of the parent element to allow nesting.
-        columnIndex = cell.parent().find('> td').index(cell.get(0)) + 1;
-        $table.find('> thead > tr, > tbody > tr, > tr').each(this.addColspanClass(columnIndex));
-      }
+    // Make each applicable row draggable.
+    // Match immediate children of the parent element to allow nesting.
+    $table.find('> tr.draggable, > tbody > tr.draggable').each(function () { self.makeDraggable(this); });
+
+    // Add a link before the table for users to show or hide weight columns.
+    $table.before($('<button type="button" class="link tabledrag-toggle-weight"></button>')
+      .attr('title', Drupal.t('Re-order rows by numerical weight instead of dragging.'))
+      .on('click', $.proxy(function (e) {
+        e.preventDefault();
+        this.toggleColumns();
+      }, this))
+      .wrap('<div class="tabledrag-toggle-weight-wrapper"></div>')
+      .parent()
+    );
+
+    // Initialize the specified columns (for example, weight or parent columns)
+    // to show or hide according to user preference. This aids accessibility
+    // so that, e.g., screen reader users can choose to enter weight values and
+    // manipulate form elements directly, rather than using drag-and-drop..
+    self.initColumns();
+
+    // Add event bindings to the document. The self variable is passed along
+    // as event handlers do not have direct access to the tableDrag object.
+    if (Modernizr.touch) {
+      $(document).on('touchmove', function (event) { return self.dragRow(event.originalEvent.touches[0], self); });
+      $(document).on('touchend', function (event) { return self.dropRow(event.originalEvent.touches[0], self); });
     }
-  }
-  this.displayColumns(showWeight);
-};
-
-/**
- * Mark cells that have colspan so we can adjust the colspan
- * instead of hiding them altogether.
- */
-Drupal.tableDrag.prototype.addColspanClass = function(columnIndex) {
-  return function () {
-    // Get the columnIndex and adjust for any colspans in this row.
-    var $row = $(this);
-    var index = columnIndex;
-    var cells = $row.children();
-    var cell;
-    cells.each(function (n) {
-      if (n < index && this.colSpan && this.colSpan > 1) {
-        index -= this.colSpan - 1;
-      }
-    });
-    if (index > 0) {
-      cell = cells.filter(':nth-child(' + index + ')');
-      if (cell[0].colSpan && cell[0].colSpan > 1) {
-        // If this cell has a colspan, mark it so we can reduce the colspan.
-        cell.addClass('tabledrag-has-colspan');
+    else {
+      $(document).on('mousemove', function (event) { return self.dragRow(event, self); });
+      $(document).on('mouseup', function (event) { return self.dropRow(event, self); });
+    }
+
+    // React to localStorage event showing or hiding weight columns.
+    $(window).on('storage', $.proxy(function (e) {
+      // Only react to 'Drupal.tableDrag.showWeight' value change.
+      if (e.originalEvent.key === 'Drupal.tableDrag.showWeight') {
+        // This was changed in another window, get the new value for this window.
+        showWeight = JSON.parse(e.originalEvent.newValue);
+        this.displayColumns(showWeight);
       }
-      else {
-        // Mark this cell so we can hide it.
-        cell.addClass('tabledrag-hide');
+    }, this));
+  };
+
+  /**
+   * Initialize columns containing form elements to be hidden by default,
+   * according to the settings for this tableDrag instance.
+   *
+   * Identify and mark each cell with a CSS class so we can easily toggle
+   * show/hide it. Finally, hide columns if user does not have a
+   * 'Drupal.tableDrag.showWeight' localStorage value.
+   */
+  Drupal.tableDrag.prototype.initColumns = function () {
+    var $table = this.$table;
+    var hidden, cell, columnIndex;
+    for (var group in this.tableSettings) {
+      if (this.tableSettings.hasOwnProperty(group)) { // Find the first field in this group.
+        for (var d in this.tableSettings[group]) {
+          if (this.tableSettings[group].hasOwnProperty(d)) {
+            var field = $table.find('.' + this.tableSettings[group][d].target + ':first');
+            if (field.length && this.tableSettings[group][d].hidden) {
+              hidden = this.tableSettings[group][d].hidden;
+              cell = field.closest('td');
+              break;
+            }
+          }
+        }
+
+        // Mark the column containing this field so it can be hidden.
+        if (hidden && cell[0]) {
+          // Add 1 to our indexes. The nth-child selector is 1 based, not 0 based.
+          // Match immediate children of the parent element to allow nesting.
+          columnIndex = cell.parent().find('> td').index(cell.get(0)) + 1;
+          $table.find('> thead > tr, > tbody > tr, > tr').each(this.addColspanClass(columnIndex));
+        }
       }
     }
+    this.displayColumns(showWeight);
   };
-};
-
-/**
- * Hide or display weight columns. Triggers an event on change.
- *
- * @param bool displayWeight
- *   'true' will show weight columns.
- */
-Drupal.tableDrag.prototype.displayColumns = function (displayWeight) {
-  if (displayWeight) {
-    this.showColumns();
-  }
-  // Default action is to hide columns.
-  else {
-    this.hideColumns();
-  }
-  // Trigger an event to allow other scripts to react to this display change.
-  // Force the extra parameter as a bool.
-  $('table.tabledrag-processed').trigger('columnschange', !!displayWeight);
-};
-
-/**
- * Toggle the weight column depending on 'showWeight' value.
- * Store only default override.
- */
-Drupal.tableDrag.prototype.toggleColumns = function () {
-  showWeight = !showWeight;
-  this.displayColumns(showWeight);
-  if (showWeight) {
-    // Save default override.
-    localStorage.setItem('Drupal.tableDrag.showWeight', showWeight);
-  }
-  else {
-    // Reset the value to its default.
-    localStorage.removeItem('Drupal.tableDrag.showWeight');
-  }
-};
-
-/**
- * Hide the columns containing weight/parent form elements.
- * Undo showColumns().
- */
-Drupal.tableDrag.prototype.hideColumns = function () {
-  var $tables = $('table.tabledrag-processed');
-  // Hide weight/parent cells and headers.
-  $tables.find('.tabledrag-hide').css('display', 'none');
-  // Show TableDrag handles.
-  $tables.find('.tabledrag-handle').css('display', '');
-  // Reduce the colspan of any effected multi-span columns.
-  $tables.find('.tabledrag-has-colspan').each(function () {
-    this.colSpan = this.colSpan - 1;
-  });
-  // Change link text.
-  $('.tabledrag-toggle-weight').text(Drupal.t('Show row weights'));
-};
-
-/**
- * Show the columns containing weight/parent form elements
- * Undo hideColumns().
- */
-Drupal.tableDrag.prototype.showColumns = function () {
-  var $tables = $('table.tabledrag-processed');
-  // Show weight/parent cells and headers.
-  $tables.find('.tabledrag-hide').css('display', '');
-  // Hide TableDrag handles.
-  $tables.find('.tabledrag-handle').css('display', 'none');
-  // Increase the colspan for any columns where it was previously reduced.
-  $tables.find('.tabledrag-has-colspan').each(function () {
-    this.colSpan = this.colSpan + 1;
-  });
-  // Change link text.
-  $('.tabledrag-toggle-weight').text(Drupal.t('Hide row weights'));
-};
-
-/**
- * Find the target used within a particular row and group.
- */
-Drupal.tableDrag.prototype.rowSettings = function (group, row) {
-  var field = $(row).find('.' + group);
-  var tableSettingsGroup = this.tableSettings[group];
-  for (var delta in tableSettingsGroup) {
-    if (tableSettingsGroup.hasOwnProperty(delta)) {
-      var targetClass = tableSettingsGroup[delta].target;
-      if (field.is('.' + targetClass)) {
-        // Return a copy of the row settings.
-        var rowSettings = {};
-        for (var n in tableSettingsGroup[delta]) {
-          if (tableSettingsGroup[delta].hasOwnProperty(n)) {
-            rowSettings[n] = tableSettingsGroup[delta][n];
-          }
+
+  /**
+   * Mark cells that have colspan so we can adjust the colspan
+   * instead of hiding them altogether.
+   */
+  Drupal.tableDrag.prototype.addColspanClass = function (columnIndex) {
+    return function () {
+      // Get the columnIndex and adjust for any colspans in this row.
+      var $row = $(this);
+      var index = columnIndex;
+      var cells = $row.children();
+      var cell;
+      cells.each(function (n) {
+        if (n < index && this.colSpan && this.colSpan > 1) {
+          index -= this.colSpan - 1;
+        }
+      });
+      if (index > 0) {
+        cell = cells.filter(':nth-child(' + index + ')');
+        if (cell[0].colSpan && cell[0].colSpan > 1) {
+          // If this cell has a colspan, mark it so we can reduce the colspan.
+          cell.addClass('tabledrag-has-colspan');
+        }
+        else {
+          // Mark this cell so we can hide it.
+          cell.addClass('tabledrag-hide');
         }
-        return rowSettings;
       }
+    };
+  };
+
+  /**
+   * Hide or display weight columns. Triggers an event on change.
+   *
+   * @param bool displayWeight
+   *   'true' will show weight columns.
+   */
+  Drupal.tableDrag.prototype.displayColumns = function (displayWeight) {
+    if (displayWeight) {
+      this.showColumns();
     }
-  }
-};
-
-/**
- * Take an item and add event handlers to make it become draggable.
- */
-Drupal.tableDrag.prototype.makeDraggable = function (item) {
-  var self = this;
-  var $item = $(item);
-  //Add a class to the title link
-  $item.find('td:first a').addClass('menu-item__link');
-  // Create the handle.
-  var handle = $('<a href="#" class="tabledrag-handle"><div class="handle">&nbsp;</div></a>').attr('title', Drupal.t('Drag to re-order'));
-  // Insert the handle after indentations (if any).
-  var $indentationLast = $item.find('td:first .indentation:last');
-  if ($indentationLast.length) {
-    $indentationLast.after(handle);
-    // Update the total width of indentation in this entire table.
-    self.indentCount = Math.max($item.find('.indentation').length, self.indentCount);
-  }
-  else {
-    $item.find('td:first').prepend(handle);
-  }
-
-  if (Modernizr.touch) {
-    handle.on('touchstart', function (event) {
-      event.preventDefault();
-      event = event.originalEvent.touches[0];
-      self.dragStart(event, self, item);
-    });
-  }
-  else {
-    handle.on('mousedown', function (event) {
-      event.preventDefault();
-      self.dragStart(event, self, item);
+    // Default action is to hide columns.
+    else {
+      this.hideColumns();
+    }
+    // Trigger an event to allow other scripts to react to this display change.
+    // Force the extra parameter as a bool.
+    $('table.tabledrag-processed').trigger('columnschange', !!displayWeight);
+  };
+
+  /**
+   * Toggle the weight column depending on 'showWeight' value.
+   * Store only default override.
+   */
+  Drupal.tableDrag.prototype.toggleColumns = function () {
+    showWeight = !showWeight;
+    this.displayColumns(showWeight);
+    if (showWeight) {
+      // Save default override.
+      localStorage.setItem('Drupal.tableDrag.showWeight', showWeight);
+    }
+    else {
+      // Reset the value to its default.
+      localStorage.removeItem('Drupal.tableDrag.showWeight');
+    }
+  };
+
+  /**
+   * Hide the columns containing weight/parent form elements.
+   * Undo showColumns().
+   */
+  Drupal.tableDrag.prototype.hideColumns = function () {
+    var $tables = $('table.tabledrag-processed');
+    // Hide weight/parent cells and headers.
+    $tables.find('.tabledrag-hide').css('display', 'none');
+    // Show TableDrag handles.
+    $tables.find('.tabledrag-handle').css('display', '');
+    // Reduce the colspan of any effected multi-span columns.
+    $tables.find('.tabledrag-has-colspan').each(function () {
+      this.colSpan = this.colSpan - 1;
     });
-  }
+    // Change link text.
+    $('.tabledrag-toggle-weight').text(Drupal.t('Show row weights'));
+  };
 
-  // Prevent the anchor tag from jumping us to the top of the page.
-  handle.on('click', function (e) {
-    e.preventDefault();
-  });
+  /**
+   * Show the columns containing weight/parent form elements
+   * Undo hideColumns().
+   */
+  Drupal.tableDrag.prototype.showColumns = function () {
+    var $tables = $('table.tabledrag-processed');
+    // Show weight/parent cells and headers.
+    $tables.find('.tabledrag-hide').css('display', '');
+    // Hide TableDrag handles.
+    $tables.find('.tabledrag-handle').css('display', 'none');
+    // Increase the colspan for any columns where it was previously reduced.
+    $tables.find('.tabledrag-has-colspan').each(function () {
+      this.colSpan = this.colSpan + 1;
+    });
+    // Change link text.
+    $('.tabledrag-toggle-weight').text(Drupal.t('Hide row weights'));
+  };
 
-  // Set blur cleanup when a handle is focused.
-  handle.on('focus', function () {
-    self.safeBlur = true;
-  });
+  /**
+   * Find the target used within a particular row and group.
+   */
+  Drupal.tableDrag.prototype.rowSettings = function (group, row) {
+    var field = $(row).find('.' + group);
+    var tableSettingsGroup = this.tableSettings[group];
+    for (var delta in tableSettingsGroup) {
+      if (tableSettingsGroup.hasOwnProperty(delta)) {
+        var targetClass = tableSettingsGroup[delta].target;
+        if (field.is('.' + targetClass)) {
+          // Return a copy of the row settings.
+          var rowSettings = {};
+          for (var n in tableSettingsGroup[delta]) {
+            if (tableSettingsGroup[delta].hasOwnProperty(n)) {
+              rowSettings[n] = tableSettingsGroup[delta][n];
+            }
+          }
+          return rowSettings;
+        }
+      }
+    }
+  };
 
-  // On blur, fire the same function as a touchend/mouseup. This is used to
-  // update values after a row has been moved through the keyboard support.
-  handle.on('blur', function (event) {
-    if (self.rowObject && self.safeBlur) {
-      self.dropRow(event, self);
+  /**
+   * Take an item and add event handlers to make it become draggable.
+   */
+  Drupal.tableDrag.prototype.makeDraggable = function (item) {
+    var self = this;
+    var $item = $(item);
+    //Add a class to the title link
+    $item.find('td:first a').addClass('menu-item__link');
+    // Create the handle.
+    var handle = $('<a href="#" class="tabledrag-handle"><div class="handle">&nbsp;</div></a>').attr('title', Drupal.t('Drag to re-order'));
+    // Insert the handle after indentations (if any).
+    var $indentationLast = $item.find('td:first .indentation:last');
+    if ($indentationLast.length) {
+      $indentationLast.after(handle);
+      // Update the total width of indentation in this entire table.
+      self.indentCount = Math.max($item.find('.indentation').length, self.indentCount);
+    }
+    else {
+      $item.find('td:first').prepend(handle);
     }
-  });
 
-  // Add arrow-key support to the handle.
-  handle.on('keydown', function (event) {
-    // If a rowObject doesn't yet exist and this isn't the tab key.
-    if (event.keyCode !== 9 && !self.rowObject) {
-      self.rowObject = new self.row(item, 'keyboard', self.indentEnabled, self.maxDepth, true);
+    if (Modernizr.touch) {
+      handle.on('touchstart', function (event) {
+        event.preventDefault();
+        event = event.originalEvent.touches[0];
+        self.dragStart(event, self, item);
+      });
+    }
+    else {
+      handle.on('mousedown', function (event) {
+        event.preventDefault();
+        self.dragStart(event, self, item);
+      });
     }
 
-    var keyChange = false;
-    var groupHeight;
-    switch (event.keyCode) {
-      case 37: // Left arrow.
-      case 63234: // Safari left arrow.
-        keyChange = true;
-        self.rowObject.indent(-1 * self.rtl);
-        break;
-      case 38: // Up arrow.
-      case 63232: // Safari up arrow.
-        var $previousRow = $(self.rowObject.element).prev('tr').eq(0);
-        var previousRow = $previousRow.get(0);
-        while (previousRow && $previousRow.is(':hidden')) {
-          $previousRow = $(previousRow).prev('tr').eq(0);
-          previousRow = $previousRow.get(0);
-        }
-        if (previousRow) {
-          self.safeBlur = false; // Do not allow the onBlur cleanup.
-          self.rowObject.direction = 'up';
-          keyChange = true;
+    // Prevent the anchor tag from jumping us to the top of the page.
+    handle.on('click', function (e) {
+      e.preventDefault();
+    });
+
+    // Set blur cleanup when a handle is focused.
+    handle.on('focus', function () {
+      self.safeBlur = true;
+    });
+
+    // On blur, fire the same function as a touchend/mouseup. This is used to
+    // update values after a row has been moved through the keyboard support.
+    handle.on('blur', function (event) {
+      if (self.rowObject && self.safeBlur) {
+        self.dropRow(event, self);
+      }
+    });
+
+    // Add arrow-key support to the handle.
+    handle.on('keydown', function (event) {
+      // If a rowObject doesn't yet exist and this isn't the tab key.
+      if (event.keyCode !== 9 && !self.rowObject) {
+        self.rowObject = new self.row(item, 'keyboard', self.indentEnabled, self.maxDepth, true);
+      }
 
-          if ($(item).is('.tabledrag-root')) {
-            // Swap with the previous top-level row.
-            groupHeight = 0;
-            while (previousRow && $previousRow.find('.indentation').length) {
-              $previousRow = $(previousRow).prev('tr').eq(0);
-              previousRow = $previousRow.get(0);
-              groupHeight += $previousRow.is(':hidden') ? 0 : previousRow.offsetHeight;
+      var keyChange = false;
+      var groupHeight;
+      switch (event.keyCode) {
+        case 37: // Left arrow.
+        case 63234: // Safari left arrow.
+          keyChange = true;
+          self.rowObject.indent(-1 * self.rtl);
+          break;
+        case 38: // Up arrow.
+        case 63232: // Safari up arrow.
+          var $previousRow = $(self.rowObject.element).prev('tr').eq(0);
+          var previousRow = $previousRow.get(0);
+          while (previousRow && $previousRow.is(':hidden')) {
+            $previousRow = $(previousRow).prev('tr').eq(0);
+            previousRow = $previousRow.get(0);
+          }
+          if (previousRow) {
+            self.safeBlur = false; // Do not allow the onBlur cleanup.
+            self.rowObject.direction = 'up';
+            keyChange = true;
+
+            if ($(item).is('.tabledrag-root')) {
+              // Swap with the previous top-level row.
+              groupHeight = 0;
+              while (previousRow && $previousRow.find('.indentation').length) {
+                $previousRow = $(previousRow).prev('tr').eq(0);
+                previousRow = $previousRow.get(0);
+                groupHeight += $previousRow.is(':hidden') ? 0 : previousRow.offsetHeight;
+              }
+              if (previousRow) {
+                self.rowObject.swap('before', previousRow);
+                // No need to check for indentation, 0 is the only valid one.
+                window.scrollBy(0, -groupHeight);
+              }
             }
-            if (previousRow) {
+            else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.draggable')) {
+              // Swap with the previous row (unless previous row is the first one
+              // and undraggable).
               self.rowObject.swap('before', previousRow);
-              // No need to check for indentation, 0 is the only valid one.
-              window.scrollBy(0, -groupHeight);
+              self.rowObject.interval = null;
+              self.rowObject.indent(0);
+              window.scrollBy(0, -parseInt(item.offsetHeight, 10));
             }
+            handle.trigger('focus'); // Regain focus after the DOM manipulation.
           }
-          else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.draggable')) {
-            // Swap with the previous row (unless previous row is the first one
-            // and undraggable).
-            self.rowObject.swap('before', previousRow);
-            self.rowObject.interval = null;
-            self.rowObject.indent(0);
-            window.scrollBy(0, -parseInt(item.offsetHeight, 10));
-          }
-          handle.trigger('focus'); // Regain focus after the DOM manipulation.
-        }
-        break;
-      case 39: // Right arrow.
-      case 63235: // Safari right arrow.
-        keyChange = true;
-        self.rowObject.indent(self.rtl);
-        break;
-      case 40: // Down arrow.
-      case 63233: // Safari down arrow.
-        var $nextRow = $(self.rowObject.group).filter(':last').next('tr').eq(0);
-        var nextRow = $nextRow.get(0);
-        while (nextRow && $nextRow.is(':hidden')) {
-          $nextRow = $(nextRow).next('tr').eq(0);
-          nextRow = $nextRow.get(0);
-        }
-        if (nextRow) {
-          self.safeBlur = false; // Do not allow the onBlur cleanup.
-          self.rowObject.direction = 'down';
+          break;
+        case 39: // Right arrow.
+        case 63235: // Safari right arrow.
           keyChange = true;
-
-          if ($(item).is('.tabledrag-root')) {
-            // Swap with the next group (necessarily a top-level one).
-            groupHeight = 0;
-            var nextGroup = new self.row(nextRow, 'keyboard', self.indentEnabled, self.maxDepth, false);
-            if (nextGroup) {
-              $(nextGroup.group).each(function () {
-                groupHeight += $(this).is(':hidden') ? 0 : this.offsetHeight;
-              });
-              var nextGroupRow = $(nextGroup.group).filter(':last').get(0);
-              self.rowObject.swap('after', nextGroupRow);
-              // No need to check for indentation, 0 is the only valid one.
-              window.scrollBy(0, parseInt(groupHeight, 10));
-            }
+          self.rowObject.indent(self.rtl);
+          break;
+        case 40: // Down arrow.
+        case 63233: // Safari down arrow.
+          var $nextRow = $(self.rowObject.group).filter(':last').next('tr').eq(0);
+          var nextRow = $nextRow.get(0);
+          while (nextRow && $nextRow.is(':hidden')) {
+            $nextRow = $(nextRow).next('tr').eq(0);
+            nextRow = $nextRow.get(0);
           }
-          else {
-            // Swap with the next row.
-            self.rowObject.swap('after', nextRow);
-            self.rowObject.interval = null;
-            self.rowObject.indent(0);
-            window.scrollBy(0, parseInt(item.offsetHeight, 10));
+          if (nextRow) {
+            self.safeBlur = false; // Do not allow the onBlur cleanup.
+            self.rowObject.direction = 'down';
+            keyChange = true;
+
+            if ($(item).is('.tabledrag-root')) {
+              // Swap with the next group (necessarily a top-level one).
+              groupHeight = 0;
+              var nextGroup = new self.row(nextRow, 'keyboard', self.indentEnabled, self.maxDepth, false);
+              if (nextGroup) {
+                $(nextGroup.group).each(function () {
+                  groupHeight += $(this).is(':hidden') ? 0 : this.offsetHeight;
+                });
+                var nextGroupRow = $(nextGroup.group).filter(':last').get(0);
+                self.rowObject.swap('after', nextGroupRow);
+                // No need to check for indentation, 0 is the only valid one.
+                window.scrollBy(0, parseInt(groupHeight, 10));
+              }
+            }
+            else {
+              // Swap with the next row.
+              self.rowObject.swap('after', nextRow);
+              self.rowObject.interval = null;
+              self.rowObject.indent(0);
+              window.scrollBy(0, parseInt(item.offsetHeight, 10));
+            }
+            handle.trigger('focus'); // Regain focus after the DOM manipulation.
           }
-          handle.trigger('focus'); // Regain focus after the DOM manipulation.
+          break;
+      }
+
+      if (self.rowObject && self.rowObject.changed === true) {
+        $(item).addClass('drag');
+        if (self.oldRowElement) {
+          $(self.oldRowElement).removeClass('drag-previous');
         }
-        break;
-    }
+        self.oldRowElement = item;
+        self.restripeTable();
+        self.onDrag();
+      }
 
-    if (self.rowObject && self.rowObject.changed === true) {
-      $(item).addClass('drag');
-      if (self.oldRowElement) {
-        $(self.oldRowElement).removeClass('drag-previous');
+      // Returning false if we have an arrow key to prevent scrolling.
+      if (keyChange) {
+        return false;
       }
-      self.oldRowElement = item;
-      self.restripeTable();
-      self.onDrag();
+    });
+
+    // Compatibility addition, return false on keypress to prevent unwanted scrolling.
+    // IE and Safari will suppress scrolling on keydown, but all other browsers
+    // need to return false on keypress. http://www.quirksmode.org/js/keys.html
+    handle.on('keypress', function (event) {
+      switch (event.keyCode) {
+        case 37: // Left arrow.
+        case 38: // Up arrow.
+        case 39: // Right arrow.
+        case 40: // Down arrow.
+          return false;
+      }
+    });
+  };
+
+  /**
+   * Pointer event initiator, creates drag object and information.
+   *
+   * @param jQuery.Event event
+   *   The event object that trigger the drag.
+   * @param Drupal.tableDrag self
+   *   The drag handle.
+   * @param DOM item
+   *   The item that that is being dragged.
+   */
+  Drupal.tableDrag.prototype.dragStart = function (event, self, item) {
+    // Create a new dragObject recording the pointer information.
+    self.dragObject = {};
+    self.dragObject.initOffset = self.getPointerOffset(item, event);
+    self.dragObject.initPointerCoords = self.pointerCoords(event);
+    if (self.indentEnabled) {
+      self.dragObject.indentPointerPos = self.dragObject.initPointerCoords;
     }
 
-    // Returning false if we have an arrow key to prevent scrolling.
-    if (keyChange) {
-      return false;
+    // If there's a lingering row object from the keyboard, remove its focus.
+    if (self.rowObject) {
+      $(self.rowObject.element).find('a.tabledrag-handle').trigger('blur');
     }
-  });
 
-  // Compatibility addition, return false on keypress to prevent unwanted scrolling.
-  // IE and Safari will suppress scrolling on keydown, but all other browsers
-  // need to return false on keypress. http://www.quirksmode.org/js/keys.html
-  handle.on('keypress', function (event) {
-    switch (event.keyCode) {
-      case 37: // Left arrow.
-      case 38: // Up arrow.
-      case 39: // Right arrow.
-      case 40: // Down arrow.
-        return false;
+    // Create a new rowObject for manipulation of this row.
+    self.rowObject = new self.row(item, 'pointer', self.indentEnabled, self.maxDepth, true);
+
+    // Save the position of the table.
+    self.table.topY = $(self.table).offset().top;
+    self.table.bottomY = self.table.topY + self.table.offsetHeight;
+
+    // Add classes to the handle and row.
+    $(item).addClass('drag');
+
+    // Set the document to use the move cursor during drag.
+    $('body').addClass('drag');
+    if (self.oldRowElement) {
+      $(self.oldRowElement).removeClass('drag-previous');
     }
-  });
-};
-
-/**
- * Pointer event initiator, creates drag object and information.
- *
- * @param jQuery.Event event
- *   The event object that trigger the drag.
- * @param Drupal.tableDrag self
- *   The drag handle.
- * @param DOM item
- *   The item that that is being dragged.
- */
-Drupal.tableDrag.prototype.dragStart = function (event, self, item) {
-  // Create a new dragObject recording the pointer information.
-  self.dragObject = {};
-  self.dragObject.initOffset = self.getPointerOffset(item, event);
-  self.dragObject.initPointerCoords = self.pointerCoords(event);
-  if (self.indentEnabled) {
-    self.dragObject.indentPointerPos = self.dragObject.initPointerCoords;
-  }
-
-  // If there's a lingering row object from the keyboard, remove its focus.
-  if (self.rowObject) {
-    $(self.rowObject.element).find('a.tabledrag-handle').trigger('blur');
-  }
-
-  // Create a new rowObject for manipulation of this row.
-  self.rowObject = new self.row(item, 'pointer', self.indentEnabled, self.maxDepth, true);
-
-  // Save the position of the table.
-  self.table.topY = $(self.table).offset().top;
-  self.table.bottomY = self.table.topY + self.table.offsetHeight;
-
-  // Add classes to the handle and row.
-  $(item).addClass('drag');
-
-  // Set the document to use the move cursor during drag.
-  $('body').addClass('drag');
-  if (self.oldRowElement) {
-    $(self.oldRowElement).removeClass('drag-previous');
-  }
-};
-
-/**
- * Pointer movement handler, bound to document.
- */
-Drupal.tableDrag.prototype.dragRow = function (event, self) {
-  if (self.dragObject) {
-    self.currentPointerCoords = self.pointerCoords(event);
-    var y = self.currentPointerCoords.y - self.dragObject.initOffset.y;
-    var x = self.currentPointerCoords.x - self.dragObject.initOffset.x;
-
-    // Check for row swapping and vertical scrolling.
-    if (y !== self.oldY) {
-      self.rowObject.direction = y > self.oldY ? 'down' : 'up';
-      self.oldY = y; // Update the old value.
-
-      // Check if the window should be scrolled (and how fast).
-      var scrollAmount = self.checkScroll(self.currentPointerCoords.y);
-      // Stop any current scrolling.
-      clearInterval(self.scrollInterval);
-      // Continue scrolling if the mouse has moved in the scroll direction.
-      if (scrollAmount > 0 && self.rowObject.direction === 'down' || scrollAmount < 0 && self.rowObject.direction === 'up') {
-        self.setScroll(scrollAmount);
-      }
+  };
 
-      // If we have a valid target, perform the swap and restripe the table.
-      var currentRow = self.findDropTargetRow(x, y);
-      if (currentRow) {
-        if (self.rowObject.direction === 'down') {
-          self.rowObject.swap('after', currentRow, self);
+  /**
+   * Pointer movement handler, bound to document.
+   */
+  Drupal.tableDrag.prototype.dragRow = function (event, self) {
+    if (self.dragObject) {
+      self.currentPointerCoords = self.pointerCoords(event);
+      var y = self.currentPointerCoords.y - self.dragObject.initOffset.y;
+      var x = self.currentPointerCoords.x - self.dragObject.initOffset.x;
+
+      // Check for row swapping and vertical scrolling.
+      if (y !== self.oldY) {
+        self.rowObject.direction = y > self.oldY ? 'down' : 'up';
+        self.oldY = y; // Update the old value.
+
+        // Check if the window should be scrolled (and how fast).
+        var scrollAmount = self.checkScroll(self.currentPointerCoords.y);
+        // Stop any current scrolling.
+        clearInterval(self.scrollInterval);
+        // Continue scrolling if the mouse has moved in the scroll direction.
+        if (scrollAmount > 0 && self.rowObject.direction === 'down' || scrollAmount < 0 && self.rowObject.direction === 'up') {
+          self.setScroll(scrollAmount);
         }
-        else {
-          self.rowObject.swap('before', currentRow, self);
+
+        // If we have a valid target, perform the swap and restripe the table.
+        var currentRow = self.findDropTargetRow(x, y);
+        if (currentRow) {
+          if (self.rowObject.direction === 'down') {
+            self.rowObject.swap('after', currentRow, self);
+          }
+          else {
+            self.rowObject.swap('before', currentRow, self);
+          }
+          self.restripeTable();
         }
-        self.restripeTable();
       }
-    }
 
-    // Similar to row swapping, handle indentations.
-    if (self.indentEnabled) {
-      var xDiff = self.currentPointerCoords.x - self.dragObject.indentPointerPos.x;
-      // Set the number of indentations the pointer has been moved left or right.
-      var indentDiff = Math.round(xDiff / self.indentAmount * self.rtl);
-      // Indent the row with our estimated diff, which may be further
-      // restricted according to the rows around this row.
-      var indentChange = self.rowObject.indent(indentDiff);
-      // Update table and pointer indentations.
-      self.dragObject.indentPointerPos.x += self.indentAmount * indentChange * self.rtl;
-      self.indentCount = Math.max(self.indentCount, self.rowObject.indents);
+      // Similar to row swapping, handle indentations.
+      if (self.indentEnabled) {
+        var xDiff = self.currentPointerCoords.x - self.dragObject.indentPointerPos.x;
+        // Set the number of indentations the pointer has been moved left or right.
+        var indentDiff = Math.round(xDiff / self.indentAmount * self.rtl);
+        // Indent the row with our estimated diff, which may be further
+        // restricted according to the rows around this row.
+        var indentChange = self.rowObject.indent(indentDiff);
+        // Update table and pointer indentations.
+        self.dragObject.indentPointerPos.x += self.indentAmount * indentChange * self.rtl;
+        self.indentCount = Math.max(self.indentCount, self.rowObject.indents);
+      }
+
+      return false;
     }
+  };
 
-    return false;
-  }
-};
-
-/**
- * Pointerup behavior.
- */
-Drupal.tableDrag.prototype.dropRow = function (event, self) {
-  var droppedRow, $droppedRow;
-
-  // Drop row functionality.
-  if (self.rowObject !== null) {
-    droppedRow = self.rowObject.element;
-    $droppedRow = $(droppedRow);
-    // The row is already in the right place so we just release it.
-    if (self.rowObject.changed === true) {
-      // Update the fields in the dropped row.
-      self.updateFields(droppedRow);
-
-      // If a setting exists for affecting the entire group, update all the
-      // fields in the entire dragged group.
-      for (var group in self.tableSettings) {
-        if (self.tableSettings.hasOwnProperty(group)) {
-          var rowSettings = self.rowSettings(group, droppedRow);
-          if (rowSettings.relationship === 'group') {
-            for (var n in self.rowObject.children) {
-              if (self.rowObject.children.hasOwnProperty(n)) {
-                self.updateField(self.rowObject.children[n], group);
+  /**
+   * Pointerup behavior.
+   */
+  Drupal.tableDrag.prototype.dropRow = function (event, self) {
+    var droppedRow, $droppedRow;
+
+    // Drop row functionality.
+    if (self.rowObject !== null) {
+      droppedRow = self.rowObject.element;
+      $droppedRow = $(droppedRow);
+      // The row is already in the right place so we just release it.
+      if (self.rowObject.changed === true) {
+        // Update the fields in the dropped row.
+        self.updateFields(droppedRow);
+
+        // If a setting exists for affecting the entire group, update all the
+        // fields in the entire dragged group.
+        for (var group in self.tableSettings) {
+          if (self.tableSettings.hasOwnProperty(group)) {
+            var rowSettings = self.rowSettings(group, droppedRow);
+            if (rowSettings.relationship === 'group') {
+              for (var n in self.rowObject.children) {
+                if (self.rowObject.children.hasOwnProperty(n)) {
+                  self.updateField(self.rowObject.children[n], group);
+                }
               }
             }
           }
         }
+
+        self.rowObject.markChanged();
+        if (self.changed === false) {
+          $(Drupal.theme('tableDragChangedWarning')).insertBefore(self.table).hide().fadeIn('slow');
+          self.changed = true;
+        }
       }
 
-      self.rowObject.markChanged();
-      if (self.changed === false) {
-        $(Drupal.theme('tableDragChangedWarning')).insertBefore(self.table).hide().fadeIn('slow');
-        self.changed = true;
+      if (self.indentEnabled) {
+        self.rowObject.removeIndentClasses();
+      }
+      if (self.oldRowElement) {
+        $(self.oldRowElement).removeClass('drag-previous');
       }
+      $droppedRow.removeClass('drag').addClass('drag-previous');
+      self.oldRowElement = droppedRow;
+      self.onDrop();
+      self.rowObject = null;
     }
 
-    if (self.indentEnabled) {
-      self.rowObject.removeIndentClasses();
-    }
-    if (self.oldRowElement) {
-      $(self.oldRowElement).removeClass('drag-previous');
+    // Functionality specific only to pointerup events.
+    if (self.dragObject !== null) {
+      self.dragObject = null;
+      $('body').removeClass('drag');
+      clearInterval(self.scrollInterval);
     }
-    $droppedRow.removeClass('drag').addClass('drag-previous');
-    self.oldRowElement = droppedRow;
-    self.onDrop();
-    self.rowObject = null;
-  }
-
-  // Functionality specific only to pointerup events.
-  if (self.dragObject !== null) {
-    self.dragObject = null;
-    $('body').removeClass('drag');
-    clearInterval(self.scrollInterval);
-  }
-};
-
-/**
- * Get the coordinates from the event (allowing for browser differences).
- */
-Drupal.tableDrag.prototype.pointerCoords = function (event) {
-  if (event.pageX || event.pageY) {
-    return { x: event.pageX, y: event.pageY };
-  }
-  return {
-    x: event.clientX + document.body.scrollLeft - document.body.clientLeft,
-    y: event.clientY + document.body.scrollTop  - document.body.clientTop
   };
-};
-
-/**
- * Given a target element and a pointer event, get the event offset from that
- * element. To do this we need the element's position and the target position.
- */
-Drupal.tableDrag.prototype.getPointerOffset = function (target, event) {
-  var docPos = $(target).offset();
-  var pointerPos = this.pointerCoords(event);
-  return { x: pointerPos.x - docPos.left, y: pointerPos.y - docPos.top };
-};
-
-/**
- * Find the row the mouse is currently over. This row is then taken and swapped
- * with the one being dragged.
- *
- * @param x
- *   The x coordinate of the mouse on the page (not the screen).
- * @param y
- *   The y coordinate of the mouse on the page (not the screen).
- */
-Drupal.tableDrag.prototype.findDropTargetRow = function (x, y) {
-  var rows = $(this.table.tBodies[0].rows).not(':hidden');
-  for (var n = 0; n < rows.length; n++) {
-    var row = rows[n];
-    var $row = $(row);
-    var rowY = $row.offset().top;
-    var rowHeight;
-    // Because Safari does not report offsetHeight on table rows, but does on
-    // table cells, grab the firstChild of the row and use that instead.
-    // http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari.
-    if (row.offsetHeight === 0) {
-      rowHeight = parseInt(row.firstChild.offsetHeight, 10) / 2;
-    }
-    // Other browsers.
-    else {
-      rowHeight = parseInt(row.offsetHeight, 10) / 2;
+
+  /**
+   * Get the coordinates from the event (allowing for browser differences).
+   */
+  Drupal.tableDrag.prototype.pointerCoords = function (event) {
+    if (event.pageX || event.pageY) {
+      return { x: event.pageX, y: event.pageY };
     }
+    return {
+      x: event.clientX + document.body.scrollLeft - document.body.clientLeft,
+      y: event.clientY + document.body.scrollTop - document.body.clientTop
+    };
+  };
+
+  /**
+   * Given a target element and a pointer event, get the event offset from that
+   * element. To do this we need the element's position and the target position.
+   */
+  Drupal.tableDrag.prototype.getPointerOffset = function (target, event) {
+    var docPos = $(target).offset();
+    var pointerPos = this.pointerCoords(event);
+    return { x: pointerPos.x - docPos.left, y: pointerPos.y - docPos.top };
+  };
+
+  /**
+   * Find the row the mouse is currently over. This row is then taken and swapped
+   * with the one being dragged.
+   *
+   * @param x
+   *   The x coordinate of the mouse on the page (not the screen).
+   * @param y
+   *   The y coordinate of the mouse on the page (not the screen).
+   */
+  Drupal.tableDrag.prototype.findDropTargetRow = function (x, y) {
+    var rows = $(this.table.tBodies[0].rows).not(':hidden');
+    for (var n = 0; n < rows.length; n++) {
+      var row = rows[n];
+      var $row = $(row);
+      var rowY = $row.offset().top;
+      var rowHeight;
+      // Because Safari does not report offsetHeight on table rows, but does on
+      // table cells, grab the firstChild of the row and use that instead.
+      // http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari.
+      if (row.offsetHeight === 0) {
+        rowHeight = parseInt(row.firstChild.offsetHeight, 10) / 2;
+      }
+      // Other browsers.
+      else {
+        rowHeight = parseInt(row.offsetHeight, 10) / 2;
+      }
 
-    // Because we always insert before, we need to offset the height a bit.
-    if ((y > (rowY - rowHeight)) && (y < (rowY + rowHeight))) {
-      if (this.indentEnabled) {
-        // Check that this row is not a child of the row being dragged.
-        for (n in this.rowObject.group) {
-          if (this.rowObject.group[n] === row) {
+      // Because we always insert before, we need to offset the height a bit.
+      if ((y > (rowY - rowHeight)) && (y < (rowY + rowHeight))) {
+        if (this.indentEnabled) {
+          // Check that this row is not a child of the row being dragged.
+          for (n in this.rowObject.group) {
+            if (this.rowObject.group[n] === row) {
+              return null;
+            }
+          }
+        }
+        else {
+          // Do not allow a row to be swapped with itself.
+          if (row === this.rowObject.element) {
             return null;
           }
         }
-      }
-      else {
-        // Do not allow a row to be swapped with itself.
-        if (row === this.rowObject.element) {
+
+        // Check that swapping with this row is allowed.
+        if (!this.rowObject.isValidSwap(row)) {
           return null;
         }
-      }
 
-      // Check that swapping with this row is allowed.
-      if (!this.rowObject.isValidSwap(row)) {
-        return null;
+        // We may have found the row the mouse just passed over, but it doesn't
+        // take into account hidden rows. Skip backwards until we find a draggable
+        // row.
+        while ($row.is(':hidden') && $row.prev('tr').is(':hidden')) {
+          $row = $row.prev('tr').eq(0);
+          row = $row.get(0);
+        }
+        return row;
       }
+    }
+    return null;
+  };
 
-      // We may have found the row the mouse just passed over, but it doesn't
-      // take into account hidden rows. Skip backwards until we find a draggable
-      // row.
-      while ($row.is(':hidden') && $row.prev('tr').is(':hidden')) {
-        $row = $row.prev('tr').eq(0);
-        row = $row.get(0);
+  /**
+   * After the row is dropped, update the table fields according to the settings
+   * set for this table.
+   *
+   * @param changedRow
+   *   DOM object for the row that was just dropped.
+   */
+  Drupal.tableDrag.prototype.updateFields = function (changedRow) {
+    for (var group in this.tableSettings) {
+      if (this.tableSettings.hasOwnProperty(group)) {
+        // Each group may have a different setting for relationship, so we find
+        // the source rows for each separately.
+        this.updateField(changedRow, group);
       }
-      return row;
     }
-  }
-  return null;
-};
-
-/**
- * After the row is dropped, update the table fields according to the settings
- * set for this table.
- *
- * @param changedRow
- *   DOM object for the row that was just dropped.
- */
-Drupal.tableDrag.prototype.updateFields = function (changedRow) {
-  for (var group in this.tableSettings) {
-    if (this.tableSettings.hasOwnProperty(group)) {
-      // Each group may have a different setting for relationship, so we find
-      // the source rows for each separately.
-      this.updateField(changedRow, group);
+  };
+
+  /**
+   * After the row is dropped, update a single table field according to specific
+   * settings.
+   *
+   * @param changedRow
+   *   DOM object for the row that was just dropped.
+   * @param group
+   *   The settings group on which field updates will occur.
+   */
+  Drupal.tableDrag.prototype.updateField = function (changedRow, group) {
+    var rowSettings = this.rowSettings(group, changedRow);
+    var $changedRow = $(changedRow);
+    var sourceRow;
+    var $previousRow;
+    var previousRow;
+    var useSibling;
+    // Set the row as its own target.
+    if (rowSettings.relationship === 'self' || rowSettings.relationship === 'group') {
+      sourceRow = changedRow;
     }
-  }
-};
-
-/**
- * After the row is dropped, update a single table field according to specific
- * settings.
- *
- * @param changedRow
- *   DOM object for the row that was just dropped.
- * @param group
- *   The settings group on which field updates will occur.
- */
-Drupal.tableDrag.prototype.updateField = function (changedRow, group) {
-  var rowSettings = this.rowSettings(group, changedRow);
-  var $changedRow = $(changedRow);
-  var sourceRow;
-  var $previousRow;
-  var previousRow;
-  var useSibling;
-  // Set the row as its own target.
-  if (rowSettings.relationship === 'self' || rowSettings.relationship === 'group') {
-    sourceRow = changedRow;
-  }
-  // Siblings are easy, check previous and next rows.
-  else if (rowSettings.relationship === 'sibling') {
-    $previousRow = $changedRow.prev('tr').eq(0);
-    previousRow = $previousRow.get(0);
-    var $nextRow = $changedRow.next('tr').eq(0);
-    var nextRow = $nextRow.get(0);
-    sourceRow = changedRow;
-    if ($previousRow.is('.draggable') && $previousRow.find('.' + group).length) {
-      if (this.indentEnabled) {
-        if ($previousRow.find('.indentations').length === $changedRow.find('.indentations').length) {
+    // Siblings are easy, check previous and next rows.
+    else if (rowSettings.relationship === 'sibling') {
+      $previousRow = $changedRow.prev('tr').eq(0);
+      previousRow = $previousRow.get(0);
+      var $nextRow = $changedRow.next('tr').eq(0);
+      var nextRow = $nextRow.get(0);
+      sourceRow = changedRow;
+      if ($previousRow.is('.draggable') && $previousRow.find('.' + group).length) {
+        if (this.indentEnabled) {
+          if ($previousRow.find('.indentations').length === $changedRow.find('.indentations').length) {
+            sourceRow = previousRow;
+          }
+        }
+        else {
           sourceRow = previousRow;
         }
       }
-      else {
-        sourceRow = previousRow;
-      }
-    }
-    else if ($nextRow.is('.draggable') && $nextRow.find('.' + group).length) {
-      if (this.indentEnabled) {
-        if ($nextRow.find('.indentations').length === $changedRow.find('.indentations').length) {
+      else if ($nextRow.is('.draggable') && $nextRow.find('.' + group).length) {
+        if (this.indentEnabled) {
+          if ($nextRow.find('.indentations').length === $changedRow.find('.indentations').length) {
+            sourceRow = nextRow;
+          }
+        }
+        else {
           sourceRow = nextRow;
         }
       }
-      else {
-        sourceRow = nextRow;
-      }
     }
-  }
-  // Parents, look up the tree until we find a field not in this group.
-  // Go up as many parents as indentations in the changed row.
-  else if (rowSettings.relationship === 'parent') {
-    $previousRow = $changedRow.prev('tr');
-    previousRow = $previousRow;
-    while ($previousRow.length && $previousRow.find('.indentation').length >= this.rowObject.indents) {
-      $previousRow = $previousRow.prev('tr');
+    // Parents, look up the tree until we find a field not in this group.
+    // Go up as many parents as indentations in the changed row.
+    else if (rowSettings.relationship === 'parent') {
+      $previousRow = $changedRow.prev('tr');
       previousRow = $previousRow;
+      while ($previousRow.length && $previousRow.find('.indentation').length >= this.rowObject.indents) {
+        $previousRow = $previousRow.prev('tr');
+        previousRow = $previousRow;
+      }
+      // If we found a row.
+      if ($previousRow.length) {
+        sourceRow = $previousRow.get(0);
+      }
+      // Otherwise we went all the way to the left of the table without finding
+      // a parent, meaning this item has been placed at the root level.
+      else {
+        // Use the first row in the table as source, because it's guaranteed to
+        // be at the root level. Find the first item, then compare this row
+        // against it as a sibling.
+        sourceRow = $(this.table).find('tr.draggable:first').get(0);
+        if (sourceRow === this.rowObject.element) {
+          sourceRow = $(this.rowObject.group[this.rowObject.group.length - 1]).next('tr.draggable').get(0);
+        }
+        useSibling = true;
+      }
     }
-    // If we found a row.
-    if ($previousRow.length) {
-      sourceRow = $previousRow.get(0);
+
+    // Because we may have moved the row from one category to another,
+    // take a look at our sibling and borrow its sources and targets.
+    this.copyDragClasses(sourceRow, changedRow, group);
+    rowSettings = this.rowSettings(group, changedRow);
+
+    // In the case that we're looking for a parent, but the row is at the top
+    // of the tree, copy our sibling's values.
+    if (useSibling) {
+      rowSettings.relationship = 'sibling';
+      rowSettings.source = rowSettings.target;
     }
-    // Otherwise we went all the way to the left of the table without finding
-    // a parent, meaning this item has been placed at the root level.
-    else {
-      // Use the first row in the table as source, because it's guaranteed to
-      // be at the root level. Find the first item, then compare this row
-      // against it as a sibling.
-      sourceRow = $(this.table).find('tr.draggable:first').get(0);
-      if (sourceRow === this.rowObject.element) {
-        sourceRow = $(this.rowObject.group[this.rowObject.group.length - 1]).next('tr.draggable').get(0);
+
+    var targetClass = '.' + rowSettings.target;
+    var targetElement = $changedRow.find(targetClass).get(0);
+
+    // Check if a target element exists in this row.
+    if (targetElement) {
+      var sourceClass = '.' + rowSettings.source;
+      var sourceElement = $(sourceClass, sourceRow).get(0);
+      switch (rowSettings.action) {
+        case 'depth':
+          // Get the depth of the target row.
+          targetElement.value = $(sourceElement).closest('tr').find('.indentation').length;
+          break;
+        case 'match':
+          // Update the value.
+          targetElement.value = sourceElement.value;
+          break;
+        case 'order':
+          var siblings = this.rowObject.findSiblings(rowSettings);
+          if ($(targetElement).is('select')) {
+            // Get a list of acceptable values.
+            var values = [];
+            $(targetElement).find('option').each(function () {
+              values.push(this.value);
+            });
+            var maxVal = values[values.length - 1];
+            // Populate the values in the siblings.
+            $(siblings).find(targetClass).each(function () {
+              // If there are more items than possible values, assign the maximum value to the row.
+              if (values.length > 0) {
+                this.value = values.shift();
+              }
+              else {
+                this.value = maxVal;
+              }
+            });
+          }
+          else {
+            // Assume a numeric input field.
+            var weight = parseInt($(siblings[0]).find(targetClass).val(), 10) || 0;
+            $(siblings).find(targetClass).each(function () {
+              this.value = weight;
+              weight++;
+            });
+          }
+          break;
       }
-      useSibling = true;
     }
-  }
-
-  // Because we may have moved the row from one category to another,
-  // take a look at our sibling and borrow its sources and targets.
-  this.copyDragClasses(sourceRow, changedRow, group);
-  rowSettings = this.rowSettings(group, changedRow);
-
-  // In the case that we're looking for a parent, but the row is at the top
-  // of the tree, copy our sibling's values.
-  if (useSibling) {
-    rowSettings.relationship = 'sibling';
-    rowSettings.source = rowSettings.target;
-  }
-
-  var targetClass = '.' + rowSettings.target;
-  var targetElement = $changedRow.find(targetClass).get(0);
-
-  // Check if a target element exists in this row.
-  if (targetElement) {
-    var sourceClass = '.' + rowSettings.source;
-    var sourceElement = $(sourceClass, sourceRow).get(0);
-    switch (rowSettings.action) {
-      case 'depth':
-        // Get the depth of the target row.
-        targetElement.value = $(sourceElement).closest('tr').find('.indentation').length;
-        break;
-      case 'match':
-        // Update the value.
-        targetElement.value = sourceElement.value;
-        break;
-      case 'order':
-        var siblings = this.rowObject.findSiblings(rowSettings);
-        if ($(targetElement).is('select')) {
-          // Get a list of acceptable values.
-          var values = [];
-          $(targetElement).find('option').each(function () {
-            values.push(this.value);
-          });
-          var maxVal = values[values.length - 1];
-          // Populate the values in the siblings.
-          $(siblings).find(targetClass).each(function () {
-            // If there are more items than possible values, assign the maximum value to the row.
-            if (values.length > 0) {
-              this.value = values.shift();
-            }
-            else {
-              this.value = maxVal;
-            }
-          });
-        }
-        else {
-          // Assume a numeric input field.
-          var weight = parseInt($(siblings[0]).find(targetClass).val(), 10) || 0;
-          $(siblings).find(targetClass).each(function () {
-            this.value = weight;
-            weight++;
-          });
-        }
-        break;
+  };
+
+  /**
+   * Copy all special tableDrag classes from one row's form elements to a
+   * different one, removing any special classes that the destination row
+   * may have had.
+   */
+  Drupal.tableDrag.prototype.copyDragClasses = function (sourceRow, targetRow, group) {
+    var sourceElement = $(sourceRow).find('.' + group);
+    var targetElement = $(targetRow).find('.' + group);
+    if (sourceElement.length && targetElement.length) {
+      targetElement[0].className = sourceElement[0].className;
     }
-  }
-};
-
-/**
- * Copy all special tableDrag classes from one row's form elements to a
- * different one, removing any special classes that the destination row
- * may have had.
- */
-Drupal.tableDrag.prototype.copyDragClasses = function (sourceRow, targetRow, group) {
-  var sourceElement = $(sourceRow).find('.' + group);
-  var targetElement = $(targetRow).find('.' + group);
-  if (sourceElement.length && targetElement.length) {
-    targetElement[0].className = sourceElement[0].className;
-  }
-};
-
-Drupal.tableDrag.prototype.checkScroll = function (cursorY) {
-  var de  = document.documentElement;
-  var b  = document.body;
-
-  var windowHeight = this.windowHeight = window.innerHeight || (de.clientHeight && de.clientWidth !== 0 ? de.clientHeight : b.offsetHeight);
-  var scrollY = this.scrollY = (document.all ? (!de.scrollTop ? b.scrollTop : de.scrollTop) : (window.pageYOffset ? window.pageYOffset : window.scrollY));
-  var trigger = this.scrollSettings.trigger;
-  var delta = 0;
-
-  // Return a scroll speed relative to the edge of the screen.
-  if (cursorY - scrollY > windowHeight - trigger) {
-    delta = trigger / (windowHeight + scrollY - cursorY);
-    delta = (delta > 0 && delta < trigger) ? delta : trigger;
-    return delta * this.scrollSettings.amount;
-  }
-  else if (cursorY - scrollY < trigger) {
-    delta = trigger / (cursorY - scrollY);
-    delta = (delta > 0 && delta < trigger) ? delta : trigger;
-    return -delta * this.scrollSettings.amount;
-  }
-};
-
-Drupal.tableDrag.prototype.setScroll = function (scrollAmount) {
-  var self = this;
-
-  this.scrollInterval = setInterval(function () {
-    // Update the scroll values stored in the object.
-    self.checkScroll(self.currentPointerCoords.y);
-    var aboveTable = self.scrollY > self.table.topY;
-    var belowTable = self.scrollY + self.windowHeight < self.table.bottomY;
-    if (scrollAmount > 0 && belowTable || scrollAmount < 0 && aboveTable) {
-      window.scrollBy(0, scrollAmount);
+  };
+
+  Drupal.tableDrag.prototype.checkScroll = function (cursorY) {
+    var de = document.documentElement;
+    var b = document.body;
+
+    var windowHeight = this.windowHeight = window.innerHeight || (de.clientHeight && de.clientWidth !== 0 ? de.clientHeight : b.offsetHeight);
+    var scrollY = this.scrollY = (document.all ? (!de.scrollTop ? b.scrollTop : de.scrollTop) : (window.pageYOffset ? window.pageYOffset : window.scrollY));
+    var trigger = this.scrollSettings.trigger;
+    var delta = 0;
+
+    // Return a scroll speed relative to the edge of the screen.
+    if (cursorY - scrollY > windowHeight - trigger) {
+      delta = trigger / (windowHeight + scrollY - cursorY);
+      delta = (delta > 0 && delta < trigger) ? delta : trigger;
+      return delta * this.scrollSettings.amount;
     }
-  }, this.scrollSettings.interval);
-};
-
-Drupal.tableDrag.prototype.restripeTable = function () {
-  // :even and :odd are reversed because jQuery counts from 0 and
-  // we count from 1, so we're out of sync.
-  // Match immediate children of the parent element to allow nesting.
-  $(this.table).find('> tbody > tr.draggable:visible, > tr.draggable:visible')
-    .removeClass('odd even')
-    .filter(':odd').addClass('even').end()
-    .filter(':even').addClass('odd');
-};
-
-/**
- * Stub function. Allows a custom handler when a row begins dragging.
- */
-Drupal.tableDrag.prototype.onDrag = function () {
-  return null;
-};
-
-/**
- * Stub function. Allows a custom handler when a row is dropped.
- */
-Drupal.tableDrag.prototype.onDrop = function () {
-  return null;
-};
-
-/**
- * Constructor to make a new object to manipulate a table row.
- *
- * @param tableRow
- *   The DOM element for the table row we will be manipulating.
- * @param method
- *   The method in which this row is being moved. Either 'keyboard' or 'mouse'.
- * @param indentEnabled
- *   Whether the containing table uses indentations. Used for optimizations.
- * @param maxDepth
- *   The maximum amount of indentations this row may contain.
- * @param addClasses
- *   Whether we want to add classes to this row to indicate child relationships.
- */
-Drupal.tableDrag.prototype.row = function (tableRow, method, indentEnabled, maxDepth, addClasses) {
-  var $tableRow = $(tableRow);
-
-  this.element = tableRow;
-  this.method = method;
-  this.group = [tableRow];
-  this.groupDepth = $tableRow.find('.indentation').length;
-  this.changed = false;
-  this.table = $tableRow.closest('table')[0];
-  this.indentEnabled = indentEnabled;
-  this.maxDepth = maxDepth;
-  this.direction = ''; // Direction the row is being moved.
-
-  if (this.indentEnabled) {
-    this.indents = $tableRow.find('.indentation').length;
-    this.children = this.findChildren(addClasses);
-    this.group = $.merge(this.group, this.children);
-    // Find the depth of this entire group.
-    for (var n = 0; n < this.group.length; n++) {
-      this.groupDepth = Math.max($(this.group[n]).find('.indentation').length, this.groupDepth);
+    else if (cursorY - scrollY < trigger) {
+      delta = trigger / (cursorY - scrollY);
+      delta = (delta > 0 && delta < trigger) ? delta : trigger;
+      return -delta * this.scrollSettings.amount;
     }
-  }
-};
-
-/**
- * Find all children of rowObject by indentation.
- *
- * @param addClasses
- *   Whether we want to add classes to this row to indicate child relationships.
- */
-Drupal.tableDrag.prototype.row.prototype.findChildren = function (addClasses) {
-  var parentIndentation = this.indents;
-  var currentRow = $(this.element, this.table).next('tr.draggable');
-  var rows = [];
-  var child = 0;
-  function rowIndentation(el, indentNum) {
-    var self = $(el);
-    if (child === 1 && (indentNum === parentIndentation)) {
-      self.addClass('tree-child-first');
+  };
+
+  Drupal.tableDrag.prototype.setScroll = function (scrollAmount) {
+    var self = this;
+
+    this.scrollInterval = setInterval(function () {
+      // Update the scroll values stored in the object.
+      self.checkScroll(self.currentPointerCoords.y);
+      var aboveTable = self.scrollY > self.table.topY;
+      var belowTable = self.scrollY + self.windowHeight < self.table.bottomY;
+      if (scrollAmount > 0 && belowTable || scrollAmount < 0 && aboveTable) {
+        window.scrollBy(0, scrollAmount);
+      }
+    }, this.scrollSettings.interval);
+  };
+
+  Drupal.tableDrag.prototype.restripeTable = function () {
+    // :even and :odd are reversed because jQuery counts from 0 and
+    // we count from 1, so we're out of sync.
+    // Match immediate children of the parent element to allow nesting.
+    $(this.table).find('> tbody > tr.draggable:visible, > tr.draggable:visible')
+      .removeClass('odd even')
+      .filter(':odd').addClass('even').end()
+      .filter(':even').addClass('odd');
+  };
+
+  /**
+   * Stub function. Allows a custom handler when a row begins dragging.
+   */
+  Drupal.tableDrag.prototype.onDrag = function () {
+    return null;
+  };
+
+  /**
+   * Stub function. Allows a custom handler when a row is dropped.
+   */
+  Drupal.tableDrag.prototype.onDrop = function () {
+    return null;
+  };
+
+  /**
+   * Constructor to make a new object to manipulate a table row.
+   *
+   * @param tableRow
+   *   The DOM element for the table row we will be manipulating.
+   * @param method
+   *   The method in which this row is being moved. Either 'keyboard' or 'mouse'.
+   * @param indentEnabled
+   *   Whether the containing table uses indentations. Used for optimizations.
+   * @param maxDepth
+   *   The maximum amount of indentations this row may contain.
+   * @param addClasses
+   *   Whether we want to add classes to this row to indicate child relationships.
+   */
+  Drupal.tableDrag.prototype.row = function (tableRow, method, indentEnabled, maxDepth, addClasses) {
+    var $tableRow = $(tableRow);
+
+    this.element = tableRow;
+    this.method = method;
+    this.group = [tableRow];
+    this.groupDepth = $tableRow.find('.indentation').length;
+    this.changed = false;
+    this.table = $tableRow.closest('table')[0];
+    this.indentEnabled = indentEnabled;
+    this.maxDepth = maxDepth;
+    this.direction = ''; // Direction the row is being moved.
+
+    if (this.indentEnabled) {
+      this.indents = $tableRow.find('.indentation').length;
+      this.children = this.findChildren(addClasses);
+      this.group = $.merge(this.group, this.children);
+      // Find the depth of this entire group.
+      for (var n = 0; n < this.group.length; n++) {
+        this.groupDepth = Math.max($(this.group[n]).find('.indentation').length, this.groupDepth);
+      }
     }
-    if (indentNum === parentIndentation) {
-      self.addClass('tree-child');
+  };
+
+  /**
+   * Find all children of rowObject by indentation.
+   *
+   * @param addClasses
+   *   Whether we want to add classes to this row to indicate child relationships.
+   */
+  Drupal.tableDrag.prototype.row.prototype.findChildren = function (addClasses) {
+    var parentIndentation = this.indents;
+    var currentRow = $(this.element, this.table).next('tr.draggable');
+    var rows = [];
+    var child = 0;
+    function rowIndentation(el, indentNum) {
+      var self = $(el);
+      if (child === 1 && (indentNum === parentIndentation)) {
+        self.addClass('tree-child-first');
+      }
+      if (indentNum === parentIndentation) {
+        self.addClass('tree-child');
+      }
+      else if (indentNum > parentIndentation) {
+        self.addClass('tree-child-horizontal');
+      }
     }
-    else if (indentNum > parentIndentation) {
-      self.addClass('tree-child-horizontal');
+    while (currentRow.length) {
+      // A greater indentation indicates this is a child.
+      if (currentRow.find('.indentation').length > parentIndentation) {
+        child++;
+        rows.push(currentRow[0]);
+        if (addClasses) {
+          currentRow.find('.indentation').each(rowIndentation);
+        }
+      }
+      else {
+        break;
+      }
+      currentRow = currentRow.next('tr.draggable');
     }
-  }
-  while (currentRow.length) {
-    // A greater indentation indicates this is a child.
-    if (currentRow.find('.indentation').length > parentIndentation) {
-      child++;
-      rows.push(currentRow[0]);
-      if (addClasses) {
-        currentRow.find('.indentation').each(rowIndentation);
+    if (addClasses && rows.length) {
+      $(rows[rows.length - 1]).find('.indentation:nth-child(' + (parentIndentation + 1) + ')').addClass('tree-child-last');
+    }
+    return rows;
+  };
+
+  /**
+   * Ensure that two rows are allowed to be swapped.
+   *
+   * @param row
+   *   DOM object for the row being considered for swapping.
+   */
+  Drupal.tableDrag.prototype.row.prototype.isValidSwap = function (row) {
+    var $row = $(row);
+    if (this.indentEnabled) {
+      var prevRow, nextRow;
+      if (this.direction === 'down') {
+        prevRow = row;
+        nextRow = $row.next('tr').get(0);
+      }
+      else {
+        prevRow = $row.prev('tr').get(0);
+        nextRow = row;
+      }
+      this.interval = this.validIndentInterval(prevRow, nextRow);
+
+      // We have an invalid swap if the valid indentations interval is empty.
+      if (this.interval.min > this.interval.max) {
+        return false;
       }
     }
-    else {
-      break;
+
+    // Do not let an un-draggable first row have anything put before it.
+    if (this.table.tBodies[0].rows[0] === row && $row.is(':not(.draggable)')) {
+      return false;
     }
-    currentRow = currentRow.next('tr.draggable');
-  }
-  if (addClasses && rows.length) {
-    $(rows[rows.length - 1]).find('.indentation:nth-child(' + (parentIndentation + 1) + ')').addClass('tree-child-last');
-  }
-  return rows;
-};
-
-/**
- * Ensure that two rows are allowed to be swapped.
- *
- * @param row
- *   DOM object for the row being considered for swapping.
- */
-Drupal.tableDrag.prototype.row.prototype.isValidSwap = function (row) {
-  var $row = $(row);
-  if (this.indentEnabled) {
-    var prevRow, nextRow;
-    if (this.direction === 'down') {
-      prevRow = row;
-      nextRow = $row.next('tr').get(0);
+
+    return true;
+  };
+
+  /**
+   * Perform the swap between two rows.
+   *
+   * @param position
+   *   Whether the swap will occur 'before' or 'after' the given row.
+   * @param row
+   *   DOM element what will be swapped with the row group.
+   */
+  Drupal.tableDrag.prototype.row.prototype.swap = function (position, row) {
+    // Makes sure only DOM object are passed to Drupal.detachBehaviors().
+    this.group.forEach(function (row) {
+      Drupal.detachBehaviors(row, drupalSettings, 'move');
+    });
+    $(row)[position](this.group);
+    // Makes sure only DOM object are passed to Drupal.attachBehaviors()s.
+    this.group.forEach(function (row) {
+      Drupal.attachBehaviors(row, drupalSettings);
+    });
+    this.changed = true;
+    this.onSwap(row);
+  };
+
+  /**
+   * Determine the valid indentations interval for the row at a given position
+   * in the table.
+   *
+   * @param prevRow
+   *   DOM object for the row before the tested position
+   *   (or null for first position in the table).
+   * @param nextRow
+   *   DOM object for the row after the tested position
+   *   (or null for last position in the table).
+   */
+  Drupal.tableDrag.prototype.row.prototype.validIndentInterval = function (prevRow, nextRow) {
+    var $prevRow = $(prevRow);
+    var minIndent, maxIndent;
+
+    // Minimum indentation:
+    // Do not orphan the next row.
+    minIndent = nextRow ? $(nextRow).find('.indentation').length : 0;
+
+    // Maximum indentation:
+    if (!prevRow || $prevRow.is(':not(.draggable)') || $(this.element).is('.tabledrag-root')) {
+      // Do not indent:
+      // - the first row in the table,
+      // - rows dragged below a non-draggable row,
+      // - 'root' rows.
+      maxIndent = 0;
     }
     else {
-      prevRow = $row.prev('tr').get(0);
-      nextRow = row;
+      // Do not go deeper than as a child of the previous row.
+      maxIndent = $prevRow.find('.indentation').length + ($prevRow.is('.tabledrag-leaf') ? 0 : 1);
+      // Limit by the maximum allowed depth for the table.
+      if (this.maxDepth) {
+        maxIndent = Math.min(maxIndent, this.maxDepth - (this.groupDepth - this.indents));
+      }
     }
-    this.interval = this.validIndentInterval(prevRow, nextRow);
 
-    // We have an invalid swap if the valid indentations interval is empty.
-    if (this.interval.min > this.interval.max) {
-      return false;
-    }
-  }
-
-  // Do not let an un-draggable first row have anything put before it.
-  if (this.table.tBodies[0].rows[0] === row && $row.is(':not(.draggable)')) {
-    return false;
-  }
-
-  return true;
-};
-
-/**
- * Perform the swap between two rows.
- *
- * @param position
- *   Whether the swap will occur 'before' or 'after' the given row.
- * @param row
- *   DOM element what will be swapped with the row group.
- */
-Drupal.tableDrag.prototype.row.prototype.swap = function (position, row) {
-  // Makes sure only DOM object are passed to Drupal.detachBehaviors().
-  this.group.forEach(function (row) {
-    Drupal.detachBehaviors(row, drupalSettings, 'move');
-  });
-  $(row)[position](this.group);
-  // Makes sure only DOM object are passed to Drupal.attachBehaviors()s.
-  this.group.forEach(function (row) {
-    Drupal.attachBehaviors(row, drupalSettings);
-  });
-  this.changed = true;
-  this.onSwap(row);
-};
-
-/**
- * Determine the valid indentations interval for the row at a given position
- * in the table.
- *
- * @param prevRow
- *   DOM object for the row before the tested position
- *   (or null for first position in the table).
- * @param nextRow
- *   DOM object for the row after the tested position
- *   (or null for last position in the table).
- */
-Drupal.tableDrag.prototype.row.prototype.validIndentInterval = function (prevRow, nextRow) {
-  var $prevRow = $(prevRow);
-  var minIndent, maxIndent;
-
-  // Minimum indentation:
-  // Do not orphan the next row.
-  minIndent = nextRow ? $(nextRow).find('.indentation').length : 0;
-
-  // Maximum indentation:
-  if (!prevRow || $prevRow.is(':not(.draggable)') || $(this.element).is('.tabledrag-root')) {
-    // Do not indent:
-    // - the first row in the table,
-    // - rows dragged below a non-draggable row,
-    // - 'root' rows.
-    maxIndent = 0;
-  }
-  else {
-    // Do not go deeper than as a child of the previous row.
-    maxIndent = $prevRow.find('.indentation').length + ($prevRow.is('.tabledrag-leaf') ? 0 : 1);
-    // Limit by the maximum allowed depth for the table.
-    if (this.maxDepth) {
-      maxIndent = Math.min(maxIndent, this.maxDepth - (this.groupDepth - this.indents));
+    return { 'min': minIndent, 'max': maxIndent };
+  };
+
+  /**
+   * Indent a row within the legal bounds of the table.
+   *
+   * @param indentDiff
+   *   The number of additional indentations proposed for the row (can be
+   *   positive or negative). This number will be adjusted to nearest valid
+   *   indentation level for the row.
+   */
+  Drupal.tableDrag.prototype.row.prototype.indent = function (indentDiff) {
+    var $group = $(this.group);
+    // Determine the valid indentations interval if not available yet.
+    if (!this.interval) {
+      var prevRow = $(this.element).prev('tr').get(0);
+      var nextRow = $group.filter(':last').next('tr').get(0);
+      this.interval = this.validIndentInterval(prevRow, nextRow);
     }
-  }
-
-  return { 'min': minIndent, 'max': maxIndent };
-};
-
-/**
- * Indent a row within the legal bounds of the table.
- *
- * @param indentDiff
- *   The number of additional indentations proposed for the row (can be
- *   positive or negative). This number will be adjusted to nearest valid
- *   indentation level for the row.
- */
-Drupal.tableDrag.prototype.row.prototype.indent = function (indentDiff) {
-  var $group = $(this.group);
-  // Determine the valid indentations interval if not available yet.
-  if (!this.interval) {
-    var prevRow = $(this.element).prev('tr').get(0);
-    var nextRow = $group.filter(':last').next('tr').get(0);
-    this.interval = this.validIndentInterval(prevRow, nextRow);
-  }
-
-  // Adjust to the nearest valid indentation.
-  var indent = this.indents + indentDiff;
-  indent = Math.max(indent, this.interval.min);
-  indent = Math.min(indent, this.interval.max);
-  indentDiff = indent - this.indents;
-
-  for (var n = 1; n <= Math.abs(indentDiff); n++) {
-    // Add or remove indentations.
-    if (indentDiff < 0) {
-      $group.find('.indentation:first').remove();
-      this.indents--;
+
+    // Adjust to the nearest valid indentation.
+    var indent = this.indents + indentDiff;
+    indent = Math.max(indent, this.interval.min);
+    indent = Math.min(indent, this.interval.max);
+    indentDiff = indent - this.indents;
+
+    for (var n = 1; n <= Math.abs(indentDiff); n++) {
+      // Add or remove indentations.
+      if (indentDiff < 0) {
+        $group.find('.indentation:first').remove();
+        this.indents--;
+      }
+      else {
+        $group.find('td:first').prepend(Drupal.theme('tableDragIndentation'));
+        this.indents++;
+      }
     }
-    else {
-      $group.find('td:first').prepend(Drupal.theme('tableDragIndentation'));
-      this.indents++;
+    if (indentDiff) {
+      // Update indentation for this row.
+      this.changed = true;
+      this.groupDepth += indentDiff;
+      this.onIndent();
     }
-  }
-  if (indentDiff) {
-    // Update indentation for this row.
-    this.changed = true;
-    this.groupDepth += indentDiff;
-    this.onIndent();
-  }
-
-  return indentDiff;
-};
-
-/**
- * Find all siblings for a row, either according to its subgroup or indentation.
- * Note that the passed-in row is included in the list of siblings.
- *
- * @param settings
- *   The field settings we're using to identify what constitutes a sibling.
- */
-Drupal.tableDrag.prototype.row.prototype.findSiblings = function (rowSettings) {
-  var siblings = [];
-  var directions = ['prev', 'next'];
-  var rowIndentation = this.indents;
-  var checkRowIndentation;
-  for (var d = 0; d < directions.length; d++) {
-    var checkRow = $(this.element)[directions[d]]();
-    while (checkRow.length) {
-      // Check that the sibling contains a similar target field.
-      if (checkRow.find('.' + rowSettings.target)) {
-        // Either add immediately if this is a flat table, or check to ensure
-        // that this row has the same level of indentation.
-        if (this.indentEnabled) {
-          checkRowIndentation = checkRow.find('.indentation').length;
-        }
 
-        if (!(this.indentEnabled) || (checkRowIndentation === rowIndentation)) {
-          siblings.push(checkRow[0]);
+    return indentDiff;
+  };
+
+  /**
+   * Find all siblings for a row, either according to its subgroup or indentation.
+   * Note that the passed-in row is included in the list of siblings.
+   *
+   * @param settings
+   *   The field settings we're using to identify what constitutes a sibling.
+   */
+  Drupal.tableDrag.prototype.row.prototype.findSiblings = function (rowSettings) {
+    var siblings = [];
+    var directions = ['prev', 'next'];
+    var rowIndentation = this.indents;
+    var checkRowIndentation;
+    for (var d = 0; d < directions.length; d++) {
+      var checkRow = $(this.element)[directions[d]]();
+      while (checkRow.length) {
+        // Check that the sibling contains a similar target field.
+        if (checkRow.find('.' + rowSettings.target)) {
+          // Either add immediately if this is a flat table, or check to ensure
+          // that this row has the same level of indentation.
+          if (this.indentEnabled) {
+            checkRowIndentation = checkRow.find('.indentation').length;
+          }
+
+          if (!(this.indentEnabled) || (checkRowIndentation === rowIndentation)) {
+            siblings.push(checkRow[0]);
+          }
+          else if (checkRowIndentation < rowIndentation) {
+            // No need to keep looking for siblings when we get to a parent.
+            break;
+          }
         }
-        else if (checkRowIndentation < rowIndentation) {
-          // No need to keep looking for siblings when we get to a parent.
+        else {
           break;
         }
+        checkRow = checkRow[directions[d]]();
       }
-      else {
-        break;
+      // Since siblings are added in reverse order for previous, reverse the
+      // completed list of previous siblings. Add the current row and continue.
+      if (directions[d] === 'prev') {
+        siblings.reverse();
+        siblings.push(this.element);
+      }
+    }
+    return siblings;
+  };
+
+  /**
+   * Remove indentation helper classes from the current row group.
+   */
+  Drupal.tableDrag.prototype.row.prototype.removeIndentClasses = function () {
+    for (var n in this.children) {
+      if (this.children.hasOwnProperty(n)) {
+        $(this.children[n]).find('.indentation')
+          .removeClass('tree-child')
+          .removeClass('tree-child-first')
+          .removeClass('tree-child-last')
+          .removeClass('tree-child-horizontal');
       }
-      checkRow = checkRow[directions[d]]();
     }
-    // Since siblings are added in reverse order for previous, reverse the
-    // completed list of previous siblings. Add the current row and continue.
-    if (directions[d] === 'prev') {
-      siblings.reverse();
-      siblings.push(this.element);
+  };
+
+  /**
+   * Add an asterisk or other marker to the changed row.
+   */
+  Drupal.tableDrag.prototype.row.prototype.markChanged = function () {
+    var marker = Drupal.theme('tableDragChangedMarker');
+    var cell = $(this.element).find('td:first');
+    if (cell.find('abbr.tabledrag-changed').length === 0) {
+      cell.append(marker);
     }
-  }
-  return siblings;
-};
-
-/**
- * Remove indentation helper classes from the current row group.
- */
-Drupal.tableDrag.prototype.row.prototype.removeIndentClasses = function () {
-  for (var n in this.children) {
-    if (this.children.hasOwnProperty(n)) {
-      $(this.children[n]).find('.indentation')
-        .removeClass('tree-child')
-        .removeClass('tree-child-first')
-        .removeClass('tree-child-last')
-        .removeClass('tree-child-horizontal');
+  };
+
+  /**
+   * Stub function. Allows a custom handler when a row is indented.
+   */
+  Drupal.tableDrag.prototype.row.prototype.onIndent = function () {
+    return null;
+  };
+
+  /**
+   * Stub function. Allows a custom handler when a row is swapped.
+   */
+  Drupal.tableDrag.prototype.row.prototype.onSwap = function (swappedRow) {
+    return null;
+  };
+
+  $.extend(Drupal.theme, {
+    tableDragChangedMarker: function () {
+      return '<abbr class="warning tabledrag-changed" title="' + Drupal.t('Changed') + '">*</abbr>';
+    },
+    tableDragIndentation: function () {
+      return '<div class="indentation">&nbsp;</div>';
+    },
+    tableDragChangedWarning: function () {
+      return '<div class="tabledrag-changed-warning messages messages--warning" role="alert">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('You have unsaved changes.') + '</div>';
     }
-  }
-};
-
-/**
- * Add an asterisk or other marker to the changed row.
- */
-Drupal.tableDrag.prototype.row.prototype.markChanged = function () {
-  var marker = Drupal.theme('tableDragChangedMarker');
-  var cell = $(this.element).find('td:first');
-  if (cell.find('abbr.tabledrag-changed').length === 0) {
-    cell.append(marker);
-  }
-};
-
-/**
- * Stub function. Allows a custom handler when a row is indented.
- */
-Drupal.tableDrag.prototype.row.prototype.onIndent = function () {
-  return null;
-};
-
-/**
- * Stub function. Allows a custom handler when a row is swapped.
- */
-Drupal.tableDrag.prototype.row.prototype.onSwap = function (swappedRow) {
-  return null;
-};
-
-$.extend(Drupal.theme, {
-  tableDragChangedMarker: function () {
-    return '<abbr class="warning tabledrag-changed" title="' + Drupal.t('Changed') + '">*</abbr>';
-  },
-  tableDragIndentation: function () {
-    return '<div class="indentation">&nbsp;</div>';
-  },
-  tableDragChangedWarning: function () {
-    return '<div class="tabledrag-changed-warning messages messages--warning" role="alert">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('You have unsaved changes.') + '</div>';
-  }
-});
+  });
 
 })(jQuery, Drupal, drupalSettings);
diff --git a/core/misc/tableheader.js b/core/misc/tableheader.js
index 2519304..d9357f7 100644
--- a/core/misc/tableheader.js
+++ b/core/misc/tableheader.js
@@ -1,254 +1,254 @@
 (function ($, Drupal, displace) {
 
-"use strict";
-
-/**
- * Attaches sticky table headers.
- */
-Drupal.behaviors.tableHeader = {
-  attach: function (context) {
-    $(window).one('scroll.TableHeaderInit', {context: context}, tableHeaderInitHandler);
-  }
-};
+  "use strict";
+
+  /**
+   * Attaches sticky table headers.
+   */
+  Drupal.behaviors.tableHeader = {
+    attach: function (context) {
+      $(window).one('scroll.TableHeaderInit', {context: context}, tableHeaderInitHandler);
+    }
+  };
 
-function scrollValue(position) {
-  return document.documentElement[position] || document.body[position];
-}
+  function scrollValue(position) {
+    return document.documentElement[position] || document.body[position];
+  }
 
 // Select and initialize sticky table headers.
-function tableHeaderInitHandler(e) {
-  var $tables = $(e.data.context).find('table.sticky-enabled').once('tableheader');
-  for (var i = 0, il = $tables.length; i < il; i++) {
-    TableHeader.tables.push(new TableHeader($tables[i]));
+  function tableHeaderInitHandler(e) {
+    var $tables = $(e.data.context).find('table.sticky-enabled').once('tableheader');
+    for (var i = 0, il = $tables.length; i < il; i++) {
+      TableHeader.tables.push(new TableHeader($tables[i]));
+    }
   }
-}
 
 // Helper method to loop through tables and execute a method.
-function forTables(method, arg) {
-  var tables = TableHeader.tables;
-  for (var i = 0, il = tables.length; i < il; i++) {
-    tables[i][method](arg);
+  function forTables(method, arg) {
+    var tables = TableHeader.tables;
+    for (var i = 0, il = tables.length; i < il; i++) {
+      tables[i][method](arg);
+    }
   }
-}
 
-function tableHeaderResizeHandler(e) {
-  forTables('recalculateSticky');
-}
+  function tableHeaderResizeHandler(e) {
+    forTables('recalculateSticky');
+  }
 
-function tableHeaderOnScrollHandler(e) {
-  forTables('onScroll');
-}
+  function tableHeaderOnScrollHandler(e) {
+    forTables('onScroll');
+  }
 
-function tableHeaderOffsetChangeHandler(e, offsets) {
-  forTables('stickyPosition', offsets.top);
-}
+  function tableHeaderOffsetChangeHandler(e, offsets) {
+    forTables('stickyPosition', offsets.top);
+  }
 
 // Bind event that need to change all tables.
-$(window).on({
-  /**
-   * When resizing table width can change, recalculate everything.
-   */
-  'resize.TableHeader': tableHeaderResizeHandler,
-
-  /**
-   * Bind only one event to take care of calling all scroll callbacks.
-   */
-  'scroll.TableHeader': tableHeaderOnScrollHandler
-});
+  $(window).on({
+    /**
+     * When resizing table width can change, recalculate everything.
+     */
+    'resize.TableHeader': tableHeaderResizeHandler,
+
+    /**
+     * Bind only one event to take care of calling all scroll callbacks.
+     */
+    'scroll.TableHeader': tableHeaderOnScrollHandler
+  });
 // Bind to custom Drupal events.
-$(document).on({
-  /**
-   * Recalculate columns width when window is resized and when show/hide
-   * weight is triggered.
-   */
-  'columnschange.TableHeader': tableHeaderResizeHandler,
-
-  /**
-   * Recalculate TableHeader.topOffset when viewport is resized
-   */
-  'drupalViewportOffsetChange.TableHeader': tableHeaderOffsetChangeHandler
-});
-
-/**
- * Constructor for the tableHeader object. Provides sticky table headers.
- *
- * TableHeader will make the current table header stick to the top of the page
- * if the table is very long.
- *
- * @param table
- *   DOM object for the table to add a sticky header to.
- *
- * @constructor
- */
-function TableHeader(table) {
-  var $table = $(table);
-
-  this.$originalTable = $table;
-  this.$originalHeader = $table.children('thead');
-  this.$originalHeaderCells = this.$originalHeader.find('> tr > th');
-  this.displayWeight = null;
-
-  this.$originalTable.addClass('sticky-table');
-  this.tableHeight = $table[0].clientHeight;
-  this.tableOffset = this.$originalTable.offset();
-
-  // React to columns change to avoid making checks in the scroll callback.
-  this.$originalTable.on('columnschange', {tableHeader: this}, function (e, display) {
-    var tableHeader = e.data.tableHeader;
-    if (tableHeader.displayWeight === null || tableHeader.displayWeight !== display) {
-      tableHeader.recalculateSticky();
-    }
-    tableHeader.displayWeight = display;
+  $(document).on({
+    /**
+     * Recalculate columns width when window is resized and when show/hide
+     * weight is triggered.
+     */
+    'columnschange.TableHeader': tableHeaderResizeHandler,
+
+    /**
+     * Recalculate TableHeader.topOffset when viewport is resized
+     */
+    'drupalViewportOffsetChange.TableHeader': tableHeaderOffsetChangeHandler
   });
 
-  // Create and display sticky header.
-  this.createSticky();
-}
-
-/**
- * Store the state of TableHeader.
- */
-$.extend(TableHeader, {
   /**
-   * This will store the state of all processed tables.
+   * Constructor for the tableHeader object. Provides sticky table headers.
    *
-   * @type {Array}
-   */
-  tables: []
-});
-
-/**
- * Extend TableHeader prototype.
- */
-$.extend(TableHeader.prototype, {
-  /**
-   * Minimum height in pixels for the table to have a sticky header.
-   */
-  minHeight: 100,
-
-  /**
-   * Absolute position of the table on the page.
-   */
-  tableOffset: null,
-
-  /**
-   * Absolute position of the table on the page.
-   */
-  tableHeight: null,
-
-  /**
-   * Boolean storing the sticky header visibility state.
+   * TableHeader will make the current table header stick to the top of the page
+   * if the table is very long.
+   *
+   * @param table
+   *   DOM object for the table to add a sticky header to.
+   *
+   * @constructor
    */
-  stickyVisible: false,
+  function TableHeader(table) {
+    var $table = $(table);
 
-  /**
-   * Create the duplicate header.
-   */
-  createSticky: function () {
-    // Clone the table header so it inherits original jQuery properties.
-    var $stickyHeader = this.$originalHeader.clone(true);
-    // Hide the table to avoid a flash of the header clone upon page load.
-    this.$stickyTable = $('<table class="sticky-header"/>')
-      .css({
-        visibility: 'hidden',
-        position: 'fixed',
-        top: '0px'
-      })
-      .append($stickyHeader)
-      .insertBefore(this.$originalTable);
-
-    this.$stickyHeaderCells = $stickyHeader.find('> tr > th');
-
-    // Initialize all computations.
-    this.recalculateSticky();
-  },
+    this.$originalTable = $table;
+    this.$originalHeader = $table.children('thead');
+    this.$originalHeaderCells = this.$originalHeader.find('> tr > th');
+    this.displayWeight = null;
 
-  /**
-   * Set absolute position of sticky.
-   *
-   * @param offsetTop
-   * @param offsetLeft
-   */
-  stickyPosition: function (offsetTop, offsetLeft) {
-    var css = {};
-    if (!isNaN(offsetTop)) {
-      css.top = offsetTop + 'px';
-    }
-    if (!isNaN(offsetLeft)) {
-      css.left = (this.tableOffset.left - offsetLeft) + 'px';
-    }
-    return this.$stickyTable.css(css);
-  },
+    this.$originalTable.addClass('sticky-table');
+    this.tableHeight = $table[0].clientHeight;
+    this.tableOffset = this.$originalTable.offset();
 
-  /**
-   * Returns true if sticky is currently visible.
-   */
-  checkStickyVisible: function () {
-    var scrollTop = scrollValue('scrollTop');
-    var tableTop = this.tableOffset.top - displace.offsets.top;
-    var tableBottom = tableTop + this.tableHeight;
-    var visible = false;
-
-    if (tableTop < scrollTop && scrollTop < (tableBottom - this.minHeight)) {
-      visible = true;
-    }
+    // React to columns change to avoid making checks in the scroll callback.
+    this.$originalTable.on('columnschange', {tableHeader: this}, function (e, display) {
+      var tableHeader = e.data.tableHeader;
+      if (tableHeader.displayWeight === null || tableHeader.displayWeight !== display) {
+        tableHeader.recalculateSticky();
+      }
+      tableHeader.displayWeight = display;
+    });
 
-    this.stickyVisible = visible;
-    return visible;
-  },
+    // Create and display sticky header.
+    this.createSticky();
+  }
 
   /**
-   * Check if sticky header should be displayed.
-   *
-   * This function is throttled to once every 250ms to avoid unnecessary calls.
-   *
-   * @param event
+   * Store the state of TableHeader.
    */
-  onScroll: function (e) {
-    this.checkStickyVisible();
-    // Track horizontal positioning relative to the viewport.
-    this.stickyPosition(null, scrollValue('scrollLeft'));
-    this.$stickyTable.css('visibility', this.stickyVisible ? 'visible' : 'hidden');
-  },
+  $.extend(TableHeader, {
+    /**
+     * This will store the state of all processed tables.
+     *
+     * @type {Array}
+     */
+    tables: []
+  });
 
   /**
-   * Event handler: recalculates position of the sticky table header.
-   *
-   * @param event
-   *   Event being triggered.
+   * Extend TableHeader prototype.
    */
-  recalculateSticky: function (event) {
-    // Update table size.
-    this.tableHeight = this.$originalTable[0].clientHeight;
-
-    // Update offset top.
-    displace.offsets.top = displace.calculateOffset('top');
-    this.tableOffset = this.$originalTable.offset();
-    this.stickyPosition(displace.offsets.top, scrollValue('scrollLeft'));
-
-    // Update columns width.
-    var $that = null;
-    var $stickyCell = null;
-    var display = null;
-    // Resize header and its cell widths.
-    // Only apply width to visible table cells. This prevents the header from
-    // displaying incorrectly when the sticky header is no longer visible.
-    for (var i = 0, il = this.$originalHeaderCells.length; i < il; i++) {
-      $that = $(this.$originalHeaderCells[i]);
-      $stickyCell = this.$stickyHeaderCells.eq($that.index());
-      display = $that.css('display');
-      if (display !== 'none') {
-        $stickyCell.css({'width': $that.css('width'), 'display': display});
+  $.extend(TableHeader.prototype, {
+    /**
+     * Minimum height in pixels for the table to have a sticky header.
+     */
+    minHeight: 100,
+
+    /**
+     * Absolute position of the table on the page.
+     */
+    tableOffset: null,
+
+    /**
+     * Absolute position of the table on the page.
+     */
+    tableHeight: null,
+
+    /**
+     * Boolean storing the sticky header visibility state.
+     */
+    stickyVisible: false,
+
+    /**
+     * Create the duplicate header.
+     */
+    createSticky: function () {
+      // Clone the table header so it inherits original jQuery properties.
+      var $stickyHeader = this.$originalHeader.clone(true);
+      // Hide the table to avoid a flash of the header clone upon page load.
+      this.$stickyTable = $('<table class="sticky-header"/>')
+        .css({
+          visibility: 'hidden',
+          position: 'fixed',
+          top: '0px'
+        })
+        .append($stickyHeader)
+        .insertBefore(this.$originalTable);
+
+      this.$stickyHeaderCells = $stickyHeader.find('> tr > th');
+
+      // Initialize all computations.
+      this.recalculateSticky();
+    },
+
+    /**
+     * Set absolute position of sticky.
+     *
+     * @param offsetTop
+     * @param offsetLeft
+     */
+    stickyPosition: function (offsetTop, offsetLeft) {
+      var css = {};
+      if (!isNaN(offsetTop)) {
+        css.top = offsetTop + 'px';
       }
-      else {
-        $stickyCell.css('display', 'none');
+      if (!isNaN(offsetLeft)) {
+        css.left = (this.tableOffset.left - offsetLeft) + 'px';
       }
+      return this.$stickyTable.css(css);
+    },
+
+    /**
+     * Returns true if sticky is currently visible.
+     */
+    checkStickyVisible: function () {
+      var scrollTop = scrollValue('scrollTop');
+      var tableTop = this.tableOffset.top - displace.offsets.top;
+      var tableBottom = tableTop + this.tableHeight;
+      var visible = false;
+
+      if (tableTop < scrollTop && scrollTop < (tableBottom - this.minHeight)) {
+        visible = true;
+      }
+
+      this.stickyVisible = visible;
+      return visible;
+    },
+
+    /**
+     * Check if sticky header should be displayed.
+     *
+     * This function is throttled to once every 250ms to avoid unnecessary calls.
+     *
+     * @param event
+     */
+    onScroll: function (e) {
+      this.checkStickyVisible();
+      // Track horizontal positioning relative to the viewport.
+      this.stickyPosition(null, scrollValue('scrollLeft'));
+      this.$stickyTable.css('visibility', this.stickyVisible ? 'visible' : 'hidden');
+    },
+
+    /**
+     * Event handler: recalculates position of the sticky table header.
+     *
+     * @param event
+     *   Event being triggered.
+     */
+    recalculateSticky: function (event) {
+      // Update table size.
+      this.tableHeight = this.$originalTable[0].clientHeight;
+
+      // Update offset top.
+      displace.offsets.top = displace.calculateOffset('top');
+      this.tableOffset = this.$originalTable.offset();
+      this.stickyPosition(displace.offsets.top, scrollValue('scrollLeft'));
+
+      // Update columns width.
+      var $that = null;
+      var $stickyCell = null;
+      var display = null;
+      // Resize header and its cell widths.
+      // Only apply width to visible table cells. This prevents the header from
+      // displaying incorrectly when the sticky header is no longer visible.
+      for (var i = 0, il = this.$originalHeaderCells.length; i < il; i++) {
+        $that = $(this.$originalHeaderCells[i]);
+        $stickyCell = this.$stickyHeaderCells.eq($that.index());
+        display = $that.css('display');
+        if (display !== 'none') {
+          $stickyCell.css({'width': $that.css('width'), 'display': display});
+        }
+        else {
+          $stickyCell.css('display', 'none');
+        }
+      }
+      this.$stickyTable.css('width', this.$originalTable.outerWidth());
     }
-    this.$stickyTable.css('width', this.$originalTable.outerWidth());
-  }
-});
+  });
 
 // Expose constructor in the public space.
-Drupal.TableHeader = TableHeader;
+  Drupal.TableHeader = TableHeader;
 
 }(jQuery, Drupal, window.parent.Drupal.displace));
diff --git a/core/misc/tableresponsive.js b/core/misc/tableresponsive.js
index 4f45dee..95ba1a3 100644
--- a/core/misc/tableresponsive.js
+++ b/core/misc/tableresponsive.js
@@ -1,139 +1,139 @@
 (function ($, Drupal, window) {
 
-"use strict";
+  "use strict";
 
-/**
- * Attach the tableResponsive function to Drupal.behaviors.
- */
-Drupal.behaviors.tableResponsive = {
-  attach: function (context, settings) {
-    var $tables = $(context).find('table.responsive-enabled').once('tableresponsive');
-    if ($tables.length) {
-      for (var i = 0, il = $tables.length; i < il; i++) {
-        TableResponsive.tables.push(new TableResponsive($tables[i]));
+  /**
+   * Attach the tableResponsive function to Drupal.behaviors.
+   */
+  Drupal.behaviors.tableResponsive = {
+    attach: function (context, settings) {
+      var $tables = $(context).find('table.responsive-enabled').once('tableresponsive');
+      if ($tables.length) {
+        for (var i = 0, il = $tables.length; i < il; i++) {
+          TableResponsive.tables.push(new TableResponsive($tables[i]));
+        }
       }
     }
-  }
-};
+  };
 
-/**
- * The TableResponsive object optimizes table presentation for all screen sizes.
- *
- * A responsive table hides columns at small screen sizes, leaving the most
- * important columns visible to the end user. Users should not be prevented from
- * accessing all columns, however. This class adds a toggle to a table with
- * hidden columns that exposes the columns. Exposing the columns will likely
- * break layouts, but it provides the user with a means to access data, which
- * is a guiding principle of responsive design.
- */
-function TableResponsive (table) {
-  this.table = table;
-  this.$table = $(table);
-  this.showText = Drupal.t('Show all columns');
-  this.hideText = Drupal.t('Hide unimportant columns');
-  // Store a reference to the header elements of the table so that the DOM is
-  // traversed only once to find them.
-  this.$headers = this.$table.find('th');
-  // Add a link before the table for users to show or hide weight columns.
-  this.$link = $('<button type="button" class="link tableresponsive-toggle"></button>')
-    .attr('title', Drupal.t('Show table cells that were hidden to make the table fit within a small screen.'))
-    .on('click', $.proxy(this, 'eventhandlerToggleColumns'));
+  /**
+   * The TableResponsive object optimizes table presentation for all screen sizes.
+   *
+   * A responsive table hides columns at small screen sizes, leaving the most
+   * important columns visible to the end user. Users should not be prevented from
+   * accessing all columns, however. This class adds a toggle to a table with
+   * hidden columns that exposes the columns. Exposing the columns will likely
+   * break layouts, but it provides the user with a means to access data, which
+   * is a guiding principle of responsive design.
+   */
+  function TableResponsive(table) {
+    this.table = table;
+    this.$table = $(table);
+    this.showText = Drupal.t('Show all columns');
+    this.hideText = Drupal.t('Hide unimportant columns');
+    // Store a reference to the header elements of the table so that the DOM is
+    // traversed only once to find them.
+    this.$headers = this.$table.find('th');
+    // Add a link before the table for users to show or hide weight columns.
+    this.$link = $('<button type="button" class="link tableresponsive-toggle"></button>')
+      .attr('title', Drupal.t('Show table cells that were hidden to make the table fit within a small screen.'))
+      .on('click', $.proxy(this, 'eventhandlerToggleColumns'));
 
-  this.$table.before($('<div class="tableresponsive-toggle-columns"></div>').append(this.$link));
+    this.$table.before($('<div class="tableresponsive-toggle-columns"></div>').append(this.$link));
 
-  // Attach a resize handler to the window.
-  $(window)
-    .on('resize.tableresponsive', $.proxy(this, 'eventhandlerEvaluateColumnVisibility'))
-    .trigger('resize.tableresponsive');
-}
+    // Attach a resize handler to the window.
+    $(window)
+      .on('resize.tableresponsive', $.proxy(this, 'eventhandlerEvaluateColumnVisibility'))
+      .trigger('resize.tableresponsive');
+  }
 
-/**
- * Extend the TableResponsive function with a list of managed tables.
- */
-$.extend(TableResponsive, {
-  tables: []
-});
+  /**
+   * Extend the TableResponsive function with a list of managed tables.
+   */
+  $.extend(TableResponsive, {
+    tables: []
+  });
 
-/**
- * Associates an action link with the table that will show hidden columns.
- *
- * Columns are assumed to be hidden if their header has the class priority-low
- * or priority-medium.
- */
-$.extend(TableResponsive.prototype, {
-  eventhandlerEvaluateColumnVisibility: function (e) {
-    var pegged = parseInt(this.$link.data('pegged'), 10);
-    var hiddenLength = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden').length;
-    // If the table has hidden columns, associate an action link with the table
-    // to show the columns.
-    if (hiddenLength > 0) {
-      this.$link.show().text(this.showText);
-    }
-    // When the toggle is pegged, its presence is maintained because the user
-    // has interacted with it. This is necessary to keep the link visible if the
-    // user adjusts screen size and changes the visibilty of columns.
-    if (!pegged && hiddenLength === 0) {
-      this.$link.hide().text(this.hideText);
-    }
-  },
-  // Toggle the visibility of columns classed with either 'priority-low' or
-  // 'priority-medium'.
-  eventhandlerToggleColumns: function (e) {
-    e.preventDefault();
-    var self = this;
-    var $hiddenHeaders = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden');
-    this.$revealedCells = this.$revealedCells || $();
-    // Reveal hidden columns.
-    if ($hiddenHeaders.length > 0) {
-      $hiddenHeaders.each(function (index, element) {
-        var $header = $(this);
-        var position = $header.prevAll('th').length;
-        self.$table.find('tbody tr').each(function () {
-          var $cells = $(this).find('td:eq(' + position + ')');
-          $cells.show();
-          // Keep track of the revealed cells, so they can be hidden later.
-          self.$revealedCells = $().add(self.$revealedCells).add($cells);
+  /**
+   * Associates an action link with the table that will show hidden columns.
+   *
+   * Columns are assumed to be hidden if their header has the class priority-low
+   * or priority-medium.
+   */
+  $.extend(TableResponsive.prototype, {
+    eventhandlerEvaluateColumnVisibility: function (e) {
+      var pegged = parseInt(this.$link.data('pegged'), 10);
+      var hiddenLength = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden').length;
+      // If the table has hidden columns, associate an action link with the table
+      // to show the columns.
+      if (hiddenLength > 0) {
+        this.$link.show().text(this.showText);
+      }
+      // When the toggle is pegged, its presence is maintained because the user
+      // has interacted with it. This is necessary to keep the link visible if the
+      // user adjusts screen size and changes the visibilty of columns.
+      if (!pegged && hiddenLength === 0) {
+        this.$link.hide().text(this.hideText);
+      }
+    },
+    // Toggle the visibility of columns classed with either 'priority-low' or
+    // 'priority-medium'.
+    eventhandlerToggleColumns: function (e) {
+      e.preventDefault();
+      var self = this;
+      var $hiddenHeaders = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden');
+      this.$revealedCells = this.$revealedCells || $();
+      // Reveal hidden columns.
+      if ($hiddenHeaders.length > 0) {
+        $hiddenHeaders.each(function (index, element) {
+          var $header = $(this);
+          var position = $header.prevAll('th').length;
+          self.$table.find('tbody tr').each(function () {
+            var $cells = $(this).find('td:eq(' + position + ')');
+            $cells.show();
+            // Keep track of the revealed cells, so they can be hidden later.
+            self.$revealedCells = $().add(self.$revealedCells).add($cells);
+          });
+          $header.show();
+          // Keep track of the revealed headers, so they can be hidden later.
+          self.$revealedCells = $().add(self.$revealedCells).add($header);
         });
-        $header.show();
-        // Keep track of the revealed headers, so they can be hidden later.
-        self.$revealedCells = $().add(self.$revealedCells).add($header);
-      });
-      this.$link.text(this.hideText).data('pegged', 1);
-    }
-    // Hide revealed columns.
-    else {
-      this.$revealedCells.hide();
-      // Strip the 'display:none' declaration from the style attributes of
-      // the table cells that .hide() added.
-      this.$revealedCells.each(function (index, element) {
-        var $cell = $(this);
-        var properties = $cell.attr('style').split(';');
-        var newProps = [];
-        // The hide method adds display none to the element. The element should
-        // be returned to the same state it was in before the columns were
-        // revealed, so it is necessary to remove the display none
-        // value from the style attribute.
-        var match =  /^display\s*\:\s*none$/;
-        for (var i = 0; i < properties.length; i++) {
-          var prop = properties[i];
-          prop.trim();
-          // Find the display:none property and remove it.
-          var isDisplayNone = match.exec(prop);
-          if (isDisplayNone) {
-            continue;
+        this.$link.text(this.hideText).data('pegged', 1);
+      }
+      // Hide revealed columns.
+      else {
+        this.$revealedCells.hide();
+        // Strip the 'display:none' declaration from the style attributes of
+        // the table cells that .hide() added.
+        this.$revealedCells.each(function (index, element) {
+          var $cell = $(this);
+          var properties = $cell.attr('style').split(';');
+          var newProps = [];
+          // The hide method adds display none to the element. The element should
+          // be returned to the same state it was in before the columns were
+          // revealed, so it is necessary to remove the display none
+          // value from the style attribute.
+          var match = /^display\s*\:\s*none$/;
+          for (var i = 0; i < properties.length; i++) {
+            var prop = properties[i];
+            prop.trim();
+            // Find the display:none property and remove it.
+            var isDisplayNone = match.exec(prop);
+            if (isDisplayNone) {
+              continue;
+            }
+            newProps.push(prop);
           }
-          newProps.push(prop);
-        }
-        // Return the rest of the style attribute values to the element.
-        $cell.attr('style', newProps.join(';'));
-      });
-      this.$link.text(this.showText).data('pegged', 0);
-      // Refresh the toggle link.
-      $(window).trigger('resize.tableresponsive');
+          // Return the rest of the style attribute values to the element.
+          $cell.attr('style', newProps.join(';'));
+        });
+        this.$link.text(this.showText).data('pegged', 0);
+        // Refresh the toggle link.
+        $(window).trigger('resize.tableresponsive');
+      }
     }
-  }
-});
+  });
 // Make the TableResponsive object available in the Drupal namespace.
-Drupal.TableResponsive = TableResponsive;
+  Drupal.TableResponsive = TableResponsive;
 
 })(jQuery, Drupal, window);
diff --git a/core/misc/tableselect.js b/core/misc/tableselect.js
index da3a722..a55b97c 100644
--- a/core/misc/tableselect.js
+++ b/core/misc/tableselect.js
@@ -1,93 +1,93 @@
 (function ($, Drupal) {
 
-"use strict";
+  "use strict";
 
-Drupal.behaviors.tableSelect = {
-  attach: function (context, settings) {
-    // Select the inner-most table in case of nested tables.
-    $(context).find('th.select-all').closest('table').once('table-select', Drupal.tableSelect);
-  }
-};
-
-Drupal.tableSelect = function () {
-  // Do not add a "Select all" checkbox if there are no rows with checkboxes in the table
-  if ($(this).find('td input[type="checkbox"]').length === 0) {
-    return;
-  }
-
-  // Keep track of the table, which checkbox is checked and alias the settings.
-  var table = this, checkboxes, lastChecked;
-  var $table = $(table);
-  var strings = { 'selectAll': Drupal.t('Select all rows in this table'), 'selectNone': Drupal.t('Deselect all rows in this table') };
-  var updateSelectAll = function (state) {
-    // Update table's select-all checkbox (and sticky header's if available).
-    $table.prev('table.sticky-header').addBack().find('th.select-all input[type="checkbox"]').each(function() {
-      $(this).attr('title', state ? strings.selectNone : strings.selectAll);
-      this.checked = state;
-    });
+  Drupal.behaviors.tableSelect = {
+    attach: function (context, settings) {
+      // Select the inner-most table in case of nested tables.
+      $(context).find('th.select-all').closest('table').once('table-select', Drupal.tableSelect);
+    }
   };
 
-  // Find all <th> with class select-all, and insert the check all checkbox.
-  $table.find('th.select-all').prepend($('<input type="checkbox" class="form-checkbox" />').attr('title', strings.selectAll)).on('click', function (event) {
-    if ($(event.target).is('input[type="checkbox"]')) {
-      // Loop through all checkboxes and set their state to the select all checkbox' state.
-      checkboxes.each(function () {
-        this.checked = event.target.checked;
-        // Either add or remove the selected class based on the state of the check all checkbox.
-        $(this).closest('tr').toggleClass('selected', this.checked);
-      });
-      // Update the title and the state of the check all box.
-      updateSelectAll(event.target.checked);
+  Drupal.tableSelect = function () {
+    // Do not add a "Select all" checkbox if there are no rows with checkboxes in the table
+    if ($(this).find('td input[type="checkbox"]').length === 0) {
+      return;
     }
-  });
 
-  // For each of the checkboxes within the table that are not disabled.
-  checkboxes = $table.find('td input[type="checkbox"]:enabled').on('click', function (e) {
-    // Either add or remove the selected class based on the state of the check all checkbox.
-    $(this).closest('tr').toggleClass('selected', this.checked);
+    // Keep track of the table, which checkbox is checked and alias the settings.
+    var table = this, checkboxes, lastChecked;
+    var $table = $(table);
+    var strings = { 'selectAll': Drupal.t('Select all rows in this table'), 'selectNone': Drupal.t('Deselect all rows in this table') };
+    var updateSelectAll = function (state) {
+      // Update table's select-all checkbox (and sticky header's if available).
+      $table.prev('table.sticky-header').addBack().find('th.select-all input[type="checkbox"]').each(function () {
+        $(this).attr('title', state ? strings.selectNone : strings.selectAll);
+        this.checked = state;
+      });
+    };
 
-    // If this is a shift click, we need to highlight everything in the range.
-    // Also make sure that we are actually checking checkboxes over a range and
-    // that a checkbox has been checked or unchecked before.
-    if (e.shiftKey && lastChecked && lastChecked !== e.target) {
-      // We use the checkbox's parent TR to do our range searching.
-      Drupal.tableSelectRange($(e.target).closest('tr')[0], $(lastChecked).closest('tr')[0], e.target.checked);
-    }
+    // Find all <th> with class select-all, and insert the check all checkbox.
+    $table.find('th.select-all').prepend($('<input type="checkbox" class="form-checkbox" />').attr('title', strings.selectAll)).on('click', function (event) {
+      if ($(event.target).is('input[type="checkbox"]')) {
+        // Loop through all checkboxes and set their state to the select all checkbox' state.
+        checkboxes.each(function () {
+          this.checked = event.target.checked;
+          // Either add or remove the selected class based on the state of the check all checkbox.
+          $(this).closest('tr').toggleClass('selected', this.checked);
+        });
+        // Update the title and the state of the check all box.
+        updateSelectAll(event.target.checked);
+      }
+    });
 
-    // If all checkboxes are checked, make sure the select-all one is checked too, otherwise keep unchecked.
-    updateSelectAll((checkboxes.length === checkboxes.filter(':checked').length));
+    // For each of the checkboxes within the table that are not disabled.
+    checkboxes = $table.find('td input[type="checkbox"]:enabled').on('click', function (e) {
+      // Either add or remove the selected class based on the state of the check all checkbox.
+      $(this).closest('tr').toggleClass('selected', this.checked);
 
-    // Keep track of the last checked checkbox.
-    lastChecked = e.target;
-  });
-};
+      // If this is a shift click, we need to highlight everything in the range.
+      // Also make sure that we are actually checking checkboxes over a range and
+      // that a checkbox has been checked or unchecked before.
+      if (e.shiftKey && lastChecked && lastChecked !== e.target) {
+        // We use the checkbox's parent TR to do our range searching.
+        Drupal.tableSelectRange($(e.target).closest('tr')[0], $(lastChecked).closest('tr')[0], e.target.checked);
+      }
 
-Drupal.tableSelectRange = function (from, to, state) {
-  // We determine the looping mode based on the the order of from and to.
-  var mode = from.rowIndex > to.rowIndex ? 'previousSibling' : 'nextSibling';
+      // If all checkboxes are checked, make sure the select-all one is checked too, otherwise keep unchecked.
+      updateSelectAll((checkboxes.length === checkboxes.filter(':checked').length));
 
-  // Traverse through the sibling nodes.
-  for (var i = from[mode], $i; i; i = i[mode]) {
-    // Make sure that we're only dealing with elements.
-    if (i.nodeType !== 1) {
-      continue;
-    }
-    $i = $(i);
-    // Either add or remove the selected class based on the state of the target checkbox.
-    $i.toggleClass('selected', state);
-    $i.find('input[type="checkbox"]').prop('checked', state);
+      // Keep track of the last checked checkbox.
+      lastChecked = e.target;
+    });
+  };
 
-    if (to.nodeType) {
-      // If we are at the end of the range, stop.
-      if (i === to) {
+  Drupal.tableSelectRange = function (from, to, state) {
+    // We determine the looping mode based on the the order of from and to.
+    var mode = from.rowIndex > to.rowIndex ? 'previousSibling' : 'nextSibling';
+
+    // Traverse through the sibling nodes.
+    for (var i = from[mode], $i; i; i = i[mode]) {
+      // Make sure that we're only dealing with elements.
+      if (i.nodeType !== 1) {
+        continue;
+      }
+      $i = $(i);
+      // Either add or remove the selected class based on the state of the target checkbox.
+      $i.toggleClass('selected', state);
+      $i.find('input[type="checkbox"]').prop('checked', state);
+
+      if (to.nodeType) {
+        // If we are at the end of the range, stop.
+        if (i === to) {
+          break;
+        }
+      }
+      // A faster alternative to doing $(i).filter(to).length.
+      else if ($.filter(to, [i]).r.length) {
         break;
       }
     }
-    // A faster alternative to doing $(i).filter(to).length.
-    else if ($.filter(to, [i]).r.length) {
-      break;
-    }
-  }
-};
+  };
 
 })(jQuery, Drupal);
diff --git a/core/misc/timezone.js b/core/misc/timezone.js
index 01f1820..9978971 100644
--- a/core/misc/timezone.js
+++ b/core/misc/timezone.js
@@ -1,68 +1,68 @@
 (function ($) {
 
-"use strict";
+  "use strict";
 
-/**
- * Set the client's system time zone as default values of form fields.
- */
-Drupal.behaviors.setTimezone = {
-  attach: function (context, settings) {
-    var $timezone = $(context).find('.timezone-detect').once('timezone');
-    if ($timezone.length) {
-      var dateString = Date();
-      // In some client environments, date strings include a time zone
-      // abbreviation, between 3 and 5 letters enclosed in parentheses,
-      // which can be interpreted by PHP.
-      var matches = dateString.match(/\(([A-Z]{3,5})\)/);
-      var abbreviation = matches ? matches[1] : 0;
+  /**
+   * Set the client's system time zone as default values of form fields.
+   */
+  Drupal.behaviors.setTimezone = {
+    attach: function (context, settings) {
+      var $timezone = $(context).find('.timezone-detect').once('timezone');
+      if ($timezone.length) {
+        var dateString = Date();
+        // In some client environments, date strings include a time zone
+        // abbreviation, between 3 and 5 letters enclosed in parentheses,
+        // which can be interpreted by PHP.
+        var matches = dateString.match(/\(([A-Z]{3,5})\)/);
+        var abbreviation = matches ? matches[1] : 0;
 
-      // For all other client environments, the abbreviation is set to "0"
-      // and the current offset from UTC and daylight saving time status are
-      // used to guess the time zone.
-      var dateNow = new Date();
-      var offsetNow = dateNow.getTimezoneOffset() * -60;
+        // For all other client environments, the abbreviation is set to "0"
+        // and the current offset from UTC and daylight saving time status are
+        // used to guess the time zone.
+        var dateNow = new Date();
+        var offsetNow = dateNow.getTimezoneOffset() * -60;
 
-      // Use January 1 and July 1 as test dates for determining daylight
-      // saving time status by comparing their offsets.
-      var dateJan = new Date(dateNow.getFullYear(), 0, 1, 12, 0, 0, 0);
-      var dateJul = new Date(dateNow.getFullYear(), 6, 1, 12, 0, 0, 0);
-      var offsetJan = dateJan.getTimezoneOffset() * -60;
-      var offsetJul = dateJul.getTimezoneOffset() * -60;
+        // Use January 1 and July 1 as test dates for determining daylight
+        // saving time status by comparing their offsets.
+        var dateJan = new Date(dateNow.getFullYear(), 0, 1, 12, 0, 0, 0);
+        var dateJul = new Date(dateNow.getFullYear(), 6, 1, 12, 0, 0, 0);
+        var offsetJan = dateJan.getTimezoneOffset() * -60;
+        var offsetJul = dateJul.getTimezoneOffset() * -60;
 
-      var isDaylightSavingTime;
-      // If the offset from UTC is identical on January 1 and July 1,
-      // assume daylight saving time is not used in this time zone.
-      if (offsetJan === offsetJul) {
-        isDaylightSavingTime = '';
-      }
-      // If the maximum annual offset is equivalent to the current offset,
-      // assume daylight saving time is in effect.
-      else if (Math.max(offsetJan, offsetJul) === offsetNow) {
-        isDaylightSavingTime = 1;
-      }
-      // Otherwise, assume daylight saving time is not in effect.
-      else {
-        isDaylightSavingTime = 0;
-      }
+        var isDaylightSavingTime;
+        // If the offset from UTC is identical on January 1 and July 1,
+        // assume daylight saving time is not used in this time zone.
+        if (offsetJan === offsetJul) {
+          isDaylightSavingTime = '';
+        }
+        // If the maximum annual offset is equivalent to the current offset,
+        // assume daylight saving time is in effect.
+        else if (Math.max(offsetJan, offsetJul) === offsetNow) {
+          isDaylightSavingTime = 1;
+        }
+        // Otherwise, assume daylight saving time is not in effect.
+        else {
+          isDaylightSavingTime = 0;
+        }
 
-      // Submit request to the system/timezone callback and set the form field
-      // to the response time zone. The client date is passed to the callback
-      // for debugging purposes. Submit a synchronous request to avoid database
-      // errors associated with concurrent requests during install.
-      var path = 'system/timezone/' + abbreviation + '/' + offsetNow + '/' + isDaylightSavingTime;
-      $.ajax({
-        async: false,
-        url: Drupal.url(path),
-        data: { date: dateString },
-        dataType: 'json',
-        success: function (data) {
-          if (data) {
-            $timezone.val(data);
+        // Submit request to the system/timezone callback and set the form field
+        // to the response time zone. The client date is passed to the callback
+        // for debugging purposes. Submit a synchronous request to avoid database
+        // errors associated with concurrent requests during install.
+        var path = 'system/timezone/' + abbreviation + '/' + offsetNow + '/' + isDaylightSavingTime;
+        $.ajax({
+          async: false,
+          url: Drupal.url(path),
+          data: { date: dateString },
+          dataType: 'json',
+          success: function (data) {
+            if (data) {
+              $timezone.val(data);
+            }
           }
-        }
-      });
+        });
+      }
     }
-  }
-};
+  };
 
 })(jQuery);
diff --git a/core/misc/vertical-tabs.js b/core/misc/vertical-tabs.js
index d45bcac..6efa4c3 100644
--- a/core/misc/vertical-tabs.js
+++ b/core/misc/vertical-tabs.js
@@ -1,215 +1,215 @@
 (function ($) {
 
-"use strict";
-
-/**
- * This script transforms a set of details into a stack of vertical
- * tabs. Another tab pane can be selected by clicking on the respective
- * tab.
- *
- * Each tab may have a summary which can be updated by another
- * script. For that to work, each details element has an associated
- * 'verticalTabCallback' (with jQuery.data() attached to the details),
- * which is called every time the user performs an update to a form
- * element inside the tab pane.
- */
-Drupal.behaviors.verticalTabs = {
-  attach: function (context) {
-
-    if (!Drupal.checkWidthBreakpoint()) {
-      return;
-    }
+  "use strict";
 
-    $(context).find('[data-vertical-tabs-panes]').once('vertical-tabs', function () {
-      var $this = $(this).addClass('vertical-tabs-panes');
-      var focusID = $this.find(':hidden.vertical-tabs-active-tab').val();
-      var tab_focus;
+  /**
+   * This script transforms a set of details into a stack of vertical
+   * tabs. Another tab pane can be selected by clicking on the respective
+   * tab.
+   *
+   * Each tab may have a summary which can be updated by another
+   * script. For that to work, each details element has an associated
+   * 'verticalTabCallback' (with jQuery.data() attached to the details),
+   * which is called every time the user performs an update to a form
+   * element inside the tab pane.
+   */
+  Drupal.behaviors.verticalTabs = {
+    attach: function (context) {
 
-      // Check if there are some details that can be converted to vertical-tabs
-      var $details = $this.find('> details');
-      if ($details.length === 0) {
+      if (!Drupal.checkWidthBreakpoint()) {
         return;
       }
 
-      // Create the tab column.
-      var tab_list = $('<ul class="vertical-tabs-list"></ul>');
-      $this.wrap('<div class="vertical-tabs clearfix"></div>').before(tab_list);
+      $(context).find('[data-vertical-tabs-panes]').once('vertical-tabs', function () {
+        var $this = $(this).addClass('vertical-tabs-panes');
+        var focusID = $this.find(':hidden.vertical-tabs-active-tab').val();
+        var tab_focus;
 
-      // Transform each details into a tab.
-      $details.each(function () {
-        var $this = $(this);
-        var vertical_tab = new Drupal.verticalTab({
-          title: $this.find('> summary').text(),
-          details: $this
-        });
-        tab_list.append(vertical_tab.item);
-        $this
-          .removeClass('collapsed')
-          // prop() can't be used on browsers not supporting details element,
-          // the style won't apply to them if prop() is used.
-          .attr('open', true)
-          .addClass('vertical-tabs-pane')
-          .data('verticalTab', vertical_tab);
-        if (this.id === focusID) {
-          tab_focus = $this;
+        // Check if there are some details that can be converted to vertical-tabs
+        var $details = $this.find('> details');
+        if ($details.length === 0) {
+          return;
         }
-      });
 
-      $(tab_list).find('> li:first').addClass('first');
-      $(tab_list).find('> li:last').addClass('last');
+        // Create the tab column.
+        var tab_list = $('<ul class="vertical-tabs-list"></ul>');
+        $this.wrap('<div class="vertical-tabs clearfix"></div>').before(tab_list);
+
+        // Transform each details into a tab.
+        $details.each(function () {
+          var $this = $(this);
+          var vertical_tab = new Drupal.verticalTab({
+            title: $this.find('> summary').text(),
+            details: $this
+          });
+          tab_list.append(vertical_tab.item);
+          $this
+            .removeClass('collapsed')
+            // prop() can't be used on browsers not supporting details element,
+            // the style won't apply to them if prop() is used.
+            .attr('open', true)
+            .addClass('vertical-tabs-pane')
+            .data('verticalTab', vertical_tab);
+          if (this.id === focusID) {
+            tab_focus = $this;
+          }
+        });
 
-      if (!tab_focus) {
-        // If the current URL has a fragment and one of the tabs contains an
-        // element that matches the URL fragment, activate that tab.
-        var $locationHash = $this.find(window.location.hash);
-        if (window.location.hash && $locationHash.length) {
-          tab_focus = $locationHash.closest('.vertical-tabs-pane');
+        $(tab_list).find('> li:first').addClass('first');
+        $(tab_list).find('> li:last').addClass('last');
+
+        if (!tab_focus) {
+          // If the current URL has a fragment and one of the tabs contains an
+          // element that matches the URL fragment, activate that tab.
+          var $locationHash = $this.find(window.location.hash);
+          if (window.location.hash && $locationHash.length) {
+            tab_focus = $locationHash.closest('.vertical-tabs-pane');
+          }
+          else {
+            tab_focus = $this.find('> .vertical-tabs-pane:first');
+          }
         }
-        else {
-          tab_focus = $this.find('> .vertical-tabs-pane:first');
+        if (tab_focus.length) {
+          tab_focus.data('verticalTab').focus();
         }
-      }
-      if (tab_focus.length) {
-        tab_focus.data('verticalTab').focus();
-      }
-    });
-  }
-};
-
-/**
- * The vertical tab object represents a single tab within a tab group.
- *
- * @param settings
- *   An object with the following keys:
- *   - title: The name of the tab.
- *   - details: The jQuery object of the details element that is the tab pane.
- */
-Drupal.verticalTab = function (settings) {
-  var self = this;
-  $.extend(this, settings, Drupal.theme('verticalTab', settings));
-
-  this.link.attr('href', '#' + settings.details.attr('id'));
-
-  this.link.on('click', function (e) {
-    e.preventDefault();
-    self.focus();
-  });
-
-  // Keyboard events added:
-  // Pressing the Enter key will open the tab pane.
-  this.link.on('keydown', function (event) {
-    event.preventDefault();
-    if (event.keyCode === 13) {
-      self.focus();
-      // Set focus on the first input field of the visible details/tab pane.
-      $(".vertical-tabs-pane :input:visible:enabled:first").trigger('focus');
+      });
     }
-  });
-
-  this.details
-    .on('summaryUpdated', function () {
-      self.updateSummary();
-    })
-    .trigger('summaryUpdated');
-};
+  };
 
-Drupal.verticalTab.prototype = {
   /**
-   * Displays the tab's content pane.
+   * The vertical tab object represents a single tab within a tab group.
+   *
+   * @param settings
+   *   An object with the following keys:
+   *   - title: The name of the tab.
+   *   - details: The jQuery object of the details element that is the tab pane.
    */
-  focus: function () {
+  Drupal.verticalTab = function (settings) {
+    var self = this;
+    $.extend(this, settings, Drupal.theme('verticalTab', settings));
+
+    this.link.attr('href', '#' + settings.details.attr('id'));
+
+    this.link.on('click', function (e) {
+      e.preventDefault();
+      self.focus();
+    });
+
+    // Keyboard events added:
+    // Pressing the Enter key will open the tab pane.
+    this.link.on('keydown', function (event) {
+      event.preventDefault();
+      if (event.keyCode === 13) {
+        self.focus();
+        // Set focus on the first input field of the visible details/tab pane.
+        $(".vertical-tabs-pane :input:visible:enabled:first").trigger('focus');
+      }
+    });
+
     this.details
-      .siblings('.vertical-tabs-pane')
+      .on('summaryUpdated', function () {
+        self.updateSummary();
+      })
+      .trigger('summaryUpdated');
+  };
+
+  Drupal.verticalTab.prototype = {
+    /**
+     * Displays the tab's content pane.
+     */
+    focus: function () {
+      this.details
+        .siblings('.vertical-tabs-pane')
         .each(function () {
           var tab = $(this).data('verticalTab');
           tab.details.hide();
           tab.item.removeClass('selected');
         })
         .end()
-      .show()
-      .siblings(':hidden.vertical-tabs-active-tab')
+        .show()
+        .siblings(':hidden.vertical-tabs-active-tab')
         .val(this.details.attr('id'));
-    this.item.addClass('selected');
-    // Mark the active tab for screen readers.
-    $('#active-vertical-tab').remove();
-    this.link.append('<span id="active-vertical-tab" class="visually-hidden">' + Drupal.t('(active tab)') + '</span>');
-  },
-
-  /**
-   * Updates the tab's summary.
-   */
-  updateSummary: function () {
-    this.summary.html(this.details.drupalGetSummary());
-  },
-
-  /**
-   * Shows a vertical tab pane.
-   */
-  tabShow: function () {
-    // Display the tab.
-    this.item.show();
-    // Show the vertical tabs.
-    this.item.closest('.form-type-vertical-tabs').show();
-    // Update .first marker for items. We need recurse from parent to retain the
-    // actual DOM element order as jQuery implements sortOrder, but not as public
-    // method.
-    this.item.parent().children('.vertical-tab-button').removeClass('first')
-      .filter(':visible:first').addClass('first');
-    // Display the details element.
-    this.details.removeClass('vertical-tab-hidden').show();
-    // Focus this tab.
-    this.focus();
-    return this;
-  },
+      this.item.addClass('selected');
+      // Mark the active tab for screen readers.
+      $('#active-vertical-tab').remove();
+      this.link.append('<span id="active-vertical-tab" class="visually-hidden">' + Drupal.t('(active tab)') + '</span>');
+    },
+
+    /**
+     * Updates the tab's summary.
+     */
+    updateSummary: function () {
+      this.summary.html(this.details.drupalGetSummary());
+    },
+
+    /**
+     * Shows a vertical tab pane.
+     */
+    tabShow: function () {
+      // Display the tab.
+      this.item.show();
+      // Show the vertical tabs.
+      this.item.closest('.form-type-vertical-tabs').show();
+      // Update .first marker for items. We need recurse from parent to retain the
+      // actual DOM element order as jQuery implements sortOrder, but not as public
+      // method.
+      this.item.parent().children('.vertical-tab-button').removeClass('first')
+        .filter(':visible:first').addClass('first');
+      // Display the details element.
+      this.details.removeClass('vertical-tab-hidden').show();
+      // Focus this tab.
+      this.focus();
+      return this;
+    },
+
+    /**
+     * Hides a vertical tab pane.
+     */
+    tabHide: function () {
+      // Hide this tab.
+      this.item.hide();
+      // Update .first marker for items. We need recurse from parent to retain the
+      // actual DOM element order as jQuery implements sortOrder, but not as public
+      // method.
+      this.item.parent().children('.vertical-tab-button').removeClass('first')
+        .filter(':visible:first').addClass('first');
+      // Hide the details element.
+      this.details.addClass('vertical-tab-hidden').hide();
+      // Focus the first visible tab (if there is one).
+      var $firstTab = this.details.siblings('.vertical-tabs-pane:not(.vertical-tab-hidden):first');
+      if ($firstTab.length) {
+        $firstTab.data('verticalTab').focus();
+      }
+      // Hide the vertical tabs (if no tabs remain).
+      else {
+        this.item.closest('.form-type-vertical-tabs').hide();
+      }
+      return this;
+    }
+  };
 
   /**
-   * Hides a vertical tab pane.
+   * Theme function for a vertical tab.
+   *
+   * @param settings
+   *   An object with the following keys:
+   *   - title: The name of the tab.
+   * @return
+   *   This function has to return an object with at least these keys:
+   *   - item: The root tab jQuery element
+   *   - link: The anchor tag that acts as the clickable area of the tab
+   *       (jQuery version)
+   *   - summary: The jQuery element that contains the tab summary
    */
-  tabHide: function () {
-    // Hide this tab.
-    this.item.hide();
-    // Update .first marker for items. We need recurse from parent to retain the
-    // actual DOM element order as jQuery implements sortOrder, but not as public
-    // method.
-    this.item.parent().children('.vertical-tab-button').removeClass('first')
-      .filter(':visible:first').addClass('first');
-    // Hide the details element.
-    this.details.addClass('vertical-tab-hidden').hide();
-    // Focus the first visible tab (if there is one).
-    var $firstTab = this.details.siblings('.vertical-tabs-pane:not(.vertical-tab-hidden):first');
-    if ($firstTab.length) {
-      $firstTab.data('verticalTab').focus();
-    }
-    // Hide the vertical tabs (if no tabs remain).
-    else {
-      this.item.closest('.form-type-vertical-tabs').hide();
-    }
-    return this;
-  }
-};
-
-/**
- * Theme function for a vertical tab.
- *
- * @param settings
- *   An object with the following keys:
- *   - title: The name of the tab.
- * @return
- *   This function has to return an object with at least these keys:
- *   - item: The root tab jQuery element
- *   - link: The anchor tag that acts as the clickable area of the tab
- *       (jQuery version)
- *   - summary: The jQuery element that contains the tab summary
- */
-Drupal.theme.verticalTab = function (settings) {
-  var tab = {};
-  tab.item = $('<li class="vertical-tab-button" tabindex="-1"></li>')
-    .append(tab.link = $('<a href="#"></a>')
-      .append(tab.title = $('<strong></strong>').text(settings.title))
-      .append(tab.summary = $('<span class="summary"></span>')
-    )
-  );
-  return tab;
-};
+  Drupal.theme.verticalTab = function (settings) {
+    var tab = {};
+    tab.item = $('<li class="vertical-tab-button" tabindex="-1"></li>')
+      .append(tab.link = $('<a href="#"></a>')
+        .append(tab.title = $('<strong></strong>').text(settings.title))
+        .append(tab.summary = $('<span class="summary"></span>')
+        )
+      );
+    return tab;
+  };
 
 })(jQuery);
