diff --git a/.jshintrc b/.jshintrc
index 3460a97..b86259f 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -12,6 +12,7 @@
   "predef"    : [
     "Drupal",
     "drupalSettings",
+    "domready",
     "jQuery",
     "_",
     "matchMedia",
diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index 45a5bac..71a6cb0 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -78,6 +78,46 @@ Drupal.behaviors.AJAX = {
 };
 
 /**
+ * Build an error message from an Ajax response.
+ */
+Drupal.ajaxError = function (xmlhttp, uri) {
+  var statusCode, statusText, pathText, responseText, readyStateText, message;
+  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})) : "";
+
+  message = statusCode + pathText + statusText + responseText + readyStateText;
+  return message;
+};
+
+/**
  * Ajax object.
  *
  * All Ajax objects on a page are accessible through the global Drupal.ajax
@@ -684,4 +724,26 @@ Drupal.ajax.prototype.commands = {
   }
 };
 
+/**
+ * Freeze the current body height (as minimum height). Used to prevent
+ * unnecessary upwards scrolling when doing DOM manipulations.
+ */
+Drupal.freezeHeight = function () {
+  Drupal.unfreezeHeight();
+  $('<div id="freeze-height"></div>').css({
+    position: 'absolute',
+    top: '0px',
+    left: '0px',
+    width: '1px',
+    height: $('body').css('height')
+  }).appendTo('body');
+};
+
+/**
+ * Unfreeze the body height.
+ */
+Drupal.unfreezeHeight = function () {
+  $('#freeze-height').remove();
+};
+
 })(jQuery, this);
diff --git a/core/misc/drupal.js b/core/misc/drupal.js
index 627e264..394bd44 100644
--- a/core/misc/drupal.js
+++ b/core/misc/drupal.js
@@ -1,11 +1,16 @@
-var Drupal = Drupal || { 'behaviors': {}, 'locale': {} };
+var Drupal = { behaviors: {}, locale: {} };
 
-// Allow other JavaScript libraries to use $.
-jQuery.noConflict();
+// Class indicating that JS is enabled; used for styling purpose.
+document.documentElement.className += ' js';
+
+// When using jQuery allow other JavaScript libraries to use $.
+if (window.jQuery) {
+  jQuery.noConflict();
+}
 
 // JavaScript should be made compatible with libraries other than jQuery by
 // wrapping it in an anonymous closure.
-(function ($, Drupal, drupalSettings) {
+(function (domready, Drupal, drupalSettings) {
 
 "use strict";
 
@@ -94,6 +99,9 @@ Drupal.attachBehaviors = function (context, settings) {
   }
 };
 
+// Attach all behaviors.
+domready(function () { Drupal.attachBehaviors(document, drupalSettings); });
+
 /**
  * Detach registered behaviors from a page element.
  *
@@ -314,6 +322,15 @@ Drupal.formatPlural = function (count, singular, plural, args, options) {
 };
 
 /**
+ * Encodes a Drupal path for use in a URL.
+ *
+ * For aesthetic reasons slashes are not escaped.
+ */
+Drupal.encodePath = function (item) {
+  return window.encodeURIComponent(item).replace(/%2F/g, '/');
+};
+
+/**
  * Generate the themed representation of a Drupal object.
  *
  * All requests for themed output must go through this function. It examines
@@ -341,121 +358,15 @@ Drupal.theme = function (func) {
 };
 
 /**
- * Freeze the current body height (as minimum height). Used to prevent
- * unnecessary upwards scrolling when doing DOM manipulations.
- */
-Drupal.freezeHeight = function () {
-  Drupal.unfreezeHeight();
-  $('<div id="freeze-height"></div>').css({
-    position: 'absolute',
-    top: '0px',
-    left: '0px',
-    width: '1px',
-    height: $('body').css('height')
-  }).appendTo('body');
-};
-
-/**
- * Unfreeze the body height.
- */
-Drupal.unfreezeHeight = function () {
-  $('#freeze-height').remove();
-};
-
-/**
- * Encodes a Drupal path for use in a URL.
+ * Formats text for emphasized display in a placeholder inside a sentence.
  *
- * For aesthetic reasons slashes are not escaped.
- */
-Drupal.encodePath = function (item) {
-  return window.encodeURIComponent(item).replace(/%2F/g, '/');
-};
-
-/**
- * Get the text selection in a textarea.
- */
-Drupal.getSelection = function (element) {
-  var range1, range2, start, end;
-  if (typeof element.selectionStart !== 'number' && document.selection) {
-    // The current selection.
-    range1 = document.selection.createRange();
-    range2 = range1.duplicate();
-    // Select all text.
-    range2.moveToElementText(element);
-    // Now move 'dummy' end point to end point of original range.
-    range2.setEndPoint('EndToEnd', range1);
-    // Now we can calculate start and end points.
-    start = range2.text.length - range1.text.length;
-    end = start + range1.text.length;
-    return { 'start': start, 'end': end };
-  }
-  return { 'start': element.selectionStart, 'end': element.selectionEnd };
-};
-
-/**
- * Build an error message from an Ajax response.
+ * @param str
+ *   The text to format (plain-text).
+ * @return
+ *   The formatted text (html).
  */
-Drupal.ajaxError = function (xmlhttp, uri) {
-  var statusCode, statusText, pathText, responseText, readyStateText, message;
-  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})) : "";
-
-  message = statusCode + pathText + statusText + responseText + readyStateText;
-  return message;
+Drupal.theme.placeholder = function (str) {
+  return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>';
 };
 
-// Class indicating that JS is enabled; used for styling purpose.
-$('html').addClass('js');
-
-//Attach all behaviors.
-$(function () {
-  Drupal.attachBehaviors(document, drupalSettings);
-});
-
-/**
- * The default themes.
- */
-$.extend(Drupal.theme, {
-
-  /**
-   * Formats text for emphasized display in a placeholder inside a sentence.
-   *
-   * @param str
-   *   The text to format (plain-text).
-   * @return
-   *   The formatted text (html).
-   */
-  placeholder: function (str) {
-    return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>';
-  }
-});
-
-})(jQuery, Drupal, window.drupalSettings);
+})(domready, Drupal, window.drupalSettings);
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
index 89cba50..4244c13 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
@@ -219,7 +219,7 @@ function testReset() {
    * Tests adding inline scripts.
    */
   function testAddInline() {
-    drupal_add_library('system', 'drupal');
+    drupal_add_library('system', 'jquery');
     $inline = 'jQuery(function () { });';
     $javascript = drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer'));
     $this->assertTrue(array_key_exists('core/misc/jquery.js', $javascript), 'jQuery is added when inline scripts are added.');
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index eee53b1..b723182 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1222,7 +1222,7 @@ function system_library_info() {
       'core/misc/drupal.js' => array('group' => JS_LIBRARY, 'weight' => -18),
     ),
     'dependencies' => array(
-      array('system', 'jquery'),
+      array('system', 'domready'),
     ),
   );
 
@@ -1460,6 +1460,16 @@ function system_library_info() {
     ),
   );
 
+  // domReady.
+  $libraries['domready'] = array(
+    'title' => 'domReady',
+    'website' => 'https://github.com/ded/domready',
+    'version' => 'master',
+    'js' => array(
+      'core/misc/domready/ready.min.js' => array('group' => JS_LIBRARY, 'weight' => -21),
+    ),
+  );
+
   // jQuery.
   $libraries['jquery'] = array(
     'title' => 'jQuery',
