diff --git a/.eslintrc b/.eslintrc
index 14f7b95..e6124e4 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -42,6 +42,15 @@
     "strict": 2,
     // Warnings.
     "max-nested-callbacks": [1, 3],
+    "valid-jsdoc": [1, {
+      "prefer": {
+        "returns": "return",
+        "property": "prop"
+      },
+      "requireReturn": false,
+      "requireParamDescription": false,
+      "requireReturnDescription": false
+    }],
     // Disabled.
     "camelcase": 0,
     "consistent-return": 0,
diff --git a/core/misc/active-link.js b/core/misc/active-link.js
index 3a2f818..97c9966 100644
--- a/core/misc/active-link.js
+++ b/core/misc/active-link.js
@@ -18,6 +18,8 @@
    *
    * Does not discriminate based on element type, so allows you to set the
    * is-active class on any element: a, li…
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.activeLinks = {
     attach: function (context) {
@@ -28,7 +30,8 @@
       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 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>"]');
       }
diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index 5ec87f5..e9f4649 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -1,9 +1,24 @@
+/**
+ * @file
+ * Provides Ajax page updating via jQuery $.ajax.
+ *
+ * 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['url']` and
+ * `#ajax['wrapper']` properties. If set, this file will automatically be
+ * included to provide Ajax capabilities.
+ */
+
 (function ($, window, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
    * Attaches the Ajax behavior to each Ajax form element.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.AJAX = {
     attach: function (context, settings) {
@@ -58,7 +73,8 @@
         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.
+        // Clicked form buttons look better with the throbber than the progress
+        // bar.
         element_settings.progress = {'type': 'throbber'};
         element_settings.base = $(this).attr('id');
         element_settings.element = this;
@@ -70,6 +86,15 @@
 
   /**
    * Extends Error to provide handling for Errors in Ajax.
+   *
+   * @constructor
+   *
+   * @augments Error
+   *
+   * @param {XMLHttpRequest} xmlhttp
+   *   XMLHttpRequest object used for the failed request.
+   * @param {string} uri
+   *   The URI where the error occurred.
    */
   Drupal.AjaxError = function (xmlhttp, uri) {
 
@@ -87,14 +112,15 @@
     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.
+    // 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) {
-      // empty
+      // Empty.
     }
 
     responseText = '';
@@ -114,7 +140,18 @@
     // We don't need readyState except for status == 0.
     readyStateText = xmlhttp.status === 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
 
+    /**
+     * Formatted and translated error message.
+     *
+     * @type {string}
+     */
     this.message = statusCode + pathText + statusText + responseText + readyStateText;
+
+    /**
+     * Used by some browsers to display a more accurate stack trace.
+     *
+     * @type {string}
+     */
     this.name = 'AjaxError';
   };
 
@@ -125,8 +162,8 @@
    * Provides Ajax page updating via jQuery $.ajax.
    *
    * This function is designed to improve developer experience by wrapping the
-   * initialization of Drupal.Ajax objects and storing all created object in the
-   * Drupal.ajax.instances array.
+   * initialization of Drupal.Ajax objects and storing all created object in
+   * the {@link Drupal.ajax.instances} array.
    *
    * @example
    * Drupal.behaviors.myCustomAJAXStuff = {
@@ -158,8 +195,6 @@
    *   }
    * };
    *
-   * @see Drupal.AjaxCommands
-   *
    * @param {object} settings
    *   The settings object passed to Drupal.Ajax constructor.
    * @param {string} [settings.base]
@@ -169,6 +204,8 @@
    *   event listeners will be bound.
    *
    * @return {Drupal.Ajax}
+   *
+   * @see Drupal.AjaxCommands
    */
   Drupal.ajax = function (settings) {
     if (arguments.length !== 1) {
@@ -195,7 +232,7 @@
   /**
    * Contains all created Ajax objects.
    *
-   * @type {Array}
+   * @type {Array.<Drupal.Ajax>}
    */
   Drupal.ajax.instances = [];
 
@@ -205,8 +242,8 @@
    * The Ajax 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['url'] and
-   * #ajax['wrapper'] properties. If set, this file will automatically be
+   * Drupal uses this file to enhance form elements with `#ajax['url']` and
+   * `#ajax['wrapper']` properties. If set, this file will automatically be
    * included to provide Ajax capabilities.
    *
    * @constructor
@@ -244,6 +281,9 @@
 
     $.extend(this, defaults, element_settings);
 
+    /**
+     * @type {Drupal.AjaxCommands}
+     */
     this.commands = new Drupal.AjaxCommands();
     this.instanceIndex = false;
 
@@ -252,15 +292,30 @@
     //   - Include the '#' for ID-based selectors.
     //   - Support non-ID-based selectors.
     if (this.wrapper) {
+
+      /**
+       * @type {string}
+       */
       this.wrapper = '#' + this.wrapper;
     }
 
+    /**
+     * @type {HTMLElement}
+     */
     this.element = element;
+
+    /**
+     * @type {object}
+     */
     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 && this.element.form) {
+
+      /**
+       * @type {jQuery}
+       */
       this.$form = $(this.element.form);
     }
 
@@ -273,15 +328,16 @@
       else if (this.element && 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.
+        // @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;
         }
@@ -300,6 +356,26 @@
     // Set the options for the ajaxSubmit function.
     // The 'this' variable will not persist inside of the options object.
     var ajax = this;
+
+    /**
+     * Set the options for the ajaxSubmit function.
+     *
+     * @name Drupal.Ajax#options
+     *
+     * @type {object}
+     *
+     * @prop {string} url
+     * @prop {object} data
+     * @prop {function} beforeSerialize
+     * @prop {function} beforeSubmit
+     * @prop {function} beforeSend
+     * @prop {function} success
+     * @prop {function} complete
+     * @prop {string} dataType
+     * @prop {object} accepts
+     * @prop {string} accepts.json
+     * @prop {string} type
+     */
     ajax.options = {
       url: ajax.url,
       data: ajax.submit,
@@ -373,6 +449,8 @@
    *
    * The wrapper format determines how the HTML is wrapped, for example in a
    * modal dialog.
+   *
+   * @const {string}
    */
   Drupal.ajax.WRAPPER_FORMAT = '_wrapper_format';
 
@@ -409,6 +487,9 @@
    * 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.
+   *
+   * @param {HTMLElement} element
+   * @param {jQuery.Event} event
    */
   Drupal.Ajax.prototype.keypressResponse = function (element, event) {
     // Create a synonym for this to reduce code confusion.
@@ -417,8 +498,8 @@
     // 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.
+    // #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();
@@ -434,6 +515,9 @@
    * 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.
+   *
+   * @param {HTMLElement} element
+   * @param {jQuery.Event} event
    */
   Drupal.Ajax.prototype.eventResponse = function (element, event) {
     event.preventDefault();
@@ -479,6 +563,10 @@
    *
    * Runs before the beforeSend() handler (see below), and unlike that one, runs
    * before field data is collected.
+   *
+   * @param {HTMLElement} element
+   * @param {object} options
+   * @param {object} options.data
    */
   Drupal.Ajax.prototype.beforeSerialize = function (element, options) {
     // Allow detaching behaviors to update field values before collecting them.
@@ -515,6 +603,10 @@
 
   /**
    * Modify form values prior to form submission.
+   *
+   * @param {object} form_values
+   * @param {HTMLElement} element
+   * @param {object} options
    */
   Drupal.Ajax.prototype.beforeSubmit = function (form_values, element, options) {
     // This function is left empty to make it simple to override for modules
@@ -523,30 +615,35 @@
 
   /**
    * Prepare the Ajax request before it is sent.
+   *
+   * @param {XMLHttpRequest} xmlhttprequest
+   * @param {object} options
+   * @param {object} options.extraData
    */
   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.
+    // 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.
+      // 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.
+      // 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;
@@ -563,7 +660,7 @@
       return;
     }
 
-    // Insert progress indicator
+    // Insert progress indicator.
     var progressIndicatorMethod = 'setProgressIndicator' + this.progress.type.slice(0, 1).toUpperCase() + this.progress.type.slice(1).toLowerCase();
     if (progressIndicatorMethod in this && typeof this[progressIndicatorMethod] === 'function') {
       this[progressIndicatorMethod].call(this);
@@ -608,6 +705,9 @@
 
   /**
    * Handler for the form redirection completion.
+   *
+   * @param {Array.<Drupal.AjaxCommands~commandDefinition>} response
+   * @param {number} status
    */
   Drupal.Ajax.prototype.success = function (response, status) {
     // Remove the progress element.
@@ -640,7 +740,13 @@
   };
 
   /**
-   * Build an effect object which tells us how to apply the effect when adding new HTML.
+   * Build an effect object to apply an effect when adding new HTML.
+   *
+   * @param {object} response
+   * @param {string} [response.effect]
+   * @param {string|number} [response.speed]
+   *
+   * @return {object}
    */
   Drupal.Ajax.prototype.getEffect = function (response) {
     var type = response.effect || this.effect;
@@ -668,6 +774,9 @@
 
   /**
    * Handler for the form redirection error.
+   *
+   * @param {object} response
+   * @param {string} uri
    */
   Drupal.Ajax.prototype.error = function (response, uri) {
     // Remove the progress element.
@@ -690,12 +799,46 @@
   };
 
   /**
-   * Provide a series of commands that the server can request the client perform.
+   * @typedef {object} Drupal.AjaxCommands~commandDefinition
+   *
+   * @prop {string} command
+   * @prop {string} [method]
+   * @prop {string} [selector]
+   * @prop {string} [data]
+   * @prop {object} [settings]
+   * @prop {bool} [asterisk]
+   * @prop {string} [text]
+   * @prop {string} [title]
+   * @prop {string} [url]
+   * @prop {object} [argument]
+   * @prop {string} [name]
+   * @prop {string} [value]
+   * @prop {string} [old]
+   * @prop {string} [new]
+   * @prop {bool} [merge]
+   * @prop {Array} [args]
+   *
+   * @see Drupal.AjaxCommands
+   */
+
+  /**
+   * Provide a series of commands that the client will perform.
+   *
+   * @constructor
    */
   Drupal.AjaxCommands = function () {};
   Drupal.AjaxCommands.prototype = {
+
     /**
      * Command to insert new content into the DOM.
+     *
+     * @param {Drupal.Ajax} ajax
+     * @param {object} response
+     * @param {string} response.data
+     * @param {string} [response.method]
+     * @param {string} [response.selector]
+     * @param {object} [response.settings]
+     * @param {number} [status]
      */
     insert: function (ajax, response, status) {
       // Get information from the response. If it is not there, default to
@@ -713,16 +856,17 @@
       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.
+      // 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;
       }
@@ -757,9 +901,9 @@
         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.
+      // 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;
@@ -769,6 +913,12 @@
 
     /**
      * Command to remove a chunk from the page.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {string} response.selector
+     * @param {object} [response.settings]
+     * @param {number} [status]
      */
     remove: function (ajax, response, status) {
       var settings = response.settings || ajax.settings || drupalSettings;
@@ -780,6 +930,12 @@
 
     /**
      * Command to mark a chunk changed.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {string} response.selector
+     * @param {bool} [response.asterisk]
+     * @param {number} [status]
      */
     changed: function (ajax, response, status) {
       if (!$(response.selector).hasClass('ajax-changed')) {
@@ -792,6 +948,12 @@
 
     /**
      * Command to provide an alert.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {string} response.text
+     * @param {string} response.title
+     * @param {number} [status]
      */
     alert: function (ajax, response, status) {
       window.alert(response.text, response.title);
@@ -799,6 +961,11 @@
 
     /**
      * Command to set the window.location, redirecting the browser.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {string} response.url
+     * @param {number} [status]
      */
     redirect: function (ajax, response, status) {
       window.location = response.url;
@@ -806,13 +973,24 @@
 
     /**
      * Command to provide the jQuery css() function.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {object} response.argument
+     * @param {number} [status]
      */
     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.
+     * Command to set the settings used for other commands in this response.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {bool} response.merge
+     * @param {object} response.settings
+     * @param {number} [status]
      */
     settings: function (ajax, response, status) {
       if (response.merge) {
@@ -825,6 +1003,13 @@
 
     /**
      * Command to attach data using jQuery's data API.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {string} response.name
+     * @param {string} response.selector
+     * @param {string|object} response.value
+     * @param {number} [status]
      */
     data: function (ajax, response, status) {
       $(response.selector).data(response.name, response.value);
@@ -832,6 +1017,13 @@
 
     /**
      * Command to apply a jQuery method.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {Array} response.args
+     * @param {string} response.method
+     * @param {string} response.selector
+     * @param {number} [status]
      */
     invoke: function (ajax, response, status) {
       var $element = $(response.selector);
@@ -840,6 +1032,11 @@
 
     /**
      * Command to restripe a table.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {string} response.selector
+     * @param {number} [status]
      */
     restripe: function (ajax, response, status) {
       // :even and :odd are reversed because jQuery counts from 0 and
@@ -853,6 +1050,12 @@
 
     /**
      * Command to update a form's build ID.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {string} response.old
+     * @param {string} response.new
+     * @param {number} [status]
      */
     update_build_id: function (ajax, response, status) {
       $('input[name="form_build_id"][value="' + response.old + '"]').val(response.new);
@@ -864,6 +1067,11 @@
      * Uses the proprietary addImport method if available as browsers which
      * support that method ignore @import statements in dynamically added
      * stylesheets.
+     *
+     * @param {Drupal.Ajax} [ajax]
+     * @param {object} response
+     * @param {string} response.data
+     * @param {number} [status]
      */
     add_css: function (ajax, response, status) {
       // Add the styles in the normal way.
diff --git a/core/misc/announce.js b/core/misc/announce.js
index 9aafbbc..188684d 100644
--- a/core/misc/announce.js
+++ b/core/misc/announce.js
@@ -1,9 +1,12 @@
 /**
+ * @file
  * Adds an HTML element and method to trigger audio UAs to read system messages.
  *
  * Use Drupal.announce() to indicate to screen reader users that an element on
  * the page has changed state. For instance, if clicking a link loads 10 more
  * items into a list, one might announce the change like this.
+ *
+ * @example
  * $('#search-list')
  *   .on('itemInsert', function (event, data) {
  *     // Insert the new items.
@@ -14,6 +17,7 @@
  *     ));
  *   });
  */
+
 (function (Drupal, debounce) {
 
   "use strict";
@@ -22,8 +26,9 @@
   var announcements = [];
 
   /**
-   * Builds a div element with the aria-live attribute and attaches it
-   * to the DOM.
+   * Builds a div element with the aria-live attribute and add it to the DOM.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.drupalAnnounce = {
     attach: function (context) {
@@ -86,12 +91,14 @@
    * These messages are then joined and append to the aria-live region as one
    * text node.
    *
-   * @param String text
+   * @param {string} text
    *   A string to be read by the UA.
-   * @param String priority
+   * @param {string} [priority='polite']
    *   A string to indicate the priority of the message. Can be either
    *   'polite' or 'assertive'. Polite is the default.
    *
+   * @return {function}
+   *
    * @see http://www.w3.org/WAI/PF/aria-practices/#liveprops
    */
   Drupal.announce = function (text, priority) {
diff --git a/core/misc/autocomplete.js b/core/misc/autocomplete.js
index 92bb867..f826281 100644
--- a/core/misc/autocomplete.js
+++ b/core/misc/autocomplete.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Autocomplete based on jQuery UI.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
@@ -7,7 +12,9 @@
   /**
    * Helper splitting terms from the autocomplete value.
    *
-   * @param {String} value
+   * @function Drupal.autocomplete.splitValues
+   *
+   * @param {string} value
    *
    * @return {Array}
    */
@@ -43,9 +50,11 @@
   /**
    * Returns the last value of an multi-value textfield.
    *
-   * @param {String} terms
+   * @function Drupal.autocomplete.extractLastTerm
+   *
+   * @param {string} terms
    *
-   * @return {String}
+   * @return {string}
    */
   function extractLastTerm(terms) {
     return autocomplete.splitValues(terms).pop();
@@ -54,9 +63,11 @@
   /**
    * The search handler is called before a search is performed.
    *
-   * @param {Object} event
+   * @function Drupal.autocomplete.options.search
    *
-   * @return {Boolean}
+   * @param {object} event
+   *
+   * @return {bool}
    */
   function searchHandler(event) {
     var options = autocomplete.options;
@@ -70,10 +81,10 @@
   }
 
   /**
-   * jQuery UI autocomplete source callback.
+   * JQuery UI autocomplete source callback.
    *
-   * @param {Object} request
-   * @param {Function} response
+   * @param {object} request
+   * @param {function} response
    */
   function sourceData(request, response) {
     var elementId = this.element.attr('id');
@@ -86,7 +97,7 @@
      * Filter through the suggestions removing all terms already tagged and
      * display the available terms to the user.
      *
-     * @param {Object} suggestions
+     * @param {object} suggestions
      */
     function showSuggestions(suggestions) {
       var tagged = autocomplete.splitValues(request.term);
@@ -103,7 +114,7 @@
     /**
      * Transforms the data object into an array and update autocomplete results.
      *
-     * @param {Object} data
+     * @param {object} data
      */
     function sourceCallbackHandler(data) {
       autocomplete.cache[elementId][term] = data;
@@ -128,7 +139,7 @@
   /**
    * Handles an autocompletefocus event.
    *
-   * @return {Boolean}
+   * @return {bool}
    */
   function focusHandler() {
     return false;
@@ -137,10 +148,10 @@
   /**
    * Handles an autocompleteselect event.
    *
-   * @param {Object} event
-   * @param {Object} ui
+   * @param {jQuery.Event} event
+   * @param {object} ui
    *
-   * @return {Boolean}
+   * @return {bool}
    */
   function selectHandler(event, ui) {
     var terms = autocomplete.splitValues(event.target.value);
@@ -161,10 +172,10 @@
   /**
    * Override jQuery UI _renderItem function to output HTML by default.
    *
-   * @param {Object} ul
-   * @param {Object} item
+   * @param {object} ul
+   * @param {object} item
    *
-   * @return {Object}
+   * @return {object}
    */
   function renderItem(ul, item) {
     return $("<li>")
@@ -174,6 +185,8 @@
 
   /**
    * Attaches the autocomplete behavior to all required fields.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.autocomplete = {
     attach: function (context) {
@@ -202,6 +215,8 @@
 
   /**
    * Autocomplete object implementation.
+   *
+   * @namespace Drupal.autocomplete
    */
   autocomplete = {
     cache: {},
@@ -209,6 +224,12 @@
     splitValues: autocompleteSplitValues,
     extractLastTerm: extractLastTerm,
     // jQuery UI autocomplete options.
+
+    /**
+     * JQuery UI option object.
+     *
+     * @name Drupal.autocomplete.options
+     */
     options: {
       source: sourceData,
       focus: focusHandler,
diff --git a/core/misc/batch.js b/core/misc/batch.js
index ee6cf68..43242ea 100644
--- a/core/misc/batch.js
+++ b/core/misc/batch.js
@@ -1,12 +1,16 @@
 /**
+ * @file
  * Drupal's batch API.
  */
+
 (function ($, Drupal) {
 
   "use strict";
 
   /**
    * Attaches the batch behavior to progress bars.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.batch = {
     attach: function (context, settings) {
diff --git a/core/misc/collapse.js b/core/misc/collapse.js
index 6aa2e25..b4472f6 100644
--- a/core/misc/collapse.js
+++ b/core/misc/collapse.js
@@ -1,9 +1,18 @@
+/**
+ * @file
+ * Polyfill for HTML5 details elements.
+ */
+
 (function ($, Modernizr, Drupal) {
 
   "use strict";
 
   /**
-   * The collapsible details object represents a single collapsible details element.
+   * The collapsible details object represents a single details element.
+   *
+   * @constructor Drupal.CollapsibleDetails
+   *
+   * @param {HTMLElement} node
    */
   function CollapsibleDetails(node) {
     this.$node = $(node);
@@ -20,22 +29,24 @@
     this.setupLegend();
   }
 
-  /**
-   * Extend CollapsibleDetails function.
-   */
-  $.extend(CollapsibleDetails, {
+  $.extend(CollapsibleDetails, /** @lends Drupal.CollapsibleDetails */{
+
     /**
      * Holds references to instantiated CollapsibleDetails objects.
+     *
+     * @type {Array.<Drupal.CollapsibleDetails>}
      */
     instances: []
   });
 
-  /**
-   * Extend CollapsibleDetails prototype.
-   */
-  $.extend(CollapsibleDetails.prototype, {
+  $.extend(CollapsibleDetails.prototype, /** @lends Drupal.CollapsibleDetails# */{
+
     /**
      * Initialize and setup summary events and markup.
+     *
+     * @fires event:summaryUpdated
+     *
+     * @listens event:summaryUpdated
      */
     setupSummary: function () {
       this.$summary = $('<span class="summary"></span>');
@@ -43,6 +54,7 @@
         .on('summaryUpdated', $.proxy(this.onSummaryUpdated, this))
         .trigger('summaryUpdated');
     },
+
     /**
      * Initialize and setup legend markup.
      */
@@ -65,20 +77,25 @@
         .append(this.$summary)
         .on('click', $.proxy(this.onLegendClick, this));
     },
+
     /**
-     * Handle legend clicks
+     * Handle legend clicks.
+     *
+     * @param {jQuery.Event} e
      */
     onLegendClick: function (e) {
       this.toggle();
       e.preventDefault();
     },
+
     /**
-     * Update summary
+     * 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.
      */
@@ -95,6 +112,11 @@
     }
   });
 
+  /**
+   * Polyfill HTML5 details element.
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.collapse = {
     attach: function (context) {
       if (Modernizr.details) {
diff --git a/core/misc/debounce.js b/core/misc/debounce.js
index 45a5b87..0239ce6 100644
--- a/core/misc/debounce.js
+++ b/core/misc/debounce.js
@@ -1,7 +1,10 @@
 /**
- * Limits the invocations of a function in a given time frame.
- *
+ * @file
  * Adapted from underscore.js with the addition Drupal namespace.
+ */
+
+/**
+ * Limits the invocations of a function in a given time frame.
  *
  * The debounce function wrapper should be used sparingly. One clear use case
  * is limiting the invocation of a callback attached to the window resize event.
@@ -11,13 +14,17 @@
  * function can be written in such a way that it is only invoked under specific
  * conditions.
  *
- * @param {Function} callback
+ * @param {function} func
  *   The function to be invoked.
- *
- * @param {Number} wait
+ * @param {number} wait
  *   The time period within which the callback function should only be
  *   invoked once. For example if the wait period is 250ms, then the callback
  *   will only be called at most 4 times per second.
+ * @param {bool} immediate
+ *   Whether we wait at the beginning or end to execute the function.
+ *
+ * @return {function}
+ *   The debounced function.
  */
 Drupal.debounce = function (func, wait, immediate) {
 
diff --git a/core/misc/dialog/dialog.ajax.js b/core/misc/dialog/dialog.ajax.js
index e786d5a..d70ca70 100644
--- a/core/misc/dialog/dialog.ajax.js
+++ b/core/misc/dialog/dialog.ajax.js
@@ -7,6 +7,11 @@
 
   "use strict";
 
+  /**
+   * Initialize dialogs for Ajax purposes.
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.dialog = {
     attach: function (context, settings) {
       var $context = $(context);
@@ -46,9 +51,10 @@
     /**
      * Scan a dialog for any primary buttons and move them to the button area.
      *
-     * @param $dialog
+     * @param {jQuery} $dialog
      *   An jQuery object containing the element that is the dialog target.
-     * @return
+     *
+     * @return {Array}
      *   An array of buttons that need to be added to the button area.
      */
     prepareDialogButtons: function ($dialog) {
@@ -81,6 +87,12 @@
 
   /**
    * Command to open a dialog.
+   *
+   * @param {Drupal.Ajax} ajax
+   * @param {object} response
+   * @param {number} [status]
+   *
+   * @return {bool|undefined}
    */
   Drupal.AjaxCommands.prototype.openDialog = function (ajax, response, status) {
     if (!response.selector) {
@@ -107,7 +119,7 @@
       response.dialogOptions.buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
     }
 
-    // Bind dialogButtonsChange
+    // Bind dialogButtonsChange.
     $dialog.on('dialogButtonsChange', function () {
       var buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
       $dialog.dialog('option', 'buttons', buttons);
@@ -131,6 +143,12 @@
    * Command to close a dialog.
    *
    * If no selector is given, it defaults to trying to close the modal.
+   *
+   * @param {Drupal.Ajax} [ajax]
+   * @param {object} response
+   * @param {string} response.selector
+   * @param {bool} response.persist
+   * @param {number} [status]
    */
   Drupal.AjaxCommands.prototype.closeDialog = function (ajax, response, status) {
     var $dialog = $(response.selector);
@@ -141,14 +159,21 @@
       }
     }
 
-    // Unbind dialogButtonsChange
+    // Unbind dialogButtonsChange.
     $dialog.off('dialogButtonsChange');
   };
 
   /**
    * Command to set a dialog property.
    *
-   * jQuery UI specific way of setting dialog options.
+   * JQuery UI specific way of setting dialog options.
+   *
+   * @param {Drupal.Ajax} [ajax]
+   * @param {object} response
+   * @param {string} response.selector
+   * @param {string} response.optionsName
+   * @param {string} response.optionValue
+   * @param {number} [status]
    */
   Drupal.AjaxCommands.prototype.setDialogOption = function (ajax, response, status) {
     var $dialog = $(response.selector);
@@ -159,6 +184,11 @@
 
   /**
    * Binds a listener on dialog creation to handle the cancel link.
+   *
+   * @param {jQuery.Event} e
+   * @param {Drupal.dialog~dialogDefinition} dialog
+   * @param {jQuery} $element
+   * @param {object} settings
    */
   $(window).on('dialog:aftercreate', function (e, dialog, $element, settings) {
     $element.on('click.dialog', '.dialog-cancel', function (e) {
@@ -170,6 +200,10 @@
 
   /**
    * Removes all 'dialog' listeners.
+   *
+   * @param {jQuery.Event} e
+   * @param {Drupal.dialog~dialogDefinition} dialog
+   * @param {jQuery} $element
    */
   $(window).on('dialog:beforeclose', function (e, dialog, $element) {
     $element.off('.dialog');
diff --git a/core/misc/dialog/dialog.jquery-ui.js b/core/misc/dialog/dialog.jquery-ui.js
index cd6e863..27fff75 100644
--- a/core/misc/dialog/dialog.jquery-ui.js
+++ b/core/misc/dialog/dialog.jquery-ui.js
@@ -2,6 +2,7 @@
  * @file
  * Adds default classes to buttons for styling purposes.
  */
+
 (function ($) {
 
   "use strict";
diff --git a/core/misc/dialog/dialog.js b/core/misc/dialog/dialog.js
index f63b405..cb7fb92 100644
--- a/core/misc/dialog/dialog.js
+++ b/core/misc/dialog/dialog.js
@@ -1,30 +1,64 @@
 /**
  * @file
+ * Dialog API inspired by HTML5 dialog element.
  *
- * Dialog API inspired by HTML5 dialog element:
- * http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#the-dialog-element
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#the-dialog-element
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
+  /**
+   * Default dialog options.
+   *
+   * @type {object}
+   *
+   * @prop {bool} [autoOpen=true]
+   * @prop {string} [dialogClass='']
+   * @prop {string} [buttonClass='button']
+   * @prop {string} [buttonPrimaryClass='button--primary']
+   * @prop {function} close
+   */
   drupalSettings.dialog = {
     autoOpen: true,
     dialogClass: '',
     // Drupal-specific extensions: see dialog.jquery-ui.js.
     buttonClass: 'button',
     buttonPrimaryClass: 'button--primary',
-    // 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.
+    // When using this API directly (when generating dialogs on the client
+    // side), you may want to override this method and do
+    // `jQuery(event.target).remove()` as well, to remove the dialog on
+    // closing.
     close: function (event) {
       Drupal.detachBehaviors(event.target, null, 'unload');
     }
   };
 
+  /**
+   * @typedef {object} Drupal.dialog~dialogDefinition
+   *
+   * @prop {boolean} open
+   *   Is the dialog open or not.
+   * @prop {*} returnValue
+   *   Return value of the dialog.
+   * @prop {function} show
+   *   Method to display the dialog on the page.
+   * @prop {function} showModal
+   *   Method to display the dialog as a modal on the page.
+   * @prop {function} close
+   *   Method to hide the dialog from the page.
+   */
+
+  /**
+   * Polyfill HTML5 dialog element with jQueryUI.
+   *
+   * @param {HTMLElement} element
+   * @param {object} options
+   *   jQuery UI options to be passed to the dialog.
+   *
+   * @return {Drupal.dialog~dialogDefinition}
+   */
   Drupal.dialog = function (element, options) {
 
     function openDialog(settings) {
diff --git a/core/misc/dialog/dialog.position.js b/core/misc/dialog/dialog.position.js
index 3e08574..72e6ddf 100644
--- a/core/misc/dialog/dialog.position.js
+++ b/core/misc/dialog/dialog.position.js
@@ -1,3 +1,14 @@
+/**
+ * @file
+ * Positioning extensions for dialogs.
+ */
+
+/**
+ * Triggers when content inside a dialog changes.
+ *
+ * @event dialogContentResize
+ */
+
 (function ($, Drupal, drupalSettings, debounce, displace) {
 
   "use strict";
@@ -12,6 +23,12 @@
    * jQuery UI dialog. Although not a built-in jQuery UI option, this can
    * be disabled by setting autoResize: false in the options array when creating
    * a new Drupal.dialog().
+   *
+   * @function Drupal.dialog~resetSize
+   *
+   * @param {jQuery.Event} event
+   *
+   * @fires event:dialogContentResize
    */
   function resetSize(event) {
     var positionOptions = ['width', 'height', 'minWidth', 'minHeight', 'maxHeight', 'maxWidth', 'position'];
@@ -46,6 +63,12 @@
 
   /**
    * Position the dialog's center at the center of displace.offsets boundaries.
+   *
+   * @function Drupal.dialog~resetPosition
+   *
+   * @param {object} options
+   *
+   * @return {object}
    */
   function resetPosition(options) {
     var offsets = displace.offsets;
diff --git a/core/misc/displace.js b/core/misc/displace.js
index a52a826..d267d36 100644
--- a/core/misc/displace.js
+++ b/core/misc/displace.js
@@ -1,13 +1,38 @@
 /**
+ * @file
  * Manages elements that can offset the size of the viewport.
  *
  * Measures and reports viewport offset dimensions from elements like the
  * toolbar that can potentially displace the positioning of other elements.
  */
+
+/**
+ * @typedef {object} Drupal.displace~offset
+ *
+ * @prop {number} top
+ * @prop {number} left
+ * @prop {number} right
+ * @prop {number} bottom
+ */
+
+/**
+ * Triggers when layout of the page changes.
+ *
+ * This is used to position fixed element on the page during page resize and
+ * Toolbar toggling.
+ *
+ * @event drupalViewportOffsetChange
+ */
+
 (function ($, Drupal, debounce) {
 
   "use strict";
 
+  /**
+   * @name Drupal.displace.offsets
+   *
+   * @type {Drupal.displace~offset}
+   */
   var offsets = {
     top: 0,
     right: 0,
@@ -17,6 +42,8 @@
 
   /**
    * Registers a resize handler on the window.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.drupalDisplace = {
     attach: function () {
@@ -33,11 +60,15 @@
   /**
    * Informs listeners of the current offset dimensions.
    *
-   * @param {boolean} broadcast
-   *   (optional) When true or undefined, causes the recalculated offsets values to be
+   * @name Drupal.displace
+   *
+   * @fires event:drupalViewportOffsetChange
+   *
+   * @param {bool} [broadcast]
+   *   When true or undefined, causes the recalculated offsets values to be
    *   broadcast to listeners.
    *
-   * @return {object}
+   * @return {Drupal.displace~offset}
    *   An object whose keys are the for sides an element -- top, right, bottom
    *   and left. The value of each key is the viewport displacement distance for
    *   that edge.
@@ -53,7 +84,7 @@
   /**
    * Determines the viewport offsets.
    *
-   * @return {object}
+   * @return {Drupal.displace~offset}
    *   An object whose keys are the for sides an element -- top, right, bottom
    *   and left. The value of each key is the viewport displacement distance for
    *   that edge.
@@ -75,6 +106,8 @@
    * numeric value, that value will be used. If no value is provided, one will
    * be calculated using the element's dimensions and placement.
    *
+   * @name Drupal.displace.calculateOffset
+   *
    * @param {string} edge
    *   The name of the edge to calculate. Can be 'top', 'right',
    *   'bottom' or 'left'.
@@ -111,7 +144,7 @@
   /**
    * Calculates displacement for element based on its dimensions and placement.
    *
-   * @param {jQuery} $el
+   * @param {HTMLElement} el
    *   The jQuery element whose dimensions and placement will be measured.
    *
    * @param {string} edge
@@ -163,15 +196,23 @@
 
   /**
    * Assign the displace function to a property of the Drupal global object.
+   *
+   * @ignore
    */
   Drupal.displace = displace;
   $.extend(Drupal.displace, {
+
     /**
-     * Expose offsets to other scripts to avoid having to recalculate offsets
+     * Expose offsets to other scripts to avoid having to recalculate offsets.
+     *
+     * @ignore
      */
     offsets: offsets,
+
     /**
      * Expose method to compute a single edge offsets.
+     *
+     * @ignore
      */
     calculateOffset: calculateOffset
   });
diff --git a/core/misc/dropbutton/dropbutton.js b/core/misc/dropbutton/dropbutton.js
index eebf354..787cc56 100644
--- a/core/misc/dropbutton/dropbutton.js
+++ b/core/misc/dropbutton/dropbutton.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Dropbutton feature.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
 
   /**
    * Process elements with the .dropbutton class on page load.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.dropButton = {
     attach: function (context, settings) {
@@ -25,6 +32,10 @@
 
   /**
    * Delegated callback for opening and closing dropbutton secondary actions.
+   *
+   * @function Drupal.DropButton~dropbuttonClickHandler
+   *
+   * @param {jQuery.Event} e
    */
   function dropbuttonClickHandler(e) {
     e.preventDefault();
@@ -37,21 +48,36 @@
    * All secondary actions beyond the first in the list are presented in a
    * dropdown list accessible through a toggle arrow associated with the button.
    *
-   * @param {jQuery} $dropbutton
-   *   A jQuery element.
+   * @constructor Drupal.DropButton
    *
-   * @param {Object} settings
+   * @param {HTMLElement} dropbutton
+   *   A DOM element.
+   * @param {object} settings
    *   A list of options including:
-   *    - {String} title: The text inside the toggle link element. This text is
-   *      hidden from visual UAs.
+   * @param {string} settings.title
+   *   The text inside the toggle link element. This text is hidden
+   *   from visual UAs.
    */
   function DropButton(dropbutton, settings) {
     // Merge defaults with settings.
     var options = $.extend({'title': Drupal.t('List additional actions')}, settings);
     var $dropbutton = $(dropbutton);
+
+    /**
+     * @type {jQuery}
+     */
     this.$dropbutton = $dropbutton;
+
+    /**
+     * @type {jQuery}
+     */
     this.$list = $dropbutton.find('.dropbutton');
-    // Find actions and mark them.
+
+    /**
+     * Find actions and mark them.
+     *
+     * @type {jQuery}
+     */
     this.$actions = this.$list.find('li').addClass('dropbutton-action');
 
     // Add the special dropdown only if there are hidden actions.
@@ -67,18 +93,31 @@
       this.$dropbutton
         .addClass('dropbutton-multiple')
         .on({
+
           /**
            * Adds a timeout to close the dropdown on mouseleave.
+           *
+           * @ignore
            */
           'mouseleave.dropbutton': $.proxy(this.hoverOut, this),
+
           /**
            * Clears timeout when mouseout of the dropdown.
+           *
+           * @ignore
            */
           'mouseenter.dropbutton': $.proxy(this.hoverIn, this),
+
           /**
            * Similar to mouseleave/mouseenter, but for keyboard navigation.
+           *
+           * @ignore
            */
           'focusout.dropbutton': $.proxy(this.focusOut, this),
+
+          /**
+           * @ignore
+           */
           'focusin.dropbutton': $.proxy(this.focusIn, this)
         });
     }
@@ -90,11 +129,11 @@
   /**
    * Extend the DropButton constructor.
    */
-  $.extend(DropButton, {
+  $.extend(DropButton, /** @lends Drupal.DropButton */{
     /**
      * Store all processed DropButtons.
      *
-     * @type {Array}
+     * @type {Array.<Drupal.DropButton>}
      */
     dropbuttons: []
   });
@@ -102,12 +141,13 @@
   /**
    * Extend the DropButton prototype.
    */
-  $.extend(DropButton.prototype, {
+  $.extend(DropButton.prototype, /** @lends Drupal.DropButton# */{
+
     /**
      * Toggle the dropbutton open and closed.
      *
-     * @param {Boolean} show
-     *   (optional) Force the dropbutton to open by passing true or to close by
+     * @param {bool} [show]
+     *   Force the dropbutton to open by passing true or to close by
      *   passing false.
      */
     toggle: function (show) {
@@ -116,6 +156,9 @@
       this.$dropbutton.toggleClass('open', show);
     },
 
+    /**
+     * @method
+     */
     hoverIn: function () {
       // Clear any previous timer we were using.
       if (this.timerID) {
@@ -123,37 +166,53 @@
       }
     },
 
+    /**
+     * @method
+     */
     hoverOut: function () {
       // Wait half a second before closing.
       this.timerID = window.setTimeout($.proxy(this, 'close'), 500);
     },
 
+    /**
+     * @method
+     */
     open: function () {
       this.toggle(true);
     },
 
+    /**
+     * @method
+     */
     close: function () {
       this.toggle(false);
     },
 
+    /**
+     * @param {jQuery.Event} e
+     */
     focusOut: function (e) {
       this.hoverOut.call(this, e);
     },
 
+    /**
+     * @param {jQuery.Event} e
+     */
     focusIn: function (e) {
       this.hoverIn.call(this, e);
     }
   });
 
-  $.extend(Drupal.theme, {
+  $.extend(Drupal.theme, /** @lends Drupal.theme */{
+
     /**
      * A toggle is an interactive element often bound to a click handler.
      *
-     * @param {Object} options
-     *   - {String} title: (optional) The HTML anchor title attribute and
-     *     text for the inner span element.
+     * @param {object} options
+     * @param {string} [options.title]
+     *   The HTML anchor title attribute and text for the inner span element.
      *
-     * @return {String}
+     * @return {string}
      *   A string representing a DOM fragment.
      */
     dropbuttonToggle: function (options) {
diff --git a/core/misc/drupal.js b/core/misc/drupal.js
index 9e9d24e..c342c69 100644
--- a/core/misc/drupal.js
+++ b/core/misc/drupal.js
@@ -1,7 +1,40 @@
 /**
- * Base framework for Drupal-specific JavaScript, behaviors, and settings.
+ * @file
+ * Defines the Drupal JS API.
  */
-window.Drupal = {behaviors: {}};
+
+/**
+ * A jQuery object.
+ *
+ * @typedef {object} jQuery
+ *
+ * @prop {number} length=0
+ */
+
+/**
+ * Variable generated by Drupal with all the configuration created from PHP.
+ *
+ * @global
+ *
+ * @var {object} drupalSettings
+ */
+
+/**
+ * Variable generated by Drupal that holds all translated strings from PHP.
+ *
+ * @global
+ *
+ * @var {object} drupalTranslations
+ */
+
+/**
+ * Global Drupal object.
+ *
+ * @global
+ *
+ * @namespace
+ */
+window.Drupal = {behaviors: {}, locale: {}};
 
 // Class indicating that JS is enabled; used for styling purpose.
 document.documentElement.className += ' js';
@@ -18,16 +51,43 @@ if (window.jQuery) {
   "use strict";
 
   /**
-   * Custom error type thrown after attach/detach if one or more behaviors failed.
+   * Custom error type thrown after attach/detach if one or more behaviors
+   * failed.
+   *
+   * @memberof Drupal
    *
-   * @param list
+   * @constructor
+   *
+   * @augments Error
+   *
+   * @param {Array} list
    *   An array of errors thrown during attach/detach.
-   * @param event
+   * @param {string} event
    *   A string containing either 'attach' or 'detach'.
+   *
+   * @inner
    */
   function DrupalBehaviorError(list, event) {
+
+    /**
+     * Setting name helps debuggers.
+     *
+     * @type {string}
+     */
     this.name = 'DrupalBehaviorError';
+
+    /**
+     * Execution phase errors were triggered.
+     *
+     * @type {string}
+     */
     this.event = event || 'attach';
+
+    /**
+     * All thrown errors.
+     *
+     * @type {Array.<Error>}
+     */
     this.list = list;
     // Makes the list of errors readable.
     var messageList = [];
@@ -36,48 +96,100 @@ if (window.jQuery) {
     for (var i = 0; i < il; i++) {
       messageList.push(this.list[i].behavior + ': ' + this.list[i].error.message);
     }
+
+    /**
+     * Final message to send to debuggers.
+     *
+     * @type {string}
+     */
     this.message = messageList.join(' ; ');
   }
 
   DrupalBehaviorError.prototype = new Error();
 
   /**
+   * Callback function initializing code run on page load and Ajax requests.
+   *
+   * @callback Drupal~behaviorAttach
+   *
+   * @param {HTMLElement} context
+   * @param {object} settings
+   *
+   * @see Drupal.attachBehaviors
+   */
+
+  /**
+   * Callback function for reverting and cleaning up behavior initialization.
+   *
+   * @callback Drupal~behaviorDetach
+   *
+   * @param {HTMLElement} context
+   * @param {object} settings
+   * @param {string} trigger
+   *   One of 'unload', 'serialize' or 'move'.
+   *
+   * @see Drupal.detachBehaviors
+   */
+
+  /**
+   * @typedef {object} Drupal~behavior
+   *
+   * @prop {Drupal~behaviorAttach} attach
+   *   Function run on page load and after an AJAX call.
+   * @prop {Drupal~behaviorDetach} detach
+   *   Function run when content is serialized or removed from the page.
+   */
+
+  /**
+   * Holds all initialization methods.
+   *
+   * @namespace Drupal.behaviors
+   *
+   * @type {Object.<string, Drupal~behavior>}
+   */
+
+  /**
    * Attach all registered behaviors to a page element.
    *
-   * Behaviors are event-triggered actions that attach to page elements, enhancing
-   * default non-JavaScript UIs. Behaviors are registered in the Drupal.behaviors
-   * object using the method 'attach' and optionally also 'detach' as follows:
-   * @code
-   *    Drupal.behaviors.behaviorName = {
-   *      attach: function (context, settings) {
-   *        ...
-   *      },
-   *      detach: function (context, settings, trigger) {
-   *        ...
-   *      }
-   *    };
-   * @endcode
-   *
-   * Drupal.attachBehaviors is added below to the jQuery.ready event and therefore
-   * runs on initial page load. Developers implementing Ajax in their solutions
-   * should also call this function after new page content has been loaded,
-   * feeding in an element to be processed, in order to attach all behaviors to
-   * the new content.
+   * Behaviors are event-triggered actions that attach to page elements,
+   * enhancing default non-JavaScript UIs. Behaviors are registered in the
+   * Drupal.behaviors object using the method 'attach' and optionally also
+   * 'detach' as follows:
+   *
+   * Drupal.attachBehaviors is added below to the jQuery.ready event and
+   * therefore runs on initial page load. Developers implementing Ajax in their
+   * solutions should also call this function after new page content has been
+   * loaded, feeding in an element to be processed, in order to attach all
+   * behaviors to the new content.
    *
    * Behaviors should use
-   * @code
-   *   var elements = $(context).find(selector).once('behavior-name');
-   * @endcode
+   *     `var elements = $(context).find(selector).once('behavior-name');`
    * to ensure the behavior is attached only once to a given element. (Doing so
-   * enables the reprocessing of given elements, which may be needed on occasion
-   * despite the ability to limit behavior attachment to a particular element.)
+   * enables the reprocessing of given elements, which may be needed on
+   * occasion despite the ability to limit behavior attachment to a particular
+   * element.)
    *
-   * @param context
-   *   An element to attach behaviors to. If none is given, the document element
-   *   is used.
-   * @param settings
+   * @example
+   * Drupal.behaviors.behaviorName = {
+   *   attach: function (context, settings) {
+   *     ...
+   *   },
+   *   detach: function (context, settings, trigger) {
+   *     ...
+   *   }
+   * };
+   *
+   * @param {Element} context
+   *   An element to attach behaviors to. If none is given, the document
+   *   element is used.
+   * @param {object} settings
    *   An object containing settings for the current context. If none is given,
    *   the global drupalSettings object is used.
+   *
+   * @see Drupal~behaviorAttach
+   * @see Drupal.detachBehaviors
+   *
+   * @throws {Drupal~DrupalBehaviorError}
    */
   Drupal.attachBehaviors = function (context, settings) {
     context = context || document;
@@ -115,16 +227,16 @@ if (window.jQuery) {
    *
    * Such implementations should use .findOnce() and .removeOnce() to find
    * elements with their corresponding Drupal.behaviors.behaviorName.attach
-   * implementation, i.e. .removeOnce('behaviorName'), to ensure the behavior is
-   * detached only from previously processed elements.
-   *
-   * @param context
-   *   An element to detach behaviors from. If none is given, the document element
-   *   is used.
-   * @param settings
-   *   An object containing settings for the current context. If none given, the
-   *   global drupalSettings object is used.
-   * @param trigger
+   * implementation, i.e. .removeOnce('behaviorName'), to ensure the behavior
+   * is detached only from previously processed elements.
+   *
+   * @param {Element} context
+   *   An element to detach behaviors from. If none is given, the document
+   *   element is used.
+   * @param {object} settings
+   *   An object containing settings for the current context. If none given,
+   *   the global drupalSettings object is used.
+   * @param {string} trigger
    *   A string containing what's causing the behaviors to be detached. The
    *   possible triggers are:
    *   - unload: (default) The context element is being removed from the DOM.
@@ -143,6 +255,9 @@ if (window.jQuery) {
    *     that WYSIWYG editors can update the hidden textarea to which they are
    *     bound.
    *
+   * @throws {Drupal~DrupalBehaviorError}
+   *
+   * @see Drupal~behaviorDetach
    * @see Drupal.attachBehaviors
    */
   Drupal.detachBehaviors = function (context, settings, trigger) {
@@ -171,7 +286,12 @@ if (window.jQuery) {
 
   /**
    * Helper to test document width for mobile configurations.
-   * @todo Temporary solution for the mobile initiative.
+   *
+   * @param {number} [width]
+   *
+   * @return {bool}
+   *
+   * @deprecated Temporary solution for the mobile initiative.
    */
   Drupal.checkWidthBreakpoint = function (width) {
     width = width || drupalSettings.widthBreakpoint || 640;
@@ -181,10 +301,12 @@ if (window.jQuery) {
   /**
    * Encode special characters in a plain-text string for display as HTML.
    *
-   * @param str
+   * @param {string} str
    *   The string to be encoded.
-   * @return
+   *
+   * @return {string}
    *   The encoded string.
+   *
    * @ingroup sanitization
    */
   Drupal.checkPlain = function (str) {
@@ -199,9 +321,9 @@ if (window.jQuery) {
   /**
    * Replace placeholders with sanitized values in a string.
    *
-   * @param {String} str
+   * @param {string} str
    *   A string with placeholders.
-   * @param {Object} args
+   * @param {object} args
    *   An object of replacements pairs to make. Incidences of any key in this
    *   array are replaced with the corresponding value. Based on the first
    *   character of the key, the value is escaped and/or themed:
@@ -210,11 +332,9 @@ if (window.jQuery) {
    *    - %variable: escape text and theme as a placeholder for user-submitted
    *      content (checkPlain + Drupal.theme('placeholder'))
    *
-   * @return {String}
-   *   Returns the replaced string.
+   * @return {string}
    *
-   * @see Drupal.t()
-   * @ingroup sanitization
+   * @see Drupal.t
    */
   Drupal.formatString = function (str, args) {
     // Keep args intact.
@@ -227,10 +347,12 @@ if (window.jQuery) {
           case '@':
             processedArgs[key] = Drupal.checkPlain(args[key]);
             break;
+
           // Pass-through.
           case '!':
             processedArgs[key] = args[key];
             break;
+
           // Escaped and placeholder.
           default:
             processedArgs[key] = Drupal.theme('placeholder', args[key]);
@@ -248,14 +370,14 @@ if (window.jQuery) {
    * The longest keys will be tried first. Once a substring has been replaced,
    * its new value will not be searched again.
    *
-   * @param {String} str
+   * @param {string} str
    *   A string with placeholders.
-   * @param {Object} args
+   * @param {object} args
    *   Key-value pairs.
    * @param {Array|null} keys
    *   Array of keys from the "args".  Internal use only.
    *
-   * @return {String}
+   * @return {string}
    *   Returns the replaced string.
    */
   Drupal.stringReplace = function (str, args, keys) {
@@ -299,18 +421,17 @@ if (window.jQuery) {
    *
    * See the documentation of the server-side t() function for further details.
    *
-   * @param str
+   * @param {string} str
    *   A string containing the English string to translate.
-   * @param args
+   * @param {Object.<string, string>} [args]
    *   An object of replacements pairs to make after translation. Incidences
    *   of any key in this array are replaced with the corresponding value.
-   *   See Drupal.formatString().
+   *   See {@link Drupal.formatString}.
+   * @param {object} [options]
+   * @param {string} [options.context='']
+   *   The context the source string belongs to.
    *
-   * @param options
-   *   - 'context' (defaults to the empty context): The context the source string
-   *     belongs to.
-   *
-   * @return
+   * @return {string}
    *   The translated string.
    */
   Drupal.t = function (str, args, options) {
@@ -330,6 +451,11 @@ if (window.jQuery) {
 
   /**
    * Returns the URL to a Drupal page.
+   *
+   * @param {string} path
+   *   Drupal path to transform to URL.
+   *
+   * @return {string}
    */
   Drupal.url = function (path) {
     return drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix + path;
@@ -346,26 +472,26 @@ if (window.jQuery) {
    * \Drupal\Core\StringTranslation\TranslationInterface::formatPlural()
    * function for more details.
    *
-   * @param {Number} count
+   * @param {number} count
    *   The item count to display.
-   * @param {String} singular
+   * @param {string} singular
    *   The string for the singular case. Please make sure it is clear this is
    *   singular, to ease translation (e.g. use "1 new comment" instead of "1
    *   new"). Do not use @count in the singular string.
-   * @param {String} plural
+   * @param {string} plural
    *   The string for the plural case. Please make sure it is clear this is
    *   plural, to ease translation. Use @count in place of the item count, as in
    *   "@count new comments".
-   * @param {Object} args
+   * @param {object} [args]
    *   An object of replacements pairs to make after translation. Incidences
    *   of any key in this array are replaced with the corresponding value.
    *   See Drupal.formatString().
    *   Note that you do not need to include @count in this array.
    *   This replacement is done automatically for the plural case.
-   * @param {Object} options
+   * @param {object} [options]
    *   The options to pass to the Drupal.t() function.
    *
-   * @return {String}
+   * @return {string}
    *   A translated string.
    */
   Drupal.formatPlural = function (count, singular, plural, args, options) {
@@ -391,6 +517,11 @@ if (window.jQuery) {
    * Encodes a Drupal path for use in a URL.
    *
    * For aesthetic reasons slashes are not escaped.
+   *
+   * @param {string} item
+   *   Unencoded path.
+   *
+   * @return {string}
    */
   Drupal.encodePath = function (item) {
     return window.encodeURIComponent(item).replace(/%2F/g, '/');
@@ -406,13 +537,16 @@ if (window.jQuery) {
    *
    * For example, to retrieve the HTML for text that should be emphasized and
    * displayed as a placeholder inside a sentence, call
-   * Drupal.theme('placeholder', text).
+   * `Drupal.theme('placeholder', text)`.
+   *
+   * @namespace
    *
-   * @param func
+   * @param {function} func
    *   The name of the theme function to call.
-   * @param ...
+   * @param {...args}
    *   Additional arguments to pass along to the theme function.
-   * @return
+   *
+   * @return {string|object|HTMLElement|jQuery}
    *   Any data the theme function returns. This could be a plain HTML string,
    *   but also a complex object.
    */
@@ -426,9 +560,10 @@ if (window.jQuery) {
   /**
    * Formats text for emphasized display in a placeholder inside a sentence.
    *
-   * @param str
+   * @param {string} str
    *   The text to format (plain-text).
-   * @return
+   *
+   * @return {string}
    *   The formatted text (html).
    */
   Drupal.theme.placeholder = function (str) {
diff --git a/core/misc/form.js b/core/misc/form.js
index b1d1fff..d73db7a 100644
--- a/core/misc/form.js
+++ b/core/misc/form.js
@@ -1,9 +1,25 @@
+/**
+ * @file
+ * Form features.
+ */
+
+/**
+ * Triggers when a value in the form changed.
+ *
+ * The event triggers when content is typed or pasted in a text field, before
+ * the change event triggers.
+ *
+ * @event formUpdated
+ */
+
 (function ($, Drupal, debounce) {
 
   "use strict";
 
   /**
    * Retrieves the summary for the first element.
+   *
+   * @return {string}
    */
   $.fn.drupalGetSummary = function () {
     var callback = this.data('summaryCallback');
@@ -13,9 +29,15 @@
   /**
    * Sets the summary for all matched elements.
    *
-   * @param callback
+   * @param {function} callback
    *   Either a function that will be called each time the summary is
    *   retrieved or a string (which is returned each time).
+   *
+   * @return {jQuery}
+   *
+   * @fires event:summaryUpdated
+   *
+   * @listens event:formUpdated
    */
   $.fn.drupalSetSummary = function (callback) {
     var self = this;
@@ -43,13 +65,13 @@
   /**
    * 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.
+   * 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.
+   * 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
@@ -57,26 +79,28 @@
    * 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:
+   * 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.
+   *   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.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.formSingleSubmit = {
     attach: function () {
@@ -99,6 +123,10 @@
 
   /**
    * Sends a 'formUpdated' event each time a form element is modified.
+   *
+   * @param {HTMLElement} element
+   *
+   * @fires event:formUpdated
    */
   function triggerFormUpdated(element) {
     $(element).trigger('formUpdated');
@@ -108,6 +136,7 @@
    * Collects the IDs of all form fields in the given form.
    *
    * @param {HTMLFormElement} form
+   *
    * @return {Array}
    */
   function fieldsList(form) {
@@ -122,6 +151,10 @@
 
   /**
    * Triggers the 'formUpdated' event on form elements when they are modified.
+   *
+   * @type {Drupal~behavior}
+   *
+   * @fires event:formUpdated
    */
   Drupal.behaviors.formUpdated = {
     attach: function (context) {
@@ -132,7 +165,8 @@
 
       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.
+        // 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);
@@ -147,7 +181,7 @@
         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
+        // If there has been a change in the fields or their order, trigger
         // formUpdated.
         if (formFields !== currentFields) {
           triggerFormUpdated(context);
@@ -172,6 +206,8 @@
 
   /**
    * Prepopulate form fields with information from the visitor browser.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.fillUserInfoFromBrowser = {
     attach: function (context, settings) {
diff --git a/core/misc/machine-name.js b/core/misc/machine-name.js
index 5319aa9..25e8b84 100644
--- a/core/misc/machine-name.js
+++ b/core/misc/machine-name.js
@@ -1,28 +1,39 @@
+/**
+ * @file
+ * Machine name functionality.
+ */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
    * Attach the machine-readable name form element behavior.
+   *
+   * @type {Drupal~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:
+     * @param {Element} context
+     * @param {object} settings
+     * @param {object} 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).
+     *   - 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.
+     *   - 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.
      */
@@ -95,9 +106,9 @@
         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.
+        // 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();
         }
@@ -160,17 +171,19 @@
     /**
      * Transliterate a human-readable name to a machine name.
      *
-     * @param source
+     * @param {string} 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.
+     * @param {object} settings
+     *   The machine name settings for the corresponding field.
+     * @param {string} settings.replace_pattern
+     *   A regular expression (without modifiers) matching disallowed characters
+     *   in the machine name; e.g., '[^a-z0-9]+'.
+     * @param {string} settings.replace
+     *   A character to replace disallowed characters with; e.g., '_' or '-'.
+     * @param {number} settings.maxlength
+     *   The maximum length of the machine name.
      *
-     * @return
+     * @return {jQuery}
      *   The transliterated source string.
      */
     transliterate: function (source, settings) {
diff --git a/core/misc/progress.js b/core/misc/progress.js
index 7305d24..62b9b27 100644
--- a/core/misc/progress.js
+++ b/core/misc/progress.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Progress bar.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
@@ -5,7 +10,9 @@
   /**
    * Theme function for the progress bar.
    *
-   * @return
+   * @param {string} id
+   *
+   * @return {string}
    *   The HTML for the progress bar.
    */
   Drupal.theme.progressBar = function (id) {
@@ -21,11 +28,19 @@
    * 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
+   * 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);
+   * @example
+   * pb = new Drupal.ProgressBar('myProgressBar');
+   * some_element.appendChild(pb.element);
+   *
+   * @constructor
+   *
+   * @param {string} id
+   * @param {function} updateCallback
+   * @param {string} method
+   * @param {function} errorCallback
    */
   Drupal.ProgressBar = function (id, updateCallback, method, errorCallback) {
     this.id = id;
@@ -33,14 +48,21 @@
     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.
+    // 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 = $(Drupal.theme('progressBar', id));
   };
 
-  $.extend(Drupal.ProgressBar.prototype, {
+  $.extend(Drupal.ProgressBar.prototype, /** @lends Drupal.ProgressBar# */{
+
     /**
      * Set the percentage and status message for the progressbar.
+     *
+     * @param {number} percentage
+     * @param {string} message
+     * @param {string} label
      */
     setProgress: function (percentage, message, label) {
       if (percentage >= 0 && percentage <= 100) {
@@ -56,6 +78,9 @@
 
     /**
      * Start monitoring progress via Ajax.
+     *
+     * @param {string} uri
+     * @param {number} delay
      */
     startMonitoring: function (uri, delay) {
       this.delay = delay;
@@ -109,6 +134,8 @@
 
     /**
      * Display errors on the page.
+     *
+     * @param {string} string
      */
     displayError: function (string) {
       var error = $('<div class="messages messages--error"></div>').html(string);
diff --git a/core/misc/states.js b/core/misc/states.js
index b969da7..3a67aea 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -1,6 +1,8 @@
 /**
+ * @file
  * Drupal's states library.
  */
+
 (function ($) {
 
   "use strict";
@@ -10,14 +12,21 @@
    *
    * Having the local states variable allows us to use the States namespace
    * without having to always declare "Drupal.states".
+   *
+   * @namespace Drupal.states
    */
   var states = Drupal.states = {
-    // An array of functions that should be postponed.
+
+    /**
+     * An array of functions that should be postponed.
+     */
     postponed: []
   };
 
   /**
    * Attaches the states.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.states = {
     attach: function (context, settings) {
@@ -48,13 +57,18 @@
   /**
    * 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.
+   * @constructor Drupal.states.Dependent
+   *
+   * @param {object} args
+   *   Object with the following keys (all of which are required)
+   * @param {jQuery} args.element
+   *   A jQuery object of the dependent element
+   * @param {Drupal.states.State} args.state
+   *   A State object describing the state that is dependent
+   * @param {object} args.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);
@@ -71,6 +85,12 @@
    * 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.
+   *
+   * @name Drupal.states.Dependent.comparisons
+   *
+   * @prop {function} RegExp
+   * @prop {function} Function
+   * @prop {function} Number
    */
   states.Dependent.comparisons = {
     'RegExp': function (reference, value) {
@@ -81,21 +101,25 @@
       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().
+      // 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
+     * @memberof Drupal.states.Dependent#
+     *
+     * @param {string} selector
      *   The CSS selector describing the dependee.
-     * @param dependeeStates
+     * @param {object} dependeeStates
      *   The list of states that have to be monitored for tracking the
      *   dependee's compliance status.
      */
@@ -113,7 +137,8 @@
       for (var i in dependeeStates) {
         if (dependeeStates.hasOwnProperty(i)) {
           state = dependeeStates[i];
-          // Make sure we're not initializing this selector/state combination twice.
+          // Make sure we're not initializing this selector/state combination
+          // twice.
           if ($.inArray(state, dependeeStates) === -1) {
             continue;
           }
@@ -135,14 +160,16 @@
     /**
      * Compares a value with a reference value.
      *
-     * @param reference
+     * @memberof Drupal.states.Dependent#
+     *
+     * @param {object} reference
      *   The value used for reference.
-     * @param selector
+     * @param {string} selector
      *   CSS selector describing the dependee.
-     * @param state
+     * @param {Drupal.states.State} state
      *   A State object describing the dependee's updated state.
      *
-     * @return
+     * @return {bool}
      *   true or false.
      */
     compare: function (reference, selector, state) {
@@ -160,11 +187,13 @@
     /**
      * Update the value of a dependee's state.
      *
-     * @param selector
+     * @memberof Drupal.states.Dependent#
+     *
+     * @param {string} selector
      *   CSS selector describing the dependee.
-     * @param state
+     * @param {Drupal.states.state} state
      *   A State object describing the dependee's updated state.
-     * @param value
+     * @param {string} value
      *   The new value for the dependee's updated state.
      */
     update: function (selector, state, value) {
@@ -177,6 +206,8 @@
 
     /**
      * Triggers change events in case a state changed.
+     *
+     * @memberof Drupal.states.Dependent#
      */
     reevaluate: function () {
       // Check whether any constraint for this dependent state is satisfied.
@@ -200,14 +231,16 @@
     /**
      * Evaluates child constraints to determine if a constraint is satisfied.
      *
-     * @param constraints
+     * @memberof Drupal.states.Dependent#
+     *
+     * @param {object|Array} constraints
      *   A constraint object or an array of constraints.
-     * @param selector
+     * @param {string} 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
+     * @return {bool}
      *   true or false, depending on whether these constraints are satisfied.
      */
     verifyConstraints: function (constraints, selector) {
@@ -219,8 +252,8 @@
         for (var i = 0; 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.
+            // 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;
             }
@@ -229,15 +262,15 @@
         }
       }
       // 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.
+      // 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.
+            // False and anything else will evaluate to false, so return when
+            // any false condition is found.
             if (result === false) { return false; }
           }
         }
@@ -248,27 +281,28 @@
     /**
      * Checks whether the value matches the requirements for this constraint.
      *
-     * @param value
+     * @memberof Drupal.states.Dependent#
+     *
+     * @param {string|Array|object} value
      *   Either the value of a state or an array/object of constraints. In the
      *   latter case, resolving the constraint continues.
-     * @param selector
+     * @param {string} [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
+     *   selector that this constraint applies to. In that case, the state key
+     *   is propagates to a selector and resolving continues.
+     * @param {Drupal.states.State} [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.
+     *   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
+     * @return {bool}
      *   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.
+      // 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;
       }
@@ -279,7 +313,7 @@
       }
 
       if (state !== null) {
-        // constraints is the actual constraints of an element to check for.
+        // 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);
       }
@@ -291,11 +325,15 @@
 
     /**
      * Gathers information about all required triggers.
+     *
+     * @memberof Drupal.states.Dependent#
+     *
+     * @return {object}
      */
     getDependees: function () {
       var cache = {};
-      // Swivel the lookup function so that we can record all available selector-
-      // state combinations for initialization.
+      // 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);
@@ -317,6 +355,11 @@
     }
   };
 
+  /**
+   * @constructor Drupal.states.Trigger
+   *
+   * @param {object} args
+   */
   states.Trigger = function (args) {
     $.extend(this, args);
 
@@ -332,6 +375,10 @@
   };
 
   states.Trigger.prototype = {
+
+    /**
+     * @memberof Drupal.states.Trigger#
+     */
     initialize: function () {
       var trigger = states.Trigger.states[this.state];
 
@@ -351,6 +398,12 @@
       this.element.data('trigger:' + this.state, true);
     },
 
+    /**
+     * @memberof Drupal.states.Trigger#
+     *
+     * @param {jQuery.Event} event
+     * @param {function} valueFn
+     */
     defaultTrigger: function (event, valueFn) {
       var oldValue = valueFn.call(this.element);
 
@@ -376,9 +429,16 @@
    * 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.
+   *
+   * @name Drupal.states.Trigger.states
+   *
+   * @prop empty
+   * @prop checked
+   * @prop value
+   * @prop collapsed
    */
   states.Trigger.states = {
-    // 'empty' describes the state to be monitored
+    // 'empty' describes the state to be monitored.
     empty: {
       // 'keyup' is the (native DOM) event that we watch for.
       'keyup': function () {
@@ -390,9 +450,9 @@
 
     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.
+        // 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.
@@ -434,9 +494,16 @@
 
   /**
    * A state object is used for describing the state and performing aliasing.
+   *
+   * @constructor Drupal.states.State
+   *
+   * @param {string} state
    */
   states.State = function (state) {
-    // We may need the original unresolved name later.
+
+    /**
+     * Original unresolved name.
+     */
     this.pristine = this.name = state;
 
     // Normalize the state name.
@@ -460,6 +527,12 @@
 
   /**
    * Creates a new State object by sanitizing the passed value.
+   *
+   * @name Drupal.states.State.sanitize
+   *
+   * @param {string|Drupal.states.State} state
+   *
+   * @return {Drupal.states.state}
    */
   states.State.sanitize = function (state) {
     if (state instanceof states.State) {
@@ -471,8 +544,10 @@
   };
 
   /**
-   * This list of aliases is used to normalize states and associates negated names
-   * with their respective inverse state.
+   * This list of aliases is used to normalize states and associates negated
+   * names with their respective inverse state.
+   *
+   * @name Drupal.states.State.aliases
    */
   states.State.aliases = {
     'enabled': '!disabled',
@@ -490,10 +565,18 @@
   };
 
   states.State.prototype = {
+
+    /**
+     * @memberof Drupal.states.State#
+     */
     invert: false,
 
     /**
      * Ensures that just using the state object returns the name.
+     *
+     * @memberof Drupal.states.State#
+     *
+     * @return {string}
      */
     toString: function () {
       return this.name;
@@ -563,6 +646,13 @@
 
   /**
    * Bitwise AND with a third undefined state.
+   *
+   * @function Drupal.states~ternary
+   *
+   * @param {*} a
+   * @param {*} b
+   *
+   * @return {bool}
    */
   function ternary(a, b) {
     if (typeof a === 'undefined') {
@@ -578,6 +668,13 @@
 
   /**
    * Inverts a (if it's not undefined) when invertState is true.
+   *
+   * @function Drupal.states~invert
+   *
+   * @param {*} a
+   * @param {bool} invertState
+   *
+   * @return {bool}
    */
   function invert(a, invertState) {
     return (invertState && typeof a !== 'undefined') ? !a : a;
@@ -585,6 +682,13 @@
 
   /**
    * Compares two values while ignoring undefined values.
+   *
+   * @function Drupal.states~compare
+   *
+   * @param {*} a
+   * @param {*} b
+   *
+   * @return {bool}
    */
   function compare(a, b) {
     if (a === b) {
diff --git a/core/misc/tabbingmanager.js b/core/misc/tabbingmanager.js
index dc21c02..8a68ee0 100644
--- a/core/misc/tabbingmanager.js
+++ b/core/misc/tabbingmanager.js
@@ -3,12 +3,38 @@
  * Manages page tabbing modifications made by modules.
  */
 
+/**
+ * Allow modules to respond to the constrain event.
+ *
+ * @event drupalTabbingConstrained
+ */
+
+/**
+ * Allow modules to respond to the tabbingContext release event.
+ *
+ * @event drupalTabbingContextReleased
+ */
+
+/**
+ * Allow modules to respond to the constrain event.
+ *
+ * @event drupalTabbingContextActivated
+ */
+
+/**
+ * Allow modules to respond to the constrain event.
+ *
+ * @event drupalTabbingContextDeactivated
+ */
+
 (function ($, Drupal) {
 
   "use strict";
 
   /**
    * Provides an API for managing page tabbing order modifications.
+   *
+   * @constructor
    */
   function TabbingManager() {
     // Tabbing sets are stored as a stack. The active set is at the top of the
@@ -22,23 +48,26 @@
   /**
    * Add public methods to the TabbingManager class.
    */
-  $.extend(TabbingManager.prototype, {
+  $.extend(TabbingManager.prototype, /** @lends TabbingManager# */{
+
     /**
      * Constrain tabbing to the specified set of elements only.
      *
-     * Makes elements outside of the specified set of elements unreachable via the
-     * tab key.
+     * Makes elements outside of the specified set of elements unreachable via
+     * the tab key.
+     *
+     * @fires event:drupalTabbingConstrained
      *
-     * @param jQuery elements
-     *   The set of elements to which tabbing should be constrained. Can also be
-     *   a jQuery-compatible selector string.
+     * @param {jQuery} elements
+     *   The set of elements to which tabbing should be constrained. Can also
+     *   be a jQuery-compatible selector string.
      *
-     * @return TabbingContext
+     * @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.
+      // tabbingContext instance will only be reactivated if the stack is
+      // unwound to it in the _unwindStack() method.
       var il = this.stack.length;
       for (var i = 0; i < il; i++) {
         this.stack[i].deactivate();
@@ -68,14 +97,15 @@
     },
 
     /**
-     * Restores a former tabbingContext when an active tabbingContext is released.
+     * Restores a former tabbingContext when an active one is released.
      *
-     * The TabbingManager stack of tabbingContext instances will be unwound from
-     * the top-most released tabbingContext down to the first non-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.
+      // 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--;
@@ -94,11 +124,11 @@
     /**
      * Makes all elements outside the of the tabbingContext's set untabbable.
      *
-     * Elements made untabbable have their original tabindex and autofocus values
-     * stored so that they might be restored later when this tabbingContext
-     * is deactivated.
+     * Elements made untabbable have their original tabindex and autofocus
+     * values stored so that they might be restored later when this
+     * tabbingContext is deactivated.
      *
-     * @param TabbingContext tabbingContext
+     * @param {TabbingContext} tabbingContext
      *   The TabbingContext instance that has been activated.
      */
     activate: function (tabbingContext) {
@@ -115,17 +145,18 @@
       for (var i = 0; i < il; i++) {
         this.recordTabindex($disabledSet.eq(i), level);
       }
-      // Make all tabbable elements outside of the active tabbing set unreachable.
+      // 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.
+      // 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 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);
       }
@@ -135,10 +166,10 @@
     /**
      * Restores that tabbable state of a tabbingContext's disabled elements.
      *
-     * Elements that were made untabbable have their original tabindex and autofocus
-     * values restored.
+     * Elements that were made untabbable have their original tabindex and
+     * autofocus values restored.
      *
-     * @param TabbingContext tabbingContext
+     * @param {TabbingContext} tabbingContext
      *   The TabbingContext instance that has been deactivated.
      */
     deactivate: function (tabbingContext) {
@@ -153,9 +184,9 @@
     /**
      * Records the tabindex and autofocus values of an untabbable element.
      *
-     * @param jQuery $set
+     * @param {jQuery} $el
      *   The set of elements that have been disabled.
-     * @param Number level
+     * @param {number} level
      *   The stack level for which the tabindex attribute should be recorded.
      */
     recordTabindex: function ($el, level) {
@@ -170,9 +201,9 @@
     /**
      * Restores the tabindex and autofocus values of a reactivated element.
      *
-     * @param jQuery $el
+     * @param {jQuery} $el
      *   The element that is being reactivated.
-     * @param Number level
+     * @param {number} level
      *   The stack level for which the tabindex attribute should be restored.
      */
     restoreTabindex: function ($el, level) {
@@ -214,19 +245,25 @@
    *
    * 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.
+   * @constructor
+   *
+   * @param {object} options
+   *   A set of initiating values
+   * @param {number} options.level
+   *   The level in the TabbingManager's stack of this tabbingContext.
+   * @param {jQuery} options.$tabbableElements
+   *   The DOM elements that should be reachable via the tab key when this
+   *   tabbingContext is active.
+   * @param {jQuery} options.$disabledElements
+   *   The DOM elements that should not be reachable via the tab key when this
+   *   tabbingContext is active.
+   * @param {bool} options.released
+   *   A released tabbingContext can never be activated again. It will be
+   *   cleaned up when the TabbingManager unwinds its stack.
+   * @param {bool} options.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, {
@@ -241,11 +278,15 @@
   /**
    * Add public methods to the TabbingContext class.
    */
-  $.extend(TabbingContext.prototype, {
+  $.extend(TabbingContext.prototype, /** @lends TabbingContext# */{
+
     /**
      * Releases this TabbingContext.
      *
-     * Once a TabbingContext object is released, it can never be activated again.
+     * Once a TabbingContext object is released, it can never be activated
+     * again.
+     *
+     * @fires event:drupalTabbingContextReleased
      */
     release: function () {
       if (!this.released) {
@@ -259,6 +300,8 @@
 
     /**
      * Activates this TabbingContext.
+     *
+     * @fires event:drupalTabbingContextActivated
      */
     activate: function () {
       // A released TabbingContext object can never be activated again.
@@ -272,6 +315,8 @@
 
     /**
      * Deactivates this TabbingContext.
+     *
+     * @fires event:drupalTabbingContextDeactivated
      */
     deactivate: function () {
       if (this.active) {
@@ -288,6 +333,10 @@
   if (Drupal.tabbingManager) {
     return;
   }
+
+  /**
+   * @type {TabbingManager}
+   */
   Drupal.tabbingManager = new TabbingManager();
 
 }(jQuery, Drupal));
diff --git a/core/misc/tabledrag.js b/core/misc/tabledrag.js
index 01d4654..cfcabc2 100644
--- a/core/misc/tabledrag.js
+++ b/core/misc/tabledrag.js
@@ -1,9 +1,21 @@
+/**
+ * @file
+ * Provide dragging capabilities to admin uis.
+ */
+
+/**
+ * Triggers when weights columns are toggled.
+ *
+ * @event columnschange
+ */
+
 (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'));
@@ -12,12 +24,15 @@
    * 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.
+   * 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.
+   * See blocks.js for an example of adding additional functionality to
+   * tableDrag.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.tableDrag = {
     attach: function (context, settings) {
@@ -38,39 +53,124 @@
   };
 
   /**
-   * Constructor for the tableDrag object. Provides table and field manipulation.
+   * Provides table and field manipulation.
+   *
+   * @constructor
    *
-   * @param table
+   * @param {HTMLElement} table
    *   DOM object for the table to be made draggable.
-   * @param tableSettings
+   * @param {object} tableSettings
    *   Settings for the table added via drupal_add_dragtable().
    */
   Drupal.tableDrag = function (table, tableSettings) {
     var self = this;
     var $table = $(table);
 
-    // Required object variables.
+    /**
+     * @type {jQuery}
+     */
     this.$table = $(table);
+
+    /**
+     *
+     * @type {HTMLElement}
+     */
     this.table = table;
+
+    /**
+     * @type {object}
+     */
     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.
+
+    /**
+     * Used to hold information about a current drag operation.
+     *
+     * @type {?HTMLElement}
+     */
+    this.dragObject = null;
+
+    /**
+     * Provides operations for row manipulation.
+     *
+     * @type {?HTMLElement}
+     */
+    this.rowObject = null;
+
+    /**
+     * Remember the previous element.
+     *
+     * @type {?HTMLElement}
+     */
+    this.oldRowElement = null;
+
+    /**
+     * Used to determine up or down direction from last mouse move.
+     *
+     * @type {number}
+     */
+    this.oldY = 0;
+
+    /**
+     *
+     * @type {bool}
+     */
+    this.changed = false;
+    // Whether anything in the entire table has changed.
+    /**
+     *
+     * @type {number}
+     */
+    this.maxDepth = 0;
+    // Maximum amount of allowed parenting.
+    /**
+     * Direction of the table.
+     *
+     * @type {number}
+     */
+    this.rtl = $(this.table).css('direction') === 'rtl' ? -1 : 1;
+
+    /**
+     *
+     * @type {bool}
+     */
     this.striping = $(this.table).data('striping') === 1;
 
-    // Configure the scroll settings.
+    /**
+     * Configure the scroll settings.
+     *
+     * @type {object}
+     *
+     * @prop {number} amount
+     * @prop {number} interval
+     * @prop {number} trigger
+     */
     this.scrollSettings = {amount: 4, interval: 50, trigger: 70};
+
+    /**
+     *
+     * @type {?number}
+     */
     this.scrollInterval = null;
+
+    /**
+     *
+     * @type {number}
+     */
     this.scrollY = 0;
+
+    /**
+     *
+     * @type {number}
+     */
     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.
+    /**
+     * 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.
+     *
+     * @type {bool}
+     */
     this.indentEnabled = false;
     for (var group in tableSettings) {
       if (tableSettings.hasOwnProperty(group)) {
@@ -87,7 +187,13 @@
       }
     }
     if (this.indentEnabled) {
-      this.indentCount = 1; // Total width of indents, set in makeDraggable.
+
+      /**
+       * Total width of indents, set in makeDraggable.
+       *
+       * @type {number}
+       */
+      this.indentCount = 1;
       // 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
@@ -96,6 +202,11 @@
       var testRow = $('<tr/>').addClass('draggable').appendTo(table);
       var testCell = $('<td/>').appendTo(testRow).prepend(indent).prepend(indent);
       var $indentation = testCell.find('.js-indentation');
+
+      /**
+       *
+       * @type {number}
+       */
       this.indentAmount = $indentation.get(1).offsetLeft - $indentation.get(0).offsetLeft;
       testRow.remove();
     }
@@ -136,7 +247,8 @@
     $(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.
+        // This was changed in another window, get the new value for this
+        // window.
         showWeight = JSON.parse(e.originalEvent.newValue);
         this.displayColumns(showWeight);
       }
@@ -144,8 +256,7 @@
   };
 
   /**
-   * Initialize columns containing form elements to be hidden by default,
-   * according to the settings for this tableDrag instance.
+   * Initialize columns containing form elements to be hidden by default.
    *
    * 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
@@ -157,7 +268,9 @@
     var cell;
     var columnIndex;
     for (var group in this.tableSettings) {
-      if (this.tableSettings.hasOwnProperty(group)) { // Find the first field in this group.
+      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).eq(0);
@@ -171,8 +284,9 @@
 
         // 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.
+          // 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));
         }
@@ -182,8 +296,13 @@
   };
 
   /**
-   * Mark cells that have colspan so we can adjust the colspan
-   * instead of hiding them altogether.
+   * Mark cells that have colspan.
+   *
+   * In order to adjust the colspan instead of hiding them altogether.
+   *
+   * @param {number} columnIndex
+   *
+   * @return {function}
    */
   Drupal.tableDrag.prototype.addColspanClass = function (columnIndex) {
     return function () {
@@ -214,7 +333,9 @@
   /**
    * Hide or display weight columns. Triggers an event on change.
    *
-   * @param bool displayWeight
+   * @fires event:columnschange
+   *
+   * @param {bool} displayWeight
    *   'true' will show weight columns.
    */
   Drupal.tableDrag.prototype.displayColumns = function (displayWeight) {
@@ -232,6 +353,7 @@
 
   /**
    * Toggle the weight column depending on 'showWeight' value.
+   *
    * Store only default override.
    */
   Drupal.tableDrag.prototype.toggleColumns = function () {
@@ -249,6 +371,7 @@
 
   /**
    * Hide the columns containing weight/parent form elements.
+   *
    * Undo showColumns().
    */
   Drupal.tableDrag.prototype.hideColumns = function () {
@@ -266,7 +389,8 @@
   };
 
   /**
-   * Show the columns containing weight/parent form elements
+   * Show the columns containing weight/parent form elements.
+   *
    * Undo hideColumns().
    */
   Drupal.tableDrag.prototype.showColumns = function () {
@@ -285,6 +409,11 @@
 
   /**
    * Find the target used within a particular row and group.
+   *
+   * @param {string} group
+   * @param {HTMLElement} row
+   *
+   * @return {object}
    */
   Drupal.tableDrag.prototype.rowSettings = function (group, row) {
     var field = $(row).find('.' + group);
@@ -308,11 +437,13 @@
 
   /**
    * Take an item and add event handlers to make it become draggable.
+   *
+   * @param {HTMLElement} item
    */
   Drupal.tableDrag.prototype.makeDraggable = function (item) {
     var self = this;
     var $item = $(item);
-    // Add a class to the title link
+    // Add a class to the title link.
     $item.find('td').eq(0).find('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'));
@@ -369,13 +500,18 @@
       var keyChange = false;
       var groupHeight;
       switch (event.keyCode) {
-        case 37: // Left arrow.
-        case 63234: // Safari left arrow.
+        // Left arrow.
+        case 37:
+        case 63234:
+          // Safari left arrow.
           keyChange = true;
           self.rowObject.indent(-1 * self.rtl);
           break;
-        case 38: // Up arrow.
-        case 63232: // Safari up arrow.
+
+        // Up arrow.
+        case 38:
+        case 63232:
+          // Safari up arrow.
           var $previousRow = $(self.rowObject.element).prev('tr').eq(0);
           var previousRow = $previousRow.get(0);
           while (previousRow && $previousRow.is(':hidden')) {
@@ -383,7 +519,8 @@
             previousRow = $previousRow.get(0);
           }
           if (previousRow) {
-            self.safeBlur = false; // Do not allow the onBlur cleanup.
+            self.safeBlur = false;
+            // Do not allow the onBlur cleanup.
             self.rowObject.direction = 'up';
             keyChange = true;
 
@@ -402,23 +539,30 @@
               }
             }
             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).
+              // 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.
+            handle.trigger('focus');
+            // Regain focus after the DOM manipulation.
           }
           break;
-        case 39: // Right arrow.
-        case 63235: // Safari right arrow.
+
+        // Right arrow.
+        case 39:
+        case 63235:
+          // Safari right arrow.
           keyChange = true;
           self.rowObject.indent(self.rtl);
           break;
-        case 40: // Down arrow.
-        case 63233: // Safari down arrow.
+
+        // Down arrow.
+        case 40:
+        case 63233:
+          // Safari down arrow.
           var $nextRow = $(self.rowObject.group).eq(-1).next('tr').eq(0);
           var nextRow = $nextRow.get(0);
           while (nextRow && $nextRow.is(':hidden')) {
@@ -426,7 +570,8 @@
             nextRow = $nextRow.get(0);
           }
           if (nextRow) {
-            self.safeBlur = false; // Do not allow the onBlur cleanup.
+            self.safeBlur = false;
+            // Do not allow the onBlur cleanup.
             self.rowObject.direction = 'down';
             keyChange = true;
 
@@ -451,7 +596,8 @@
               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;
       }
@@ -474,15 +620,20 @@
       }
     });
 
-    // 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
+    // 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.
+        // Left arrow.
+        case 37:
+        // Up arrow.
+        case 38:
+        // Right arrow.
+        case 39:
+        // Down arrow.
+        case 40:
           return false;
       }
     });
@@ -491,11 +642,11 @@
   /**
    * Pointer event initiator, creates drag object and information.
    *
-   * @param jQuery.Event event
+   * @param {jQuery.Event} event
    *   The event object that trigger the drag.
-   * @param Drupal.tableDrag self
+   * @param {Drupal.tableDrag} self
    *   The drag handle.
-   * @param DOM item
+   * @param {HTMLElement} item
    *   The item that that is being dragged.
    */
   Drupal.tableDrag.prototype.dragStart = function (event, self, item) {
@@ -531,6 +682,11 @@
 
   /**
    * Pointer movement handler, bound to document.
+   *
+   * @param {jQuery.Event} event
+   * @param {Drupal.tableDrag} self
+   *
+   * @return {bool|undefined}
    */
   Drupal.tableDrag.prototype.dragRow = function (event, self) {
     if (self.dragObject) {
@@ -541,8 +697,8 @@
       // 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.
-
+        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.
@@ -570,7 +726,8 @@
       // 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.
+        // Set the number of indentations the pointer has been moved left or
+        // right.
         var indentDiff = Math.round(xDiff / self.indentAmount);
         // Indent the row with our estimated diff, which may be further
         // restricted according to the rows around this row.
@@ -586,6 +743,9 @@
 
   /**
    * Pointerup behavior.
+   *
+   * @param {jQuery.Event} event
+   * @param {Drupal.tableDrag} self
    */
   Drupal.tableDrag.prototype.dropRow = function (event, self) {
     var droppedRow;
@@ -644,6 +804,10 @@
 
   /**
    * Get the coordinates from the event (allowing for browser differences).
+   *
+   * @param {jQuery.Event} event
+   *
+   * @return {{x: number, y: number}}
    */
   Drupal.tableDrag.prototype.pointerCoords = function (event) {
     if (event.pageX || event.pageY) {
@@ -656,8 +820,15 @@
   };
 
   /**
+   * Get the event offset from the target element.
+   *
    * 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.
+   *
+   * @param {HTMLElement} target
+   * @param {jQuery.Event} event
+   *
+   * @return {{x: number, y: number}}
    */
   Drupal.tableDrag.prototype.getPointerOffset = function (target, event) {
     var docPos = $(target).offset();
@@ -666,13 +837,16 @@
   };
 
   /**
-   * Find the row the mouse is currently over. This row is then taken and swapped
-   * with the one being dragged.
+   * Find the row the mouse is currently over.
+   *
+   * This row is then taken and swapped with the one being dragged.
    *
-   * @param x
+   * @param {number} x
    *   The x coordinate of the mouse on the page (not the screen).
-   * @param y
+   * @param {number} y
    *   The y coordinate of the mouse on the page (not the screen).
+   *
+   * @return {*}
    */
   Drupal.tableDrag.prototype.findDropTargetRow = function (x, y) {
     var rows = $(this.table.tBodies[0].rows).not(':hidden');
@@ -715,8 +889,8 @@
         }
 
         // 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.
+        // 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);
@@ -728,10 +902,9 @@
   };
 
   /**
-   * After the row is dropped, update the table fields according to the settings
-   * set for this table.
+   * After the row is dropped, update the table fields.
    *
-   * @param changedRow
+   * @param {HTMLElement} changedRow
    *   DOM object for the row that was just dropped.
    */
   Drupal.tableDrag.prototype.updateFields = function (changedRow) {
@@ -745,12 +918,11 @@
   };
 
   /**
-   * After the row is dropped, update a single table field according to specific
-   * settings.
+   * After the row is dropped, update a single table field.
    *
-   * @param changedRow
+   * @param {HTMLElement} changedRow
    *   DOM object for the row that was just dropped.
-   * @param group
+   * @param {string} group
    *   The settings group on which field updates will occur.
    */
   Drupal.tableDrag.prototype.updateField = function (changedRow, group) {
@@ -843,10 +1015,12 @@
           // Get the depth of the target row.
           targetElement.value = $(sourceElement).closest('tr').find('.js-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')) {
@@ -858,7 +1032,8 @@
             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 there are more items than possible values, assign the
+              // maximum value to the row.
               if (values.length > 0) {
                 this.value = values.shift();
               }
@@ -881,9 +1056,15 @@
   };
 
   /**
+   * Copy all tableDrag related classes from one row to another.
+   *
    * 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.
+   *
+   * @param {HTMLElement} sourceRow
+   * @param {HTMLElement} targetRow
+   * @param {string} group
    */
   Drupal.tableDrag.prototype.copyDragClasses = function (sourceRow, targetRow, group) {
     var sourceElement = $(sourceRow).find('.' + group);
@@ -893,6 +1074,10 @@
     }
   };
 
+  /**
+   * @param {number} cursorY
+   * @return {number}
+   */
   Drupal.tableDrag.prototype.checkScroll = function (cursorY) {
     var de = document.documentElement;
     var b = document.body;
@@ -921,6 +1106,9 @@
     }
   };
 
+  /**
+   * @param {number} scrollAmount
+   */
   Drupal.tableDrag.prototype.setScroll = function (scrollAmount) {
     var self = this;
 
@@ -935,6 +1123,9 @@
     }, this.scrollSettings.interval);
   };
 
+  /**
+   * Command to restripe table properly.
+   */
   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.
@@ -947,6 +1138,8 @@
 
   /**
    * Stub function. Allows a custom handler when a row begins dragging.
+   *
+   * @return {?bool}
    */
   Drupal.tableDrag.prototype.onDrag = function () {
     return null;
@@ -954,6 +1147,8 @@
 
   /**
    * Stub function. Allows a custom handler when a row is dropped.
+   *
+   * @return {?bool}
    */
   Drupal.tableDrag.prototype.onDrop = function () {
     return null;
@@ -962,16 +1157,18 @@
   /**
    * Constructor to make a new object to manipulate a table row.
    *
-   * @param tableRow
+   * @param {HTMLElement} 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
+   * @param {string} method
+   *   The method in which this row is being moved. Either 'keyboard' or
+   *   'mouse'.
+   * @param {bool} indentEnabled
    *   Whether the containing table uses indentations. Used for optimizations.
-   * @param maxDepth
+   * @param {number} 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.
+   * @param {bool} 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);
@@ -984,8 +1181,8 @@
     this.table = $tableRow.closest('table')[0];
     this.indentEnabled = indentEnabled;
     this.maxDepth = maxDepth;
-    this.direction = ''; // Direction the row is being moved.
-
+    this.direction = '';
+    // Direction the row is being moved.
     if (this.indentEnabled) {
       this.indents = $tableRow.find('.js-indentation').length;
       this.children = this.findChildren(addClasses);
@@ -1000,8 +1197,11 @@
   /**
    * Find all children of rowObject by indentation.
    *
-   * @param addClasses
-   *   Whether we want to add classes to this row to indicate child relationships.
+   * @param {bool} addClasses
+   *   Whether we want to add classes to this row to indicate child
+   *   relationships.
+   *
+   * @return {Array}
    */
   Drupal.tableDrag.prototype.row.prototype.findChildren = function (addClasses) {
     var parentIndentation = this.indents;
@@ -1045,8 +1245,10 @@
   /**
    * Ensure that two rows are allowed to be swapped.
    *
-   * @param row
+   * @param {HTMLElement} row
    *   DOM object for the row being considered for swapping.
+   *
+   * @return {bool}
    */
   Drupal.tableDrag.prototype.row.prototype.isValidSwap = function (row) {
     var $row = $(row);
@@ -1080,9 +1282,9 @@
   /**
    * Perform the swap between two rows.
    *
-   * @param position
+   * @param {string} position
    *   Whether the swap will occur 'before' or 'after' the given row.
-   * @param row
+   * @param {HTMLElement} row
    *   DOM element what will be swapped with the row group.
    */
   Drupal.tableDrag.prototype.row.prototype.swap = function (position, row) {
@@ -1100,15 +1302,16 @@
   };
 
   /**
-   * Determine the valid indentations interval for the row at a given position
-   * in the table.
+   * Determine the valid indentations interval for the row at a given position.
    *
-   * @param prevRow
+   * @param {HTMLElement|null} prevRow
    *   DOM object for the row before the tested position
    *   (or null for first position in the table).
-   * @param nextRow
+   * @param {HTMLElement|null} nextRow
    *   DOM object for the row after the tested position
    *   (or null for last position in the table).
+   *
+   * @return {{min: number, max: number}}
    */
   Drupal.tableDrag.prototype.row.prototype.validIndentInterval = function (prevRow, nextRow) {
     var $prevRow = $(prevRow);
@@ -1142,10 +1345,12 @@
   /**
    * Indent a row within the legal bounds of the table.
    *
-   * @param indentDiff
+   * @param {number} 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.
+   *
+   * @return {number}
    */
   Drupal.tableDrag.prototype.row.prototype.indent = function (indentDiff) {
     var $group = $(this.group);
@@ -1184,11 +1389,15 @@
   };
 
   /**
-   * 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.
+   * Find all siblings for a row.
    *
-   * @param settings
+   * According to its subgroup or indentation. Note that the passed-in row is
+   * included in the list of siblings.
+   *
+   * @param {object} rowSettings
    *   The field settings we're using to identify what constitutes a sibling.
+   *
+   * @return {Array}
    */
   Drupal.tableDrag.prototype.row.prototype.findSiblings = function (rowSettings) {
     var siblings = [];
@@ -1257,6 +1466,8 @@
 
   /**
    * Stub function. Allows a custom handler when a row is indented.
+   *
+   * @return {?bool}
    */
   Drupal.tableDrag.prototype.row.prototype.onIndent = function () {
     return null;
@@ -1264,18 +1475,34 @@
 
   /**
    * Stub function. Allows a custom handler when a row is swapped.
+   *
+   * @param {HTMLElement} swappedRow
+   *
+   * @return {?bool}
    */
   Drupal.tableDrag.prototype.row.prototype.onSwap = function (swappedRow) {
     return null;
   };
 
-  $.extend(Drupal.theme, {
+  $.extend(Drupal.theme, /** @lends Drupal.theme */{
+
+    /**
+     * @return {string}
+     */
     tableDragChangedMarker: function () {
       return '<abbr class="warning tabledrag-changed" title="' + Drupal.t('Changed') + '">*</abbr>';
     },
+
+    /**
+     * @return {string}
+     */
     tableDragIndentation: function () {
       return '<div class="js-indentation indentation">&nbsp;</div>';
     },
+
+    /**
+     * @return {string}
+     */
     tableDragChangedWarning: function () {
       return '<div class="tabledrag-changed-warning messages messages--warning" role="alert">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('You have unsaved changes.') + '</div>';
     }
diff --git a/core/misc/tableheader.js b/core/misc/tableheader.js
index 2d6ce16..062247b 100644
--- a/core/misc/tableheader.js
+++ b/core/misc/tableheader.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Sticky table headers.
+ */
+
 (function ($, Drupal, displace) {
 
   "use strict";
 
   /**
    * Attaches sticky table headers.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.tableHeader = {
     attach: function (context) {
@@ -48,26 +55,36 @@
 
   // Bind event that need to change all tables.
   $(window).on({
+
     /**
      * When resizing table width can change, recalculate everything.
+     *
+     * @ignore
      */
     'resize.TableHeader': tableHeaderResizeHandler,
 
     /**
      * Bind only one event to take care of calling all scroll callbacks.
+     *
+     * @ignore
      */
     'scroll.TableHeader': tableHeaderOnScrollHandler
   });
   // Bind to custom Drupal events.
   $(document).on({
+
     /**
      * Recalculate columns width when window is resized and when show/hide
      * weight is triggered.
+     *
+     * @ignore
      */
     'columnschange.TableHeader': tableHeaderResizeHandler,
 
     /**
-     * Recalculate TableHeader.topOffset when viewport is resized
+     * Recalculate TableHeader.topOffset when viewport is resized.
+     *
+     * @ignore
      */
     'drupalViewportOffsetChange.TableHeader': tableHeaderOffsetChangeHandler
   });
@@ -78,19 +95,37 @@
    * TableHeader will make the current table header stick to the top of the page
    * if the table is very long.
    *
-   * @param table
+   * @constructor Drupal.TableHeader
+   *
+   * @param {HTMLElement} table
    *   DOM object for the table to add a sticky header to.
    *
-   * @constructor
+   * @listens event:columnschange
    */
   function TableHeader(table) {
     var $table = $(table);
 
+    /**
+     * @name Drupal.TableHeader#$originalTable
+     *
+     * @type {HTMLElement}
+     */
     this.$originalTable = $table;
+
+    /**
+     * @type {jQuery}
+     */
     this.$originalHeader = $table.children('thead');
+
+    /**
+     * @type {jQuery}
+     */
     this.$originalHeaderCells = this.$originalHeader.find('> tr > th');
-    this.displayWeight = null;
 
+    /**
+     * @type {null|bool}
+     */
+    this.displayWeight = null;
     this.$originalTable.addClass('sticky-table');
     this.tableHeight = $table[0].clientHeight;
     this.tableOffset = this.$originalTable.offset();
@@ -111,11 +146,12 @@
   /**
    * Store the state of TableHeader.
    */
-  $.extend(TableHeader, {
+  $.extend(TableHeader, /** @lends Drupal.TableHeader */{
+
     /**
      * This will store the state of all processed tables.
      *
-     * @type {Array}
+     * @type {Array.<Drupal.TableHeader>}
      */
     tables: []
   });
@@ -123,24 +159,33 @@
   /**
    * Extend TableHeader prototype.
    */
-  $.extend(TableHeader.prototype, {
+  $.extend(TableHeader.prototype, /** @lends Drupal.TableHeader# */{
+
     /**
      * Minimum height in pixels for the table to have a sticky header.
+     *
+     * @type {number}
      */
     minHeight: 100,
 
     /**
      * Absolute position of the table on the page.
+     *
+     * @type {?Drupal.displace~offset}
      */
     tableOffset: null,
 
     /**
      * Absolute position of the table on the page.
+     *
+     * @type {?number}
      */
     tableHeight: null,
 
     /**
      * Boolean storing the sticky header visibility state.
+     *
+     * @type {bool}
      */
     stickyVisible: false,
 
@@ -169,8 +214,10 @@
     /**
      * Set absolute position of sticky.
      *
-     * @param offsetTop
-     * @param offsetLeft
+     * @param {number} offsetTop
+     * @param {number} offsetLeft
+     *
+     * @return {jQuery}
      */
     stickyPosition: function (offsetTop, offsetLeft) {
       var css = {};
@@ -185,6 +232,8 @@
 
     /**
      * Returns true if sticky is currently visible.
+     *
+     * @return {bool}
      */
     checkStickyVisible: function () {
       var scrollTop = scrollValue('scrollTop');
@@ -203,9 +252,10 @@
     /**
      * Check if sticky header should be displayed.
      *
-     * This function is throttled to once every 250ms to avoid unnecessary calls.
+     * This function is throttled to once every 250ms to avoid unnecessary
+     * calls.
      *
-     * @param event
+     * @param {jQuery.Event} e
      */
     onScroll: function (e) {
       this.checkStickyVisible();
@@ -217,7 +267,7 @@
     /**
      * Event handler: recalculates position of the sticky table header.
      *
-     * @param event
+     * @param {jQuery.Event} event
      *   Event being triggered.
      */
     recalculateSticky: function (event) {
diff --git a/core/misc/tableresponsive.js b/core/misc/tableresponsive.js
index b4eab62..c82968b 100644
--- a/core/misc/tableresponsive.js
+++ b/core/misc/tableresponsive.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Responsive table functionality.
+ */
+
 (function ($, Drupal, window) {
 
   "use strict";
 
   /**
    * Attach the tableResponsive function to Drupal.behaviors.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.tableResponsive = {
     attach: function (context, settings) {
@@ -18,14 +25,18 @@
   };
 
   /**
-   * The TableResponsive object optimizes table presentation for all screen sizes.
+   * The TableResponsive object optimizes table presentation for screen size.
    *
    * 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.
+   * 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.
+   *
+   * @constructor Drupal.TableResponsive
+   *
+   * @param {HTMLElement} table
    */
   function TableResponsive(table) {
     this.table = table;
@@ -51,7 +62,13 @@
   /**
    * Extend the TableResponsive function with a list of managed tables.
    */
-  $.extend(TableResponsive, {
+  $.extend(TableResponsive, /** @lends Drupal.TableResponsive */{
+
+    /**
+     * Store all created instances.
+     *
+     * @type {Array.<Drupal.TableResponsive>}
+     */
     tables: []
   });
 
@@ -61,24 +78,34 @@
    * Columns are assumed to be hidden if their header has the class priority-low
    * or priority-medium.
    */
-  $.extend(TableResponsive.prototype, {
+  $.extend(TableResponsive.prototype, /** @lends Drupal.TableResponsive# */{
+
+    /**
+     * @param {jQuery.Event} e
+     */
     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 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 visibility of columns.
+      // has interacted with it. This is necessary to keep the link visible if
+      // the user adjusts screen size and changes the visibility 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'.
+
+    /**
+     * Toggle the visibility of columns based on their priority.
+     *
+     * Columns are classed with either 'priority-low' or 'priority-medium'.
+     *
+     * @param {jQuery.Event} e
+     */
     eventhandlerToggleColumns: function (e) {
       e.preventDefault();
       var self = this;
@@ -110,10 +137,10 @@
           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.
+          // 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];
@@ -134,6 +161,7 @@
       }
     }
   });
+
   // Make the TableResponsive object available in the Drupal namespace.
   Drupal.TableResponsive = TableResponsive;
 
diff --git a/core/misc/tableselect.js b/core/misc/tableselect.js
index 78e8c90..fc8e9f2 100644
--- a/core/misc/tableselect.js
+++ b/core/misc/tableselect.js
@@ -1,7 +1,17 @@
+/**
+ * @file
+ * Table select functionality.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
 
+  /**
+   * Initialize tableSelects.
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.tableSelect = {
     attach: function (context, settings) {
       // Select the inner-most table in case of nested tables.
@@ -9,13 +19,18 @@
     }
   };
 
+  /**
+   * Callback used in {@link Drupal.behaviors.tableSelect}.
+   */
   Drupal.tableSelect = function () {
-    // Do not add a "Select all" checkbox if there are no rows with checkboxes in the table
+    // 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.
+    // Keep track of the table, which checkbox is checked and alias the
+    // settings.
     var table = this;
     var checkboxes;
     var lastChecked;
@@ -25,6 +40,10 @@
       // 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 {HTMLElement}
+         */
         this.checked = state;
       });
     };
@@ -32,10 +51,20 @@
     // 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.
+        // Loop through all checkboxes and set their state to the select all
+        // checkbox' state.
         checkboxes.each(function () {
+
+          /**
+           * @this {HTMLElement}
+           */
           this.checked = event.target.checked;
-          // Either add or remove the selected class based on the state of the check all checkbox.
+          // Either add or remove the selected class based on the state of the
+          // check all checkbox.
+
+          /**
+           * @this {HTMLElement}
+           */
           $(this).closest('tr').toggleClass('selected', this.checked);
         });
         // Update the title and the state of the check all box.
@@ -45,18 +74,24 @@
 
     // 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.
+      // Either add or remove the selected class based on the state of the
+      // check all checkbox.
+
+      /**
+       * @this {HTMLElement}
+       */
       $(this).closest('tr').toggleClass('selected', this.checked);
 
-      // 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 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);
       }
 
-      // If all checkboxes are checked, make sure the select-all one is checked too, otherwise keep unchecked.
+      // If all checkboxes are checked, make sure the select-all one is checked
+      // too, otherwise keep unchecked.
       updateSelectAll((checkboxes.length === checkboxes.filter(':checked').length));
 
       // Keep track of the last checked checkbox.
@@ -68,6 +103,11 @@
     updateSelectAll((checkboxes.length === checkboxes.filter(':checked').length));
   };
 
+  /**
+   * @param {HTMLElement} from
+   * @param {HTMLElement} to
+   * @param {bool} state
+   */
   Drupal.tableSelectRange = function (from, to, state) {
     // We determine the looping mode based on the order of from and to.
     var mode = from.rowIndex > to.rowIndex ? 'previousSibling' : 'nextSibling';
@@ -80,7 +120,8 @@
         continue;
       }
       $i = $(i);
-      // Either add or remove the selected class based on the state of the target checkbox.
+      // 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);
 
diff --git a/core/misc/timezone.js b/core/misc/timezone.js
index e7667b8..801d728 100644
--- a/core/misc/timezone.js
+++ b/core/misc/timezone.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Timezone detection.
+ */
+
 (function ($) {
 
   "use strict";
 
   /**
    * Set the client's system time zone as default values of form fields.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.setTimezone = {
     attach: function (context, settings) {
@@ -45,10 +52,11 @@
           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.
+        // 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,
diff --git a/core/misc/vertical-tabs.js b/core/misc/vertical-tabs.js
index e7f64dc..a381bdc 100644
--- a/core/misc/vertical-tabs.js
+++ b/core/misc/vertical-tabs.js
@@ -1,17 +1,31 @@
+/**
+ * @file
+ * Define vertical tabs functionality.
+ */
+
+/**
+ * Triggers when form values inside a vertical tab changes.
+ *
+ * This is used to update the summary in vertical tabs in order to know what
+ * are the important fields' values.
+ *
+ * @event summaryUpdated
+ */
+
 (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.
+   * This script transforms a set of details into a stack of vertical tabs.
    *
    * 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.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.verticalTabs = {
     attach: function (context) {
@@ -25,7 +39,8 @@
         var focusID = $this.find(':hidden.vertical-tabs__active-tab').val();
         var tab_focus;
 
-        // Check if there are some details that can be converted to vertical-tabs
+        // Check if there are some details that can be converted to
+        // vertical-tabs.
         var $details = $this.find('> details');
         if ($details.length === 0) {
           return;
@@ -79,10 +94,17 @@
   /**
    * 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.
+   * @constructor
+   *
+   * @param {object} settings
+   * @param {string} settings.title
+   *   The name of the tab.
+   * @param {jQuery} settings.details
+   *   The jQuery object of the details element that is the tab pane.
+   *
+   * @fires event:summaryUpdated
+   *
+   * @listens event:summaryUpdated
    */
   Drupal.verticalTab = function (settings) {
     var self = this;
@@ -114,6 +136,7 @@
   };
 
   Drupal.verticalTab.prototype = {
+
     /**
      * Displays the tab's content pane.
      */
@@ -144,15 +167,17 @@
 
     /**
      * Shows a vertical tab pane.
+     *
+     * @return {Drupal.verticalTab}
      */
     tabShow: function () {
       // Display the tab.
       this.item.show();
       // Show the vertical tabs.
       this.item.closest('.js-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.
+      // 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-tabs__menu-item').removeClass('first')
         .filter(':visible').eq(0).addClass('first');
       // Display the details element.
@@ -164,13 +189,15 @@
 
     /**
      * Hides a vertical tab pane.
+     *
+     * @return {Drupal.verticalTab}
      */
     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.
+      // 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-tabs__menu-item').removeClass('first')
         .filter(':visible').eq(0).addClass('first');
       // Hide the details element.
@@ -191,10 +218,12 @@
   /**
    * Theme function for a vertical tab.
    *
-   * @param settings
+   * @param {object} settings
    *   An object with the following keys:
-   *   - title: The name of the tab.
-   * @return
+   * @param {string} settings.title
+   *   The name of the tab.
+   *
+   * @return {object}
    *   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
diff --git a/core/modules/block/js/block.admin.js b/core/modules/block/js/block.admin.js
index d301ade..b399dd0 100644
--- a/core/modules/block/js/block.admin.js
+++ b/core/modules/block/js/block.admin.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Block admin behaviors.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
@@ -8,6 +13,8 @@
    * Text search input: input.block-filter-text
    * Target element:    input.block-filter-text[data-element]
    * Source text:       .block-filter-text-source
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.blockFilterByText = {
     attach: function (context, settings) {
@@ -17,7 +24,10 @@
       var $details;
 
       /**
-       * Hides the <details> element for a category if it has no visible blocks.
+       * Hides the `<details>` element for a category if it has no visible blocks.
+       *
+       * @param {number} index
+       * @param {HTMLElement} element
        */
       function hideCategoryDetails(index, element) {
         var $catDetails = $(element);
@@ -26,12 +36,17 @@
 
       /**
        * Filters the block list.
+       *
+       * @param {jQuery.Event} e
        */
       function filterBlockList(e) {
         var query = $(e.target).val().toLowerCase();
 
         /**
          * Shows or hides the block entry based on the query.
+         *
+         * @param {number} index
+         * @param {HTMLElement} block
          */
         function showBlockEntry(index, block) {
           var $block = $(block);
@@ -71,6 +86,8 @@
 
   /**
    * Highlights the block that was just placed into the block listing.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.blockHighlightPlacement = {
     attach: function (context, settings) {
diff --git a/core/modules/block/js/block.js b/core/modules/block/js/block.js
index c3a4d0d..e5c0907 100644
--- a/core/modules/block/js/block.js
+++ b/core/modules/block/js/block.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Block behaviors.
+ */
+
 (function ($, window) {
 
   "use strict";
 
   /**
    * Provide the summary information for the block settings vertical tabs.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.blockSettingsSummary = {
     attach: function () {
@@ -46,6 +53,8 @@
    *
    * This behavior is dependent on the tableDrag behavior, since it uses the
    * objects initialized in that behavior to update the row.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.blockDrag = {
     attach: function (context, settings) {
@@ -55,8 +64,8 @@
       }
 
       var table = $('#blocks');
-      var tableDrag = Drupal.tableDrag.blocks; // Get the blocks tableDrag object.
-
+      // Get the blocks tableDrag object.
+      var tableDrag = Drupal.tableDrag.blocks;
       // Add a handler for when a row is swapped, update empty regions.
       tableDrag.row.prototype.onSwap = function (swappedRow) {
         checkEmptyRegions(table, this);
diff --git a/core/modules/block_content/js/block_content.js b/core/modules/block_content/js/block_content.js
index de36d4b..1c9cea2 100644
--- a/core/modules/block_content/js/block_content.js
+++ b/core/modules/block_content/js/block_content.js
@@ -7,6 +7,9 @@
 
   "use strict";
 
+  /**
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.blockContentDetailsSummaries = {
     attach: function (context) {
       var $context = $(context);
diff --git a/core/modules/book/book.js b/core/modules/book/book.js
index df57547..e67c6a2 100644
--- a/core/modules/book/book.js
+++ b/core/modules/book/book.js
@@ -7,6 +7,9 @@
 
   "use strict";
 
+  /**
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.bookDetailsSummaries = {
     attach: function (context) {
       $(context).find('.book-outline-form').drupalSetSummary(function (context) {
diff --git a/core/modules/ckeditor/js/ckeditor.admin.js b/core/modules/ckeditor/js/ckeditor.admin.js
index ff75541..24ebfb4 100644
--- a/core/modules/ckeditor/js/ckeditor.admin.js
+++ b/core/modules/ckeditor/js/ckeditor.admin.js
@@ -2,12 +2,16 @@
  * @file
  * CKEditor button and group configuration user interface.
  */
+
 (function ($, Drupal, _, CKEDITOR) {
 
   "use strict";
 
   Drupal.ckeditor = Drupal.ckeditor || {};
 
+  /**
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.ckeditorAdmin = {
     attach: function (context) {
       // Process the CKEditor configuration fragment once.
@@ -69,13 +73,23 @@
 
   /**
    * CKEditor configuration UI methods of Backbone objects.
+   *
+   * @namespace
    */
   Drupal.ckeditor = {
 
-    // A hash of View instances.
+    /**
+     * A hash of View instances.
+     *
+     * @type {object}
+     */
     views: {},
 
-    // A hash of Model instances.
+    /**
+     * A hash of Model instances.
+     *
+     * @type {object}
+     */
     models: {},
 
     /**
@@ -86,11 +100,11 @@
      * placeholder, then a process is launched to name that group before the button
      * move is translated into configuration.
      *
-     * @param Backbone.View view
+     * @param {Backbone.View} view
      *   The Backbone View that invoked this function.
-     * @param jQuery $button
+     * @param {jQuery} $button
      *   A jQuery set that contains an li element that wraps a button element.
-     * @param function callback
+     * @param {function} callback
      *   A callback to invoke after the button group naming modal dialog has been
      *   closed.
      */
@@ -118,9 +132,9 @@
      * Each row has a placeholder group at the end of the row. A user may not move
      * an existing button group past the placeholder group at the end of a row.
      *
-     * @param Backbone.View view
+     * @param {Backbone.View} view
      *   The Backbone View that invoked this function.
-     * @param jQuery $group
+     * @param {jQuery} $group
      *   A jQuery set that contains an li element that wraps a group of buttons.
      */
     registerGroupMove: function (view, $group) {
@@ -143,11 +157,11 @@
     /**
      * Opens a Drupal dialog with a form for changing the title of a button group.
      *
-     * @param Backbone.View view
+     * @param {Backbone.View} view
      *   The Backbone View that invoked this function.
-     * @param jQuery $group
+     * @param {jQuery} $group
      *   A jQuery set that contains an li element that wraps a group of buttons.
-     * @param function callback
+     * @param {function} callback
      *   A callback to invoke after the button group naming modal dialog has been
      *   closed.
      */
@@ -157,10 +171,11 @@
       /**
        * Validates the string provided as a button group title.
        *
-       * @param DOM form
+       * @param {HTMLElement} form
        *   The form DOM element that contains the input with the new button group
        *   title string.
-       * @return Boolean
+       *
+       * @return {bool}
        *   Returns true when an error exists, otherwise returns false.
        */
       function validateForm(form) {
@@ -182,9 +197,9 @@
       /**
        * Attempts to close the dialog; Validates user input.
        *
-       * @param String action
+       * @param {string} action
        *   The dialog action chosen by the user: 'apply' or 'cancel'.
-       * @param DOM form
+       * @param {HTMLElement} form
        *   The form DOM element that contains the input with the new button group
        *   title string.
        */
@@ -203,9 +218,9 @@
         /**
          * Applies a string as the name of a CKEditor button group.
          *
-         * @param jQuery $group
+         * @param {jQuery} $group
          *   A jQuery set that contains an li element that wraps a group of buttons.
-         * @param String name
+         * @param {string} name
          *   The new name of the CKEditor button group.
          */
         function namePlaceholderGroup($group, name) {
@@ -336,9 +351,10 @@
 
   };
 
-
   /**
    * Automatically shows/hides settings of buttons-only CKEditor plugins.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.ckeditorAdminButtonPluginSettings = {
     attach: function (context) {
@@ -411,7 +427,7 @@
   /**
    * Themes a blank CKEditor row.
    *
-   * @return String
+   * @return {string}
    */
   Drupal.theme.ckeditorRow = function () {
     return '<li class="ckeditor-row placeholder" role="group"><ul class="ckeditor-toolbar-groups clearfix"></ul></li>';
@@ -420,7 +436,7 @@
   /**
    * Themes a blank CKEditor button group.
    *
-   * @return String
+   * @return {string}
    */
   Drupal.theme.ckeditorToolbarGroup = function () {
     var group = '';
@@ -434,7 +450,7 @@
   /**
    * Themes a form for changing the title of a CKEditor button group.
    *
-   * @return String
+   * @return {string}
    */
   Drupal.theme.ckeditorButtonGroupNameForm = function () {
     return '<form><input name="group-name" required="required"></form>';
@@ -443,7 +459,7 @@
   /**
    * Themes a button that will toggle the button group names in active config.
    *
-   * @return String
+   * @return {string}
    */
   Drupal.theme.ckeditorButtonGroupNamesToggle = function () {
     return '<a class="ckeditor-groupnames-toggle" role="button" aria-pressed="false"></a>';
@@ -452,7 +468,7 @@
   /**
    * Themes a button that will prompt the user to name a new button group.
    *
-   * @return String
+   * @return {string}
    */
   Drupal.theme.ckeditorNewButtonGroup = function () {
     return '<li class="ckeditor-add-new-group"><button role="button" aria-label="' + Drupal.t('Add a CKEditor button group to the end of this row.') + '">' + Drupal.t('Add group') + '</button></li>';
diff --git a/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js b/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js
index 44072df..8989717 100644
--- a/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js
+++ b/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Ckeditor drupalimage admin behavior.
+ */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
    * Provides the summary for the "drupalimage" plugin settings vertical tab.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.ckeditorDrupalImageSettingsSummary = {
     attach: function () {
diff --git a/core/modules/ckeditor/js/ckeditor.js b/core/modules/ckeditor/js/ckeditor.js
index 59f8b2e..8c1b51a 100644
--- a/core/modules/ckeditor/js/ckeditor.js
+++ b/core/modules/ckeditor/js/ckeditor.js
@@ -1,9 +1,25 @@
+/**
+ * @file
+ * Ckeditor JS API.
+ */
+
 (function (Drupal, debounce, CKEDITOR, $) {
 
   "use strict";
 
+  /**
+   * @namespace
+   */
   Drupal.editors.ckeditor = {
 
+    /**
+     * Editor attach callback.
+     *
+     * @param {HTMLElement} element
+     * @param {string} format
+     *
+     * @return {bool}
+     */
     attach: function (element, format) {
       this._loadExternalPlugins(format);
       // Also pass settings that are Drupal-specific.
@@ -26,6 +42,15 @@
       return !!CKEDITOR.replace(element, format.editorSettings);
     },
 
+    /**
+     * Editor detach callback.
+     *
+     * @param {HTMLElement} element
+     * @param {string} format
+     * @param {string} trigger
+     *
+     * @return {bool}
+     */
     detach: function (element, format, trigger) {
       var editor = CKEDITOR.dom.element.get(element).getEditor();
       if (editor) {
@@ -40,6 +65,13 @@
       return !!editor;
     },
 
+    /**
+     *
+     * @param {HTMLElement} element
+     * @param {function} callback
+     *
+     * @return {bool}
+     */
     onChange: function (element, callback) {
       var editor = CKEDITOR.dom.element.get(element).getEditor();
       if (editor) {
@@ -50,6 +82,15 @@
       return !!editor;
     },
 
+    /**
+     *
+     * @param {HTMLElement} element
+     * @param {object} format
+     * @param {string} mainToolbarId
+     * @param {string} floatedToolbarId
+     *
+     * @return {bool}
+     */
     attachInlineEditor: function (element, format, mainToolbarId, floatedToolbarId) {
       this._loadExternalPlugins(format);
       // Also pass settings that are Drupal-specific.
@@ -101,6 +142,9 @@
       return !!CKEDITOR.inline(element, settings);
     },
 
+    /**
+     * @param {object} format
+     */
     _loadExternalPlugins: function (format) {
       var externalPlugins = format.editorSettings.drupalExternalPlugins;
       // Register and load additional CKEditor plugins as necessary.
@@ -117,8 +161,11 @@
   };
 
   Drupal.ckeditor = {
+
     /**
      * Variable storing the current dialog's save callback.
+     *
+     * @type {?function}
      */
     saveCallback: null,
 
@@ -128,16 +175,16 @@
      * This dynamically loads jQuery UI (if necessary) using the Drupal AJAX
      * framework, then opens a dialog at the specified Drupal path.
      *
-     * @param editor
+     * @param {CKEditor} editor
      *   The CKEditor instance that is opening the dialog.
-     * @param string url
+     * @param {string} url
      *   The URL that contains the contents of the dialog.
-     * @param Object existingValues
+     * @param {object} existingValues
      *   Existing values that will be sent via POST to the url for the dialog
      *   contents.
-     * @param Function saveCallback
+     * @param {function} saveCallback
      *   A function to be called upon saving the dialog.
-     * @param Object dialogSettings
+     * @param {object} dialogSettings
      *   An object containing settings to be passed to the jQuery UI.
      */
     openDialog: function (editor, url, existingValues, saveCallback, dialogSettings) {
diff --git a/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js b/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js
index 5fe814d..56933ea 100644
--- a/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js
+++ b/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Ckeditor sylecombo admin behavior.
+ */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
@@ -9,6 +14,8 @@
    * plugin settings change, to ensure that the corresponding feature metadata is
    * immediately updated — i.e. ensure that HTML tags and classes entered here are
    * known to be "required", which may affect filter settings.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.ckeditorStylesComboSettings = {
     attach: function (context) {
@@ -46,10 +53,10 @@
      * parsing works identically, but instead of failing on invalid styles, we
      * just ignore those.
      *
-     * @param String styles
+     * @param {string} styles
      *   The "styles" setting.
      *
-     * @return array
+     * @return {Array}
      *   An array containing the "stylesSet" configuration.
      */
     _generateStylesSetSetting: function (styles) {
@@ -93,6 +100,8 @@
 
   /**
    * Provides the summary for the "stylescombo" plugin settings vertical tab.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.ckeditorStylesComboSettingsSummary = {
     attach: function () {
diff --git a/core/modules/ckeditor/js/models/Model.js b/core/modules/ckeditor/js/models/Model.js
index bdab6fd..9868c09 100644
--- a/core/modules/ckeditor/js/models/Model.js
+++ b/core/modules/ckeditor/js/models/Model.js
@@ -9,26 +9,58 @@
 
   /**
    * Backbone model for the CKEditor toolbar configuration state.
+   *
+   * @constructor
+   *
+   * @augments Backbone.Model
    */
-  Drupal.ckeditor.Model = Backbone.Model.extend({
-    defaults: {
-      // The CKEditor configuration that is being manipulated through the UI.
+  Drupal.ckeditor.Model = Backbone.Model.extend(/** @lends Drupal.ckeditor.Model# */{
+
+    /**
+     * Default values.
+     *
+     * @type {object}
+     */
+    defaults: /** @lends Drupal.ckeditor.Model# */{
+
+      /**
+       * The CKEditor configuration that is being manipulated through the UI.
+       */
       activeEditorConfig: null,
-      // The textarea that contains the serialized representation of the active
-      // CKEditor configuration.
+
+      /**
+       * The textarea that contains the serialized representation of the active
+       * CKEditor configuration.
+       */
       $textarea: null,
-      // Tracks whether the active toolbar DOM structure has been changed. When
-      // true, activeEditorConfig needs to be updated, and when that is updated,
-      // $textarea will also be updated.
+
+      /**
+       * Tracks whether the active toolbar DOM structure has been changed. When
+       * true, activeEditorConfig needs to be updated, and when that is updated,
+       * $textarea will also be updated.
+       */
       isDirty: false,
-      // The configuration for the hidden CKEditor instance that is used to build
-      // the features metadata.
+
+      /**
+       * The configuration for the hidden CKEditor instance that is used to build
+       * the features metadata.
+       */
       hiddenEditorConfig: null,
-      // A hash, keyed by a feature name, that details CKEditor plugin features.
+
+      /**
+       * A hash, keyed by a feature name, that details CKEditor plugin features.
+       */
       featuresMetadata: null,
-      // Whether the button group names are currently visible.
+
+      /**
+       * Whether the button group names are currently visible.
+       */
       groupNamesVisible: false
     },
+
+    /**
+     * @method
+     */
     sync: function () {
       // Push the settings into the textarea.
       this.get('$textarea').val(JSON.stringify(this.get('activeEditorConfig')));
diff --git a/core/modules/ckeditor/js/plugins/drupalimage/plugin.js b/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
index fd18c5a..68eb7fe 100644
--- a/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
+++ b/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
@@ -7,8 +7,12 @@
  *   uses to track where images are being used)
  * - use a Drupal-native dialog (that is in fact just an alterable Drupal form
  *   like any other) instead of CKEditor's own dialogs.
- *   @see \Drupal\editor\Form\EditorImageDialog
+ *
+ * @see \Drupal\editor\Form\EditorImageDialog
+ *
+ * @ignore
  */
+
 (function ($, Drupal, CKEDITOR) {
 
   "use strict";
diff --git a/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js b/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js
index cbb6160..1dffb23 100644
--- a/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js
+++ b/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js
@@ -5,8 +5,11 @@
  * This alters the existing CKEditor image2 widget plugin, which is already
  * altered by the Drupal Image plugin, to:
  * - allow for the data-caption and data-align attributes to be set
- * - mimic the upcasting behavior of the caption_filter filter
+ * - mimic the upcasting behavior of the caption_filter filter.
+ *
+ * @ignore
  */
+
 (function (CKEDITOR) {
 
   "use strict";
@@ -220,9 +223,10 @@
    * Function will check first the passed element itself and then all its
    * children in DFS order.
    *
-   * @param CKEDITOR.htmlParser.element element
-   * @param String name
-   * @return CKEDITOR.htmlParser.element
+   * @param {CKEDITOR.htmlParser.element} element
+   * @param {string} name
+   *
+   * @return {CKEDITOR.htmlParser.element}
    */
   function findElementByName(element, name) {
     if (element.name === name) {
@@ -233,7 +237,8 @@
     element.forEach(function (el) {
       if (el.name === name) {
         found = el;
-        return false; // Stop here.
+        // Stop here.
+        return false;
       }
     }, CKEDITOR.NODE_ELEMENT);
     return found;
diff --git a/core/modules/ckeditor/js/plugins/drupallink/plugin.js b/core/modules/ckeditor/js/plugins/drupallink/plugin.js
index 04d8aba..c26445b 100644
--- a/core/modules/ckeditor/js/plugins/drupallink/plugin.js
+++ b/core/modules/ckeditor/js/plugins/drupallink/plugin.js
@@ -1,6 +1,8 @@
 /**
  * @file
  * Drupal Link plugin.
+ *
+ * @ignore
  */
 
 (function ($, Drupal, drupalSettings, CKEDITOR) {
@@ -199,6 +201,7 @@
    *
    * The following selection will all return the link element.
    *
+   * @example
    *  <a href="#">li^nk</a>
    *  <a href="#">[link]</a>
    *  text[<a href="#">link]</a>
@@ -207,6 +210,8 @@
    *  [<a href="#"><b>li]nk</b></a>
    *
    * @param {CKEDITOR.editor} editor
+   *
+   * @return {?bool}
    */
   function getSelectedLink(editor) {
     var selection = editor.getSelection();
diff --git a/core/modules/ckeditor/js/views/AuralView.js b/core/modules/ckeditor/js/views/AuralView.js
index 5acd776..439e8dd 100644
--- a/core/modules/ckeditor/js/views/AuralView.js
+++ b/core/modules/ckeditor/js/views/AuralView.js
@@ -7,11 +7,11 @@
 
   "use strict";
 
-  /**
-   * Backbone View for CKEditor toolbar configuration; aural UX (output only).
-   */
-  Drupal.ckeditor.AuralView = Backbone.View.extend({
+  Drupal.ckeditor.AuralView = Backbone.View.extend(/** @lends Drupal.ckeditor.AuralView# */{
 
+    /**
+     * @type {object}
+     */
     events: {
       'click .ckeditor-buttons a': 'announceButtonHelp',
       'click .ckeditor-multiple-buttons a': 'announceSeparatorHelp',
@@ -21,7 +21,11 @@
     },
 
     /**
-     * {@inheritdoc}
+     * Backbone View for CKEditor toolbar configuration; aural UX (output only).
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       // Announce the button and group positions when the model is no longer
@@ -32,8 +36,8 @@
     /**
      * Calls announce on buttons and groups when their position is changed.
      *
-     * @param Drupal.ckeditor.ConfigurationModel model
-     * @param Boolean isDirty
+     * @param {Drupal.ckeditor.ConfigurationModel} model
+     * @param {bool} isDirty
      *   A model attribute that indicates if the changed toolbar configuration
      *   has been stored or not.
      */
@@ -57,7 +61,7 @@
     /**
      * Handles the focus event of elements in the active and available toolbars.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     onFocus: function (event) {
       event.stopPropagation();
@@ -76,7 +80,7 @@
     /**
      * Announces the current position of a button group.
      *
-     * @param jQuery $group
+     * @param {jQuery} $group
      *   A jQuery set that contains an li element that wraps a group of buttons.
      */
     announceButtonGroupPosition: function ($group) {
@@ -106,7 +110,7 @@
     /**
      * Announces current button position.
      *
-     * @param jQuery $button
+     * @param {jQuery} $button
      *   A jQuery set that contains an li element that wraps a button.
      */
     announceButtonPosition: function ($button) {
@@ -166,7 +170,7 @@
     /**
      * Provides help information when a button is clicked.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     announceButtonHelp: function (event) {
       var $link = $(event.currentTarget);
@@ -194,7 +198,7 @@
     /**
      * Provides help information when a separator is clicked.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     announceSeparatorHelp: function (event) {
       var $link = $(event.currentTarget);
diff --git a/core/modules/ckeditor/js/views/ControllerView.js b/core/modules/ckeditor/js/views/ControllerView.js
index 7d77943..125debf 100644
--- a/core/modules/ckeditor/js/views/ControllerView.js
+++ b/core/modules/ckeditor/js/views/ControllerView.js
@@ -7,15 +7,19 @@
 
   "use strict";
 
-  /**
-   * Backbone View acting as a controller for CKEditor toolbar configuration.
-   */
-  Drupal.ckeditor.ControllerView = Backbone.View.extend({
+  Drupal.ckeditor.ControllerView = Backbone.View.extend(/** @lends Drupal.ckeditor.ControllerView# */{
 
+    /**
+     * @type {object}
+     */
     events: {},
 
     /**
-     * {@inheritdoc}
+     * Backbone View acting as a controller for CKEditor toolbar configuration.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.getCKEditorFeatures(this.model.get('hiddenEditorConfig'), this.disableFeaturesDisallowedByFilters.bind(this));
@@ -28,16 +32,18 @@
     /**
      * Converts the active toolbar DOM structure to an object representation.
      *
-     * @param Drupal.ckeditor.ConfigurationModel model
+     * @param {Drupal.ckeditor.ConfigurationModel} model
      *   The state model for the CKEditor configuration.
-     * @param Boolean isDirty
+     * @param {bool} isDirty
      *   Tracks whether the active toolbar DOM structure has been changed.
      *   isDirty is toggled back to false in this method.
-     * @param Object options
+     * @param {object} options
      *   An object that includes:
-     *   - Boolean broadcast: (optional) A flag that controls whether a
-     *     CKEditorToolbarChanged event should be fired for configuration
-     *     changes.
+     * @param {bool} [options.broadcast]
+     *   A flag that controls whether a CKEditorToolbarChanged event should be
+     *   fired for configuration changes.
+     *
+     * @fires event:CKEditorToolbarChanged
      */
     parseEditorDOM: function (model, isDirty, options) {
       if (isDirty) {
@@ -100,10 +106,10 @@
      * must be provided that will receive a hash of Drupal.EditorFeature
      * features keyed by feature (button) name.
      *
-     * @param Object CKEditorConfig
+     * @param {object} CKEditorConfig
      *   An object that represents the configuration settings for a CKEditor
      *   editor component.
-     * @param Function callback
+     * @param {function} callback
      *   A function to invoke when the instanceReady event is fired by the
      *   CKEditor object.
      */
@@ -192,9 +198,10 @@
      * Retrieves the feature for a given button from featuresMetadata. Returns
      * false if the given button is in fact a divider.
      *
-     * @param String button
+     * @param {string} button
      *   The name of a CKEditor button.
-     * @return Object
+     *
+     * @return {object}
      *   The feature metadata object for a button.
      */
     getFeatureForButton: function (button) {
@@ -218,7 +225,7 @@
     /**
      * Checks buttons against filter settings; disables disallowed buttons.
      *
-     * @param Object features
+     * @param {object} features
      *   A map of Drupal.EditorFeature objects.
      */
     disableFeaturesDisallowedByFilters: function (features) {
@@ -272,7 +279,7 @@
     /**
      * Sets up broadcasting of CKEditor toolbar configuration changes.
      *
-     * @param jQuery $ckeditorToolbar
+     * @param {jQuery} $ckeditorToolbar
      *   The active toolbar DOM element wrapped in jQuery.
      */
     broadcastConfigurationChanges: function ($ckeditorToolbar) {
@@ -329,14 +336,15 @@
     /**
      * Returns the list of buttons from an editor configuration.
      *
-     * @param Object config
+     * @param {object} config
      *   A CKEditor configuration object.
-     * @return Array
+     *
+     * @return {Array}
      *   A list of buttons in the CKEditor configuration.
      */
     getButtonList: function (config) {
       var buttons = [];
-      // Remove the rows
+      // Remove the rows.
       config = _.flatten(config);
 
       // Loop through the button groups and pull out the buttons.
diff --git a/core/modules/ckeditor/js/views/KeyboardView.js b/core/modules/ckeditor/js/views/KeyboardView.js
index 2a2868a..ecd088c 100644
--- a/core/modules/ckeditor/js/views/KeyboardView.js
+++ b/core/modules/ckeditor/js/views/KeyboardView.js
@@ -7,13 +7,14 @@
 
   "use strict";
 
-  /**
-   * Backbone View for CKEditor toolbar configuration; keyboard UX.
-   */
-  Drupal.ckeditor.KeyboardView = Backbone.View.extend({
+  Drupal.ckeditor.KeyboardView = Backbone.View.extend(/** @lends Drupal.ckeditor.KeyboardView# */{
 
     /**
-     * {@inheritdoc}
+     * Backbone View for CKEditor toolbar configuration; keyboard UX.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       // Add keyboard arrow support.
@@ -22,7 +23,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     render: function () {
     },
@@ -30,7 +31,7 @@
     /**
      * Handles keypresses on a CKEditor configuration button.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     onPressButton: function (event) {
       var upDownKeys = [
@@ -181,7 +182,7 @@
     /**
      * Handles keypresses on a CKEditor configuration group.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     onPressGroup: function (event) {
       var upDownKeys = [
diff --git a/core/modules/ckeditor/js/views/VisualView.js b/core/modules/ckeditor/js/views/VisualView.js
index 95d56e7..b9779a2 100644
--- a/core/modules/ckeditor/js/views/VisualView.js
+++ b/core/modules/ckeditor/js/views/VisualView.js
@@ -1,16 +1,14 @@
 /**
  * @file
- * A Backbone View that provides the visual UX view of CKEditor toolbar configuration.
+ * A Backbone View that provides the visual UX view of CKEditor toolbar
+ *   configuration.
  */
 
 (function (Drupal, Backbone, $) {
 
   "use strict";
 
-  /**
-   * Backbone View for CKEditor toolbar configuration; visual UX.
-   */
-  Drupal.ckeditor.VisualView = Backbone.View.extend({
+  Drupal.ckeditor.VisualView = Backbone.View.extend(/** @lends Drupal.ckeditor.VisualView# */{
 
     events: {
       'click .ckeditor-toolbar-group-name': 'onGroupNameClick',
@@ -19,7 +17,11 @@
     },
 
     /**
-     * {@inheritdoc}
+     * Backbone View for CKEditor toolbar configuration; visual UX.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.listenTo(this.model, 'change:isDirty change:groupNamesVisible', this.render);
@@ -32,7 +34,12 @@
     },
 
     /**
-     * {@inheritdoc}
+     *
+     * @param {*} model
+     * @param {string} [value]
+     * @param {object} changedAttributes
+     *
+     * @return {Drupal.ckeditor.VisualView}
      */
     render: function (model, value, changedAttributes) {
       this.insertPlaceholders();
@@ -57,7 +64,7 @@
     /**
      * Handles clicks to a button group name.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     onGroupNameClick: function (event) {
       var $group = $(event.currentTarget).closest('.ckeditor-toolbar-group');
@@ -69,6 +76,8 @@
 
     /**
      * Handles clicks on the button group names toggle button.
+     *
+     * @param {jQuery.Event} event
      */
     onGroupNamesToggleClick: function (event) {
       this.model.set('groupNamesVisible', !this.model.get('groupNamesVisible'));
@@ -78,17 +87,17 @@
     /**
      * Prompts the user to provide a name for a new button group; inserts it.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     onAddGroupButtonClick: function (event) {
 
       /**
        * Inserts a new button if the openGroupNameDialog function returns true.
        *
-       * @param Boolean success
+       * @param {bool} success
        *   A flag that indicates if the user created a new group (true) or
        *   canceled out of the dialog (false).
-       * @param jQuery $group
+       * @param {jQuery} $group
        *   A jQuery DOM fragment that represents the new button group. It has
        *   not been added to the DOM yet.
        */
@@ -110,8 +119,8 @@
     /**
      * Handles jQuery Sortable stop sort of a button group.
      *
-     * @param jQuery.Event event
-     * @param Object ui
+     * @param {jQuery.Event} event
+     * @param {object} ui
      *   A jQuery.ui.sortable argument that contains information about the
      *   elements involved in the sort action.
      */
@@ -128,8 +137,8 @@
     /**
      * Handles jQuery Sortable start sort of a button.
      *
-     * @param jQuery.Event event
-     * @param Object ui
+     * @param {jQuery.Event} event
+     * @param {object} ui
      *   A jQuery.ui.sortable argument that contains information about the
      *   elements involved in the sort action.
      */
@@ -143,8 +152,8 @@
     /**
      * Handles jQuery Sortable stop sort of a button.
      *
-     * @param jQuery.Event event
-     * @param Object ui
+     * @param {jQuery.Event} event
+     * @param {object} ui
      *   A jQuery.ui.sortable argument that contains information about the
      *   elements involved in the sort action.
      */
diff --git a/core/modules/color/color.js b/core/modules/color/color.js
index 4423d56..25c9d0c 100644
--- a/core/modules/color/color.js
+++ b/core/modules/color/color.js
@@ -7,6 +7,9 @@
 
   "use strict";
 
+  /**
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.color = {
     attach: function (context, settings) {
       var i;
@@ -49,7 +52,8 @@
           width.push(parseInt(gradient.css('width'), 10) / 10);
           // Add rows (or columns for horizontal gradients).
           // Each gradient line should have a height (or width for horizontal
-          // gradients) of 10px (because we divided the height/width by 10 above).
+          // gradients) of 10px (because we divided the height/width by 10
+          // above).
           for (j = 0; j < (settings.gradients[i].direction === 'vertical' ? height[i] : width[i]); ++j) {
             gradient.append('<div class="gradient-line"></div>');
           }
@@ -82,11 +86,19 @@
       /**
        * Shifts a given color, using a reference pair (ref in HSL).
        *
-       * This algorithm ensures relative ordering on the saturation and luminance
-       * axes is preserved, and performs a simple hue shift.
+       * This algorithm ensures relative ordering on the saturation and
+       * luminance axes is preserved, and performs a simple hue shift.
        *
        * It is also symmetrical. If: shift_color(c, a, b) === d, then
        * shift_color(d, b, a) === c.
+       *
+       * @function Drupal.color~shift_color
+       *
+       * @param {string} given
+       * @param {Array} ref1
+       * @param {Array} ref2
+       *
+       * @return {string}
        */
       function shift_color(given, ref1, ref2) {
         var d;
@@ -129,6 +141,11 @@
 
       /**
        * Callback for Farbtastic when a new color is chosen.
+       *
+       * @param {HTMLElement} input
+       * @param {string} color
+       * @param {bool} propagate
+       * @param {bool} colorScheme
        */
       function callback(input, color, propagate, colorScheme) {
         var matched;
@@ -182,6 +199,8 @@
 
       /**
        * Focuses Farbtastic on a particular field.
+       *
+       * @param {jQuery.Event} e
        */
       function focus(e) {
         var input = e.target;
@@ -203,7 +222,7 @@
       // Initialize color fields.
       form.find('.js-color-palette input.form-text')
         .each(function () {
-          // Extract palette field name
+          // Extract palette field name.
           this.key = this.id.substring(13);
 
           // Link to color picker temporarily to initialize.
diff --git a/core/modules/color/preview.js b/core/modules/color/preview.js
index f121ade..956b53e 100644
--- a/core/modules/color/preview.js
+++ b/core/modules/color/preview.js
@@ -7,14 +7,26 @@
 
   "use strict";
 
+  /**
+   * @namespace
+   */
   Drupal.color = {
+
+    /**
+     * @param {Element} context
+     * @param {object} settings
+     * @param {HTMLFormElement} form
+     * @param {object} farb
+     * @param {number} height
+     * @param {number} width
+     */
     callback: function (context, settings, form, farb, height, width) {
       var accum;
       var delta;
       // Solid background.
       form.find('.color-preview').css('backgroundColor', form.find('.color-palette input[name="palette[base]"]').val());
 
-      // Text preview
+      // Text preview.
       form.find('#text').css('color', form.find('.color-palette input[name="palette[text]"]').val());
       form.find('#text a, #text h2').css('color', form.find('.color-palette input[name="palette[link]"]').val());
 
diff --git a/core/modules/comment/comment-entity-form.js b/core/modules/comment/comment-entity-form.js
index b41ab84..9e90979 100644
--- a/core/modules/comment/comment-entity-form.js
+++ b/core/modules/comment/comment-entity-form.js
@@ -7,6 +7,10 @@
 
   "use strict";
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.commentFieldsetSummaries = {
     attach: function (context) {
       var $context = $(context);
diff --git a/core/modules/comment/js/comment-by-viewer.js b/core/modules/comment/js/comment-by-viewer.js
index 0abea0d..4f597e0 100644
--- a/core/modules/comment/js/comment-by-viewer.js
+++ b/core/modules/comment/js/comment-by-viewer.js
@@ -1,12 +1,16 @@
 /**
+ * @file
  * Attaches behaviors for the Comment module's "by-viewer" class.
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
    * Add 'by-viewer' class to comments written by the current user.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.commentByViewer = {
     attach: function (context) {
diff --git a/core/modules/comment/js/comment-new-indicator.js b/core/modules/comment/js/comment-new-indicator.js
index b15e67c..8a2bf07 100644
--- a/core/modules/comment/js/comment-new-indicator.js
+++ b/core/modules/comment/js/comment-new-indicator.js
@@ -1,15 +1,19 @@
 /**
+ * @file
  * Attaches behaviors for the Comment module's "new" indicator.
  *
  * May only be loaded for authenticated users, with the History module
  * installed.
  */
+
 (function ($, Drupal, window) {
 
   "use strict";
 
   /**
    * Render "new" comment indicators wherever necessary.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.commentNewIndicator = {
     attach: function (context) {
diff --git a/core/modules/comment/js/node-new-comments-link.js b/core/modules/comment/js/node-new-comments-link.js
index 97c7871..fce15aa 100644
--- a/core/modules/comment/js/node-new-comments-link.js
+++ b/core/modules/comment/js/node-new-comments-link.js
@@ -1,15 +1,19 @@
 /**
+ * @file
  * Attaches behaviors for the Comment module's "X new comments" link.
  *
  * May only be loaded for authenticated users, with the History module
  * installed.
  */
+
 (function ($, Drupal) {
 
   "use strict";
 
   /**
    * Render "X new comments" links wherever necessary.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.nodeNewCommentsLink = {
     attach: function (context) {
diff --git a/core/modules/content_translation/content_translation.admin.js b/core/modules/content_translation/content_translation.admin.js
index 857cbd7..0071b6e 100644
--- a/core/modules/content_translation/content_translation.admin.js
+++ b/core/modules/content_translation/content_translation.admin.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Content Translation admin behaviors.
+ */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
    * Forces applicable options to be checked as translatable.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.contentTranslationDependentOptions = {
     attach: function (context) {
@@ -66,6 +73,8 @@
 
   /**
    * Makes field translatability inherit bundle translatability.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.contentTranslation = {
     attach: function (context) {
diff --git a/core/modules/contextual/js/contextual.js b/core/modules/contextual/js/contextual.js
index eccb54b..3694f45 100644
--- a/core/modules/contextual/js/contextual.js
+++ b/core/modules/contextual/js/contextual.js
@@ -33,12 +33,12 @@
   }
 
   /**
-   * Initializes a contextual link: updates its DOM, sets up model and views
+   * Initializes a contextual link: updates its DOM, sets up model and views.
    *
-   * @param jQuery $contextual
+   * @param {jQuery} $contextual
    *   A contextual links placeholder DOM element, containing the actual
    *   contextual links as rendered by the server.
-   * @param string html
+   * @param {string} html
    *   The server-side rendered HTML for this contextual link.
    */
   function initContextual($contextual, html) {
@@ -97,7 +97,7 @@
    *
    * This only deals with two levels of nesting; deeper levels are not touched.
    *
-   * @param jQuery $contextual
+   * @param {jQuery} $contextual
    *   A contextual links placeholder DOM element, containing the actual
    *   contextual links as rendered by the server.
    */
@@ -138,6 +138,8 @@
    * Events
    *   Contextual triggers an event that can be used by other scripts.
    *   - drupalContextualLinkAdded: Triggered when a contextual link is added.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.contextual = {
     attach: function (context) {
@@ -206,23 +208,38 @@
     }
   };
 
+  /**
+   * @namespace
+   */
   Drupal.contextual = {
-    // The Drupal.contextual.View instances associated with each list element of
-    // contextual links.
+    /**
+     * The Drupal.contextual.View instances associated with each list element of
+     * contextual links.
+     *
+     * @type {Array}
+     */
     views: [],
 
-    // The Drupal.contextual.RegionView instances associated with each contextual
-    // region element.
+    /**
+     * The Drupal.contextual.RegionView instances associated with each contextual
+     * region element.
+     *
+     * @type {Array}
+     */
     regionViews: []
   };
 
-  // A Backbone.Collection of Drupal.contextual.StateModel instances.
+  /**
+   * A Backbone.Collection of Drupal.contextual.StateModel instances.
+   *
+   * @type {Backbone.Collection}
+   */
   Drupal.contextual.collection = new Backbone.Collection([], {model: Drupal.contextual.StateModel});
 
   /**
    * A trigger is an interactive element often bound to a click handler.
    *
-   * @return String
+   * @return {string}
    *   A string representing a DOM fragment.
    */
   Drupal.theme.contextualTrigger = function () {
diff --git a/core/modules/contextual/js/contextual.toolbar.js b/core/modules/contextual/js/contextual.toolbar.js
index 4641890..c6b752c 100644
--- a/core/modules/contextual/js/contextual.toolbar.js
+++ b/core/modules/contextual/js/contextual.toolbar.js
@@ -14,9 +14,9 @@
   };
 
   /**
-   * Initializes a contextual link: updates its DOM, sets up model and views
+   * Initializes a contextual link: updates its DOM, sets up model and views.
    *
-   * @param DOM links
+   * @param {HTMLElement} context
    *   A contextual links DOM element as rendered by the server.
    */
   function initContextualToolbar(context) {
@@ -45,6 +45,8 @@
 
   /**
    * Attaches contextual's edit toolbar tab behavior.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.contextualToolbar = {
     attach: function (context) {
@@ -54,8 +56,15 @@
     }
   };
 
+  /**
+   * @namespace
+   */
   Drupal.contextualToolbar = {
-    // The Drupal.contextualToolbar.Model instance.
+    /**
+     * The Drupal.contextualToolbar.Model instance.
+     *
+     * @type {?Drupal.contextualToolbar.StateModel}
+     */
     model: null
   };
 
diff --git a/core/modules/contextual/js/models/StateModel.js b/core/modules/contextual/js/models/StateModel.js
index 24907b0..0396835 100644
--- a/core/modules/contextual/js/models/StateModel.js
+++ b/core/modules/contextual/js/models/StateModel.js
@@ -9,20 +9,58 @@
 
   /**
    * Models the state of a contextual link's trigger, list & region.
+   *
+   * @constructor
+   *
+   * @augments Backbone.Model
    */
-  Drupal.contextual.StateModel = Backbone.Model.extend({
+  Drupal.contextual.StateModel = Backbone.Model.extend(/** @lends Drupal.contextual.StateModel# */{
 
-    defaults: {
-      // The title of the entity to which these contextual links apply.
+    /**
+     * @type {object}
+     *
+     * @prop {string} title
+     * @prop {bool} regionIsHovered
+     * @prop {bool} hasFocus
+     * @prop {bool} isOpen
+     * @prop {bool} isLocked
+     */
+    defaults: /** @lends Drupal.contextual.StateModel# */{
+
+      /**
+       * The title of the entity to which these contextual links apply.
+       *
+       * @type {string}
+       */
       title: '',
-      // Represents if the contextual region is being hovered.
+
+      /**
+       * Represents if the contextual region is being hovered.
+       *
+       * @type {bool}
+       */
       regionIsHovered: false,
-      // Represents if the contextual trigger or options have focus.
+
+      /**
+       * Represents if the contextual trigger or options have focus.
+       *
+       * @type {bool}
+       */
       hasFocus: false,
-      // Represents if the contextual options for an entity are available to
-      // be selected (i.e. whether the list of options is visible).
+
+      /**
+       * Represents if the contextual options for an entity are available to
+       * be selected (i.e. whether the list of options is visible).
+       *
+       * @type {bool}
+       */
       isOpen: false,
-      // When the model is locked, the trigger remains active.
+
+      /**
+       * When the model is locked, the trigger remains active.
+       *
+       * @type {bool}
+       */
       isLocked: false
     },
 
@@ -30,6 +68,8 @@
      * Opens or closes the contextual link.
      *
      * If it is opened, then also give focus.
+     *
+     * @return {Drupal.contextual.StateModel}
      */
     toggleOpen: function () {
       var newIsOpen = !this.get('isOpen');
@@ -45,6 +85,8 @@
      *
      * Does not call blur() because we want to allow a contextual link to have
      * focus, yet be closed for example when hovering.
+     *
+     * @return {Drupal.contextual.StateModel}
      */
     close: function () {
       this.set('isOpen', false);
@@ -55,6 +97,8 @@
      * Gives focus to this contextual link.
      *
      * Also closes + removes focus from every other contextual link.
+     *
+     * @return {Drupal.contextual.StateModel}
      */
     focus: function () {
       this.set('hasFocus', true);
@@ -69,6 +113,8 @@
 
     /**
      * Removes focus from this contextual link, unless it is open.
+     *
+     * @return {Drupal.contextual.StateModel}
      */
     blur: function () {
       if (!this.get('isOpen')) {
diff --git a/core/modules/contextual/js/toolbar/models/StateModel.js b/core/modules/contextual/js/toolbar/models/StateModel.js
index 360b9fb..5fdb4d1 100644
--- a/core/modules/contextual/js/toolbar/models/StateModel.js
+++ b/core/modules/contextual/js/toolbar/models/StateModel.js
@@ -7,33 +7,62 @@
 
   "use strict";
 
-  /**
-   * Models the state of the edit mode toggle.
-   */
-  Drupal.contextualToolbar.StateModel = Backbone.Model.extend({
+  Drupal.contextualToolbar.StateModel = Backbone.Model.extend(/** @lends Drupal.contextualToolbar.StateModel# */{
 
-    defaults: {
-      // Indicates whether the toggle is currently in "view" or "edit" mode.
+    /**
+     * @type {object}
+     *
+     * @prop isViewing
+     * @prop isVisible
+     * @prop contextualCount
+     * @prop tabbingContext
+     */
+    defaults: /** @lends Drupal.contextualToolbar.StateModel# */{
+
+      /**
+       * Indicates whether the toggle is currently in "view" or "edit" mode.
+       *
+       * @type {bool}
+       */
       isViewing: true,
-      // Indicates whether the toggle should be visible or hidden. Automatically
-      // calculated, depends on contextualCount.
+
+      /**
+       * Indicates whether the toggle should be visible or hidden. Automatically
+       * calculated, depends on contextualCount.
+       *
+       * @type {bool}
+       */
       isVisible: false,
-      // Tracks how many contextual links exist on the page.
+
+      /**
+       * Tracks how many contextual links exist on the page.
+       *
+       * @type {number}
+       */
       contextualCount: 0,
-      // A TabbingContext object as returned by Drupal.TabbingManager: the set
-      // of tabbable elements when edit mode is enabled.
+
+      /**
+       * A TabbingContext object as returned by Drupal.TabbingManager: the set
+       * of tabbable elements when edit mode is enabled.
+       *
+       * @type {?*}
+       */
       tabbingContext: null
     },
 
     /**
-     * {@inheritdoc}
+     * Models the state of the edit mode toggle.
+     *
+     * @constructs
+     *
+     * @augments Backbone.Model
      *
-     * @param Object attrs
-     * @param Object options
+     * @param {object} attrs
+     * @param {object} options
      *   An object with the following option:
-     *     - Backbone.collection contextualCollection: the collection of
-     *       Drupal.contextual.StateModel models that represent the contextual
-     *       links on the page.
+     * @param {Backbone.collection} options.contextualCollection
+     *   The collection of {@link Drupal.contextual.StateModel} models that
+     *   represent the contextual links on the page.
      */
     initialize: function (attrs, options) {
       // Respond to new/removed contextual links.
@@ -57,9 +86,9 @@
     /**
      * Tracks the number of contextual link models in the collection.
      *
-     * @param Drupal.contextual.StateModel contextualModel
+     * @param {Drupal.contextual.StateModel} contextualModel
      *   The contextual links model that was added or removed.
-     * @param Backbone.Collection contextualCollection
+     * @param {Backbone.Collection} contextualCollection
      *    The collection of contextual link models.
      */
     countContextualLinks: function (contextualModel, contextualCollection) {
@@ -69,9 +98,9 @@
     /**
      * Lock newly added contextual links if edit mode is enabled.
      *
-     * @param Drupal.contextual.StateModel contextualModel
+     * @param {Drupal.contextual.StateModel} contextualModel
      *   The contextual links model that was added.
-     * @param Backbone.Collection contextualCollection
+     * @param {Backbone.Collection} [contextualCollection]
      *    The collection of contextual link models.
      */
     lockNewContextualLinks: function (contextualModel, contextualCollection) {
diff --git a/core/modules/contextual/js/toolbar/views/AuralView.js b/core/modules/contextual/js/toolbar/views/AuralView.js
index 38f7363..1344df8 100644
--- a/core/modules/contextual/js/toolbar/views/AuralView.js
+++ b/core/modules/contextual/js/toolbar/views/AuralView.js
@@ -7,16 +7,23 @@
 
   "use strict";
 
-  /**
-   * Renders the aural view of the edit mode toggle (i.e.screen reader support).
-   */
-  Drupal.contextualToolbar.AuralView = Backbone.View.extend({
+  Drupal.contextualToolbar.AuralView = Backbone.View.extend(/** @lends Drupal.contextualToolbar.AuralView# */{
 
-    // Tracks whether the tabbing constraint announcement has been read once yet.
+    /**
+     * Tracks whether the tabbing constraint announcement has been read once yet.
+     *
+     * @type {bool}
+     */
     announcedOnce: false,
 
-    /*
-     * {@inheritdoc}
+    /**
+     * Renders the aural view of the edit mode toggle (screen reader support).
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
+     *
+     * @param {object} options
      */
     initialize: function (options) {
       this.options = options;
@@ -28,7 +35,9 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {Drupal.contextualToolbar.AuralView}
      */
     render: function () {
       // Render the state.
@@ -39,11 +48,6 @@
 
     /**
      * Limits tabbing to the contextual links and edit mode toolbar tab.
-     *
-     * @param Drupal.contextualToolbar.StateModel model
-     *   A Drupal.contextualToolbar.StateModel model.
-     * @param bool isViewing
-     *   The value of the isViewing attribute in the model.
      */
     manageTabbing: function () {
       var tabbingContext = this.model.get('tabbingContext');
@@ -75,7 +79,7 @@
     /**
      * Responds to esc and tab key press events.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     onKeypress: function (event) {
       // The first tab key press is tracked so that an annoucement about tabbing
diff --git a/core/modules/contextual/js/toolbar/views/VisualView.js b/core/modules/contextual/js/toolbar/views/VisualView.js
index 41b095f..0aa71dd 100644
--- a/core/modules/contextual/js/toolbar/views/VisualView.js
+++ b/core/modules/contextual/js/toolbar/views/VisualView.js
@@ -7,13 +7,11 @@
 
   "use strict";
 
-  /**
-   * Renders the visual view of the edit mode toggle. Listens to mouse & touch.
-   *
-   * Handles edit mode toggle interactions.
-   */
-  Drupal.contextualToolbar.VisualView = Backbone.View.extend({
+  Drupal.contextualToolbar.VisualView = Backbone.View.extend(/** @lends Drupal.contextualToolbar.VisualView# */{
 
+    /**
+     * @return {object}
+     */
     events: function () {
       // Prevents delay and simulated mouse events.
       var touchEndToClick = function (event) {
@@ -30,7 +28,13 @@
     },
 
     /**
-     * {@inheritdoc}
+     * Renders the visual view of the edit mode toggle. Listens to mouse & touch.
+     *
+     * Handles edit mode toggle interactions.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.listenTo(this.model, 'change', this.render);
@@ -38,7 +42,9 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {Drupal.contextualToolbar.VisualView}
      */
     render: function () {
       // Render the visibility.
@@ -52,12 +58,12 @@
     /**
      * Model change handler; persists the isViewing value to localStorage.
      *
-     * isViewing === true is the default, so only stores in localStorage when
+     * `isViewing === true` is the default, so only stores in localStorage when
      * it's not the default value (i.e. false).
      *
-     * @param Drupal.contextualToolbar.StateModel model
-     *   A Drupal.contextualToolbar.StateModel model.
-     * @param bool isViewing
+     * @param {Drupal.contextualToolbar.StateModel} model
+     *   A {@link Drupal.contextualToolbar.StateModel} model.
+     * @param {bool} isViewing
      *   The value of the isViewing attribute in the model.
      */
     persist: function (model, isViewing) {
diff --git a/core/modules/contextual/js/views/AuralView.js b/core/modules/contextual/js/views/AuralView.js
index 40aff22..407f151 100644
--- a/core/modules/contextual/js/views/AuralView.js
+++ b/core/modules/contextual/js/views/AuralView.js
@@ -7,13 +7,16 @@
 
   "use strict";
 
-  /**
-   * Renders the aural view of a contextual link (i.e. screen reader support).
-   */
-  Drupal.contextual.AuralView = Backbone.View.extend({
+  Drupal.contextual.AuralView = Backbone.View.extend(/** @lends Drupal.contextual.AuralView# */{
 
     /**
-     * {@inheritdoc}
+     * Renders the aural view of a contextual link (i.e. screen reader support).
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
+     *
+     * @param {object} options
      */
     initialize: function (options) {
       this.options = options;
@@ -28,7 +31,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     render: function () {
       var isOpen = this.model.get('isOpen');
diff --git a/core/modules/contextual/js/views/KeyboardView.js b/core/modules/contextual/js/views/KeyboardView.js
index d6ebcec..4cf54ad 100644
--- a/core/modules/contextual/js/views/KeyboardView.js
+++ b/core/modules/contextual/js/views/KeyboardView.js
@@ -7,10 +7,11 @@
 
   "use strict";
 
-  /**
-   * Provides keyboard interaction for a contextual link.
-   */
-  Drupal.contextual.KeyboardView = Backbone.View.extend({
+  Drupal.contextual.KeyboardView = Backbone.View.extend(/** @lends Drupal.contextual.KeyboardView# */{
+
+    /**
+     * @type {object}
+     */
     events: {
       'focus .trigger': 'focus',
       'focus .contextual-links a': 'focus',
@@ -26,14 +27,22 @@
     },
 
     /**
-     * {@inheritdoc}
+     * Provides keyboard interaction for a contextual link.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
-      // The timer is used to create a delay before dismissing the contextual
-      // links on blur. This is only necessary when keyboard users tab into
-      // contextual links without edit mode (i.e. without TabbingManager).
-      // That means that if we decide to disable tabbing of contextual links
-      // without edit mode, all this timer logic can go away.
+      /**
+       * The timer is used to create a delay before dismissing the contextual
+       * links on blur. This is only necessary when keyboard users tab into
+       * contextual links without edit mode (i.e. without TabbingManager).
+       * That means that if we decide to disable tabbing of contextual links
+       * without edit mode, all this timer logic can go away.
+       *
+       * @type {NaN|number}
+       */
       this.timer = NaN;
     },
 
diff --git a/core/modules/contextual/js/views/RegionView.js b/core/modules/contextual/js/views/RegionView.js
index 10c5c51..b64ee45 100644
--- a/core/modules/contextual/js/views/RegionView.js
+++ b/core/modules/contextual/js/views/RegionView.js
@@ -7,11 +7,11 @@
 
   "use strict";
 
-  /**
-   * Renders the visual view of a contextual region element.
-   */
-  Drupal.contextual.RegionView = Backbone.View.extend({
+  Drupal.contextual.RegionView = Backbone.View.extend(/** @lends Drupal.contextual.RegionView# */{
 
+    /**
+     * @return {object}
+     */
     events: function () {
       var mapping = {
         mouseenter: function () { this.model.set('regionIsHovered', true); },
@@ -27,14 +27,20 @@
     },
 
     /**
-     * {@inheritdoc}
+     * Renders the visual view of a contextual region element.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.listenTo(this.model, 'change:hasFocus', this.render);
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {Drupal.contextual.RegionView}
      */
     render: function () {
       this.$el.toggleClass('focus', this.model.get('hasFocus'));
diff --git a/core/modules/contextual/js/views/VisualView.js b/core/modules/contextual/js/views/VisualView.js
index c40b30a..8da3c19 100644
--- a/core/modules/contextual/js/views/VisualView.js
+++ b/core/modules/contextual/js/views/VisualView.js
@@ -7,11 +7,11 @@
 
   "use strict";
 
-  /**
-   * Renders the visual view of a contextual link. Listens to mouse & touch.
-   */
-  Drupal.contextual.VisualView = Backbone.View.extend({
+  Drupal.contextual.VisualView = Backbone.View.extend(/** @lends Drupal.contextual.VisualView# */{
 
+    /**
+     * @return {object}
+     */
     events: function () {
       // Prevents delay and simulated mouse events.
       var touchEndToClick = function (event) {
@@ -32,14 +32,20 @@
     },
 
     /**
-     * {@inheritdoc}
+     * Renders the visual view of a contextual link. Listens to mouse & touch.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.listenTo(this.model, 'change', this.render);
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {Drupal.contextual.VisualView}
      */
     render: function () {
       var isOpen = this.model.get('isOpen');
diff --git a/core/modules/editor/js/editor.admin.js b/core/modules/editor/js/editor.admin.js
index 4cbfdc7..553cbf5 100644
--- a/core/modules/editor/js/editor.admin.js
+++ b/core/modules/editor/js/editor.admin.js
@@ -11,69 +11,81 @@
 
   "use strict";
 
+  /**
+   * @namespace
+   */
   Drupal.editorConfiguration = {
 
     /**
-     * Must be called by a specific text editor's configuration whenever a feature
-     * is added by the user.
+     * Must be called by a specific text editor's configuration whenever a
+     * feature is added by the user.
      *
-     * Triggers the drupalEditorFeatureAdded event on the document, which receives
-     * a Drupal.EditorFeature object.
+     * Triggers the drupalEditorFeatureAdded event on the document, which
+     * receives a Drupal.EditorFeature object.
      *
-     * @param Drupal.EditorFeature feature
+     * @param {Drupal.EditorFeature} feature
      *   A text editor feature object.
+     *
+     * @fires event:drupalEditorFeatureAdded
      */
     addedFeature: function (feature) {
       $(document).trigger('drupalEditorFeatureAdded', feature);
     },
 
     /**
-     * Must be called by a specific text editor's configuration whenever a feature
-     * is removed by the user.
+     * Must be called by a specific text editor's configuration whenever a
+     * feature is removed by the user.
      *
      * Triggers the drupalEditorFeatureRemoved event on the document, which
      * receives a Drupal.EditorFeature object.
      *
-     * @param Drupal.EditorFeature feature
+     * @param {Drupal.EditorFeature} feature
      *   A text editor feature object.
+     *
+     * @fires event:drupalEditorFeatureRemoved
      */
     removedFeature: function (feature) {
       $(document).trigger('drupalEditorFeatureRemoved', feature);
     },
 
     /**
-     * Must be called by a specific text editor's configuration whenever a feature
-     * is modified, i.e. has different rules.
+     * Must be called by a specific text editor's configuration whenever a
+     * feature is modified, i.e. has different rules.
      *
-     * For example when the "Bold" button is configured to use the <b> tag instead
-     * of the <strong> tag.
+     * For example when the "Bold" button is configured to use the <b> tag
+     * instead of the <strong> tag.
      *
      * Triggers the drupalEditorFeatureModified event on the document, which
      * receives a Drupal.EditorFeature object.
      *
-     * @param Drupal.EditorFeature feature
+     * @param {Drupal.EditorFeature} feature
      *   A text editor feature object.
+     *
+     * @fires event:drupalEditorFeatureModified
      */
     modifiedFeature: function (feature) {
       $(document).trigger('drupalEditorFeatureModified', feature);
     },
 
     /**
-     * May be called by a specific text editor's configuration whenever a feature
-     * is being added, to check whether it would require the filter settings to be
-     * updated.
+     * May be called by a specific text editor's configuration whenever a
+     * feature is being added, to check whether it would require the filter
+     * settings to be updated.
      *
-     * The canonical use case is when a text editor is being enabled: preferably
-     * this would not cause the filter settings to be changed; rather, the default
-     * set of buttons (features) for the text editor should adjust itself to not
-     * cause filter setting changes.
+     * The canonical use case is when a text editor is being enabled:
+     * preferably
+     * this would not cause the filter settings to be changed; rather, the
+     * default set of buttons (features) for the text editor should adjust
+     * itself to not cause filter setting changes.
      *
      * Note: for filters to integrate with this functionality, it is necessary
-     * that they implement Drupal.filterSettingsForEditors[filterID].getRules().
+     * that they implement
+     * Drupal.filterSettingsForEditors[filterID].getRules().
      *
-     * @param Drupal.EditorFeature feature
+     * @param {Drupal.EditorFeature} feature
      *   A text editor feature object.
-     * @return Boolean
+     *
+     * @return {bool}
      *   Whether the given feature is allowed by the current filters.
      */
     featureIsAllowedByFilters: function (feature) {
@@ -102,22 +114,27 @@
        *   };
        *
        * In this example, the given text editor feature resulted in the above
-       * universe, which shows that it must be allowed to generate the a, strong
-       * and img tags. For the a tag, it must be able to set the "href" attribute
-       * and the "external" class. For the strong tag, no further properties are
-       * required. For the img tag, the "src" attribute is required.
-       * The "tag" key is used to track whether that tag was explicitly allowed by
-       * one of the filter's rules. The "touchedByAllowedPropertyRule" key is used
-       * for state tracking that is essential for filterStatusAllowsFeature() to
-       * be able to reason: when all of a filter's rules have been applied, and
-       * none of the forbidden rules matched (which would have resulted in early
-       * termination) yet the universe has not been made empty (which would be the
-       * end result if everything in the universe were explicitly allowed), then
-       * this piece of state data enables us to determine whether a tag whose
-       * properties were not all explicitly allowed are in fact still allowed,
-       * because its tag was explicitly allowed and there were no filter rules
-       * applying "allowed tag property value" restrictions for this particular
-       * tag.
+       * universe, which shows that it must be allowed to generate the a,
+       * strong
+       * and img tags. For the a tag, it must be able to set the "href"
+       * attribute and the "external" class. For the strong tag, no further
+       * properties are required. For the img tag, the "src" attribute is
+       * required. The "tag" key is used to track whether that tag was
+       * explicitly allowed by one of the filter's rules. The
+       * "touchedByAllowedPropertyRule" key is used for state tracking that is
+       * essential for filterStatusAllowsFeature() to be able to reason: when
+       * all of a filter's rules have been applied, and none of the forbidden
+       * rules matched (which would have resulted in early termination) yet the
+       * universe has not been made empty (which would be the end result if
+       * everything in the universe were explicitly allowed), then this piece
+       * of state data enables us to determine whether a tag whose properties
+       * were not all explicitly allowed are in fact still allowed, because its
+       * tag was explicitly allowed and there were no filter rules applying
+       * "allowed tag property value" restrictions for this particular tag.
+       *
+       * @param {object} feature
+       *
+       * @return {object}
        *
        * @see findPropertyValueOnTag()
        * @see filterStatusAllowsFeature()
@@ -151,9 +168,9 @@
             continue;
           }
 
-          // Expand the existing universe, assume that each tags' property value
-          // is disallowed. If the filter rules allow everything in the feature's
-          // universe, then the feature is allowed.
+          // Expand the existing universe, assume that each tags' property
+          // value is disallowed. If the filter rules allow everything in the
+          // feature's universe, then the feature is allowed.
           for (var p = 0; p < properties.length; p++) {
             var property = properties[p];
             for (var pv = 0; pv < featureRule.required[property].length; pv++) {
@@ -169,6 +186,10 @@
       /**
        * Provided a section of a feature or filter rule, checks if no property
        * values are defined for all properties: attributes, classes and styles.
+       *
+       * @param {object} section
+       *
+       * @return {bool}
        */
       function emptyProperties(section) {
         return section.attributes.length === 0 && section.classes.length === 0 && section.styles.length === 0;
@@ -178,6 +199,14 @@
        * Calls findPropertyValueOnTag on the given tag for every property value
        * that is listed in the "propertyValues" parameter. Supports the wildcard
        * tag.
+       *
+       * @param {object} universe
+       * @param {string} tag
+       * @param {string} property
+       * @param {Array} propertyValues
+       * @param {bool} allowing
+       *
+       * @return {bool}
        */
       function findPropertyValuesOnTag(universe, tag, property, propertyValues, allowing) {
         // Detect the wildcard case.
@@ -196,6 +225,13 @@
 
       /**
        * Calls findPropertyValuesOnAllTags for all tags in the universe.
+       *
+       * @param {object} universe
+       * @param {string} property
+       * @param {Array} propertyValues
+       * @param {bool} allowing
+       *
+       * @return {bool}
        */
       function findPropertyValuesOnAllTags(universe, property, propertyValues, allowing) {
         var atLeastOneFound = false;
@@ -208,10 +244,18 @@
       }
 
       /**
-       * Finds out if a specific property value (potentially containing wildcards)
-       * exists on the given tag. When the "allowing" parameter equals true, the
-       * universe will be updated if that specific property value exists.
-       * Returns true if found, false otherwise.
+       * Finds out if a specific property value (potentially containing
+       * wildcards) exists on the given tag. When the "allowing" parameter
+       * equals true, the universe will be updated if that specific property
+       * value exists. Returns true if found, false otherwise.
+       *
+       * @param {object} universe
+       * @param {string} tag
+       * @param {string} property
+       * @param {string} propertyValue
+       * @param {bool} allowing
+       *
+       * @return {bool}
        */
       function findPropertyValueOnTag(universe, tag, property, propertyValue, allowing) {
         // If the tag does not exist in the universe, then it definitely can't
@@ -258,6 +302,11 @@
       /**
        * Deletes a tag from the universe if the tag itself and each of its
        * properties are marked as allowed.
+       *
+       * @param {object} universe
+       * @param {string} tag
+       *
+       * @return {bool}
        */
       function deleteFromUniverseIfAllowed(universe, tag) {
         // Detect the wildcard case.
@@ -273,6 +322,10 @@
 
       /**
        * Calls deleteFromUniverseIfAllowed for all tags in the universe.
+       *
+       * @param {object} universe
+       *
+       * @return {bool}
        */
       function deleteAllTagsFromUniverseIfAllowed(universe) {
         var atLeastOneDeleted = false;
@@ -287,6 +340,11 @@
       /**
        * Checks if any filter rule forbids either a tag or a tag property value
        * that exists in the universe.
+       *
+       * @param {object} universe
+       * @param {object} filterStatus
+       *
+       * @return {bool}
        */
       function anyForbiddenFilterRuleMatches(universe, filterStatus) {
         var properties = ['attributes', 'styles', 'classes'];
@@ -315,8 +373,8 @@
               // … then iterate over all properties …
               for (var k = 0; k < properties.length; k++) {
                 var property = properties[k];
-                // … and return true if just one of the forbidden property values
-                // for this tag and property is listed in the universe.
+                // … and return true if just one of the forbidden property
+                // values for this tag and property is listed in the universe.
                 if (findPropertyValuesOnTag(universe, tag, property, filterRule.restrictedTags.forbidden[property], false)) {
                   return true;
                 }
@@ -329,10 +387,13 @@
       }
 
       /**
-       * Applies every filter rule's explicit allowing of a tag or a tag property
-       * value to the universe. Whenever both the tag and all of its required
-       * property values are marked as explicitly allowed, they are deleted from
-       * the universe.
+       * Applies every filter rule's explicit allowing of a tag or a tag
+       * property value to the universe. Whenever both the tag and all of its
+       * required property values are marked as explicitly allowed, they are
+       * deleted from the universe.
+       *
+       * @param {object} universe
+       * @param {object} filterStatus
        */
       function markAllowedTagsAndPropertyValues(universe, filterStatus) {
         var properties = ['attributes', 'styles', 'classes'];
@@ -365,9 +426,10 @@
               // … then iterate over all properties …
               for (var k = 0; k < properties.length; k++) {
                 var property = properties[k];
-                // … and try to delete this tag from the universe if just one of
-                // the allowed property values for this tag and property is listed
-                // in the universe. (Because everything might be allowed now.)
+                // … and try to delete this tag from the universe if just one
+                // of the allowed property values for this tag and property is
+                // listed in the universe. (Because everything might be allowed
+                // now.)
                 if (findPropertyValuesOnTag(universe, tag, property, filterRule.restrictedTags.allowed[property], true)) {
                   deleteFromUniverseIfAllowed(universe, tag);
                 }
@@ -383,6 +445,11 @@
        * requirements and then checking whether anything in the filter prevents
        * that.
        *
+       * @param {object} filterStatus
+       * @param {object} feature
+       *
+       * @return {bool}
+       *
        * @see generateUniverseFromFeatureRequirements()
        */
       function filterStatusAllowsFeature(filterStatus, feature) {
@@ -391,8 +458,8 @@
           return true;
         }
 
-        // A feature that specifies no rules has no HTML requirements and is hence
-        // allowed by definition.
+        // A feature that specifies no rules has no HTML requirements and is
+        // hence allowed by definition.
         if (feature.rules.length === 0) {
           return true;
         }
@@ -418,17 +485,16 @@
         // universe will become empty.
         markAllowedTagsAndPropertyValues(universe, filterStatus);
 
-        // If there was at least one filter rule allowing tags, then everything in
-        // the universe must be allowed for this feature to be allowed, and thus
-        // by now it must be empty.
-        // However, it is still possible that the filter allows the feature, due
-        // to no rules for allowing tag property values and/or rules for
-        // forbidding tag property values. For details: see the comments below.
-        //
+        // If there was at least one filter rule allowing tags, then everything
+        // in the universe must be allowed for this feature to be allowed, and
+        // thus by now it must be empty. However, it is still possible that the
+        // filter allows the feature, due to no rules for allowing tag property
+        // values and/or rules for forbidding tag property values. For details:
+        // see the comments below.
         // @see generateUniverseFromFeatureRequirements()
         if (_.some(_.pluck(filterStatus.rules, 'allow'))) {
-          // If the universe is empty, then everything was explicitly allowed and
-          // our job is done: this filter allows this feature!
+          // If the universe is empty, then everything was explicitly allowed
+          // and our job is done: this filter allows this feature!
           if (_.isEmpty(universe)) {
             return true;
           }
@@ -440,13 +506,13 @@
               return false;
             }
             // Every tag was explicitly allowed, but since the universe is not
-            // empty, one or more tag properties are disallowed. However, if only
-            // blacklisting of tag properties was applied to these tags, and no
-            // whitelisting was ever applied, then it's still fine: since none of
-            // the tag properties were blacklisted, we got to this point, and since
-            // no whitelisting was applied, it doesn't matter that the properties:
-            // this could never have happened anyway.
-            // It's only this late that we can know this for certain.
+            // empty, one or more tag properties are disallowed. However, if
+            // only blacklisting of tag properties was applied to these tags,
+            // and no whitelisting was ever applied, then it's still fine:
+            // since none of the tag properties were blacklisted, we got to
+            // this point, and since no whitelisting was applied, it doesn't
+            // matter that the properties: this could never have happened
+            // anyway. It's only this late that we can know this for certain.
             else {
               var tags = _.keys(universe);
               // Figure out if there was any rule applying whitelisting tag
@@ -471,7 +537,8 @@
         }
       }
 
-      // If any filter's current status forbids the editor feature, return false.
+      // If any filter's current status forbids the editor feature, return
+      // false.
       Drupal.filterConfiguration.update();
       for (var filterID in Drupal.filterConfiguration.statuses) {
         if (Drupal.filterConfiguration.statuses.hasOwnProperty(filterID)) {
@@ -487,25 +554,89 @@
   };
 
   /**
+   * Constructor for an editor feature HTML rule.
+   *
+   * Intended to be used in combination with {@link Drupal.EditorFeature}.
+   *
+   * A text editor feature rule object describes both:
+   *  - required HTML tags, attributes, styles and classes: without these, the
+   *    text editor feature is unable to function. It's possible that a
+   *  - allowed HTML tags, attributes, styles and classes: these are optional
+   *    in the strictest sense, but it is possible that the feature generates
+   *    them.
+   *
+   * The structure can be very clearly seen below: there's a "required" and an
+   * "allowed" key. For each of those, there are objects with the "tags",
+   * "attributes", "styles" and "classes" keys. For all these keys the values
+   * are initialized to the empty array. List each possible value as an array
+   * value. Besides the "required" and "allowed" keys, there's an optional
+   * "raw" key: it allows text editor implementations to optionally pass in
+   * their raw representation instead of the Drupal-defined representation for
+   * HTML rules.
+   *
+   * @example
+   * tags: ['<a>']
+   * attributes: ['href', 'alt']
+   * styles: ['color', 'text-decoration']
+   * classes: ['external', 'internal']
+   *
+   * @constructor
+   *
+   * @see Drupal.EditorFeature
+   */
+  Drupal.EditorFeatureHTMLRule = function () {
+
+    /**
+     *
+     * @type {object}
+     *
+     * @prop {Array} tags
+     * @prop {Array} attributes
+     * @prop {Array} styles
+     * @prop {Array} classes
+     */
+    this.required = {tags: [], attributes: [], styles: [], classes: []};
+
+    /**
+     *
+     * @type {object}
+     *
+     * @prop {Array} tags
+     * @prop {Array} attributes
+     * @prop {Array} styles
+     * @prop {Array} classes
+     */
+    this.allowed = {tags: [], attributes: [], styles: [], classes: []};
+
+    /**
+     *
+     * @type {null}
+     */
+    this.raw = null;
+  };
+
+  /**
    * A text editor feature object. Initialized with the feature name.
    *
-   * Contains a set of HTML rules (Drupal.EditorFeatureHTMLRule objects) that
-   * describe which HTML tags, attributes, styles and classes are required (i.e.
-   * essential for the feature to function at all) and which are allowed (i.e. the
-   * feature may generate this, but they're not essential).
+   * Contains a set of HTML rules ({@link Drupal.EditorFeatureHTMLRule} objects)
+   * that describe which HTML tags, attributes, styles and classes are required
+   * (i.e. essential for the feature to function at all) and which are allowed
+   * (i.e. the feature may generate this, but they're not essential).
+   *
+   * It is necessary to allow for multiple HTML rules per feature: with just
+   * one HTML rule per feature, there is not enough expressiveness to describe
+   * certain cases. For example: a "table" feature would probably require the
+   * `<table>` tag, and might allow e.g. the "summary" attribute on that tag.
+   * However, the table feature would also require the `<tr>` and `<td>` tags,
+   * but it doesn't make sense to allow for a "summary" attribute on these tags.
+   * Hence these would need to be split in two separate rules.
    *
-   * It is necessary to allow for multiple HTML rules per feature: with just one
-   * HTML rule per feature, there is not enough expressiveness to describe certain
-   * cases. For example: a "table" feature would probably require the <table> tag,
-   * and might allow for e.g. the "summary" attribute on that tag. However, the
-   * table feature would also require the <tr> and <td> tags, but it doesn't make
-   * sense to allow for a "summary" attribute on these tags. Hence these would
-   * need to be split in two separate rules.
+   * HTML rules must be added with the `addHTMLRule()` method. A feature that
+   * has zero HTML rules does not create or modify HTML.
    *
-   * HTML rules must be added with the addHTMLRule() method. A feature that has
-   * zero HTML rules does not create or modify HTML.
+   * @constructor
    *
-   * @param String name
+   * @param {string} name
    *   The name of the feature.
    *
    * @see Drupal.EditorFeatureHTMLRule
@@ -518,7 +649,7 @@
   /**
    * Adds a HTML rule to the list of HTML rules for this feature.
    *
-   * @param Drupal.editorFeatureHTMLRule rule
+   * @param {Drupal.EditorFeatureHTMLRule} rule
    *   A text editor feature HTML rule.
    */
   Drupal.EditorFeature.prototype.addHTMLRule = function (rule) {
@@ -526,66 +657,53 @@
   };
 
   /**
-   * Constructor for an editor feature HTML rule. Intended to be used in
-   * combination with Drupal.EditorFeature.
-   *
-   * A text editor feature rule object describes both
-   *  - required HTML tags, attributes, styles and classes: without these, the
-   *    text editor feature is unable to function. It's possible that a
-   *  - allowed HTML tags, attributes, styles and classes: these are optional in
-   *    the strictest sense, but it is possible that the feature generates them.
-   *
-   * The structure can be very clearly seen below: there's a "required" and an
-   * "allowed" key. For each of those, there are objects with the "tags",
-   * "attributes", "styles" and "classes" keys. For all these keys the values are
-   * initialized to the empty array. List each possible value as an array value.
-   * Besides the "required" and "allowed" keys, there's an optional "raw" key: it
-   * allows text editor implementations to optionally pass in their raw
-   * representation instead of the Drupal-defined representation for HTML rules.
-   *
-   * Examples:
-   *  - tags: ['<a>']
-   *  - attributes: ['href', 'alt']
-   *  - styles: ['color', 'text-decoration']
-   *  - classes: ['external', 'internal']
-   */
-  Drupal.EditorFeatureHTMLRule = function () {
-    this.required = {tags: [], attributes: [], styles: [], classes: []};
-    this.allowed = {tags: [], attributes: [], styles: [], classes: []};
-    this.raw = null;
-  };
-
-  /**
-   * Constructor for a text filter status object. Initialized with the filter ID.
+   * Text filter status object. Initialized with the filter ID.
    *
    * Indicates whether the text filter is currently active (enabled) or not.
    *
-   * Contains a set of HTML rules (Drupal.FilterHTMLRule objects) that describe
-   * which HTML tags are allowed or forbidden. They can also describe for a set of
-   * tags (or all tags) which attributes, styles and classes are allowed and which
-   * are forbidden.
+   * Contains a set of HTML rules ({@link Drupal.FilterHTMLRule} objects) that
+   * describe which HTML tags are allowed or forbidden. They can also describe
+   * for a set of tags (or all tags) which attributes, styles and classes are
+   * allowed and which are forbidden.
    *
-   * It is necessary to allow for multiple HTML rules per feature, for analogous
-   * reasons as Drupal.EditorFeature.
+   * It is necessary to allow for multiple HTML rules per feature, for
+   * analogous reasons as {@link Drupal.EditorFeature}.
    *
-   * HTML rules must be added with the addHTMLRule() method. A filter that has
+   * HTML rules must be added with the `addHTMLRule()` method. A filter that has
    * zero HTML rules does not disallow any HTML.
    *
-   * @param String name
+   * @constructor
+   *
+   * @param {string} name
    *   The name of the feature.
    *
    * @see Drupal.FilterHTMLRule
    */
   Drupal.FilterStatus = function (name) {
+
+    /**
+     *
+     * @type {string}
+     */
     this.name = name;
+
+    /**
+     *
+     * @type {bool}
+     */
     this.active = false;
+
+    /**
+     *
+     * @type {Array.<Drupal.FilterHTMLRule>}
+     */
     this.rules = [];
   };
 
   /**
    * Adds a HTML rule to the list of HTML rules for this filter.
    *
-   * @param Drupal.FilterHTMLRule rule
+   * @param {Drupal.FilterHTMLRule} rule
    *   A text filter HTML rule.
    */
   Drupal.FilterStatus.prototype.addHTMLRule = function (rule) {
@@ -593,59 +711,72 @@
   };
 
   /**
-   * A text filter HTML rule object. Intended to be used in combination with
-   * Drupal.FilterStatus.
+   * A text filter HTML rule object.
+   *
+   * Intended to be used in combination with {@link Drupal.FilterStatus}.
    *
-   * A text filter rule object describes
+   * A text filter rule object describes:
    *  1. allowed or forbidden tags: (optional) whitelist or blacklist HTML tags
-   *  2. restricted tag properties: (optional) whitelist or blacklist attributes,
-   *     styles and classes on a set of HTML tags.
+   *  2. restricted tag properties: (optional) whitelist or blacklist
+   *     attributes, styles and classes on a set of HTML tags.
    *
    * Typically, each text filter rule object does either 1 or 2, not both.
    *
    * The structure can be very clearly seen below:
-   *  1. use the "tags" key to list HTML tags, and set the "allow" key to either
-   *     true (to allow these HTML tags) or false (to forbid these HTML tags). If
-   *     you leave the "tags" key's default value (the empty array), no
-   *     restrictions are applied.
-   *  2. all nested within the "restrictedTags" key: use the "tags" subkey to list
-   *     HTML tags to which you want to apply property restrictions, then use the
-   *     "allowed" subkey to whitelist specific property values, and similarly use
-   *     the "forbidden" subkey to blacklist specific property values.
+   *  1. use the "tags" key to list HTML tags, and set the "allow" key to
+   *     either true (to allow these HTML tags) or false (to forbid these HTML
+   *     tags). If you leave the "tags" key's default value (the empty array),
+   *     no restrictions are applied.
+   *  2. all nested within the "restrictedTags" key: use the "tags" subkey to
+   *     list HTML tags to which you want to apply property restrictions, then
+   *     use the "allowed" subkey to whitelist specific property values, and
+   *     similarly use the "forbidden" subkey to blacklist specific property
+   *     values.
+   *
+   * @example <caption>Whitelist the "p", "strong" and "a" HTML tags.</caption>
+   * {
+   *   tags: ['p', 'strong', 'a'],
+   *   allow: true,
+   *   restrictedTags: {
+   *     tags: [],
+   *     allowed: { attributes: [], styles: [], classes: [] },
+   *     forbidden: { attributes: [], styles: [], classes: [] }
+   *   }
+   * }
+   * @example <caption>For the "a" HTML tag, only allow the "href" attribute
+   * and the "external" class and disallow the "target" attribute.</caption>
+   * {
+   *   tags: [],
+   *   allow: null,
+   *   restrictedTags: {
+   *     tags: ['a'],
+   *     allowed: { attributes: ['href'], styles: [], classes: ['external'] },
+   *     forbidden: { attributes: ['target'], styles: [], classes: [] }
+   *   }
+   * }
+   * @example <caption>For all tags, allow the "data-*" attribute (that is, any
+   * attribute that begins with "data-").</caption>
+   * {
+   *   tags: [],
+   *   allow: null,
+   *   restrictedTags: {
+   *     tags: ['*'],
+   *     allowed: { attributes: ['data-*'], styles: [], classes: [] },
+   *     forbidden: { attributes: [], styles: [], classes: [] }
+   *   }
+   * }
    *
-   * Examples:
-   *  - Whitelist the "p", "strong" and "a" HTML tags:
-   *    {
-   *      tags: ['p', 'strong', 'a'],
-   *      allow: true,
-   *      restrictedTags: {
-   *        tags: [],
-   *        allowed: { attributes: [], styles: [], classes: [] },
-   *        forbidden: { attributes: [], styles: [], classes: [] }
-   *      }
-   *    }
-   *  - For the "a" HTML tag, only allow the "href" attribute and the "external"
-   *    class and disallow the "target" attribute.
-   *    {
-   *      tags: [],
-   *      allow: null,
-   *      restrictedTags: {
-   *        tags: ['a'],
-   *        allowed: { attributes: ['href'], styles: [], classes: ['external'] },
-   *        forbidden: { attributes: ['target'], styles: [], classes: [] }
-   *      }
-   *    }
-   *  - For all tags, allow the "data-*" attribute (that is, any attribute that
-   *    begins with "data-").
-   *    {
-   *      tags: [],
-   *      allow: null,
-   *      restrictedTags: {
-   *        tags: ['*'],
-   *        allowed: { attributes: ['data-*'], styles: [], classes: [] },
-   *        forbidden: { attributes: [], styles: [], classes: [] }
-   *      }
-   *    }
+   * @return {{
+   *   tags: Array,
+   *   allow: null,
+   *   restrictedTags: {
+   *     tags: Array,
+   *     allowed: {attributes: Array, styles: Array, classes: Array},
+   *     forbidden: {attributes: Array, styles: Array, classes: Array}
+   *   }
+   *  }}
+   *
+   *  @see Drupal.FilterStatus
    */
   Drupal.FilterHTMLRule = function () {
     return {
@@ -664,21 +795,29 @@
   /**
    * Tracks the configuration of all text filters in Drupal.FilterStatus objects
    * for Drupal.editorConfiguration.featureIsAllowedByFilters().
+   *
+   * @namespace
    */
   Drupal.filterConfiguration = {
 
     /**
      * Drupal.FilterStatus objects, keyed by filter ID.
+     *
+     * @type {Object.<string, Drupal.FilterStatus>}
      */
     statuses: {},
 
     /**
-     * Live filter setting parsers, keyed by filter ID, for those filters that
-     * implement it.
+     * Live filter setting parsers.
      *
-     * Filters should load the implementing JavaScript on the filter configuration
-     * form and implement Drupal.filterSettings[filterID].getRules(), which should
-     * return an array of Drupal.FilterHTMLRule objects.
+     * Object keyed by filter ID, for those filters that implement it.
+     *
+     * Filters should load the implementing JavaScript on the filter
+     * configuration form and implement
+     * `Drupal.filterSettings[filterID].getRules()`, which should return an
+     * array of {@link Drupal.FilterHTMLRule} objects.
+     *
+     * @namespace
      */
     liveSettingParsers: {},
 
@@ -686,7 +825,7 @@
      * Updates all Drupal.FilterStatus objects to reflect the current state.
      *
      * Automatically checks whether a filter is currently enabled or not. To
-     * support more finegrained
+     * support more finegrained.
      *
      * If a filter implements a live setting parser, then that will be used to
      * keep the HTML rules for the Drupal.FilterStatus object up-to-date.
@@ -709,6 +848,8 @@
 
   /**
    * Initializes Drupal.filterConfiguration.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.initializeFilterConfiguration = {
     attach: function (context, settings) {
@@ -719,7 +860,8 @@
         var nameAttribute = $checkbox.attr('name');
 
         // The filter's checkbox has a name attribute of the form
-        // "filters[<name of filter>][status]", parse "<name of filter>" from it.
+        // "filters[<name of filter>][status]", parse "<name of filter>"
+        // from it.
         var filterID = nameAttribute.substring(8, nameAttribute.indexOf(']'));
 
         // Create a Drupal.FilterStatus object to track the state (whether it's
diff --git a/core/modules/editor/js/editor.dialog.js b/core/modules/editor/js/editor.dialog.js
index 3ec2372..04b9403 100644
--- a/core/modules/editor/js/editor.dialog.js
+++ b/core/modules/editor/js/editor.dialog.js
@@ -1,4 +1,5 @@
 /**
+ * @file
  * AJAX commands used by Editor module.
  */
 
@@ -9,10 +10,18 @@
   /**
    * Command to save the contents of an editor-provided modal.
    *
-   * This command does not close the open modal. It should be followed by a call
-   * to Drupal.AjaxCommands.prototype.closeDialog. Editors that are integrated
-   * with dialogs must independently listen for an editor:dialogsave event to save
-   * the changes into the contents of their interface.
+   * This command does not close the open modal. It should be followed by a
+   * call to `Drupal.AjaxCommands.prototype.closeDialog`. Editors that are
+   * integrated with dialogs must independently listen for an
+   * `editor:dialogsave` event to save the changes into the contents of their
+   * interface.
+   *
+   * @param {Drupal.Ajax} [ajax]
+   * @param {object} response
+   * @param {Array} response.values
+   * @param {number} [status]
+   *
+   * @fires event:editor:dialogsave
    */
   Drupal.AjaxCommands.prototype.editorDialogSave = function (ajax, response, status) {
     $(window).trigger('editor:dialogsave', [response.values]);
diff --git a/core/modules/editor/js/editor.formattedTextEditor.js b/core/modules/editor/js/editor.formattedTextEditor.js
index e624f67..ba40173 100644
--- a/core/modules/editor/js/editor.formattedTextEditor.js
+++ b/core/modules/editor/js/editor.formattedTextEditor.js
@@ -10,26 +10,52 @@
  * JavaScript would use:
  *  - Drupal.editors.magical.attachInlineEditor()
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
-  Drupal.quickedit.editors.editor = Drupal.quickedit.EditorView.extend({
+  /**
+   * Editor.
+   *
+   * @constructor
+   *
+   * @augments Drupal.quickedit.EditorView
+   */
+  Drupal.quickedit.editors.editor = Drupal.quickedit.EditorView.extend(/** @lends Drupal.quickedit.editors.editor# */{
 
-    // The text format for this field.
+    /**
+     * The text format for this field.
+     *
+     * @type {?string}
+     */
     textFormat: null,
 
-    // Indicates whether this text format has transformations.
+    /**
+     * Indicates whether this text format has transformations.
+     *
+     * @type {?bool}
+     */
     textFormatHasTransformations: null,
 
-    // Stores a reference to the text editor object for this field.
+    /**
+     * Stores a reference to the text editor object for this field.
+     *
+     * @type {?Drupal.quickedit.EditorModel}
+     */
     textEditor: null,
 
-    // Stores the textual DOM element that is being in-place edited.
+    /**
+     * Stores the textual DOM element that is being in-place edited.
+     *
+     * @type {?jQuery}
+     */
     $textElement: null,
 
     /**
-     * {@inheritdoc}
+     * @constructs
+     *
+     * @param {object} options
      */
     initialize: function (options) {
       Drupal.quickedit.EditorView.prototype.initialize.call(this, options);
@@ -46,14 +72,19 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {jQuery}
      */
     getEditedElement: function () {
       return this.$textElement;
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @param {object} fieldModel
+     * @param {string} state
      */
     stateChange: function (fieldModel, state) {
       var editorModel = this.model;
@@ -143,14 +174,16 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {object}
      */
     getQuickEditUISettings: function () {
       return {padding: true, unifiedToolbar: true, fullWidthToolbar: true, popup: false};
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     revert: function () {
       this.$textElement.html(this.model.get('originalValue'));
@@ -162,7 +195,7 @@
      * More accurately: it re-filters formatted text to exclude transformation
      * filters used by the text format.
      *
-     * @param Function callback
+     * @param {function} callback
      *   A callback function that will receive the untransformed text.
      *
      * @see \Drupal\editor\Ajax\GetUntransformedTextCommand
diff --git a/core/modules/editor/js/editor.js b/core/modules/editor/js/editor.js
index 1b26b0f..61f4b96 100644
--- a/core/modules/editor/js/editor.js
+++ b/core/modules/editor/js/editor.js
@@ -10,10 +10,10 @@
   /**
    * Finds the text area field associated with the given text format selector.
    *
-   * @param jQuery $formatSelector
+   * @param {jQuery} $formatSelector
    *   A text format selector DOM element.
    *
-   * @return DOM
+   * @return {HTMLElement}
    *   The text area DOM element, if it was found.
    */
   function findFieldForFormatSelector($formatSelector) {
@@ -26,9 +26,9 @@
   /**
    * Changes the text editor on a text area.
    *
-   * @param DOM field
+   * @param {HTMLElement} field
    *   The text area DOM element.
-   * @param String newFormatID
+   * @param {string} newFormatID
    *   The text format we're changing to; the text editor for the currently
    *   active text format will be detached, and the text editor for the new text
    *   format will be attached.
@@ -58,7 +58,7 @@
   /**
    * Handles changes in text format.
    *
-   * @param jQuery.Event event
+   * @param {jQuery.Event} event
    */
   function onTextFormatChange(event) {
     var $select = $(event.target);
@@ -129,11 +129,15 @@
 
   /**
    * Initialize an empty object for editors to place their attachment code.
+   *
+   * @namespace
    */
   Drupal.editors = {};
 
   /**
    * Enables editors on text_format elements.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.editor = {
     attach: function (context, settings) {
@@ -214,6 +218,19 @@
     }
   };
 
+  /**
+   * Attach editor behaviors to the field.
+   *
+   * @param {HTMLElement} field
+   *   The textarea DOM element.
+   * @param {object} format
+   *   The text format that's being activated, from
+   *   drupalSettings.editor.formats.
+   *
+   * @listens event:change
+   *
+   * @fires event:formUpdated
+   */
   Drupal.editorAttach = function (field, format) {
     if (format.editor) {
       // HTML5 validation cannot ever work for WYSIWYG editors, because WYSIWYG
@@ -240,6 +257,17 @@
     }
   };
 
+  /**
+   * Detach editor behaviors from the field.
+   *
+   * @param {HTMLElement} field
+   *   The textarea DOM element.
+   * @param {object} format
+   *   The text format that's being activated, from
+   *   drupalSettings.editor.formats.
+   * @param {string} trigger
+   *   Trigger value from the detach behavior.
+   */
   Drupal.editorDetach = function (field, format, trigger) {
     if (format.editor) {
       // Restore the HTML5 validation "required" attribute if it was removed in
@@ -261,13 +289,14 @@
   /**
    * Filter away XSS attack vectors when switching text formats.
    *
-   * @param DOM field
+   * @param {HTMLElement} field
    *   The textarea DOM element.
-   * @param Object format
-   *   The text format that's being activated, from drupalSettings.editor.formats.
-   * @param String originalFormatID
+   * @param {object} format
+   *   The text format that's being activated, from
+   *   drupalSettings.editor.formats.
+   * @param {string} originalFormatID
    *   The text format ID of the original text format.
-   * @param Function callback
+   * @param {function} callback
    *   A callback to be called (with no parameters) after the field's value has
    *   been XSS filtered.
    */
diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js
index 9bdbe50..fceb94e 100644
--- a/core/modules/field_ui/field_ui.js
+++ b/core/modules/field_ui/field_ui.js
@@ -7,14 +7,17 @@
 
   "use strict";
 
+  /**
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.fieldUIFieldStorageAddForm = {
     attach: function (context) {
       var $form = $(context).find('#field-ui-field-storage-add-form').once('field_ui_add');
       if ($form.length) {
-        // Add a few 'form-required' css classes here. We can not use the Form API
-        // '#required' property because both label elements for "add new" and
-        // "re-use existing" can never be filled and submitted at the same time.
-        // The actual validation will happen server-side.
+        // Add a few 'form-required' css classes here. We can not use the Form
+        // API '#required' property because both label elements for "add new"
+        // and "re-use existing" can never be filled and submitted at the same
+        // time. The actual validation will happen server-side.
         $form.find(
           '.form-item-label label,' +
           '.form-item-field-name label,' +
@@ -52,6 +55,10 @@
     }
   };
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.fieldUIDisplayOverview = {
     attach: function (context, settings) {
       $(context).find('table#field-display-overview').once('field-display-overview').each(function () {
@@ -60,9 +67,17 @@
     }
   };
 
+  /**
+   * @namespace
+   */
   Drupal.fieldUIOverview = {
+
     /**
      * Attaches the fieldUIOverview behavior.
+     *
+     * @param {HTMLTableElement} table
+     * @param {object} rowsData
+     * @param {object} rowHandlers
      */
     attach: function (table, rowsData, rowHandlers) {
       var tableDrag = Drupal.tableDrag[table.id];
@@ -79,7 +94,8 @@
           var data = rowsData[row.id];
           data.tableDrag = tableDrag;
 
-          // Create the row handler, make it accessible from the DOM row element.
+          // Create the row handler, make it accessible from the DOM row
+          // element.
           var rowHandler = new rowHandlers[data.rowHandler](row, data);
           $(row).data('fieldUIRowHandler', rowHandler);
         }
@@ -140,9 +156,7 @@
      *
      * Copied from block.js.
      *
-     * @param table
-     *   The table DOM element.
-     * @param rowObject
+     * @param {HTMLElement} draggedRow
      *   The tableDrag rowObject for the row being dragged.
      */
     onSwap: function (draggedRow) {
@@ -152,7 +166,8 @@
         // If the dragged row is in this region, but above the message row, swap
         // it down one space.
         if ($this.prev('tr').get(0) === rowObject.group[rowObject.group.length - 1]) {
-          // Prevent a recursion problem when using the keyboard to move rows up.
+          // Prevent a recursion problem when using the keyboard to move rows
+          // up.
           if ((rowObject.method !== 'keyboard' || rowObject.direction === 'down')) {
             rowObject.swap('after', this);
           }
@@ -175,7 +190,7 @@
      * The #ajax behavior is therefore not attached directly to the selects, but
      * triggered manually through a hidden #ajax 'Refresh' button.
      *
-     * @param rows
+     * @param {object} rows
      *   A hash object, whose keys are the names of the rows to refresh (they
      *   will receive the 'ajax-new-content' effect on the server side), and
      *   whose values are the DOM element in the row that should get an Ajax
@@ -210,6 +225,8 @@
 
   /**
    * Row handlers for the 'Manage display' screen.
+   *
+   * @namespace
    */
   Drupal.fieldUIDisplayOverview = {};
 
@@ -218,10 +235,14 @@
    *
    * This handler is used for both fields and 'extra fields' rows.
    *
-   * @param row
+   * @constructor
+   *
+   * @param {HTMLTableRowElement} row
    *   The row DOM element.
-   * @param data
+   * @param {object} data
    *   Additional data to be populated in the constructed object.
+   *
+   * @return {Drupal.fieldUIDisplayOverview.field}
    */
   Drupal.fieldUIDisplayOverview.field = function (row, data) {
     this.row = row;
@@ -237,8 +258,11 @@
   };
 
   Drupal.fieldUIDisplayOverview.field.prototype = {
+
     /**
      * Returns the region corresponding to the current form values of the row.
+     *
+     * @return {string}
      */
     getRegion: function () {
       return (this.$pluginSelect.val() === 'hidden') ? 'hidden' : 'content';
@@ -247,16 +271,18 @@
     /**
      * Reacts to a row being changed regions.
      *
-     * This function is called when the row is moved to a different region, as a
+     * This function is called when the row is moved to a different region, as
+     * a
      * result of either :
-     * - a drag-and-drop action (the row's form elements then probably need to be
-     *   updated accordingly)
+     * - a drag-and-drop action (the row's form elements then probably need to
+     * be updated accordingly)
      * - user input in one of the form elements watched by the
      *   Drupal.fieldUIOverview.onChange change listener.
      *
-     * @param region
+     * @param {string} region
      *   The name of the new region for the row.
-     * @return
+     *
+     * @return {object}
      *   A hash object indicating which rows should be Ajax-updated as a result
      *   of the change, in the format expected by
      *   Drupal.displayOverview.AJAXRefreshRows().
@@ -271,8 +297,9 @@
       // if (region !== 'hidden') {
       if (region === 'content') {
         if (currentValue === 'hidden') {
-          // Restore the formatter back to the default formatter. Pseudo-fields do
-          // not have default formatters, we just return to 'visible' for those.
+          // Restore the formatter back to the default formatter. Pseudo-fields
+          // do not have default formatters, we just return to 'visible' for
+          // those.
           value = (typeof this.defaultPlugin !== 'undefined') ? this.defaultPlugin : this.$pluginSelect.find('option').val();
         }
       }
diff --git a/core/modules/file/file.js b/core/modules/file/file.js
index 8f0c9db..73487e2 100644
--- a/core/modules/file/file.js
+++ b/core/modules/file/file.js
@@ -13,6 +13,8 @@
 
   /**
    * Attach behaviors to managed file element upload fields.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.fileValidateAutoAttach = {
     attach: function (context, settings) {
@@ -49,6 +51,8 @@
 
   /**
    * Attach behaviors to managed file element upload fields.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.fileAutoUpload = {
     attach: function (context) {
@@ -63,6 +67,8 @@
 
   /**
    * Attach behaviors to the file upload and remove buttons.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.fileButtons = {
     attach: function (context) {
@@ -79,6 +85,8 @@
 
   /**
    * Attach behaviors to links within managed file elements.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.filePreviewLinks = {
     attach: function (context) {
@@ -91,10 +99,17 @@
 
   /**
    * File upload utility functions.
+   *
+   * @namespace
    */
   Drupal.file = Drupal.file || {
+
     /**
      * Client-side file input validation of file extensions.
+     *
+     * @name Drupal.file.validateExtension
+     *
+     * @param {jQuery.Event} event
      */
     validateExtension: function (event) {
       event.preventDefault();
@@ -124,14 +139,24 @@
         }
       }
     },
+
     /**
      * Trigger the upload_button mouse event to auto-upload as a managed file.
+     *
+     * @name Drupal.file.triggetUploadButton
+     *
+     * @param {jQuery.Event} event
      */
     triggerUploadButton: function (event) {
       $(event.target).closest('.form-managed-file').find('.js-form-submit').trigger('mousedown');
     },
+
     /**
      * Prevent file uploads when using buttons not intended to upload.
+     *
+     * @name Drupal.file.disableFields
+     *
+     * @param {jQuery.Event} event
      */
     disableFields: function (event) {
       var $clickedButton = $(this).findOnce('ajax');
@@ -149,20 +174,26 @@
 
       // Temporarily disable upload fields other than the one we're currently
       // working with. Filter out fields that are already disabled so that they
-      // do not get enabled when we re-enable these fields at the end of behavior
-      // processing. Re-enable in a setTimeout set to a relatively short amount
-      // of time (1 second). All the other mousedown handlers (like Drupal's Ajax
-      // behaviors) are executed before any timeout functions are called, so we
-      // don't have to worry about the fields being re-enabled too soon.
-      // @todo If the previous sentence is true, why not set the timeout to 0?
+      // do not get enabled when we re-enable these fields at the end of
+      // behavior processing. Re-enable in a setTimeout set to a relatively
+      // short amount of time (1 second). All the other mousedown handlers
+      // (like Drupal's Ajax behaviors) are executed before any timeout
+      // functions are called, so we don't have to worry about the fields being
+      // re-enabled too soon. @todo If the previous sentence is true, why not
+      // set the timeout to 0?
       var $fieldsToTemporarilyDisable = $('div.form-managed-file input.form-file').not($enabledFields).not(':disabled');
       $fieldsToTemporarilyDisable.prop('disabled', true);
       setTimeout(function () {
         $fieldsToTemporarilyDisable.prop('disabled', false);
       }, 1000);
     },
+
     /**
      * Add progress bar support if possible.
+     *
+     * @name Drupal.file.progressBar
+     *
+     * @param {jQuery.Event} event
      */
     progressBar: function (event) {
       var $clickedButton = $(this);
@@ -183,8 +214,13 @@
         $clickedButton.closest('div.form-managed-file').find('div.ajax-progress-bar').slideDown();
       }, 500);
     },
+
     /**
      * Open links to files within forms in a new window.
+     *
+     * @name Drupal.file.openInNewWindow
+     *
+     * @param {jQuery.Event} event
      */
     openInNewWindow: function (event) {
       event.preventDefault();
diff --git a/core/modules/filter/filter.admin.js b/core/modules/filter/filter.admin.js
index ba650c8..e14634c 100644
--- a/core/modules/filter/filter.admin.js
+++ b/core/modules/filter/filter.admin.js
@@ -7,6 +7,10 @@
 
   "use strict";
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.filterStatus = {
     attach: function (context, settings) {
       var $context = $(context);
diff --git a/core/modules/filter/filter.filter_html.admin.js b/core/modules/filter/filter.filter_html.admin.js
index d8e36c4..0854cf8 100644
--- a/core/modules/filter/filter.filter_html.admin.js
+++ b/core/modules/filter/filter.filter_html.admin.js
@@ -7,12 +7,19 @@
 
   "use strict";
 
-  /**
-   * Implement a live setting parser to prevent text editors from automatically
-   * enabling buttons that are not allowed by this filter's configuration.
-   */
   if (Drupal.filterConfiguration) {
+
+    /**
+     * Implement a live setting parser to prevent text editors from automatically
+     * enabling buttons that are not allowed by this filter's configuration.
+     *
+     * @namespace
+     */
     Drupal.filterConfiguration.liveSettingParsers.filter_html = {
+
+      /**
+       * @return {Array}
+       */
       getRules: function () {
         var currentValue = $('#edit-filters-filter-html-settings-allowed-html').val();
         var rules = [];
@@ -37,6 +44,12 @@
     };
   }
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   *
+   * @todo Remove everything but 'attach' and 'detach' and make a proper object.
+   */
   Drupal.behaviors.filterFilterHtmlUpdating = {
 
     // The form item contains the "Allowed HTML tags" setting.
@@ -114,12 +127,12 @@
      * The filter_html filter is only concerned with the required tags, not with
      * any properties, nor with each feature's "allowed" tags.
      *
-     * @param Array userAllowedTags
+     * @param {Array} userAllowedTags
      *   The list of user-defined allowed tags.
-     * @param Object newFeatures
+     * @param {object} newFeatures
      *   A list of Drupal.EditorFeature objects' rules, keyed by their name.
      *
-     * @return Array
+     * @return {Array}
      *   A list of new allowed tags.
      */
     _calculateAutoAllowedTags: function (userAllowedTags, newFeatures) {
@@ -141,10 +154,10 @@
     /**
      * Parses the value of this.$allowedHTMLFormItem.
      *
-     * @param String setting
+     * @param {string} setting
      *   The string representation of the setting. e.g. "<p> <br> <a>"
      *
-     * @return Array
+     * @return {Array}
      *   The array representation of the setting. e.g. ['p', 'br', 'a']
      */
     _parseSetting: function (setting) {
@@ -154,10 +167,10 @@
     /**
      * Generates the value of this.$allowedHTMLFormItem.
      *
-     * @param Array setting
+     * @param {Array} tags
      *   The array representation of the setting. e.g. ['p', 'br', 'a']
      *
-     * @return Array
+     * @return {Array}
      *   The string representation of the setting. e.g. "<p> <br> <a>"
      */
     _generateSetting: function (tags) {
@@ -169,9 +182,10 @@
   /**
    * Theme function for the filter_html update message.
    *
-   * @param Array tags
+   * @param {Array} tags
    *   An array of the new tags that are to be allowed.
-   * @return
+   *
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.filterFilterHTMLUpdateMessage = function (tags) {
diff --git a/core/modules/filter/filter.js b/core/modules/filter/filter.js
index 38797e5..58b595f 100644
--- a/core/modules/filter/filter.js
+++ b/core/modules/filter/filter.js
@@ -9,6 +9,8 @@
 
   /**
    * Displays the guidelines of the selected text format automatically.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.filterGuidelines = {
     attach: function (context) {
diff --git a/core/modules/history/js/history.js b/core/modules/history/js/history.js
index 5030790..cba7787 100644
--- a/core/modules/history/js/history.js
+++ b/core/modules/history/js/history.js
@@ -1,8 +1,10 @@
 /**
+ * @file
  * JavaScript API for the History module, with client-side caching.
  *
  * May only be loaded for authenticated users, with the History module enabled.
  */
+
 (function ($, Drupal, drupalSettings, storage) {
 
   "use strict";
@@ -19,14 +21,17 @@
     embeddedLastReadTimestamps = drupalSettings.history.lastReadTimestamps;
   }
 
+  /**
+   * @namespace
+   */
   Drupal.history = {
 
     /**
      * Fetch "last read" timestamps for the given nodes.
      *
-     * @param Array nodeIDs
+     * @param {Array} nodeIDs
      *   An array of node IDs.
-     * @param Function callback
+     * @param {function} callback
      *   A callback that is called after the requested timestamps were fetched.
      */
     fetchTimestamps: function (nodeIDs, callback) {
@@ -55,10 +60,10 @@
     /**
      * Get the last read timestamp for the given node.
      *
-     * @param Number|String nodeID
+     * @param {number|string} nodeID
      *   A node ID.
      *
-     * @return Number
+     * @return {number}
      *   A UNIX timestamp.
      */
     getLastRead: function (nodeID) {
@@ -72,7 +77,7 @@
     /**
      * Marks a node as read, store the last read timestamp in client-side storage.
      *
-     * @param Number|String nodeID
+     * @param {number|string} nodeID
      *   A node ID.
      */
     markAsRead: function (nodeID) {
@@ -98,12 +103,12 @@
      * Any content that was published before the oldest known reading also never
      * gets a "new" or "updated" indicator, because it must've been read already.
      *
-     * @param Number|String nodeID
+     * @param {number|string} nodeID
      *   A node ID.
-     * @param Number contentTimestamp
+     * @param {number} contentTimestamp
      *   The time at which some content (e.g. a comment) was published.
      *
-     * @return Boolean
+     * @return {bool}
      *   Whether a server check is necessary for the given node and its timestamp.
      */
     needsServerCheck: function (nodeID, contentTimestamp) {
diff --git a/core/modules/history/js/mark-as-read.js b/core/modules/history/js/mark-as-read.js
index b2ba518..848d351 100644
--- a/core/modules/history/js/mark-as-read.js
+++ b/core/modules/history/js/mark-as-read.js
@@ -1,8 +1,12 @@
 /**
+ * @file
  * Marks the nodes listed in drupalSettings.history.nodesToMarkAsRead as read.
  *
  * Uses the History module JavaScript API.
+ *
+ * @see Drupal.history
  */
+
 (function (window, Drupal, drupalSettings) {
 
   "use strict";
diff --git a/core/modules/language/language.admin.js b/core/modules/language/language.admin.js
index 0c14619..0a7c9e1 100644
--- a/core/modules/language/language.admin.js
+++ b/core/modules/language/language.admin.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Language admin behavior.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
 
   /**
    * Makes language negotiation inherit user interface negotiation.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.negotiationLanguage = {
     attach: function () {
diff --git a/core/modules/locale/locale.admin.js b/core/modules/locale/locale.admin.js
index 9c32c5e..c7bac21 100644
--- a/core/modules/locale/locale.admin.js
+++ b/core/modules/locale/locale.admin.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Locale admin behavior.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
 
   /**
-   * Marks changes of translations
+   * Marks changes of translations.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.localeTranslateDirty = {
     attach: function () {
@@ -41,6 +48,8 @@
 
   /**
    * Show/hide the description details on Available translation updates page.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.hideUpdateInformation = {
     attach: function (context, settings) {
@@ -73,10 +82,20 @@
     }
   };
 
-  $.extend(Drupal.theme, {
+  $.extend(Drupal.theme, /** @lends Drupal.theme */{
+
+    /**
+     *
+     * @return {string}
+     */
     localeTranslateChangedMarker: function () {
       return '<abbr class="warning ajax-changed" title="' + Drupal.t('Changed') + '">*</abbr>';
     },
+
+    /**
+     *
+     * @return {string}
+     */
     localeTranslateChangedWarning: function () {
       return '<div class="clearfix messages messages--warning">' + Drupal.theme('localeTranslateChangedMarker') + ' ' + Drupal.t('Changes made in this table will not be saved until the form is submitted.') + '</div>';
     }
diff --git a/core/modules/locale/locale.bulk.js b/core/modules/locale/locale.bulk.js
index 80952d0..7ddafd0 100644
--- a/core/modules/locale/locale.bulk.js
+++ b/core/modules/locale/locale.bulk.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Locale behavior.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
@@ -6,6 +11,8 @@
    * Select the language code of an imported file based on its filename.
    *
    * This only works if the file name ends with "LANGCODE.po".
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.importLanguageCodeSelector = {
     attach: function (context, settings) {
diff --git a/core/modules/locale/locale.datepicker.js b/core/modules/locale/locale.datepicker.js
index 4628eda..197fc42 100644
--- a/core/modules/locale/locale.datepicker.js
+++ b/core/modules/locale/locale.datepicker.js
@@ -9,6 +9,8 @@
 
   /**
    * Attaches language support to the jQuery UI datepicker component.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.localeDatepicker = {
     attach: function (context, settings) {
diff --git a/core/modules/locale/tests/locale_test.js b/core/modules/locale/tests/locale_test.js
index 336d979..ba62b75 100644
--- a/core/modules/locale/tests/locale_test.js
+++ b/core/modules/locale/tests/locale_test.js
@@ -1,6 +1,8 @@
 /**
  * @file
  * JavaScript for locale_test.module.
+ *
+ * @ignore
  */
 
 Drupal.t("Standard Call t");
diff --git a/core/modules/menu_ui/menu_ui.admin.js b/core/modules/menu_ui/menu_ui.admin.js
index 8c037c5..5120d6e 100644
--- a/core/modules/menu_ui/menu_ui.admin.js
+++ b/core/modules/menu_ui/menu_ui.admin.js
@@ -1,7 +1,16 @@
+/**
+ * @file
+ * Menu UI admin behaviors.
+ */
+
 (function ($) {
 
   "use strict";
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.menuUiChangeParentItems = {
     attach: function (context, settings) {
       var $menu = $('#edit-menu').once('menu-parent');
diff --git a/core/modules/menu_ui/menu_ui.js b/core/modules/menu_ui/menu_ui.js
index 3859b7a..2103952 100644
--- a/core/modules/menu_ui/menu_ui.js
+++ b/core/modules/menu_ui/menu_ui.js
@@ -1,7 +1,16 @@
+/**
+ * @file
+ * Menu UI behaviors.
+ */
+
 (function ($) {
 
   "use strict";
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.menuUiDetailsSummaries = {
     attach: function (context) {
       $(context).find('.menu-link-form').drupalSetSummary(function (context) {
@@ -18,6 +27,8 @@
 
   /**
    * Automatically fill in a menu link title, if possible.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.menuUiLinkAutomaticTitle = {
     attach: function (context) {
diff --git a/core/modules/node/content_types.js b/core/modules/node/content_types.js
index c77a2c3..77ab168 100644
--- a/core/modules/node/content_types.js
+++ b/core/modules/node/content_types.js
@@ -7,6 +7,10 @@
 
   "use strict";
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.contentTypes = {
     attach: function (context) {
       var $context = $(context);
diff --git a/core/modules/node/node.js b/core/modules/node/node.js
index cf0f979..af2ed46 100644
--- a/core/modules/node/node.js
+++ b/core/modules/node/node.js
@@ -7,6 +7,10 @@
 
   "use strict";
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.nodeDetailsSummaries = {
     attach: function (context) {
       var $context = $(context);
diff --git a/core/modules/node/node.preview.js b/core/modules/node/node.preview.js
index 09ce7a0..d69cf3b 100644
--- a/core/modules/node/node.preview.js
+++ b/core/modules/node/node.preview.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Preview behaviors.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
@@ -5,6 +10,8 @@
   /**
    * Disabling all links (except local fragment identifiers such as href="#frag")
    * in node previews to prevent users from leaving the page.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.nodePreviewDestroyLinks = {
     attach: function (context) {
@@ -52,6 +59,8 @@
 
   /**
    * Switch view mode.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.nodePreviewSwitchViewMode = {
     attach: function (context) {
@@ -64,6 +73,10 @@
     }
   };
 
+  /**
+   *
+   * @return {string}
+   */
   Drupal.theme.nodePreviewModal = function () {
     return '<p>' +
       Drupal.t('Leaving the preview will cause unsaved changes to be lost. Are you sure you want to leave the preview?') +
diff --git a/core/modules/path/path.js b/core/modules/path/path.js
index aa91bb2..474cf87 100644
--- a/core/modules/path/path.js
+++ b/core/modules/path/path.js
@@ -6,6 +6,10 @@
 
   "use strict";
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.pathDetailsSummaries = {
     attach: function (context) {
       $(context).find('.path-form').drupalSetSummary(function (context) {
diff --git a/core/modules/quickedit/js/editors/formEditor.js b/core/modules/quickedit/js/editors/formEditor.js
index 8dc3fb5..ed20245 100644
--- a/core/modules/quickedit/js/editors/formEditor.js
+++ b/core/modules/quickedit/js/editors/formEditor.js
@@ -7,16 +7,32 @@
 
   "use strict";
 
-  Drupal.quickedit.editors.form = Drupal.quickedit.EditorView.extend({
+  /**
+   * @constructor
+   *
+   * @augments Drupal.quickedit.EditorView
+   */
+  Drupal.quickedit.editors.form = Drupal.quickedit.EditorView.extend(/** @lends Drupal.quickedit.editors.form# */{
 
-    // Tracks the form container DOM element that is used while in-place editing.
+    /**
+     * Tracks the form container DOM element that is used while in-place editing.
+     *
+     * @type {?jQuery}
+     */
     $formContainer: null,
 
-    // Holds the Drupal.ajax object
+    /**
+     * Holds the Drupal.Ajax object.
+     *
+     * @type {Drupal.Ajax}
+     */
     formSaveAjax: null,
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @param {object} fieldModel
+     * @param {string} state
      */
     stateChange: function (fieldModel, state) {
       var from = fieldModel.previous('state');
@@ -24,28 +40,36 @@
       switch (to) {
         case 'inactive':
           break;
+
         case 'candidate':
           if (from !== 'inactive') {
             this.removeForm();
           }
           break;
+
         case 'highlighted':
           break;
+
         case 'activating':
           // If coming from an invalid state, then the form is already loaded.
           if (from !== 'invalid') {
             this.loadForm();
           }
           break;
+
         case 'active':
           break;
+
         case 'changed':
           break;
+
         case 'saving':
           this.save();
           break;
+
         case 'saved':
           break;
+
         case 'invalid':
           this.showValidationErrors();
           break;
@@ -53,7 +77,9 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {object}
      */
     getQuickEditUISettings: function () {
       return {padding: true, unifiedToolbar: true, fullWidthToolbar: true, popup: true};
@@ -155,7 +181,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     save: function () {
       var $formContainer = this.$formContainer;
@@ -213,7 +239,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     showValidationErrors: function () {
       this.$formContainer
diff --git a/core/modules/quickedit/js/editors/plainTextEditor.js b/core/modules/quickedit/js/editors/plainTextEditor.js
index f380a40..98bf4bf 100644
--- a/core/modules/quickedit/js/editors/plainTextEditor.js
+++ b/core/modules/quickedit/js/editors/plainTextEditor.js
@@ -1,19 +1,25 @@
 /**
  * @file
- * contentEditable-based in-place editor for plain text content.
+ * ContentEditable-based in-place editor for plain text content.
  */
 
 (function ($, _, Drupal) {
 
   "use strict";
 
-  Drupal.quickedit.editors.plain_text = Drupal.quickedit.EditorView.extend({
+  Drupal.quickedit.editors.plain_text = Drupal.quickedit.EditorView.extend(/** @lends Drupal.quickedit.editors.plain_text# */{
 
-    // Stores the textual DOM element that is being in-place edited.
+    /**
+     * Stores the textual DOM element that is being in-place edited.
+     */
     $textElement: null,
 
     /**
-     * {@inheritdoc}
+     * @constructs
+     *
+     * @augments Drupal.quickedit.EditorView
+     *
+     * @param {object} options
      */
     initialize: function (options) {
       Drupal.quickedit.EditorView.prototype.initialize.call(this, options);
@@ -32,7 +38,7 @@
       }
       editorModel.set('originalValue', $.trim(this.$textElement.text()));
 
-      // Sets the state to 'changed' whenever the value changes
+      // Sets the state to 'changed' whenever the value changes.
       var previousText = editorModel.get('originalValue');
       $textElement.on('keyup paste', function (event) {
         var currentText = $.trim($textElement.text());
@@ -45,14 +51,20 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {jQuery}
      */
     getEditedElement: function () {
       return this.$textElement;
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @param {object} fieldModel
+     * @param {string} state
+     * @param {object} options
      */
     stateChange: function (fieldModel, state, options) {
       var from = fieldModel.previous('state');
@@ -60,6 +72,7 @@
       switch (to) {
         case 'inactive':
           break;
+
         case 'candidate':
           if (from !== 'inactive') {
             this.$textElement.removeAttr('contenteditable');
@@ -68,8 +81,10 @@
             this.removeValidationErrors();
           }
           break;
+
         case 'highlighted':
           break;
+
         case 'activating':
           // Defer updating the field model until the current state change has
           // propagated, to not trigger a nested state change event.
@@ -77,19 +92,24 @@
             fieldModel.set('state', 'active');
           });
           break;
+
         case 'active':
           this.$textElement.attr('contenteditable', 'true');
           break;
+
         case 'changed':
           break;
+
         case 'saving':
           if (from === 'invalid') {
             this.removeValidationErrors();
           }
           this.save(options);
           break;
+
         case 'saved':
           break;
+
         case 'invalid':
           this.showValidationErrors();
           break;
@@ -97,14 +117,16 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {object}
      */
     getQuickEditUISettings: function () {
       return {padding: true, unifiedToolbar: false, fullWidthToolbar: false, popup: false};
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     revert: function () {
       this.$textElement.html(this.model.get('originalValue'));
diff --git a/core/modules/quickedit/js/models/AppModel.js b/core/modules/quickedit/js/models/AppModel.js
index 1682e7f..a94fecc 100644
--- a/core/modules/quickedit/js/models/AppModel.js
+++ b/core/modules/quickedit/js/models/AppModel.js
@@ -9,18 +9,47 @@
 
   "use strict";
 
-  Drupal.quickedit.AppModel = Backbone.Model.extend({
+  /**
+   * @constructor
+   *
+   * @augments Backbone.Model
+   */
+  Drupal.quickedit.AppModel = Backbone.Model.extend(/** @lends Drupal.quickedit.AppModel# */{
 
-    defaults: {
-      // The currently state = 'highlighted' Drupal.quickedit.FieldModel, if
-      // any.
-      // @see Drupal.quickedit.FieldModel.states
+    /**
+     * @type {object}
+     *
+     * @prop {?Drupal.quickedit.FieldModel} highlightedField
+     * @prop {?Drupal.quickedit.FieldModel} activeField
+     * @prop {?Drupal.dialog~dialogDefinition} activeModal
+     */
+    defaults: /** @lends Drupal.quickedit.AppModel# */{
+
+      /**
+       * The currently state = 'highlighted' Drupal.quickedit.FieldModel, if
+       * any.
+       *
+       * @type {?Drupal.quickedit.FieldModel}
+       *
+       * @see Drupal.quickedit.FieldModel.states
+       */
       highlightedField: null,
-      // The currently state = 'active' Drupal.quickedit.FieldModel, if any.
-      // @see Drupal.quickedit.FieldModel.states
+
+      /**
+       * The currently state = 'active' Drupal.quickedit.FieldModel, if any.
+       *
+       * @type {?Drupal.quickedit.FieldModel}
+       *
+       * @see Drupal.quickedit.FieldModel.states
+       */
       activeField: null,
-      // Reference to a Drupal.dialog instance if a state change requires
-      // confirmation.
+
+      /**
+       * Reference to a Drupal.dialog instance if a state change requires
+       * confirmation.
+       *
+       * @type {?Drupal.dialog~dialogDefinition}
+       */
       activeModal: null
     }
 
diff --git a/core/modules/quickedit/js/models/BaseModel.js b/core/modules/quickedit/js/models/BaseModel.js
index 06112cf..22f6b2f 100644
--- a/core/modules/quickedit/js/models/BaseModel.js
+++ b/core/modules/quickedit/js/models/BaseModel.js
@@ -7,10 +7,16 @@
 
   "use strict";
 
-  Drupal.quickedit.BaseModel = Backbone.Model.extend({
+  Drupal.quickedit.BaseModel = Backbone.Model.extend(/** @lends Drupal.quickedit.BaseModel# */{
 
     /**
-     * {@inheritdoc}
+     * @constructs
+     *
+     * @augments Backbone.Model
+     *
+     * @param {object} options
+     *
+     * @return {Drupal.quickedit.BaseModel}
      */
     initialize: function (options) {
       this.__initialized = true;
@@ -18,7 +24,12 @@
     },
 
     /**
-     * {@inheritdoc}
+     *
+     * @param {object|string} key
+     * @param {*} val
+     * @param {*} [options]
+     *
+     * @return {*}
      */
     set: function (key, val, options) {
       if (this.__initialized) {
diff --git a/core/modules/quickedit/js/models/EditorModel.js b/core/modules/quickedit/js/models/EditorModel.js
index 059b13e..bd2019a 100644
--- a/core/modules/quickedit/js/models/EditorModel.js
+++ b/core/modules/quickedit/js/models/EditorModel.js
@@ -9,16 +9,35 @@
 
   "use strict";
 
-  Drupal.quickedit.EditorModel = Backbone.Model.extend({
+  /**
+   * @constructor
+   *
+   * @augments Backbone.Model
+   */
+  Drupal.quickedit.EditorModel = Backbone.Model.extend(/** @lends Drupal.quickedit.EditorModel# */{
 
-    defaults: {
-      // Not the full HTML representation of this field, but the "actual"
-      // original value of the field, stored by the used in-place editor, and
-      // in a representation that can be chosen by the in-place editor.
+    /**
+     * @prop {?null} originalValue
+     * @prop {?null} currentValue
+     * @prop {?null} validationErrors
+     */
+    defaults: /** @lends Drupal.quickedit.EditorModel# */{
+
+      /**
+       * Not the full HTML representation of this field, but the "actual"
+       * original value of the field, stored by the used in-place editor, and
+       * in a representation that can be chosen by the in-place editor.
+       */
       originalValue: null,
-      // Analogous to originalValue, but the current value.
+
+      /**
+       * Analogous to originalValue, but the current value.
+       */
       currentValue: null,
-      // Stores any validation errors to be rendered.
+
+      /**
+       * Stores any validation errors to be rendered.
+       */
       validationErrors: null
     }
 
diff --git a/core/modules/quickedit/js/models/EntityModel.js b/core/modules/quickedit/js/models/EntityModel.js
index 0760aed..010df9a 100644
--- a/core/modules/quickedit/js/models/EntityModel.js
+++ b/core/modules/quickedit/js/models/EntityModel.js
@@ -7,58 +7,100 @@
 
   "use strict";
 
-  Drupal.quickedit.EntityModel = Drupal.quickedit.BaseModel.extend({
+  Drupal.quickedit.EntityModel = Drupal.quickedit.BaseModel.extend(/** @lends Drupal.quickedit.EntityModel# */{
 
-    defaults: {
-      // The DOM element that represents this entity. It may seem bizarre to
-      // have a DOM element in a Backbone Model, but we need to be able to map
-      // entities in the DOM to EntityModels in memory.
+    /**
+     * @type {object}
+     */
+    defaults: /** @lends Drupal.quickedit.EntityModel# */{
+
+      /**
+       * The DOM element that represents this entity. It may seem bizarre to
+       * have a DOM element in a Backbone Model, but we need to be able to map
+       * entities in the DOM to EntityModels in memory.
+       */
       el: null,
-      // An entity ID, of the form "<entity type>/<entity ID>", e.g. "node/1".
+
+      /**
+       * An entity ID, of the form "<entity type>/<entity ID>", e.g. "node/1".
+       */
       entityID: null,
-      // An entity instance ID. The first instance of a specific entity (i.e. with
-      // a given entity ID) is assigned 0, the second 1, and so on.
+
+      /**
+       * An entity instance ID. The first instance of a specific entity (i.e. with
+       * a given entity ID) is assigned 0, the second 1, and so on.
+       */
       entityInstanceID: null,
-      // The unique ID of this entity instance on the page, of the form "<entity
-      // type>/<entity ID>[entity instance ID]", e.g. "node/1[0]".
+
+      /**
+       * The unique ID of this entity instance on the page, of the form `<entity
+       * type>/<entity ID>[entity instance ID]`, e.g. `node/1[0]`.
+       */
       id: null,
-      // The label of the entity.
+
+      /**
+       * The label of the entity.
+       */
       label: null,
-      // A Drupal.quickedit.FieldCollection for all fields of this entity.
+
+      /**
+       * A Drupal.quickedit.FieldCollection for all fields of this entity.
+       */
       fields: null,
 
       // The attributes below are stateful. The ones above will never change
       // during the life of a EntityModel instance.
-
-      // Indicates whether this instance of this entity is currently being
-      // edited in-place.
+      /**
+       * Indicates whether this instance of this entity is currently being
+       * edited in-place.
+       */
       isActive: false,
-      // Whether one or more fields have already been stored in
-      // PrivateTempStore.
+
+      /**
+       * Whether one or more fields have already been stored in
+       * PrivateTempStore.
+       */
       inTempStore: false,
-      // Whether one or more fields have already been stored in PrivateTempStore
-      // *or* the field that's currently being edited is in the 'changed' or a
-      // later state. In other words, this boolean indicates whether a "Save"
-      // button is necessary or not.
+
+      /**
+       * Whether one or more fields have already been stored in PrivateTempStore
+       * *or* the field that's currently being edited is in the 'changed' or a
+       * later state. In other words, this boolean indicates whether a "Save"
+       * button is necessary or not.
+       */
       isDirty: false,
-      // Whether the request to the server has been made to commit this entity.
-      // Used to prevent multiple such requests.
+
+      /**
+       * Whether the request to the server has been made to commit this entity.
+       * Used to prevent multiple such requests.
+       */
       isCommitting: false,
-      // The current processing state of an entity.
+
+      /**
+       * The current processing state of an entity.
+       */
       state: 'closed',
-      // The IDs of the fields whose new values have been stored in
-      // PrivateTempStore. We must store this on the EntityModel as well (even
-      // though it already is on the FieldModel) because when a field is
-      // rerendered, its FieldModel is destroyed and this allows us to
-      // transition it back to the proper state.
+
+      /**
+       * The IDs of the fields whose new values have been stored in
+       * PrivateTempStore. We must store this on the EntityModel as well (even
+       * though it already is on the FieldModel) because when a field is
+       * rerendered, its FieldModel is destroyed and this allows us to
+       * transition it back to the proper state.
+       */
       fieldsInTempStore: [],
-      // A flag the tells the application that this EntityModel must be reloaded
-      // in order to restore the original values to its fields in the client.
+
+      /**
+       * A flag the tells the application that this EntityModel must be reloaded
+       * in order to restore the original values to its fields in the client.
+       */
       reload: false
     },
 
     /**
-     * {@inheritdoc}
+     * @constructs
+     *
+     * @augments Drupal.quickedit.BaseModel
      */
     initialize: function () {
       this.set('fields', new Drupal.quickedit.FieldCollection());
@@ -77,10 +119,11 @@
     /**
      * Updates FieldModels' states when an EntityModel change occurs.
      *
-     * @param Drupal.quickedit.EntityModel entityModel
-     * @param String state
-     *   The state of the associated entity. One of Drupal.quickedit.EntityModel.states.
-     * @param Object options
+     * @param {Drupal.quickedit.EntityModel} entityModel
+     * @param {string} state
+     *   The state of the associated entity. One of
+     *   {@link Drupal.quickedit.EntityModel.states}.
+     * @param {object} options
      */
     stateChange: function (entityModel, state, options) {
       var to = state;
@@ -195,12 +238,12 @@
      *
      * Helper function.
      *
-     * @param Drupal.quickedit.EntityModel entityModel
+     * @param {Drupal.quickedit.EntityModel} entityModel
      *   The model of the entity for which a field's state attribute has changed.
-     * @param Drupal.quickedit.FieldModel fieldModel
+     * @param {Drupal.quickedit.FieldModel} fieldModel
      *   The model of the field whose state attribute has changed.
      *
-     * @see fieldStateChange()
+     * @see Drupal.quickedit.EntityModel#fieldStateChange
      */
     _updateInTempStoreAttributes: function (entityModel, fieldModel) {
       var current = fieldModel.get('state');
@@ -233,10 +276,11 @@
     /**
      * Reacts to state changes in this entity's fields.
      *
-     * @param Drupal.quickedit.FieldModel fieldModel
+     * @param {Drupal.quickedit.FieldModel} fieldModel
      *   The model of the field whose state attribute changed.
-     * @param String state
-     *   The state of the associated field. One of Drupal.quickedit.FieldModel.states.
+     * @param {string} state
+     *   The state of the associated field. One of
+     *   {@link Drupal.quickedit.FieldModel.states}.
      */
     fieldStateChange: function (fieldModel, state) {
       var entityModel = this;
@@ -354,10 +398,10 @@
     /**
      * Fires an AJAX request to the REST save URL for an entity.
      *
-     * @param options
+     * @param {object} options
      *   An object of options that contains:
-     *     - success: (optional) A function to invoke if the entity is success-
-     *     fully saved.
+     * @param {function} [options.success]
+     *   A function to invoke if the entity is successfully saved.
      */
     save: function (options) {
       var entityModel = this;
@@ -393,19 +437,22 @@
     },
 
     /**
-     * {@inheritdoc}
      *
-     * @param Object attrs
+     * @param {object} attrs
      *   The attributes changes in the save or set call.
-     * @param Object options
+     * @param {object} options
      *   An object with the following option:
-     *     - String reason (optional): a string that conveys a particular reason
-     *       to allow for an exceptional state change.
-     *     - Array accept-field-states (optional) An array of strings that
-     *     represent field states that the entities must be in to validate. For
-     *     example, if accept-field-states is ['candidate', 'highlighted'], then
-     *     all the fields of the entity must be in either of these two states
-     *     for the save or set call to validate and proceed.
+     * @param {string} [options.reason]
+     *   A string that conveys a particular reason to allow for an exceptional
+     *   state change.
+     * @param {Array} options.accept-field-states
+     *   An array of strings that represent field states that the entities must
+     *   be in to validate. For example, if `accept-field-states` is
+     *   `['candidate', 'highlighted']`, then all the fields of the entity must
+     *   be in either of these two states for the save or set call to
+     *   validate and proceed.
+     *
+     * @return {string}
      */
     validate: function (attrs, options) {
       var acceptedFieldStates = options['accept-field-states'] || [];
@@ -444,7 +491,18 @@
       }
     },
 
-    // Like @see AppView.acceptEditorStateChange()
+    /**
+     *
+     * @param {string} from
+     * @param {string} to
+     * @param {object} context
+     * @param {string} context.reason
+     * @param {bool} context.confirming
+     *
+     * @return {bool}
+     *
+     * @see Drupal.quickedit.AppView#acceptEditorStateChange
+     */
     _acceptStateChange: function (from, to, context) {
       var accept = true;
 
@@ -481,9 +539,11 @@
     },
 
     /**
-     * @param Array acceptedFieldStates
-     *   @see validate()
-     * @return Boolean
+     * @param {Array} acceptedFieldStates
+     *
+     * @return {bool}
+     *
+     * @see Drupal.quickedit.EntityModel#validate
      */
     _fieldsHaveAcceptableStates: function (acceptedFieldStates) {
       var accept = true;
@@ -504,7 +564,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @param {object} options
      */
     destroy: function (options) {
       Drupal.quickedit.BaseModel.prototype.destroy.call(this, options);
@@ -518,18 +578,20 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     sync: function () {
       // We don't use REST updates to sync.
       return;
     }
 
-  }, {
+  }, /** @lends Drupal.quickedit.EntityModel */{
 
     /**
      * A list (sequence) of all possible states an entity can be in during
      * in-place editing.
+     *
+     * @enum
      */
     states: [
       // Initial state, like field's 'inactive' OR the user has just finished
@@ -587,11 +649,12 @@
     /**
      * Indicates whether the 'from' state comes before the 'to' state.
      *
-     * @param String from
+     * @param {string} from
      *   One of Drupal.quickedit.EntityModel.states.
-     * @param String to
+     * @param {string} to
      *   One of Drupal.quickedit.EntityModel.states.
-     * @return Boolean
+     *
+     * @return {bool}
      */
     followsStateSequence: function (from, to) {
       return _.indexOf(this.states, from) < _.indexOf(this.states, to);
@@ -599,7 +662,16 @@
 
   });
 
-  Drupal.quickedit.EntityCollection = Backbone.Collection.extend({
+  /**
+   * @constructor
+   *
+   * @augments Backbone.Collection
+   */
+  Drupal.quickedit.EntityCollection = Backbone.Collection.extend(/** @lends Drupal.quickedit.EntityCollection# */{
+
+    /**
+     * @type {Drupal.quickedit.EntityModel}
+     */
     model: Drupal.quickedit.EntityModel
   });
 
diff --git a/core/modules/quickedit/js/models/FieldModel.js b/core/modules/quickedit/js/models/FieldModel.js
index 6bd4e44..43fadab 100644
--- a/core/modules/quickedit/js/models/FieldModel.js
+++ b/core/modules/quickedit/js/models/FieldModel.js
@@ -7,62 +7,112 @@
 
   "use strict";
 
-  /**
-   * State of an in-place editable field in the DOM.
-   */
-  Drupal.quickedit.FieldModel = Drupal.quickedit.BaseModel.extend({
+  Drupal.quickedit.FieldModel = Drupal.quickedit.BaseModel.extend(/** @lends Drupal.quickedit.FieldModel# */{
+
+    /**
+     * @type {object}
+     */
+    defaults: /** @lends Drupal.quickedit.FieldModel# */{
 
-    defaults: {
-      // The DOM element that represents this field. It may seem bizarre to have
-      // a DOM element in a Backbone Model, but we need to be able to map fields
-      // in the DOM to FieldModels in memory.
+      /**
+       * The DOM element that represents this field. It may seem bizarre to have
+       * a DOM element in a Backbone Model, but we need to be able to map fields
+       * in the DOM to FieldModels in memory.
+       */
       el: null,
-      // A field ID, of the form
-      // "<entity type>/<id>/<field name>/<language>/<view mode>", e.g.
-      // "node/1/field_tags/und/full".
+
+      /**
+       * A field ID, of the form
+       * `<entity type>/<id>/<field name>/<language>/<view mode>`
+       *
+       * @example
+       * "node/1/field_tags/und/full"
+       */
       fieldID: null,
-      // The unique ID of this field within its entity instance on the page, of
-      // the form "<entity type>/<id>/<field name>/<language>/<view mode>[entity instance ID]",
-      // e.g. "node/1/field_tags/und/full[0]".
+
+      /**
+       * The unique ID of this field within its entity instance on the page, of
+       * the form `<entity type>/<id>/<field name>/<language>/<view
+       * mode>[entity instance ID]`.
+       *
+       * @example
+       * "node/1/field_tags/und/full[0]"
+       */
       id: null,
-      // A Drupal.quickedit.EntityModel. Its "fields" attribute, which is a
-      // FieldCollection, is automatically updated to include this FieldModel.
+
+      /**
+       * A Drupal.quickedit.EntityModel. Its "fields" attribute, which is a
+       * FieldCollection, is automatically updated to include this FieldModel.
+       */
       entity: null,
-      // This field's metadata as returned by the QuickEditController::metadata().
+
+      /**
+       * This field's metadata as returned by the
+       * QuickEditController::metadata().
+       */
       metadata: null,
-      // Callback function for validating changes between states. Receives the
-      // previous state, new state, context, and a callback
+
+      /**
+       * Callback function for validating changes between states. Receives the
+       * previous state, new state, context, and a callback.
+       */
       acceptStateChange: null,
-      // A logical field ID, of the form
-      // "<entity type>/<id>/<field name>/<language>", i.e. the fieldID without
-      // the view mode, to be able to identify other instances of the same field
-      // on the page but rendered in a different view mode. e.g. "node/1/field_tags/und".
+
+      /**
+       * A logical field ID, of the form
+       * `<entity type>/<id>/<field name>/<language>`, i.e. the fieldID without
+       * the view mode, to be able to identify other instances of the same
+       * field on the page but rendered in a different view mode.
+       *
+       * @example
+       * "node/1/field_tags/und".
+       */
       logicalFieldID: null,
 
       // The attributes below are stateful. The ones above will never change
       // during the life of a FieldModel instance.
 
-      // In-place editing state of this field. Defaults to the initial state.
-      // Possible values: @see Drupal.quickedit.FieldModel.states.
+      /**
+       * In-place editing state of this field. Defaults to the initial state.
+       * Possible values: @see Drupal.quickedit.FieldModel.states.
+       */
       state: 'inactive',
-      // The field is currently in the 'changed' state or one of the following
-      // states in which the field is still changed.
+
+      /**
+       * The field is currently in the 'changed' state or one of the following
+       * states in which the field is still changed.
+       */
       isChanged: false,
-      // Is tracked by the EntityModel, is mirrored here solely for decorative
-      // purposes: so that FieldDecorationView.renderChanged() can react to it.
+
+      /**
+       * Is tracked by the EntityModel, is mirrored here solely for decorative
+       * purposes: so that FieldDecorationView.renderChanged() can react to it.
+       */
       inTempStore: false,
-      // The full HTML representation of this field (with the element that has
-      // the data-quickedit-field-id as the outer element). Used to propagate
-      // changes from this field to other instances of the same field storage.
+
+      /**
+       * The full HTML representation of this field (with the element that has
+       * the data-quickedit-field-id as the outer element). Used to propagate
+       * changes from this field to other instances of the same field storage.
+       */
       html: null,
-      // An object containing the full HTML representations (values) of other view
-      // modes (keys) of this field, for other instances of this field displayed
-      // in a different view mode.
+
+      /**
+       * An object containing the full HTML representations (values) of other
+       * view modes (keys) of this field, for other instances of this field
+       * displayed in a different view mode.
+       */
       htmlForOtherViewModes: null
     },
 
     /**
-     * {@inheritdoc}
+     * State of an in-place editable field in the DOM.
+     *
+     * @constructs
+     *
+     * @augments Drupal.quickedit.BaseModel
+     *
+     * @param {object} options
      */
     initialize: function (options) {
       // Store the original full HTML representation of this field.
@@ -79,7 +129,8 @@
     },
 
     /**
-     * {@inheritdoc}
+     *
+     * @param {object} options
      */
     destroy: function (options) {
       if (this.get('state') !== 'inactive') {
@@ -89,7 +140,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     sync: function () {
       // We don't use REST updates to sync.
@@ -97,7 +148,22 @@
     },
 
     /**
-     * {@inheritdoc}
+     *
+     * @param {object} attrs
+     *   The attributes changes in the save or set call.
+     * @param {object} options
+     *   An object with the following option:
+     * @param {string} [options.reason]
+     *   A string that conveys a particular reason to allow for an exceptional
+     *   state change.
+     * @param {Array} options.accept-field-states
+     *   An array of strings that represent field states that the entities must
+     *   be in to validate. For example, if `accept-field-states` is
+     *   `['candidate', 'highlighted']`, then all the fields of the entity must
+     *   be in either of these two states for the save or set call to
+     *   validate and proceed.
+     *
+     * @return {string}
      */
     validate: function (attrs, options) {
       var current = this.get('state');
@@ -117,7 +183,7 @@
     /**
      * Extracts the entity ID from this field's ID.
      *
-     * @return String
+     * @return {string}
      *   An entity ID: a string of the format `<entity type>/<id>`.
      */
     getEntityID: function () {
@@ -127,7 +193,7 @@
     /**
      * Extracts the view mode ID from this field's ID.
      *
-     * @return String
+     * @return {string}
      *   A view mode ID.
      */
     getViewMode: function () {
@@ -137,16 +203,16 @@
     /**
      * Find other instances of this field with different view modes.
      *
-     * @return Array
+     * @return {Array}
      *   An array containing view mode IDs.
      */
     findOtherViewModes: function () {
       var currentField = this;
       var otherViewModes = [];
       Drupal.quickedit.collections.fields
-        // Find all instances of fields that display the same logical field (same
-        // entity, same field, just a different instance and maybe a different
-        // view mode).
+        // Find all instances of fields that display the same logical field
+        // (same entity, same field, just a different instance and maybe a
+        // different view mode).
         .where({logicalFieldID: currentField.get('logicalFieldID')})
         .forEach(function (field) {
           // Ignore the current field.
@@ -164,11 +230,13 @@
       return otherViewModes;
     }
 
-  }, {
+  }, /** @lends Drupal.quickedit.FieldModel */{
 
     /**
-     * A list (sequence) of all possible states a field can be in during in-place
-     * editing.
+     * A list (sequence) of all possible states a field can be in during
+     * in-place editing.
+     *
+     * @enum
      */
     states: [
       // The field associated with this FieldModel is linked to an EntityModel;
@@ -178,13 +246,14 @@
       // This is both the initial (not yet in-place editing) and the end state (
       // finished in-place editing).
       'inactive',
-      // The user is in-place editing this entity, and this field is a candidate
+      // The user is in-place editing this entity, and this field is a
+      // candidate
       // for in-place editing. In-place editor should not
       // - Trigger: user.
-      // - Guarantees: entity is ready, in-place editor (EditorView) is associated
-      //   with the field.
-      // - Expected behavior: visual indicators around the field indicate it is
-      //   available for in-place editing, no in-place editor presented yet.
+      // - Guarantees: entity is ready, in-place editor (EditorView) is
+      // associated with the field. - Expected behavior: visual indicators
+      // around the field indicate it is available for in-place editing, no
+      // in-place editor presented yet.
       'candidate',
       // User is highlighting this field.
       // - Trigger: user.
@@ -192,13 +261,12 @@
       // - Expected behavior: visual indicators to convey highlighting, in-place
       //   editing toolbar shows field's label.
       'highlighted',
-      // User has activated the in-place editing of this field; in-place editor is
-      // activating.
-      // - Trigger: user.
-      // - Guarantees: see 'candidate'.
-      // - Expected behavior: loading indicator, in-place editor is loading remote
-      //   data (e.g. retrieve form from back-end). Upon retrieval of remote data,
-      //   the in-place editor transitions the field's state to 'active'.
+      // User has activated the in-place editing of this field; in-place editor
+      // is activating. - Trigger: user. - Guarantees: see 'candidate'. -
+      // Expected behavior: loading indicator, in-place editor is loading
+      // remote data (e.g. retrieve form from back-end). Upon retrieval of
+      // remote data, the in-place editor transitions the field's state to
+      // 'active'.
       'activating',
       // In-place editor has finished loading remote data; ready for use.
       // - Trigger: in-place editor.
@@ -224,11 +292,12 @@
       // - Trigger: in-place editor.
       // - Guarantees: see 'candidate' and 'active'.
       // - Expected behavior: transition back to 'candidate' state because the
-      //   deed is done. Then: 1) transition to 'inactive' to allow the field to
-      //   be rerendered, 2) destroy the FieldModel (which also destroys attached
-      //   views like the EditorView), 3) replace the existing field HTML with the
-      //   existing HTML and 4) attach behaviors again so that the field becomes
-      //   available again for in-place editing.
+      //   deed is done. Then: 1) transition to 'inactive' to allow the field
+      // to
+      //   be rerendered, 2) destroy the FieldModel (which also destroys
+      // attached views like the EditorView), 3) replace the existing field
+      // HTML with the existing HTML and 4) attach behaviors again so that the
+      // field becomes available again for in-place editing.
       'saved',
       // In-place editor has failed to saved the changed field: there were
       // validation errors.
@@ -242,11 +311,12 @@
     /**
      * Indicates whether the 'from' state comes before the 'to' state.
      *
-     * @param String from
-     *   One of Drupal.quickedit.FieldModel.states.
-     * @param String to
-     *   One of Drupal.quickedit.FieldModel.states.
-     * @return Boolean
+     * @param {string} from
+     *   One of {@link Drupal.quickedit.FieldModel.states}.
+     * @param {string} to
+     *   One of {@link Drupal.quickedit.FieldModel.states}.
+     *
+     * @return {bool}
      */
     followsStateSequence: function (from, to) {
       return _.indexOf(this.states, from) < _.indexOf(this.states, to);
@@ -254,7 +324,16 @@
 
   });
 
-  Drupal.quickedit.FieldCollection = Backbone.Collection.extend({
+  /**
+   * @constructor
+   *
+   * @augments Backbone.Collection
+   */
+  Drupal.quickedit.FieldCollection = Backbone.Collection.extend(/** @lends Drupal.quickedit.FieldCollection */{
+
+    /**
+     * @type {Drupal.quickedit.FieldModel}
+     */
     model: Drupal.quickedit.FieldModel
   });
 
diff --git a/core/modules/quickedit/js/quickedit.js b/core/modules/quickedit/js/quickedit.js
index 7dcb6cb..539fa56 100644
--- a/core/modules/quickedit/js/quickedit.js
+++ b/core/modules/quickedit/js/quickedit.js
@@ -5,7 +5,7 @@
  * Everything happens asynchronously, to allow for:
  *   - dynamically rendered contextual links
  *   - asynchronously retrieved (and cached) per-field in-place editing metadata
- *   - asynchronous setup of in-place editable field and "Quick edit" link
+ *   - asynchronous setup of in-place editable field and "Quick edit" link.
  *
  * To achieve this, there are several queues:
  *   - fieldsMetadataQueue: fields whose metadata still needs to be fetched.
@@ -63,6 +63,10 @@
    */
   var entityInstancesTracker = {};
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.quickedit = {
     attach: function (context) {
       // Initialize the Quick Edit app once per page load.
@@ -114,10 +118,21 @@
     }
   };
 
+  /**
+   *
+   * @namespace
+   */
   Drupal.quickedit = {
-    // A Drupal.quickedit.AppView instance.
+
+    /**
+     * A {@link Drupal.quickedit.AppView} instance.
+     */
     app: null,
 
+    /**
+     * @prop {Array.<Drupal.quickedit.EntityModel>} entities
+     * @prop {Array.<Drupal.quickedit.FieldModel>} fields
+     */
     collections: {
       // All in-place editable entities (Drupal.quickedit.EntityModel) on the
       // page.
@@ -126,29 +141,77 @@
       fields: null
     },
 
-    // In-place editors will register themselves in this object.
+    /**
+     * In-place editors will register themselves in this object.
+     *
+     * @namespace
+     */
     editors: {},
 
-    // Per-field metadata that indicates whether in-place editing is allowed,
-    // which in-place editor should be used, etc.
+    /**
+     * Per-field metadata that indicates whether in-place editing is allowed,
+     * which in-place editor should be used, etc.
+     *
+     * @namespace
+     */
     metadata: {
+      /**
+       *
+       * @param {string} fieldID
+       *
+       * @return {bool}
+       */
       has: function (fieldID) {
         return storage.getItem(this._prefixFieldID(fieldID)) !== null;
       },
+
+      /**
+       *
+       * @param {string} fieldID
+       * @param {object} metadata
+       */
       add: function (fieldID, metadata) {
         storage.setItem(this._prefixFieldID(fieldID), JSON.stringify(metadata));
       },
+
+      /**
+       *
+       * @param {string} fieldID
+       * @param {string} [key]
+       * @return {object|*}
+       */
       get: function (fieldID, key) {
         var metadata = JSON.parse(storage.getItem(this._prefixFieldID(fieldID)));
         return (typeof key === 'undefined') ? metadata : metadata[key];
       },
+
+      /**
+       *
+       * @param {string} fieldID
+       *
+       * @return {string}
+       */
       _prefixFieldID: function (fieldID) {
         return 'Drupal.quickedit.metadata.' + fieldID;
       },
+
+      /**
+       *
+       * @param {string} fieldID
+       *
+       * @return {string}
+       */
       _unprefixFieldID: function (fieldID) {
         // Strip "Drupal.quickedit.metadata.", which is 26 characters long.
         return fieldID.substring(26);
       },
+
+      /**
+       *
+       * @param {string} fieldIDs
+       *
+       * @return {Array}
+       */
       intersection: function (fieldIDs) {
         var prefixedFieldIDs = _.map(fieldIDs, this._prefixFieldID);
         var intersection = _.intersection(prefixedFieldIDs, _.keys(sessionStorage));
@@ -176,6 +239,11 @@
   /**
    * Detect contextual links on entities annotated by Quick Edit; queue these to
    * be processed.
+   *
+   * @param {jQuery.Event} event
+   * @param {object} data
+   *
+   * @listens event:drupalContextualLinkAdded
    */
   $(document).on('drupalContextualLinkAdded', function (event, data) {
     if (data.$region.is('[data-quickedit-entity-id]')) {
@@ -201,10 +269,11 @@
   /**
    * Extracts the entity ID from a field ID.
    *
-   * @param String fieldID
+   * @param {string} fieldID
    *   A field ID: a string of the format
    *   `<entity type>/<id>/<field name>/<language>/<view mode>`.
-   * @return String
+   *
+   * @return {string}
    *   An entity ID: a string of the format `<entity type>/<id>`.
    */
   function extractEntityID(fieldID) {
@@ -214,7 +283,7 @@
   /**
    * Initialize the Quick Edit app.
    *
-   * @param DOM bodyElement
+   * @param {HTMLElement} bodyElement
    *   This document's body element.
    */
   function initQuickEdit(bodyElement) {
@@ -234,7 +303,7 @@
   /**
    * Assigns the entity an instance ID.
    *
-   * @param DOM entityElement.
+   * @param {HTMLElement} entityElement
    *   A Drupal Entity API entity's DOM element with a data-quickedit-entity-id
    *   attribute.
    */
@@ -255,7 +324,7 @@
   /**
    * Fetch the field's metadata; queue or initialize it (if EntityModel exists).
    *
-   * @param DOM fieldElement
+   * @param {HTMLElement} fieldElement
    *   A Drupal Field API field's DOM element with a data-quickedit-field-id
    *   attribute.
    */
@@ -308,13 +377,13 @@
   /**
    * Initialize a field; create FieldModel.
    *
-   * @param DOM fieldElement
+   * @param {HTMLElement} fieldElement
    *   The field's DOM element.
-   * @param String fieldID
+   * @param {string} fieldID
    *   The field's ID.
-   * @param String entityID
+   * @param {string} entityID
    *   The field's entity's ID.
-   * @param String entityInstanceID
+   * @param {string} entityInstanceID
    *   The field's entity's instance ID.
    */
   function initializeField(fieldElement, fieldID, entityID, entityInstanceID) {
@@ -344,7 +413,7 @@
    *
    * Fields whose metadata is missing are tracked at fieldsMetadataQueue.
    *
-   * @param Function callback
+   * @param {function} callback
    *   A callback function that receives field elements whose metadata will just
    *   have been fetched.
    */
@@ -381,9 +450,9 @@
    * Loads missing in-place editor's attachments (JavaScript and CSS files).
    *
    * Missing in-place editors are those whose fields are actively being used on
-   * the page but don't have
+   * the page but don't have.
    *
-   * @param Function callback
+   * @param {function} callback
    *   Callback function to be called when the missing in-place editors (if any)
    *   have been inserted into the DOM. i.e. they may still be loading.
    */
@@ -429,7 +498,7 @@
   /**
    * Attempts to set up a "Quick edit" link and corresponding EntityModel.
    *
-   * @param Object contextualLink
+   * @param {object} contextualLink
    *   An object with the following properties:
    *     - String entityID: a Quick Edit entity identifier, e.g. "node/1" or
    *       "block_content/5".
@@ -438,13 +507,13 @@
    *       instance of this entity).
    *     - DOM el: element pointing to the contextual links placeholder for this
    *       entity.
-   *     - DOM region: element pointing to the contextual region for this entity.
-   * @return Boolean
+   *     - DOM region: element pointing to the contextual region of this entity.
+   *
+   * @return {bool}
    *   Returns true when a contextual the given contextual link metadata can be
-   *   removed from the queue (either because the contextual link has been set up
-   *   or because it is certain that in-place editing is not allowed for any of
-   *   its fields).
-   *   Returns false otherwise.
+   *   removed from the queue (either because the contextual link has been set
+   *   up or because it is certain that in-place editing is not allowed for any
+   *   of its fields). Returns false otherwise.
    */
   function initializeEntityContextualLink(contextualLink) {
     var metadata = Drupal.quickedit.metadata;
@@ -540,7 +609,7 @@
    *
    * Note: this will not delete an entity that is actively being in-place edited.
    *
-   * @param jQuery $context
+   * @param {jQuery} $context
    *   The context within which to delete.
    */
   function deleteContainedModelsAndQueues($context) {
diff --git a/core/modules/quickedit/js/theme.js b/core/modules/quickedit/js/theme.js
index a6d1d91..94af0d9 100644
--- a/core/modules/quickedit/js/theme.js
+++ b/core/modules/quickedit/js/theme.js
@@ -10,10 +10,11 @@
   /**
    * Theme function for a "backstage" for the Quick Edit module.
    *
-   * @param Object settings
-   *   An object with the following keys:
-   *   - String id: the id to apply to the backstage.
-   * @return String
+   * @param {object} settings
+   * @param {string} settings.id
+   *   the id to apply to the backstage.
+   *
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.quickeditBackstage = function (settings) {
@@ -25,10 +26,11 @@
   /**
    * Theme function for a toolbar container of the Quick Edit module.
    *
-   * @param Object settings
-   *   An object with the following keys:
-   *   - String id: the id to apply to the toolbar container.
-   * @return String
+   * @param {object} settings
+   * @param {string} settings.id
+   *   the id to apply to the backstage.
+   *
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.quickeditEntityToolbar = function (settings) {
@@ -47,11 +49,13 @@
   /**
    * Theme function for a toolbar container of the Quick Edit module.
    *
-   * @param Object settings
-   *   An object with the following keys:
-   *   - String entityLabel: The title of the active entity.
-   *   - String fieldLabel: The label of the highlighted or active field.
-   * @return String
+   * @param {object} settings
+   * @param {string} settings.entityLabel
+   *   The title of the active entity.
+   * @param {string} settings.fieldLabel
+   *   The label of the highlighted or active field.
+   *
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.quickeditEntityToolbarLabel = function (settings) {
@@ -61,7 +65,7 @@
   /**
    * Element that defines a containing box of the placement of the entity toolbar.
    *
-   * @return String
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.quickeditEntityToolbarFence = function () {
@@ -71,10 +75,11 @@
   /**
    * Theme function for a toolbar container of the Quick Edit module.
    *
-   * @param settings
-   *   An object with the following keys:
-   *   - id: the id to apply to the toolbar container.
-   * @return
+   * @param {object} settings
+   * @param {string} settings.id
+   *   The id to apply to the toolbar container.
+   *
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.quickeditFieldToolbar = function (settings) {
@@ -84,12 +89,15 @@
   /**
    * Theme function for a toolbar toolgroup of the Quick Edit module.
    *
-   * @param Object settings
-   *   An object with the following keys:
-   *   - String id: (optional) the id of the toolgroup
-   *   - String classes: the class of the toolgroup.
-   *   - Array buttons: @see Drupal.theme.quickeditButtons().
-   * @return String
+   * @param {object} settings
+   * @param {string} [settings.id]
+   *   The id of the toolgroup.
+   * @param {string} settings.classes
+   *   The class of the toolgroup.
+   * @param {Array} settings.buttons
+   *   See {@link Drupal.theme.quickeditButtons}.
+   *
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.quickeditToolgroup = function (settings) {
@@ -112,13 +120,13 @@
    *
    * Can be used for the buttons both in the toolbar toolgroups and in the modal.
    *
-   * @param Object settings
-   *   An object with the following keys:
-   *   - buttons: an array of objects with the following keys:
-   *     - String type: the type of the button (defaults to 'button')
-   *     - Array classes: the classes of the button.
-   *     - String label: the label of the button.
-   * @return String
+   * @param {object} settings
+   * @param {Array} settings.buttons
+   * - String type: the type of the button (defaults to 'button')
+   * - Array classes: the classes of the button.
+   * - String label: the label of the button.
+   *
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.quickeditButtons = function (settings) {
@@ -146,11 +154,13 @@
   /**
    * Theme function for a form container of the Quick Edit module.
    *
-   * @param Object settings
-   *   An object with the following keys:
-   *   - String id: the id to apply to the toolbar container.
-   *   - String loadingMsg: The message to show while loading.
-   * @return String
+   * @param {object} settings
+   * @param {string} settings.id
+   *   The id to apply to the toolbar container.
+   * @param {string} settings.loadingMsg
+   *   The message to show while loading.
+   *
+   * @return {string}
    *   The corresponding HTML.
    */
   Drupal.theme.quickeditFormContainer = function (settings) {
diff --git a/core/modules/quickedit/js/util.js b/core/modules/quickedit/js/util.js
index e8a9643..a8bda3c 100644
--- a/core/modules/quickedit/js/util.js
+++ b/core/modules/quickedit/js/util.js
@@ -7,19 +7,37 @@
 
   "use strict";
 
+  /**
+   * @namespace
+   */
   Drupal.quickedit.util = Drupal.quickedit.util || {};
 
+  /**
+   * @namespace
+   */
   Drupal.quickedit.util.constants = {};
+
+  /**
+   *
+   * @type {string}
+   */
   Drupal.quickedit.util.constants.transitionEnd = "transitionEnd.quickedit webkitTransitionEnd.quickedit transitionend.quickedit msTransitionEnd.quickedit oTransitionEnd.quickedit";
 
   /**
    * Converts a field id into a formatted url path.
    *
-   * @param String id
-   *   The id of an editable field. For example, 'node/1/body/und/full'.
-   * @param String urlFormat
-   *   The Controller route for field processing. For example,
-   *   '/quickedit/form/!entity_type/!id/!field_name/!langcode/!view_mode'.
+   * @example
+   * Drupal.quickedit.util.buildUrl(
+   *   'node/1/body/und/full',
+   *   '/quickedit/form/!entity_type/!id/!field_name/!langcode/!view_mode'
+   * );
+   *
+   * @param {string} id
+   *   The id of an editable field.
+   * @param {string} urlFormat
+   *   The Controller route for field processing.
+   *
+   * @return {string}
    */
   Drupal.quickedit.util.buildUrl = function (id, urlFormat) {
     var parts = id.split('/');
@@ -35,9 +53,9 @@
   /**
    * Shows a network error modal dialog.
    *
-   * @param String title
+   * @param {string} title
    *   The title to use in the modal dialog.
-   * @param String message
+   * @param {string} message
    *   The message to use in the modal dialog.
    */
   Drupal.quickedit.util.networkErrorModal = function (title, message) {
@@ -65,6 +83,9 @@
     networkErrorModal.showModal();
   };
 
+  /**
+   * @namespace
+   */
   Drupal.quickedit.util.form = {
 
     /**
@@ -73,20 +94,23 @@
      * Leverages Drupal.ajax' ability to have scoped (per-instance) command
      * implementations to be able to call a callback.
      *
-     * @param Object options
+     * @param {object} options
      *   An object with the following keys:
-     *    - jQuery $el: (required) DOM element necessary for Drupal.ajax to
-     *      perform AJAX commands.
-     *    - String fieldID: (required) the field ID that uniquely identifies the
-     *      field for which this form will be loaded.
-     *    - Boolean nocssjs: (required) boolean indicating whether no CSS and JS
-     *      should be returned (necessary when the form is invisible to the user).
-     *    - Boolean reset: (required) boolean indicating whether the data stored
-     *      for this field's entity in PrivateTempStore should be used or reset.
-     * @param Function callback
-     *   A callback function that will receive the form to be inserted, as well as
-     *   the ajax object, necessary if the callback wants to perform other AJAX
-     *   commands.
+     * @param {jQuery} options.$el
+     *   DOM element necessary for Drupal.ajax to perform AJAX commands.
+     * @param {string} options.fieldID
+     *   The field ID that uniquely identifies the field for which this form
+     *   will be loaded.
+     * @param {bool} options.nocssjs
+     *   Boolean indicating whether no CSS and JS should be returned (necessary
+     *   when the form is invisible to the user).
+     * @param {bool} options.reset
+     *   Boolean indicating whether the data stored for this field's entity in
+     *   PrivateTempStore should be used or reset.
+     * @param {function} callback
+     *   A callback function that will receive the form to be inserted, as well
+     *   as the ajax object, necessary if the callback wants to perform other
+     *   Ajax commands.
      */
     load: function (options, callback) {
       var fieldID = options.fieldID;
@@ -115,20 +139,24 @@
         callback(response.data, ajax);
         Drupal.ajax.instances[this.instanceIndex] = null;
       };
-      // This will ensure our scoped quickeditFieldForm AJAX command gets called.
+      // This will ensure our scoped quickeditFieldForm AJAX command gets
+      // called.
       formLoaderAjax.execute();
     },
 
     /**
      * Creates a Drupal.ajax instance that is used to save a form.
      *
-     * @param Object options
-     *   An object with the following keys:
-     *    - nocssjs: (required) boolean indicating whether no CSS and JS should be
-     *      returned (necessary when the form is invisible to the user).
-     *    - other_view_modes: (required) array containing view mode IDs (of other
-     *      instances of this field on the page).
-     * @return Drupal.ajax
+     * @param {object} options
+     * @param {bool} options.nocssjs
+     *   Boolean indicating whether no CSS and JS should be returned (necessary
+     *   when the form is invisible to the user).
+     * @param {Array.<string>} options.other_view_modes
+     *   Array containing view mode IDs (of other instances of this field on the
+     *   page).
+     * @param {jQuery} $submit
+     *
+     * @return {Drupal.Ajax}
      *   A Drupal.ajax instance.
      */
     ajaxifySaving: function (options, $submit) {
@@ -144,6 +172,11 @@
         },
         // Reimplement the success handler to ensure Drupal.attachBehaviors() does
         // not get called on the form.
+
+        /**
+         * @param {Drupal.AjaxCommands~commandDefinition} response
+         * @param {number} [status]
+         */
         success: function (response, status) {
           for (var i in response) {
             if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) {
@@ -161,9 +194,9 @@
     /**
      * Cleans up the Drupal.ajax instance that is used to save the form.
      *
-     * @param Drupal.ajax ajax
-     *   A Drupal.ajax instance that was returned by
-     *   Drupal.quickedit.form.ajaxifySaving().
+     * @param {Drupal.Ajax} ajax
+     *   A Drupal.Ajax instance that was returned by
+     *   {@link Drupal.quickedit.form.ajaxifySaving}.
      */
     unajaxifySaving: function (ajax) {
       $(ajax.element).off('click.quickedit');
diff --git a/core/modules/quickedit/js/views/AppView.js b/core/modules/quickedit/js/views/AppView.js
index 767aa16..514e301 100644
--- a/core/modules/quickedit/js/views/AppView.js
+++ b/core/modules/quickedit/js/views/AppView.js
@@ -18,16 +18,21 @@
   // the original HTML.
   var reload = false;
 
-  Drupal.quickedit.AppView = Backbone.View.extend({
+  Drupal.quickedit.AppView = Backbone.View.extend(/** @lends Drupal.quickedit.AppView# */{
 
     /**
-     * {@inheritdoc}
+     * @constructs
      *
-     * @param Object options
+     * @augments Backbone.View
+     *
+     * @param {object} options
      *   An object with the following keys:
-     *   - Drupal.quickedit.AppModel model: the application state model
-     *   - Drupal.quickedit.EntityCollection entitiesCollection: all on-page entities
-     *   - Drupal.quickedit.FieldCollection fieldsCollection: all on-page fields
+     * @param {Drupal.quickedit.AppModel} options.model
+     *   The application state model.
+     * @param {Drupal.quickedit.EntityCollection} options.entitiesCollection
+     *   All on-page entities.
+     * @param {Drupal.quickedit.FieldCollection} options.fieldsCollection
+     *   All on-page fields
      */
     initialize: function (options) {
       // AppView's configuration for handling states.
@@ -57,10 +62,11 @@
     /**
      * Handles setup/teardown and state changes when the active entity changes.
      *
-     * @param Drupal.quickedit.EntityModel entityModel
+     * @param {Drupal.quickedit.EntityModel} entityModel
      *   An instance of the EntityModel class.
-     * @param String state
-     *   The state of the associated field. One of Drupal.quickedit.EntityModel.states.
+     * @param {string} state
+     *   The state of the associated field. One of
+     *   {@link Drupal.quickedit.EntityModel.states}.
      */
     appStateChange: function (entityModel, state) {
       var app = this;
@@ -86,6 +92,7 @@
             entityModel.set('state', 'opening');
           });
           break;
+
         case 'closed':
           entityToolbarView = entityModel.toolbarView;
           // First, tear down the in-place editors.
@@ -112,14 +119,16 @@
      *
      * This is what ensures that the app is in control of what happens.
      *
-     * @param String from
+     * @param {string} from
      *   The previous state.
-     * @param String to
+     * @param {string} to
      *   The new state.
-     * @param null|Object context
+     * @param {null|object} context
      *   The context that is trying to trigger the state change.
-     * @param Drupal.quickedit.FieldModel fieldModel
+     * @param {Drupal.quickedit.FieldModel} fieldModel
      *   The fieldModel to which this change applies.
+     *
+     * @return {bool}
      */
     acceptEditorStateChange: function (from, to, context, fieldModel) {
       var accept = true;
@@ -244,7 +253,7 @@
      *
      * Must happen before the fieldModel's state is changed to 'candidate'.
      *
-     * @param Drupal.quickedit.FieldModel fieldModel
+     * @param {Drupal.quickedit.FieldModel} fieldModel
      *   The field for which an in-place editor must be set up.
      */
     setupEditor: function (fieldModel) {
@@ -293,7 +302,7 @@
      *
      * Must happen after the fieldModel's state is changed to 'inactive'.
      *
-     * @param Drupal.quickedit.FieldModel fieldModel
+     * @param {Drupal.quickedit.FieldModel} fieldModel
      *   The field for which an in-place editor must be torn down.
      */
     teardownEditor: function (fieldModel) {
@@ -320,7 +329,9 @@
     /**
      * Asks the user to confirm whether he wants to stop editing via a modal.
      *
-     * @see acceptEditorStateChange()
+     * @param {Drupal.quickedit.EntityModel} entityModel
+     *
+     * @see Drupal.quickedit.AppView#acceptEditorStateChange
      */
     confirmEntityDeactivation: function (entityModel) {
       var that = this;
@@ -391,9 +402,10 @@
     /**
      * Reacts to field state changes; tracks global state.
      *
-     * @param Drupal.quickedit.FieldModel fieldModel
-     * @param String state
-     *   The state of the associated field. One of Drupal.quickedit.FieldModel.states.
+     * @param {Drupal.quickedit.FieldModel} fieldModel
+     * @param {string} state
+     *   The state of the associated field. One of
+     *   {@link Drupal.quickedit.FieldModel.states}.
      */
     editorStateChange: function (fieldModel, state) {
       var from = fieldModel.previous('state');
@@ -423,15 +435,15 @@
     /**
      * Render an updated field (a field whose 'html' attribute changed).
      *
-     * @param Drupal.quickedit.FieldModel fieldModel
+     * @param {Drupal.quickedit.FieldModel} fieldModel
      *   The FieldModel whose 'html' attribute changed.
-     * @param String html
+     * @param {string} html
      *   The updated 'html' attribute.
-     * @param Object options
+     * @param {object} options
      *   An object with the following keys:
-     *   - Boolean propagation: whether this change to the 'html' attribute
-     *     occurred because of the propagation of changes to another instance of
-     *     this field.
+     * @param {bool} options.propagation
+     *   Whether this change to the 'html' attribute occurred because of the
+     *   propagation of changes to another instance of this field.
      */
     renderUpdatedField: function (fieldModel, html, options) {
       // Get data necessary to rerender property before it is unavailable.
@@ -485,17 +497,17 @@
     /**
      * Propagates the changes to an updated field to all instances of that field.
      *
-     * @param Drupal.quickedit.FieldModel updatedField
+     * @param {Drupal.quickedit.FieldModel} updatedField
      *   The FieldModel whose 'html' attribute changed.
-     * @param String html
+     * @param {string} html
      *   The updated 'html' attribute.
-     * @param Object options
+     * @param {object} options
      *   An object with the following keys:
-     *   - Boolean propagation: whether this change to the 'html' attribute
-     *     occurred because of the propagation of changes to another instance of
-     *     this field.
+     * @param {bool} options.propagation
+     *   Whether this change to the 'html' attribute occurred because of the
+     *   propagation of changes to another instance of this field.
      *
-     * @see Drupal.quickedit.AppView.renderUpdatedField()
+     * @see Drupal.quickedit.AppView#renderUpdatedField
      */
     propagateUpdatedField: function (updatedField, html, options) {
       // Don't propagate field updates that themselves were caused by propagation.
@@ -538,7 +550,7 @@
      *
      * This happens when a field was modified, saved and hence rerendered.
      *
-     * @param Drupal.quickedit.FieldModel fieldModel
+     * @param {Drupal.quickedit.FieldModel} fieldModel
      *   A field that was just added to the collection of fields.
      */
     rerenderedFieldToCandidate: function (fieldModel) {
@@ -560,7 +572,7 @@
      * EntityModel Collection change handler, called on change:isActive, enforces
      * a single active entity.
      *
-     * @param Drupal.quickedit.EntityModel
+     * @param {Drupal.quickedit.EntityModel} changedEntityModel
      *   The entityModel instance whose active state has changed.
      */
     enforceSingleActiveEntity: function (changedEntityModel) {
diff --git a/core/modules/quickedit/js/views/ContextualLinkView.js b/core/modules/quickedit/js/views/ContextualLinkView.js
index 6c50617..75036b1 100644
--- a/core/modules/quickedit/js/views/ContextualLinkView.js
+++ b/core/modules/quickedit/js/views/ContextualLinkView.js
@@ -7,8 +7,13 @@
 
   "use strict";
 
-  Drupal.quickedit.ContextualLinkView = Backbone.View.extend({
+  Drupal.quickedit.ContextualLinkView = Backbone.View.extend(/** @lends Drupal.quickedit.ContextualLinkView# */{
 
+    /**
+     * Define all events to listen to.
+     *
+     * @return {object}
+     */
     events: function () {
       // Prevents delay and simulated mouse events.
       function touchEndToClick(event) {
@@ -26,13 +31,18 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @constructs
      *
-     * @param Object options
+     * @augments Backbone.View
+     *
+     * @param {object} options
      *   An object with the following keys:
-     *   - Drupal.quickedit.EntityModel model: the associated entity's model
-     *   - Drupal.quickedit.AppModel appModel: the application state model
-     *   - strings: the strings for the "Quick edit" link
+     * @param {Drupal.quickedit.EntityModel} options.model
+     *   The associated entity's model.
+     * @param {Drupal.quickedit.AppModel} options.appModel
+     *   The application state model.
+     * @param {object} options.strings
+     *   The strings for the "Quick edit" link.
      */
     initialize: function (options) {
       // Insert the text of the quick edit toggle.
@@ -44,7 +54,11 @@
     },
 
     /**
-     * {@inheritdoc}
+     *
+     * @param {Drupal.quickedit.EntityModel} entityModel
+     * @param {bool} isActive
+     *
+     * @return {Drupal.quickedit.ContextualLinkView}
      */
     render: function (entityModel, isActive) {
       this.$el.find('a').attr('aria-pressed', isActive);
diff --git a/core/modules/quickedit/js/views/EditorView.js b/core/modules/quickedit/js/views/EditorView.js
index e13b0a1..f78a697 100644
--- a/core/modules/quickedit/js/views/EditorView.js
+++ b/core/modules/quickedit/js/views/EditorView.js
@@ -7,36 +7,35 @@
 
   "use strict";
 
-  /**
-   * A base implementation that outlines the structure for in-place editors.
-   *
-   * Specific in-place editor implementations should subclass (extend) this View
-   * and override whichever method they deem necessary to override.
-   *
-   * Look at Drupal.quickedit.editors.form and
-   * Drupal.quickedit.editors.plain_text for examples.
-   *
-   * @see Drupal.quickedit.EditorModel
-   */
-  Drupal.quickedit.EditorView = Backbone.View.extend({
+  Drupal.quickedit.EditorView = Backbone.View.extend(/** @lends Drupal.quickedit.EditorView# */{
 
     /**
-     * {@inheritdoc}
+     * A base implementation that outlines the structure for in-place editors.
+     *
+     * Specific in-place editor implementations should subclass (extend) this View
+     * and override whichever method they deem necessary to override.
      *
      * Typically you would want to override this method to set the originalValue
      * attribute in the FieldModel to such a value that your in-place editor can
      * revert to the original value when necessary.
      *
-     * If you override this method, you should call this method (the parent
-     * class' initialize()) first, like this:
-     *   Drupal.quickedit.EditorView.prototype.initialize.call(this, options);
+     * @example <caption>If you override this method, you should call this
+     * method (the parent class' initialize()) first.</caption>
+     * Drupal.quickedit.EditorView.prototype.initialize.call(this, options);
+     *
+     * @constructs
      *
-     * For an example, @see Drupal.quickedit.editors.plain_text.
+     * @augments Backbone.View
      *
-     * @param Object options
+     * @param {object} options
      *   An object with the following keys:
-     *   - Drupal.quickedit.EditorModel model: the in-place editor state model
-     *   - Drupal.quickedit.FieldModel fieldModel: the field model
+     * @param {Drupal.quickedit.EditorModel} options.model
+     *   The in-place editor state model.
+     * @param {Drupal.quickedit.FieldModel} options.fieldModel
+     *   The field model.
+     *
+     * @see Drupal.quickedit.EditorModel
+     * @see Drupal.quickedit.editors.plain_text
      */
     initialize: function (options) {
       this.fieldModel = options.fieldModel;
@@ -44,7 +43,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     remove: function () {
       // The el property is the field, which should not be removed. Remove the
@@ -63,16 +62,18 @@
      * e.g. using a WYSIWYG editor on a body field should happen on the DOM
      * element containing the text itself, not on the field wrapper.
      *
-     * For example, @see Drupal.quickedit.editors.plain_text.
-     *
-     * @return jQuery
+     * @return {jQuery}
      *   A jQuery-wrapped DOM element.
+     *
+     * @see Drupal.quickedit.editors.plain_text
      */
     getEditedElement: function () {
       return this.$el;
     },
 
     /**
+     *
+     * @return {object}
      * Returns 3 Quick Edit UI settings that depend on the in-place editor:
      *  - Boolean padding: indicates whether padding should be applied to the
      *    edited element, to guarantee legibility of text.
@@ -90,9 +91,10 @@
     /**
      * Determines the actions to take given a change of state.
      *
-     * @param Drupal.quickedit.FieldModel fieldModel
-     * @param String state
-     *   The state of the associated field. One of Drupal.quickedit.FieldModel.states.
+     * @param {Drupal.quickedit.FieldModel} fieldModel
+     * @param {string} state
+     *   The state of the associated field. One of
+     *   {@link Drupal.quickedit.FieldModel.states}.
      */
     stateChange: function (fieldModel, state) {
       var from = fieldModel.previous('state');
@@ -102,19 +104,21 @@
           // An in-place editor view will not yet exist in this state, hence
           // this will never be reached. Listed for sake of completeness.
           break;
+
         case 'candidate':
           // Nothing to do for the typical in-place editor: it should not be
           // visible yet.
-
           // Except when we come from the 'invalid' state, then we clean up.
           if (from === 'invalid') {
             this.removeValidationErrors();
           }
           break;
+
         case 'highlighted':
           // Nothing to do for the typical in-place editor: it should not be
           // visible yet.
           break;
+
         case 'activating':
           // The user has indicated he wants to do in-place editing: if
           // something needs to be loaded (CSS/JavaScript/server data/…), then
@@ -130,13 +134,16 @@
             fieldModel.set('state', 'active');
           });
           break;
+
         case 'active':
           // The user can now actually use the in-place editor.
           break;
+
         case 'changed':
           // Nothing to do for the typical in-place editor. The UI will show an
           // indicator that the field has changed.
           break;
+
         case 'saving':
           // When the user has indicated he wants to save his changes to this
           // field, this state will be entered.
@@ -148,12 +155,14 @@
           }
           this.save();
           break;
+
         case 'saved':
           // Nothing to do for the typical in-place editor. Immediately after
           // being saved, a field will go to the 'candidate' state, where it
           // should no longer be visible (after all, the field will then again
           // just be a *candidate* to be in-place edited).
           break;
+
         case 'invalid':
           // The modified field value was attempted to be saved, but there were
           // validation errors.
@@ -167,7 +176,6 @@
      */
     revert: function () {
       // A no-op by default; each editor should implement reverting itself.
-
       // Note that if the in-place editor does not cause the FieldModel's
       // element to be modified, then nothing needs to happen.
     },
diff --git a/core/modules/quickedit/js/views/EntityDecorationView.js b/core/modules/quickedit/js/views/EntityDecorationView.js
index 69a4767..e4607ef 100644
--- a/core/modules/quickedit/js/views/EntityDecorationView.js
+++ b/core/modules/quickedit/js/views/EntityDecorationView.js
@@ -7,26 +7,28 @@
 
   "use strict";
 
-  Drupal.quickedit.EntityDecorationView = Backbone.View.extend({
+  Drupal.quickedit.EntityDecorationView = Backbone.View.extend(/** @lends Drupal.quickedit.EntityDecorationView# */{
 
     /**
-     * {@inheritdoc}
-     *
      * Associated with the DOM root node of an editable entity.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.listenTo(this.model, 'change', this.render);
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     render: function () {
       this.$el.toggleClass('quickedit-entity-active', this.model.get('isActive'));
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     remove: function () {
       this.setElement(null);
diff --git a/core/modules/quickedit/js/views/EntityToolbarView.js b/core/modules/quickedit/js/views/EntityToolbarView.js
index 800311d..fffde11 100644
--- a/core/modules/quickedit/js/views/EntityToolbarView.js
+++ b/core/modules/quickedit/js/views/EntityToolbarView.js
@@ -7,10 +7,16 @@
 
   "use strict";
 
-  Drupal.quickedit.EntityToolbarView = Backbone.View.extend({
+  Drupal.quickedit.EntityToolbarView = Backbone.View.extend(/** @lends Drupal.quickedit.EntityToolbarView# */{
 
+    /**
+     * @type {?jQuery}
+     */
     _fieldToolbarRoot: null,
 
+    /**
+     * @return {object}
+     */
     events: function () {
       var map = {
         'click button.action-save': 'onClickSave',
@@ -21,7 +27,12 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @constructs
+     *
+     * @augments Backbone.View
+     *
+     * @param {object} options
+     * @param {Drupal.quickedit.AppModel} options.appModel
      */
     initialize: function (options) {
       var that = this;
@@ -57,7 +68,9 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {Drupal.quickedit.EntityToolbarView}
      */
     render: function () {
       if (this.model.get('isActive')) {
@@ -98,6 +111,7 @@
             .removeAttr('disabled')
             .attr('aria-hidden', !isDirty);
           break;
+
         // The changes to the fields of the entity are being committed.
         case 'committing':
           $button
@@ -105,6 +119,7 @@
             .text(Drupal.t('Saving'))
             .attr('disabled', 'disabled');
           break;
+
         default:
           $button.attr('aria-hidden', true);
           break;
@@ -114,7 +129,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     remove: function () {
       // Remove additional DOM elements controlled by this View.
@@ -130,7 +145,7 @@
     /**
      * Repositions the entity toolbar on window scroll and resize.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     windowChangeHandler: function (event) {
       this.position();
@@ -139,15 +154,17 @@
     /**
      * Determines the actions to take given a change of state.
      *
-     * @param Drupal.quickedit.FieldModel model
-     * @param String state
-     *   The state of the associated field. One of Drupal.quickedit.FieldModel.states.
+     * @param {Drupal.quickedit.FieldModel} model
+     * @param {string} state
+     *   The state of the associated field. One of
+     *   {@link Drupal.quickedit.FieldModel.states}.
      */
     fieldStateChange: function (model, state) {
       switch (state) {
         case 'active':
           this.render();
           break;
+
         case 'invalid':
           this.render();
           break;
@@ -157,8 +174,8 @@
     /**
      * Uses the jQuery.ui.position() method to position the entity toolbar.
      *
-     * @param jQuery|DOM element
-     *   (optional) The element against which the entity toolbar is positioned.
+     * @param {HTMLElement} [element]
+     *   The element against which the entity toolbar is positioned.
      */
     position: function (element) {
       clearTimeout(this.timer);
@@ -169,7 +186,8 @@
       var edge = (document.documentElement.dir === 'rtl') ? 'right' : 'left';
       // A time unit to wait until the entity toolbar is repositioned.
       var delay = 0;
-      // Determines what check in the series of checks below should be evaluated
+      // Determines what check in the series of checks below should be
+      // evaluated.
       var check = 0;
       // When positioned against an active field that has padding, we should
       // ignore that padding when positioning the toolbar, to not unnecessarily
@@ -186,11 +204,13 @@
             // Position against a specific element.
             of = element;
             break;
+
           case 1:
             // Position against a form container.
             activeField = Drupal.quickedit.app.model.get('activeField');
             of = activeField && activeField.editorView && activeField.editorView.$formContainer && activeField.editorView.$formContainer.find('.quickedit-form');
             break;
+
           case 2:
             // Position against an active field.
             of = activeField && activeField.editorView && activeField.editorView.getEditedElement();
@@ -198,12 +218,14 @@
               horizontalPadding = 5;
             }
             break;
+
           case 3:
             // Position against a highlighted field.
             highlightedField = Drupal.quickedit.app.model.get('highlightedField');
             of = highlightedField && highlightedField.editorView && highlightedField.editorView.getEditedElement();
             delay = 250;
             break;
+
           default:
             var fieldModels = this.model.get('fields').models;
             var topMostPosition = 1000000;
@@ -230,18 +252,21 @@
        * Invoked as the 'using' callback of jquery.ui.position() in
        * positionToolbar().
        *
-       * @param Object suggested
+       * @param {*} view
+       * @param {object} suggested
        *   A hash of top and left values for the position that should be set. It
        *   can be forwarded to .css() or .animate().
-       * @param Object info
+       * @param {object} info
        *   The position and dimensions of both the 'my' element and the 'of'
        *   elements, as well as calculations to their relative position. This
        *   object contains the following properties:
-       *     - Object element: A hash that contains information about the HTML
-       *     element that will be positioned. Also known as the 'my' element.
-       *     - Object target: A hash that contains information about the HTML
-       *     element that the 'my' element will be positioned against. Also known
-       *     as the 'of' element.
+       * @param {object} info.element
+       *   A hash that contains information about the HTML element that will be
+       *   positioned. Also known as the 'my' element.
+       * @param {object} info.target
+       *   A hash that contains information about the HTML element that the
+       *   'my' element will be positioned against. Also known as the 'of'
+       *   element.
        */
       function refinePosition(view, suggested, info) {
         // Determine if the pointer should be on the top or bottom.
@@ -317,7 +342,7 @@
     /**
      * Set the model state to 'saving' when the save button is clicked.
      *
-     * @param jQuery event
+     * @param {jQuery.Event} event
      */
     onClickSave: function (event) {
       event.stopPropagation();
@@ -329,7 +354,7 @@
     /**
      * Sets the model state to candidate when the cancel button is clicked.
      *
-     * @param jQuery event
+     * @param {jQuery.Event} event
      */
     onClickCancel: function (event) {
       event.preventDefault();
@@ -341,7 +366,7 @@
      *
      * Without this, it may reposition itself, away from the user's cursor!
      *
-     * @param jQuery event
+     * @param {jQuery.Event} event
      */
     onMouseenter: function (event) {
       clearTimeout(this.timer);
@@ -349,6 +374,8 @@
 
     /**
      * Builds the entity toolbar HTML; attaches to DOM; sets starting position.
+     *
+     * @return {jQuery}
      */
     buildToolbarEl: function () {
       var $toolbar = $(Drupal.theme('quickeditEntityToolbar', {
@@ -390,7 +417,7 @@
     /**
      * Returns the DOM element that fields will attach their toolbars to.
      *
-     * @return jQuery
+     * @return {jQuery}
      *   The DOM element that fields will attach their toolbars to.
      */
     getToolbarRoot: function () {
@@ -436,9 +463,9 @@
     /**
      * Adds classes to a toolgroup.
      *
-     * @param String toolgroup
+     * @param {string} toolgroup
      *   A toolgroup name.
-     * @param String classes
+     * @param {string} classes
      *   A string of space-delimited class names that will be applied to the
      *   wrapping element of the toolbar group.
      */
@@ -449,9 +476,9 @@
     /**
      * Removes classes from a toolgroup.
      *
-     * @param String toolgroup
+     * @param {string} toolgroup
      *   A toolgroup name.
-     * @param String classes
+     * @param {string} classes
      *   A string of space-delimited class names that will be removed from the
      *   wrapping element of the toolbar group.
      */
@@ -462,9 +489,10 @@
     /**
      * Finds a toolgroup.
      *
-     * @param String toolgroup
+     * @param {string} toolgroup
      *   A toolgroup name.
-     * @return jQuery
+     *
+     * @return {jQuery}
      *   The toolgroup DOM element.
      */
     _find: function (toolgroup) {
@@ -474,7 +502,7 @@
     /**
      * Shows a toolgroup.
      *
-     * @param String toolgroup
+     * @param {string} toolgroup
      *   A toolgroup name.
      */
     show: function (toolgroup) {
diff --git a/core/modules/quickedit/js/views/FieldDecorationView.js b/core/modules/quickedit/js/views/FieldDecorationView.js
index 49491da..689ef9d 100644
--- a/core/modules/quickedit/js/views/FieldDecorationView.js
+++ b/core/modules/quickedit/js/views/FieldDecorationView.js
@@ -7,10 +7,16 @@
 
   "use strict";
 
-  Drupal.quickedit.FieldDecorationView = Backbone.View.extend({
+  Drupal.quickedit.FieldDecorationView = Backbone.View.extend(/** @lends Drupal.quickedit.FieldDecorationView# */{
 
+    /**
+     * @type {null}
+     */
     _widthAttributeIsEmpty: null,
 
+    /**
+     * @type {object}
+     */
     events: {
       'mouseenter.quickedit': 'onMouseEnter',
       'mouseleave.quickedit': 'onMouseLeave',
@@ -20,11 +26,14 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @constructs
      *
-     * @param Object options
+     * @augments Backbone.View
+     *
+     * @param {object} options
      *   An object with the following keys:
-     *   - Drupal.quickedit.EditorView editorView: the editor object view.
+     * @param {Drupal.quickedit.EditorView} options.editorView
+     *   The editor object view.
      */
     initialize: function (options) {
       this.editorView = options.editorView;
@@ -34,7 +43,7 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     remove: function () {
       // The el property is the field, which should not be removed. Remove the
@@ -46,8 +55,8 @@
     /**
      * Determines the actions to take given a change of state.
      *
-     * @param Drupal.quickedit.FieldModel model
-     * @param String state
+     * @param {Drupal.quickedit.FieldModel} model
+     * @param {string} state
      *   The state of the associated field. One of Drupal.quickedit.FieldModel.states.
      */
     stateChange: function (model, state) {
@@ -57,6 +66,7 @@
         case 'inactive':
           this.undecorate();
           break;
+
         case 'candidate':
           this.decorate();
           if (from !== 'inactive') {
@@ -68,14 +78,17 @@
           }
           this._unpad();
           break;
+
         case 'highlighted':
           this.startHighlight();
           break;
+
         case 'activating':
           // NOTE: this state is not used by every editor! It's only used by those
           // that need to interact with the server.
           this.prepareEdit();
           break;
+
         case 'active':
           if (from !== 'activating') {
             this.prepareEdit();
@@ -84,13 +97,17 @@
             this._pad();
           }
           break;
+
         case 'changed':
           this.model.set('isChanged', true);
           break;
+
         case 'saving':
           break;
+
         case 'saved':
           break;
+
         case 'invalid':
           break;
       }
@@ -109,7 +126,7 @@
     /**
      * Starts hover; transitions to 'highlight' state.
      *
-     * @param jQuery event
+     * @param {jQuery.Event} event
      */
     onMouseEnter: function (event) {
       var that = this;
@@ -120,7 +137,7 @@
     /**
      * Stops hover; transitions to 'candidate' state.
      *
-     * @param jQuery event
+     * @param {jQuery.Event} event
      */
     onMouseLeave: function (event) {
       var that = this;
@@ -131,7 +148,7 @@
     /**
      * Transition to 'activating' stage.
      *
-     * @param jQuery event
+     * @param {jQuery.Event} event
      */
     onClick: function (event) {
       this.model.set('state', 'activating');
@@ -212,8 +229,8 @@
       var self = this;
 
       // Add 5px padding for readability. This means we'll freeze the current
-      // width and *then* add 5px padding, hence ensuring the padding is added "on
-      // the outside".
+      // width and *then* add 5px padding, hence ensuring the padding is added
+      // "on the outside".
       // 1) Freeze the width (if it's not already set); don't use animations.
       if (this.$el[0].style.width === "") {
         this._widthAttributeIsEmpty = true;
@@ -294,7 +311,9 @@
      * Convert extraneous values and information into numbers ready for
      * subtraction.
      *
-     * @param DOM $e
+     * @param {jQuery} $e
+     *
+     * @return {object}
      */
     _getPositionProperties: function ($e) {
       var p;
@@ -314,10 +333,12 @@
     },
 
     /**
-     * Replaces blank or 'auto' CSS "position: <value>" values with "0px".
+     * Replaces blank or 'auto' CSS `position: <value>` values with "0px".
+     *
+     * @param {string} [pos]
+     *   The value for a CSS position declaration.
      *
-     * @param String pos
-     *   (optional) The value for a CSS position declaration.
+     * @return {string}
      */
     _replaceBlankPosition: function (pos) {
       if (pos === 'auto' || !pos) {
diff --git a/core/modules/quickedit/js/views/FieldToolbarView.js b/core/modules/quickedit/js/views/FieldToolbarView.js
index 24676ed..b43d7f2 100644
--- a/core/modules/quickedit/js/views/FieldToolbarView.js
+++ b/core/modules/quickedit/js/views/FieldToolbarView.js
@@ -7,22 +7,44 @@
 
   "use strict";
 
-  Drupal.quickedit.FieldToolbarView = Backbone.View.extend({
+  Drupal.quickedit.FieldToolbarView = Backbone.View.extend(/** @lends Drupal.quickedit.FieldToolbarView# */{
 
-    // The edited element, as indicated by EditorView.getEditedElement().
+    /**
+     * The edited element, as indicated by EditorView.getEditedElement.
+     *
+     * @type {?jQuery}
+     */
     $editedElement: null,
 
-    // A reference to the in-place editor.
+    /**
+     * A reference to the in-place editor.
+     *
+     * @type {?Drupal.quickedit.EditorView}
+     */
     editorView: null,
 
+    /**
+     * @type {?string}
+     */
     _id: null,
 
     /**
-     * {@inheritdoc}
+     * @constructs
+     *
+     * @augments Backbone.View
+     *
+     * @param {object} options
+     * @param {jQuery} options.$editedElement
+     * @param {Drupal.quickedit.EditorView} options.editorView
      */
     initialize: function (options) {
       this.$editedElement = options.$editedElement;
       this.editorView = options.editorView;
+
+      /**
+       *
+       * @type {jQuery}
+       */
       this.$root = this.$el;
 
       // Generate a DOM-compatible ID for the form container DOM element.
@@ -32,7 +54,9 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {Drupal.quickedit.FieldToolbarView}
      */
     render: function () {
       // Render toolbar and set it as the view's element.
@@ -49,8 +73,8 @@
     /**
      * Determines the actions to take given a change of state.
      *
-     * @param Drupal.quickedit.FieldModel model
-     * @param String state
+     * @param {Drupal.quickedit.FieldModel} model
+     * @param {string} state
      *   The state of the associated field. One of Drupal.quickedit.FieldModel.states.
      */
     stateChange: function (model, state) {
@@ -59,6 +83,7 @@
       switch (to) {
         case 'inactive':
           break;
+
         case 'candidate':
           // Remove the view's existing element if we went to the 'activating'
           // state or later, because it will be recreated. Not doing this would
@@ -68,8 +93,10 @@
             this.setElement();
           }
           break;
+
         case 'highlighted':
           break;
+
         case 'activating':
           this.render();
 
@@ -81,14 +108,19 @@
             this.insertWYSIWYGToolGroups();
           }
           break;
+
         case 'active':
           break;
+
         case 'changed':
           break;
+
         case 'saving':
           break;
+
         case 'saved':
           break;
+
         case 'invalid':
           break;
       }
@@ -120,7 +152,7 @@
      *
      * Only used to make sane hovering behavior possible.
      *
-     * @return String
+     * @return {string}
      *   A string that can be used as the ID for this toolbar's container.
      */
     getId: function () {
@@ -132,7 +164,7 @@
      *
      * Used to provide an abstraction for any WYSIWYG editor to plug in.
      *
-     * @return String
+     * @return {string}
      *   A string that can be used as the ID.
      */
     getFloatedWysiwygToolgroupId: function () {
@@ -144,7 +176,7 @@
      *
      * Used to provide an abstraction for any WYSIWYG editor to plug in.
      *
-     * @return String
+     * @return {string}
      *   A string that can be used as the ID.
      */
     getMainWysiwygToolgroupId: function () {
@@ -154,9 +186,10 @@
     /**
      * Finds a toolgroup.
      *
-     * @param String toolgroup
+     * @param {string} toolgroup
      *   A toolgroup name.
-     * @return jQuery
+     *
+     * @return {jQuery}
      */
     _find: function (toolgroup) {
       return this.$el.find('.quickedit-toolgroup.' + toolgroup);
@@ -165,7 +198,7 @@
     /**
      * Shows a toolgroup.
      *
-     * @param String toolgroup
+     * @param {string} toolgroup
      *   A toolgroup name.
      */
     show: function (toolgroup) {
diff --git a/core/modules/simpletest/simpletest.js b/core/modules/simpletest/simpletest.js
index b1c63de..6630cc4 100644
--- a/core/modules/simpletest/simpletest.js
+++ b/core/modules/simpletest/simpletest.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Simpletest behaviors.
+ */
+
 (function ($) {
 
   "use strict";
 
   /**
    * Collapses table rows followed by group rows on the test listing page.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.simpleTestGroupCollapse = {
     attach: function (context) {
@@ -25,6 +32,8 @@
 
   /**
    * Toggles test checkboxes to match the group checkbox.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.simpleTestSelectAll = {
     attach: function (context) {
@@ -64,6 +73,8 @@
    * Text search input: input.table-filter-text
    * Target table:      input.table-filter-text[data-table]
    * Source text:       .table-filter-text-source
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.simpletestTableFilterByText = {
     attach: function (context) {
diff --git a/core/modules/statistics/statistics.js b/core/modules/statistics/statistics.js
index 35bba66..f892dd4 100644
--- a/core/modules/statistics/statistics.js
+++ b/core/modules/statistics/statistics.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Statistics functionality.
+ */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
diff --git a/core/modules/system/system.js b/core/modules/system/system.js
index 31096f9..e052c3f 100644
--- a/core/modules/system/system.js
+++ b/core/modules/system/system.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * System behaviors.
+ */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
@@ -9,6 +14,8 @@
    * When a field is filled out, apply its value to other fields that will likely
    * use the same value. In the installer this is used to populate the
    * administrator email address with the same value as the site email address.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.copyFieldValue = {
     attach: function (context) {
@@ -34,12 +41,13 @@
         $('#' + ids.join(', #')).removeOnce('copy-field-values').off('blur');
       }
     },
+
     /**
      * Event handler that fill the target element with the specified value.
      *
-     * @param e
+     * @param {jQuery.Event} e
      *   Event object.
-     * @param value
+     * @param {string} value
      *   Custom value from jQuery trigger.
      */
     valueTargetCopyHandler: function (e, value) {
@@ -48,10 +56,13 @@
         $target.val(value);
       }
     },
+
     /**
      * Handler for a Blur event on a source field.
      *
      * This event handler will trigger a 'value:copy' event on all dependent fields.
+     *
+     * @param {jQuery.Event} e
      */
     valueSourceBlurHandler: function (e) {
       var value = $(e.target).val();
diff --git a/core/modules/system/system.modules.js b/core/modules/system/system.modules.js
index 45ddf3b..49a9879 100644
--- a/core/modules/system/system.modules.js
+++ b/core/modules/system/system.modules.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Module page behaviors.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
@@ -11,6 +16,8 @@
    * Text search input: input.table-filter-text
    * Target table:      input.table-filter-text[data-table]
    * Source text:       .table-filter-text-source
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.tableFilterByText = {
     attach: function (context, settings) {
diff --git a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.js b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.js
index 28364a2..39bf0bb 100644
--- a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.js
+++ b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.js
@@ -1,2 +1,6 @@
-
-/* This file is for testing asset file inclusion, no contents are necessary. */
+/**
+ * @file
+ * This file is for testing asset file inclusion, no contents are necessary.
+ *
+ * @ignore
+ */
diff --git a/core/modules/taxonomy/taxonomy.js b/core/modules/taxonomy/taxonomy.js
index 8ffe502..fb4c0ce 100644
--- a/core/modules/taxonomy/taxonomy.js
+++ b/core/modules/taxonomy/taxonomy.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Taxonomy behaviors.
+ */
+
 (function ($) {
 
   "use strict";
@@ -7,12 +12,15 @@
    *
    * This behavior is dependent on the tableDrag behavior, since it uses the
    * objects initialized in that behavior to update the row.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.termDrag = {
     attach: function (context, settings) {
       var backStep = settings.taxonomy.backStep;
       var forwardStep = settings.taxonomy.forwardStep;
-      var tableDrag = Drupal.tableDrag.taxonomy; // Get the blocks tableDrag object.
+      // Get the blocks tableDrag object.
+      var tableDrag = Drupal.tableDrag.taxonomy;
       var $table = $('#taxonomy');
       var rows = $table.find('tr').length;
 
diff --git a/core/modules/text/text.js b/core/modules/text/text.js
index 7360e44..82fdf2a 100644
--- a/core/modules/text/text.js
+++ b/core/modules/text/text.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * Text behaviors.
+ */
+
 (function ($) {
 
   "use strict";
 
   /**
    * Auto-hide summary textarea if empty and show hide and unhide links.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.textSummary = {
     attach: function (context, settings) {
diff --git a/core/modules/toolbar/js/escapeAdmin.js b/core/modules/toolbar/js/escapeAdmin.js
index 0544a40..f47b8b9 100644
--- a/core/modules/toolbar/js/escapeAdmin.js
+++ b/core/modules/toolbar/js/escapeAdmin.js
@@ -1,8 +1,8 @@
 /**
  * @file
- *
  * Replaces the home link in toolbar with a back to site link.
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
@@ -24,6 +24,8 @@
    *
    * Back to site link points to the last non-administrative page the user visited
    * within the same browser tab.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.escapeAdmin = {
     attach: function () {
diff --git a/core/modules/toolbar/js/models/MenuModel.js b/core/modules/toolbar/js/models/MenuModel.js
index 07bc942..5f302bb 100644
--- a/core/modules/toolbar/js/models/MenuModel.js
+++ b/core/modules/toolbar/js/models/MenuModel.js
@@ -9,9 +9,23 @@
 
   /**
    * Backbone Model for collapsible menus.
+   *
+   * @constructor
+   *
+   * @augments Backbone.Model
    */
-  Drupal.toolbar.MenuModel = Backbone.Model.extend({
-    defaults: {
+  Drupal.toolbar.MenuModel = Backbone.Model.extend(/** @lends Drupal.toolbar.MenuModel# */{
+
+    /**
+     * @type {object}
+     *
+     * @prop {object} subtrees
+     */
+    defaults: /** @lends Drupal.toolbar.MenuModel# */{
+
+      /**
+       * @type {object}
+       */
       subtrees: {}
     }
   });
diff --git a/core/modules/toolbar/js/models/ToolbarModel.js b/core/modules/toolbar/js/models/ToolbarModel.js
index 77433bf..a3bad56 100644
--- a/core/modules/toolbar/js/models/ToolbarModel.js
+++ b/core/modules/toolbar/js/models/ToolbarModel.js
@@ -9,43 +9,123 @@
 
   /**
    * Backbone model for the toolbar.
+   *
+   * @constructor
+   *
+   * @augments Backbone.Model
    */
-  Drupal.toolbar.ToolbarModel = Backbone.Model.extend({
-    defaults: {
-      // The active toolbar tab. All other tabs should be inactive under
-      // normal circumstances. It will remain active across page loads. The
-      // active item is stored as an ID selector e.g. '#toolbar-item--1'.
+  Drupal.toolbar.ToolbarModel = Backbone.Model.extend(/** @lends Drupal.toolbar.ToolbarModel# */{
+
+    /**
+     * @type {object}
+     *
+     * @prop activeTab
+     * @prop activeTray
+     * @prop isOriented
+     * @prop isFixed
+     * @prop areSubtreesLoaded
+     * @prop isViewportOverflowConstrained
+     * @prop orientation
+     * @prop locked
+     * @prop isTrayToggleVisible
+     * @prop height
+     * @prop offsets
+     */
+    defaults: /** @lends Drupal.toolbar.ToolbarModel# */{
+
+      /**
+       * The active toolbar tab. All other tabs should be inactive under
+       * normal circumstances. It will remain active across page loads. The
+       * active item is stored as an ID selector e.g. '#toolbar-item--1'.
+       *
+       * @type {?string}
+       */
       activeTab: null,
-      // Represents whether a tray is open or not. Stored as an ID selector e.g.
-      // '#toolbar-item--1-tray'.
+
+      /**
+       * Represents whether a tray is open or not. Stored as an ID selector e.g.
+       * '#toolbar-item--1-tray'.
+       *
+       * @type {?string}
+       */
       activeTray: null,
-      // Indicates whether the toolbar is displayed in an oriented fashion,
-      // either horizontal or vertical.
+
+      /**
+       * Indicates whether the toolbar is displayed in an oriented fashion,
+       * either horizontal or vertical.
+       *
+       * @type {bool}
+       */
       isOriented: false,
-      // Indicates whether the toolbar is positioned absolute (false) or fixed
-      // (true).
+
+      /**
+       * Indicates whether the toolbar is positioned absolute (false) or fixed
+       * (true).
+       *
+       * @type {bool}
+       */
       isFixed: false,
-      // Menu subtrees are loaded through an AJAX request only when the Toolbar
-      // is set to a vertical orientation.
+
+      /**
+       * Menu subtrees are loaded through an AJAX request only when the Toolbar
+       * is set to a vertical orientation.
+       *
+       * @type {bool}
+       */
       areSubtreesLoaded: false,
-      // If the viewport overflow becomes constrained, isFixed must be true so
-      // that elements in the trays aren't lost off-screen and impossible to
-      // get to.
+
+      /**
+       * If the viewport overflow becomes constrained, isFixed must be true so
+       * that elements in the trays aren't lost off-screen and impossible to
+       * get to.
+       *
+       * @type {bool}
+       */
       isViewportOverflowConstrained: false,
-      // The orientation of the active tray.
+
+      /**
+       * The orientation of the active tray.
+       *
+       * @type {string}
+       */
       orientation: 'vertical',
-      // A tray is locked if a user toggled it to vertical. Otherwise a tray
-      // will switch between vertical and horizontal orientation based on the
-      // configured breakpoints. The locked state will be maintained across page
-      // loads.
+
+      /**
+       * A tray is locked if a user toggled it to vertical. Otherwise a tray
+       * will switch between vertical and horizontal orientation based on the
+       * configured breakpoints. The locked state will be maintained across page
+       * loads.
+       *
+       * @type {bool}
+       */
       locked: false,
-      // Indicates whether the tray orientation toggle is visible.
+
+      /**
+       * Indicates whether the tray orientation toggle is visible.
+       *
+       * @type {bool}
+       */
       isTrayToggleVisible: false,
-      // The height of the toolbar.
+
+      /**
+       * The height of the toolbar.
+       *
+       * @type {?number}
+       */
       height: null,
-      // The current viewport offsets determined by Drupal.displace(). The
-      // offsets suggest how a module might position is components relative to
-      // the viewport.
+
+      /**
+       * The current viewport offsets determined by Drupal.displace(). The
+       * offsets suggest how a module might position is components relative to
+       * the viewport.
+       *
+       * @type {object}
+       *
+       * @prop {number} top
+       * @prop {number} right
+       * @prop {number} bottom
+       * @prop {number} left
+       */
       offsets: {
         top: 0,
         right: 0,
@@ -55,7 +135,12 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @param {object} attributes
+     * @param {object} options
+     *
+     * @return {string}
      */
     validate: function (attributes, options) {
       // Prevent the orientation being set to horizontal if it is locked, unless
diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js
index efbad03..cd44b7f 100644
--- a/core/modules/toolbar/js/toolbar.js
+++ b/core/modules/toolbar/js/toolbar.js
@@ -1,8 +1,8 @@
 /**
- * @file toolbar.js
- *
+ * @file
  * Defines the behavior of the Drupal administration toolbar.
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
@@ -33,9 +33,10 @@
    * point directly to a resource or toggle the visibility of a tray.
    *
    * Modules register tabs with hook_toolbar().
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.toolbar = {
-
     attach: function (context) {
       // Verify that the user agent understands media queries. Complex admin
       // toolbar layouts require media query support.
@@ -138,16 +139,30 @@
 
   /**
    * Toolbar methods of Backbone objects.
+   *
+   * @namespace
    */
   Drupal.toolbar = {
 
-    // A hash of View instances.
+    /**
+     * A hash of View instances.
+     *
+     * @type {object.<string, Backbone.View>}
+     */
     views: {},
 
-    // A hash of Model instances.
+    /**
+     * A hash of Model instances.
+     *
+     * @type {object.<string, Backbone.Model>}
+     */
     models: {},
 
-    // A hash of MediaQueryList objects tracked by the toolbar.
+    /**
+     * A hash of MediaQueryList objects tracked by the toolbar.
+     *
+     * @type {object.<string, object>}
+     */
     mql: {},
 
     /**
@@ -155,13 +170,18 @@
      *
      * A deferred object that is resolved by an inlined JavaScript callback.
      *
-     * JSONP callback.
+     * @type {jQuery.Deferred}
+     *
      * @see toolbar_subtrees_jsonp().
      */
     setSubtrees: new $.Deferred(),
 
     /**
      * Respond to configured narrow media query changes.
+     *
+     * @param {Drupal.toolbar.ToolbarModel} model
+     * @param {string} label
+     * @param {object} mql
      */
     mediaQueryChangeHandler: function (model, label, mql) {
       switch (label) {
@@ -177,11 +197,13 @@
             model.set({'orientation': 'vertical'}, {validate: true});
           }
           break;
+
         case 'toolbar.standard':
           model.set({
             'isFixed': mql.matches
           });
           break;
+
         case 'toolbar.wide':
           model.set({
             'orientation': ((mql.matches) ? 'horizontal' : 'vertical')
@@ -192,6 +214,7 @@
             'isTrayToggleVisible': mql.matches
           });
           break;
+
         default:
           break;
       }
@@ -201,7 +224,7 @@
   /**
    * A toggle is an interactive element often bound to a click handler.
    *
-   * @return {String}
+   * @return {string}
    *   A string representing a DOM fragment.
    */
   Drupal.theme.toolbarOrientationToggle = function () {
diff --git a/core/modules/toolbar/js/toolbar.menu.js b/core/modules/toolbar/js/toolbar.menu.js
index c14d0d4..bebced9 100644
--- a/core/modules/toolbar/js/toolbar.menu.js
+++ b/core/modules/toolbar/js/toolbar.menu.js
@@ -1,8 +1,11 @@
 /**
+ * @file
  * Builds a nested accordion widget.
  *
  * Invoke on an HTML list element with the jQuery plugin pattern.
- * - For example, $('.menu').drupalToolbarMenu();
+ *
+ * @example
+ * $('.menu').drupalToolbarMenu();
  */
 
 (function ($, Drupal, drupalSettings) {
@@ -77,7 +80,7 @@
       // Adjust the toggle text.
       $toggle
         .find('.action')
-        // Expand Structure, Collapse Structure
+        // Expand Structure, Collapse Structure.
         .text((switcher) ? ui.handleClose : ui.handleOpen);
     }
 
@@ -121,7 +124,7 @@
      * @param {jQuery} $lists
      *   A jQuery object of ul elements.
      *
-     * @param {Integer} level
+     * @param {number} level
      *   The current level number to be assigned to the list elements.
      */
     function markListLevels($lists, level) {
@@ -175,7 +178,12 @@
   /**
    * A toggle is an interactive element often bound to a click handler.
    *
-   * @return {String}
+   * @param {object} options
+   * @param {string} options.class
+   * @param {string} options.action
+   * @param {string} options.text
+   *
+   * @return {string}
    *   A string representing a DOM fragment.
    */
   Drupal.theme.toolbarMenuItemToggle = function (options) {
diff --git a/core/modules/toolbar/js/views/BodyVisualView.js b/core/modules/toolbar/js/views/BodyVisualView.js
index 00abcf2..7499646 100644
--- a/core/modules/toolbar/js/views/BodyVisualView.js
+++ b/core/modules/toolbar/js/views/BodyVisualView.js
@@ -7,20 +7,21 @@
 
   "use strict";
 
-  /**
-   * Adjusts the body element with the toolbar position and dimension changes.
-   */
-  Drupal.toolbar.BodyVisualView = Backbone.View.extend({
+  Drupal.toolbar.BodyVisualView = Backbone.View.extend(/** @lends Drupal.toolbar.BodyVisualView# */{
 
     /**
-     * {@inheritdoc}
+     * Adjusts the body element with the toolbar position and dimension changes.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.listenTo(this.model, 'change:orientation change:offsets change:activeTray change:isOriented change:isFixed change:isViewportOverflowConstrained', this.render);
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     render: function () {
       var $body = $('body');
diff --git a/core/modules/toolbar/js/views/MenuVisualView.js b/core/modules/toolbar/js/views/MenuVisualView.js
index d90b6d0..29e56ea 100644
--- a/core/modules/toolbar/js/views/MenuVisualView.js
+++ b/core/modules/toolbar/js/views/MenuVisualView.js
@@ -7,19 +7,21 @@
 
   "use strict";
 
-  /**
-   * Backbone View for collapsible menus.
-   */
-  Drupal.toolbar.MenuVisualView = Backbone.View.extend({
+  Drupal.toolbar.MenuVisualView = Backbone.View.extend(/** @lends Drupal.toolbar.MenuVisualView# */{
+
     /**
-     * {@inheritdoc}
+     * Backbone View for collapsible menus.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.listenTo(this.model, 'change:subtrees', this.render);
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
      */
     render: function () {
       var subtrees = this.model.get('subtrees');
diff --git a/core/modules/toolbar/js/views/ToolbarAuralView.js b/core/modules/toolbar/js/views/ToolbarAuralView.js
index 9a2183e..d5f6f19 100644
--- a/core/modules/toolbar/js/views/ToolbarAuralView.js
+++ b/core/modules/toolbar/js/views/ToolbarAuralView.js
@@ -7,13 +7,17 @@
 
   "use strict";
 
-  /**
-   * Backbone view for the aural feedback of the toolbar.
-   */
-  Drupal.toolbar.ToolbarAuralView = Backbone.View.extend({
+  Drupal.toolbar.ToolbarAuralView = Backbone.View.extend(/** @lends Drupal.toolbar.ToolbarAuralView# */{
 
     /**
-     * {@inheritdoc}
+     * Backbone view for the aural feedback of the toolbar.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
+     *
+     * @param {object} options
+     * @param {object} options.strings
      */
     initialize: function (options) {
       this.strings = options.strings;
@@ -25,8 +29,8 @@
     /**
      * Announces an orientation change.
      *
-     * @param Drupal.Toolbar.ToolbarModel model
-     * @param String orientation
+     * @param {Drupal.Toolbar.ToolbarModel} model
+     * @param {string} orientation
      *   The new value of the orientation attribute in the model.
      */
     onOrientationChange: function (model, orientation) {
@@ -38,8 +42,8 @@
     /**
      * Announces a changed active tray.
      *
-     * @param Drupal.Toolbar.ToolbarModel model
-     * @param Element orientation
+     * @param {Drupal.toolbar.ToolbarModel} model
+     * @param {HTMLElement} tray
      *   The new value of the tray attribute in the model.
      */
     onActiveTrayChange: function (model, tray) {
diff --git a/core/modules/toolbar/js/views/ToolbarVisualView.js b/core/modules/toolbar/js/views/ToolbarVisualView.js
index f30bde3..3459404 100644
--- a/core/modules/toolbar/js/views/ToolbarVisualView.js
+++ b/core/modules/toolbar/js/views/ToolbarVisualView.js
@@ -7,11 +7,11 @@
 
   "use strict";
 
-  /**
-   * Backbone view for the toolbar element. Listens to mouse & touch.
-   */
-  Drupal.toolbar.ToolbarVisualView = Backbone.View.extend({
+  Drupal.toolbar.ToolbarVisualView = Backbone.View.extend(/** @lends Drupal.toolbar.ToolbarVisualView# */{
 
+    /**
+     * @return {object}
+     */
     events: function () {
       // Prevents delay and simulated mouse events.
       var touchEndToClick = function (event) {
@@ -28,7 +28,14 @@
     },
 
     /**
-     * {@inheritdoc}
+     * Backbone view for the toolbar element. Listens to mouse & touch.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
+     *
+     * @param {object} options
+     * @param {object} options.strings
      */
     initialize: function (options) {
       this.strings = options.strings;
@@ -48,7 +55,9 @@
     },
 
     /**
-     * {@inheritdoc}
+     * @inheritdoc
+     *
+     * @return {Drupal.toolbar.ToolbarVisualView}
      */
     render: function () {
       this.updateTabs();
@@ -81,7 +90,7 @@
     /**
      * Responds to a toolbar tab click.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     onTabClick: function (event) {
       // If this tab has a tray associated with it, it is considered an
@@ -101,7 +110,7 @@
     /**
      * Toggles the orientation of a toolbar tray.
      *
-     * @param jQuery.Event event
+     * @param {jQuery.Event} event
      */
     onOrientationToggleClick: function (event) {
       var orientation = this.model.get('orientation');
diff --git a/core/modules/tour/js/tour.js b/core/modules/tour/js/tour.js
index 08e5688..d4f8bca 100644
--- a/core/modules/tour/js/tour.js
+++ b/core/modules/tour/js/tour.js
@@ -14,12 +14,14 @@
    *
    * It uses the query string for:
    * - tour: When ?tour=1 is present, the tour will start automatically
-   *         after the page has loaded.
+   *   after the page has loaded.
    * - tips: Pass ?tips=class in the url to filter the available tips to
-   *         the subset which match the given class.
+   *   the subset which match the given class.
    *
-   * Example:
-   *   http://example.com/foo?tour=1&tips=bar
+   * @example
+   * http://example.com/foo?tour=1&tips=bar
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.tour = {
     attach: function (context) {
@@ -35,7 +37,8 @@
           .on('change:isActive', function (model, isActive) {
             $(document).trigger((isActive) ? 'drupalTourStarted' : 'drupalTourStopped');
           })
-          // Initialization: check whether a tour is available on the current page.
+          // Initialization: check whether a tour is available on the current
+          // page.
           .set('tour', $(context).find('ol#tour'));
 
         // Start the tour immediately if toggled via query string.
@@ -46,31 +49,72 @@
     }
   };
 
-  Drupal.tour = Drupal.tour || {models: {}, views: {}};
+  /**
+   * @namespace
+   */
+  Drupal.tour = Drupal.tour || {
+
+    /**
+     * @namespace Drupal.tour.models
+     */
+    models: {},
+
+    /**
+     * @namespace Drupal.tour.views
+     */
+    views: {}
+  };
 
   /**
    * Backbone Model for tours.
+   *
+   * @constructor
+   *
+   * @augments Backbone.Model
    */
-  Drupal.tour.models.StateModel = Backbone.Model.extend({
-    defaults: {
-      // Indicates whether the Drupal root window has a tour.
+  Drupal.tour.models.StateModel = Backbone.Model.extend(/** @lends Drupal.tour.models.StateModel# */{
+
+    /**
+     * @type {object}
+     */
+    defaults: /** @lends Drupal.tour.models.StateModel# */{
+
+      /**
+       * Indicates whether the Drupal root window has a tour.
+       *
+       * @type {Array}
+       */
       tour: [],
-      // Indicates whether the tour is currently running.
+
+      /**
+       * Indicates whether the tour is currently running.
+       *
+       * @type {bool}
+       */
       isActive: false,
-      // Indicates which tour is the active one (necessary to cleanly stop).
+
+      /**
+       * Indicates which tour is the active one (necessary to cleanly stop).
+       *
+       * @type {Array}
+       */
       activeTour: []
     }
   });
 
-  /**
-   * Handles edit mode toggle interactions.
-   */
-  Drupal.tour.views.ToggleTourView = Backbone.View.extend({
+  Drupal.tour.views.ToggleTourView = Backbone.View.extend(/** @lends Drupal.tour.views.ToggleTourView# */{
 
+    /**
+     * @type {object}
+     */
     events: {'click': 'onClick'},
 
     /**
-     * Implements Backbone Views' initialize().
+     * Handles edit mode toggle interactions.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
      */
     initialize: function () {
       this.listenTo(this.model, 'change:tour change:isActive', this.render);
@@ -78,7 +122,9 @@
     },
 
     /**
-     * Implements Backbone Views' render().
+     * @inheritdoc
+     *
+     * @return {Drupal.tour.views.ToggleTourView}
      */
     render: function () {
       // Render the visibility.
@@ -103,7 +149,8 @@
           $tour.joyride({
             autoStart: true,
             postRideCallback: function () { that.model.set('isActive', false); },
-            template: { // HTML segments for tip layout
+            // HTML segments for tip layout.
+            template: {
               link: '<a href=\"#close\" class=\"joyride-close-tip\">&times;</a>',
               button: '<a href=\"#\" class=\"button button--primary joyride-next-tip\"></a>'
             }
@@ -119,6 +166,8 @@
 
     /**
      * Toolbar tab click event handler; toggles isActive.
+     *
+     * @param {jQuery.Event} event
      */
     onClick: function (event) {
       this.model.set('isActive', !this.model.get('isActive'));
@@ -129,8 +178,8 @@
     /**
      * Gets the tour.
      *
-     * @return jQuery
-     *   A jQuery element pointing to a <ol> containing tour items.
+     * @return {jQuery}
+     *   A jQuery element pointing to a `<ol>` containing tour items.
      */
     _getTour: function () {
       return this.model.get('tour');
@@ -139,7 +188,7 @@
     /**
      * Gets the relevant document as a jQuery element.
      *
-     * @return jQuery
+     * @return {jQuery}
      *   A jQuery element pointing to the document within which a tour would be
      *   started given the current state.
      */
@@ -148,22 +197,21 @@
     },
 
     /**
-     * Removes tour items for elements that don't have matching page elements or
-     * are explicitly filtered out via the 'tips' query string.
+     * Removes tour items for elements that don't have matching page elements.
      *
-     * Example:
-     *   http://example.com/foo?tips=bar
+     * Or that are explicitly filtered out via the 'tips' query string.
      *
-     *   The above will filter out tips that do not have a matching page element or
-     *   don't have the "bar" class.
+     * @example <caption>This will filter out tips that do not have a matching
+     * page element or don't have the "bar" class.</caption>
+     * http://example.com/foo?tips=bar
      *
-     * @param jQuery $tour
-     *   A jQuery element pointing to a <ol> containing tour items.
-     * @param jQuery $document
+     * @param {jQuery} $tour
+     *   A jQuery element pointing to a `<ol>` containing tour items.
+     * @param {jQuery} $document
      *   A jQuery element pointing to the document within which the elements
      *   should be sought.
      *
-     * @see _getDocument()
+     * @see Drupal.tour.views.ToggleTourView#_getDocument()
      */
     _removeIrrelevantTourItems: function ($tour, $document) {
       var removals = false;
diff --git a/core/modules/user/user.js b/core/modules/user/user.js
index 615689c..e988f74 100644
--- a/core/modules/user/user.js
+++ b/core/modules/user/user.js
@@ -1,10 +1,17 @@
+/**
+ * @file
+ * User behaviors.
+ */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
-   * Attach handlers to evaluate the strength of any password fields and to check
-   * that its confirmation is correct.
+   * Attach handlers to evaluate the strength of any password fields and to
+   * check that its confirmation is correct.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.password = {
     attach: function (context, settings) {
@@ -60,7 +67,8 @@
               $passwordSuggestions.html(result.message);
             }
 
-            // Only show the description box if a weakness exists in the password.
+            // Only show the description box if a weakness exists in the
+            // password.
             $passwordSuggestions.toggle(result.strength !== 100);
 
             // Adjust the length of the strength indicator.
@@ -94,6 +102,11 @@
    * Evaluate the strength of a user's password.
    *
    * Returns the estimated strength and the relevant output message.
+   *
+   * @param {string} password
+   * @param {object} translate
+   *
+   * @return {object}
    */
   Drupal.evaluatePasswordStrength = function (password, translate) {
     var indicatorText;
@@ -107,8 +120,8 @@
     var hasNumbers = /[0-9]/.test(password);
     var hasPunctuation = /[^a-zA-Z0-9]/.test(password);
 
-    // If there is a username edit box on the page, compare password to that, otherwise
-    // use value from the database.
+    // If there is a username edit box on the page, compare password to that,
+    // otherwise use value from the database.
     var $usernameBox = $('input.username');
     var username = ($usernameBox.length > 0) ? $usernameBox.val() : translate.username;
 
@@ -162,7 +175,8 @@
       strength = 5;
     }
 
-    // Based on the strength, work out what text should be shown by the password strength meter.
+    // Based on the strength, work out what text should be shown by the
+    // password strength meter.
     if (strength < 60) {
       indicatorText = translate.weak;
       indicatorClass = 'is-weak';
diff --git a/core/modules/user/user.permissions.js b/core/modules/user/user.permissions.js
index 6e473fa..4db8454 100644
--- a/core/modules/user/user.permissions.js
+++ b/core/modules/user/user.permissions.js
@@ -1,9 +1,16 @@
+/**
+ * @file
+ * User permission page behaviors.
+ */
+
 (function ($) {
 
   "use strict";
 
   /**
    * Shows checked and disabled checkboxes for inherited permissions.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.permissions = {
     attach: function (context) {
diff --git a/core/modules/views/js/ajax_view.js b/core/modules/views/js/ajax_view.js
index ae373bb..50be456 100644
--- a/core/modules/views/js/ajax_view.js
+++ b/core/modules/views/js/ajax_view.js
@@ -2,12 +2,16 @@
  * @file
  * Handles AJAX fetching of views, including filter submission and response.
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
-   * Attaches the AJAX behavior to Views exposed filter forms and key View links.
+   * Attaches the AJAX behavior to Views exposed filter forms and key View
+   * links.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.ViewsAjaxView = {};
   Drupal.behaviors.ViewsAjaxView.attach = function () {
@@ -21,11 +25,23 @@
     }
   };
 
+  /**
+   * @namespace
+   */
   Drupal.views = {};
+
+  /**
+   * @type {object.<string, Drupal.views.ajaxView>}
+   */
   Drupal.views.instances = {};
 
   /**
    * Javascript object for a certain view.
+   *
+   * @constructor
+   *
+   * @param {object} settings
+   * @param {string} settings.view_dom_id
    */
   Drupal.views.ajaxView = function (settings) {
     var selector = '.view-dom-id-' + settings.view_dom_id;
@@ -34,7 +50,8 @@
     // Retrieve the path to use for views' ajax.
     var ajax_path = drupalSettings.views.ajax_path;
 
-    // If there are multiple views this might've ended up showing up multiple times.
+    // If there are multiple views this might've ended up showing up multiple
+    // times.
     if (ajax_path.constructor.toString().indexOf("Array") !== -1) {
       ajax_path = ajax_path[0];
     }
@@ -45,7 +62,8 @@
       // Remove the question mark and Drupal path component if any.
       queryString = queryString.slice(1).replace(/q=[^&]+&?|&?render=[^&]+/, '');
       if (queryString !== '') {
-        // If there is a '?' in ajax_path, clean url are on and & should be used to add parameters.
+        // If there is a '?' in ajax_path, clean url are on and & should be
+        // used to add parameters.
         queryString = ((/\?/.test(ajax_path)) ? '&' : '?') + queryString;
       }
     }
@@ -86,6 +104,9 @@
     this.refreshViewAjax = Drupal.ajax(self_settings);
   };
 
+  /**
+   * @method
+   */
   Drupal.views.ajaxView.prototype.attachExposedFormAjax = function () {
     var button = $('input[type=submit], input[type=image]', this.$exposed_form);
     button = button[0];
@@ -97,6 +118,12 @@
     this.exposedFormAjax = Drupal.ajax(self_settings);
   };
 
+  /**
+   * @return {bool}
+   *   If there is at least one parent with a view class return false.
+   *
+   * @todo remove .size() replace with .length.
+   */
   Drupal.views.ajaxView.prototype.filterNestedViews = function () {
     // If there is at least one parent with a view class, this view
     // is nested (e.g., an attachment). Bail.
@@ -113,6 +140,9 @@
 
   /**
    * Attach the ajax behavior to a singe link.
+   *
+   * @param {string} id
+   * @param {HTMLElement} link
    */
   Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function (id, link) {
     var $link = $(link);
@@ -136,6 +166,12 @@
     this.pagerAjax = Drupal.ajax(self_settings);
   };
 
+  /**
+   *
+   * @param {Drupal.Ajax} [ajax]
+   * @param {object} response
+   * @param {string} response.selector
+   */
   Drupal.AjaxCommands.prototype.viewsScrollTop = function (ajax, response) {
     // Scroll to the top of the view. This will allow users
     // to browse newly loaded content after e.g. clicking a pager
@@ -149,7 +185,7 @@
     while ($(scrollTarget).scrollTop() === 0 && $(scrollTarget).parent()) {
       scrollTarget = $(scrollTarget).parent();
     }
-    // Only scroll upward
+    // Only scroll upward.
     if (offset.top - 10 < $(scrollTarget).scrollTop()) {
       $(scrollTarget).animate({scrollTop: (offset.top - 10)}, 500);
     }
diff --git a/core/modules/views/js/base.js b/core/modules/views/js/base.js
index d28b21d..d428229 100644
--- a/core/modules/views/js/base.js
+++ b/core/modules/views/js/base.js
@@ -2,14 +2,22 @@
  * @file
  * Some basic behaviors and utility functions for Views.
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
+  /**
+   * @namespace
+   */
   Drupal.Views = {};
 
   /**
    * Helper function to parse a querystring.
+   *
+   * @param {string} query
+   *
+   * @return {object}
    */
   Drupal.Views.parseQueryString = function (query) {
     var args = {};
@@ -31,6 +39,11 @@
 
   /**
    * Helper function to return a view's arguments based on a path.
+   *
+   * @param {string} href
+   * @param {string} viewPath
+   *
+   * @return {object}
    */
   Drupal.Views.parseViewArgs = function (href, viewPath) {
     var returnObj = {};
@@ -46,12 +59,16 @@
 
   /**
    * Strip off the protocol plus domain from an href.
+   *
+   * @param {string} href
+   *
+   * @return {string}
    */
   Drupal.Views.pathPortion = function (href) {
     // Remove e.g. http://example.com if present.
     var protocol = window.location.protocol;
     if (href.substring(0, protocol.length) === protocol) {
-      // 2 is the length of the '//' that normally follows the protocol
+      // 2 is the length of the '//' that normally follows the protocol.
       href = href.substring(href.indexOf('/', protocol.length + 2));
     }
     return href;
@@ -59,6 +76,10 @@
 
   /**
    * Return the Drupal path portion of an href.
+   *
+   * @param {string} href
+   *
+   * @return {string}
    */
   Drupal.Views.getPath = function (href) {
     href = Drupal.Views.pathPortion(href);
diff --git a/core/modules/views/js/views-contextual.js b/core/modules/views/js/views-contextual.js
index e5eb14b..e0fe169 100644
--- a/core/modules/views/js/views-contextual.js
+++ b/core/modules/views/js/views-contextual.js
@@ -2,10 +2,15 @@
  * @file
  * Javascript related to contextual links.
  */
+
 (function ($) {
 
   "use strict";
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.viewsContextualLinks = {
     attach: function (context) {
       var id = $('body').attr('data-views-page-contextual-id');
diff --git a/core/modules/views/tests/modules/views_test_data/views_cache.test.js b/core/modules/views/tests/modules/views_test_data/views_cache.test.js
index 8dd17c1..4089267 100644
--- a/core/modules/views/tests/modules/views_test_data/views_cache.test.js
+++ b/core/modules/views/tests/modules/views_test_data/views_cache.test.js
@@ -1,5 +1,8 @@
 /**
  * @file
  * Just a placeholder file for the test.
+ *
  * @see ViewsCacheTest::testHeaderStorage
+ *
+ * @ignore
  */
diff --git a/core/modules/views_ui/js/ajax.js b/core/modules/views_ui/js/ajax.js
index 492b63e..3079bad 100644
--- a/core/modules/views_ui/js/ajax.js
+++ b/core/modules/views_ui/js/ajax.js
@@ -2,15 +2,30 @@
  * @file
  * Handles AJAX submission and response in Views UI.
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
+  /**
+   *
+   * @param {Drupal.Ajax} [ajax]
+   * @param {object} response
+   * @param {string} response.selector
+   * @param {number} [status]
+   */
   Drupal.AjaxCommands.prototype.viewsHighlight = function (ajax, response, status) {
     $('.hilited').removeClass('hilited');
     $(response.selector).addClass('hilited');
   };
 
+  /**
+   *
+   * @param {Drupal.Ajax} [ajax]
+   * @param {object} response
+   * @param {bool} response.changed
+   * @param {number} [status]
+   */
   Drupal.AjaxCommands.prototype.viewsShowButtons = function (ajax, response, status) {
     $('div.views-edit-view div.form-actions').removeClass('js-hide');
     if (response.changed) {
@@ -18,12 +33,26 @@
     }
   };
 
+  /**
+   *
+   * @param {Drupal.Ajax} [ajax]
+   * @param {object} [response]
+   * @param {number} [status]
+   */
   Drupal.AjaxCommands.prototype.viewsTriggerPreview = function (ajax, response, status) {
     if ($('input#edit-displays-live-preview').is(':checked')) {
       $('#preview-submit').trigger('click');
     }
   };
 
+  /**
+   *
+   * @param {Drupal.Ajax} [ajax]
+   * @param {object} response
+   * @param {string} response.siteName
+   * @param {string} response.title
+   * @param {number} [status]
+   */
   Drupal.AjaxCommands.prototype.viewsReplaceTitle = function (ajax, response, status) {
     var doc = document;
     // For the <title> element, make a best-effort attempt to replace the page
@@ -40,7 +69,9 @@
   };
 
   /**
-   * Get rid of irritating tabledrag messages
+   * Get rid of irritating tabledrag messages.
+   *
+   * @return {Array}
    */
   Drupal.theme.tableDragChangedWarning = function () {
     return [];
@@ -48,6 +79,8 @@
 
   /**
    * Trigger preview when the "live preview" checkbox is checked.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.livePreview = {
     attach: function (context) {
@@ -61,6 +94,8 @@
 
   /**
    * Sync preview display.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.syncPreviewDisplay = {
     attach: function (context) {
@@ -74,6 +109,10 @@
     }
   };
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.viewsAjax = {
     collapseReplaced: false,
     attach: function (context, settings) {
diff --git a/core/modules/views_ui/js/dialog.views.js b/core/modules/views_ui/js/dialog.views.js
index bdfd185..6f22e7f 100644
--- a/core/modules/views_ui/js/dialog.views.js
+++ b/core/modules/views_ui/js/dialog.views.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Views dialog behaviors.
+ */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
@@ -25,6 +30,10 @@
     }
   }
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.viewsModalContent = {
     attach: function (context) {
       $('body').once('viewsDialog').on('dialogContentResize.viewsDialog', '.ui-dialog-content', handleDialogResize);
diff --git a/core/modules/views_ui/js/views-admin.js b/core/modules/views_ui/js/views-admin.js
index e1d0750..89b4299 100644
--- a/core/modules/views_ui/js/views-admin.js
+++ b/core/modules/views_ui/js/views-admin.js
@@ -2,14 +2,20 @@
  * @file
  * Some basic behaviors and utility functions for Views UI.
  */
+
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
+  /**
+   * @namespace
+   */
   Drupal.viewsUi = {};
 
   /**
    * Improve the user experience of the views edit interface.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewsUiEditView = {
     attach: function () {
@@ -22,8 +28,10 @@
   };
 
   /**
-   * In the add view wizard, use the view name to prepopulate form fields such as
-   * page title and menu link.
+   * In the add view wizard, use the view name to prepopulate form fields such
+   * as page title and menu link.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewsUiAddView = {
     attach: function (context) {
@@ -33,8 +41,8 @@
       var replace = '-';
       var suffix;
 
-      // The page title, block title, and menu link fields can all be prepopulated
-      // with the view name - no regular expression needed.
+      // The page title, block title, and menu link fields can all be
+      // prepopulated with the view name - no regular expression needed.
       var $fields = $context.find('[id^="edit-page-title"], [id^="edit-block-title"], [id^="edit-page-link-properties-title"]');
       if ($fields.length) {
         if (!this.fieldsFiller) {
@@ -42,10 +50,11 @@
         }
         else {
           // After an AJAX response, this.fieldsFiller will still have event
-          // handlers bound to the old version of the form fields (which don't exist
-          // anymore). The event handlers need to be unbound and then rebound to the
-          // new markup. Note that jQuery.live is difficult to make work in this
-          // case because the IDs of the form fields change on every AJAX response.
+          // handlers bound to the old version of the form fields (which don't
+          // exist anymore). The event handlers need to be unbound and then
+          // rebound to the new markup. Note that jQuery.live is difficult to
+          // make work in this case because the IDs of the form fields change
+          // on every AJAX response.
           this.fieldsFiller.rebind($fields);
         }
       }
@@ -61,8 +70,8 @@
         }
       }
 
-      // Populate the RSS feed field with a URLified version of the view name, and
-      // an .xml suffix (to make it unique).
+      // Populate the RSS feed field with a URLified version of the view name,
+      // and an .xml suffix (to make it unique).
       var $feedField = $context.find('[id^="edit-page-feed-properties-path"]');
       if ($feedField.length) {
         if (!this.feedFiller) {
@@ -81,38 +90,75 @@
    *
    * Prepopulates a form field based on the view name.
    *
-   * @param $target
+   * @constructor
+   *
+   * @param {jQuery} $target
    *   A jQuery object representing the form field or fields to prepopulate.
-   * @param exclude
-   *   (optional) A regular expression representing characters to exclude from
+   * @param {bool} [exclude=false]
+   *   A regular expression representing characters to exclude from
    *   the target field.
-   * @param replace
-   *   (optional) A string to use as the replacement value for disallowed
-   *   characters.
-   * @param suffix
-   *   (optional) A suffix to append at the end of the target field content.
+   * @param {string} [replace='']
+   *   A string to use as the replacement value for disallowed characters.
+   * @param {string} [suffix='']
+   *   A suffix to append at the end of the target field content.
    */
   Drupal.viewsUi.FormFieldFiller = function ($target, exclude, replace, suffix) {
+
+    /**
+     *
+     * @type {jQuery}
+     */
     this.source = $('#edit-label');
+
+    /**
+     *
+     * @type {jQuery}
+     */
     this.target = $target;
+
+    /**
+     *
+     * @type {bool}
+     */
     this.exclude = exclude || false;
+
+    /**
+     *
+     * @type {string}
+     */
     this.replace = replace || '';
+
+    /**
+     *
+     * @type {string}
+     */
     this.suffix = suffix || '';
 
     // Create bound versions of this instance's object methods to use as event
-    // handlers. This will let us easily unbind those specific handlers later on.
-    // NOTE: jQuery.proxy will not work for this because it assumes we want only
-    // one bound version of an object method, whereas we need one version per
-    // object instance.
+    // handlers. This will let us easily unbind those specific handlers later
+    // on. NOTE: jQuery.proxy will not work for this because it assumes we want
+    // only one bound version of an object method, whereas we need one version
+    // per object instance.
     var self = this;
+
+    /**
+     *
+     * @return {*}
+     */
     this.populate = function () { return self._populate.call(self); };
+
+    /**
+     *
+     * @return {*}
+     */
     this.unbind = function () { return self._unbind.call(self); };
 
     this.bind();
     // Object constructor; no return value.
   };
 
-  $.extend(Drupal.viewsUi.FormFieldFiller.prototype, {
+  $.extend(Drupal.viewsUi.FormFieldFiller.prototype, /** @lends Drupal.viewsUi.FormFieldFiller# */{
+
     /**
      * Bind the form-filling behavior.
      */
@@ -126,6 +172,8 @@
 
     /**
      * Get the source form field value as altered by the passed-in parameters.
+     *
+     * @return {string}
      */
     getTransliterated: function () {
       var from = this.source.val();
@@ -157,7 +205,9 @@
     },
 
     /**
-     * Bind event handlers to the new form fields, after they're replaced via AJAX.
+     * Bind event handlers to new form fields, after they're replaced via Ajax.
+     *
+     * @param {jQuery} $fields
      */
     rebind: function ($fields) {
       this.target = $fields;
@@ -165,6 +215,10 @@
     }
   });
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.addItemForm = {
     attach: function (context) {
       var $context = $(context);
@@ -174,21 +228,45 @@
         $form = $context.find('form[id^="views-ui-add-handler-form"]');
       }
       if ($form.once('views-ui-add-handler-form').length) {
-        // If we we have an unprocessed views-ui-add-handler-form, let's instantiate.
+        // If we we have an unprocessed views-ui-add-handler-form, let's
+        // instantiate.
         new Drupal.viewsUi.AddItemForm($form);
       }
     }
   };
 
+  /**
+   *
+   * @constructor
+   *
+   * @param {jQuery} $form
+   */
   Drupal.viewsUi.AddItemForm = function ($form) {
+
+    /**
+     *
+     * @type {jQuery}
+     */
     this.$form = $form;
     this.$form.find('.views-filterable-options :checkbox').on('click', $.proxy(this.handleCheck, this));
-    // Find the wrapper of the displayed text.
+
+    /**
+     * Find the wrapper of the displayed text.
+     */
     this.$selected_div = this.$form.find('.views-selected-options').parent();
     this.$selected_div.hide();
+
+    /**
+     *
+     * @type {Array}
+     */
     this.checkedItems = [];
   };
 
+  /**
+   *
+   * @param {jQuery.Event} event
+   */
   Drupal.viewsUi.AddItemForm.prototype.handleCheck = function (event) {
     var $target = $(event.target);
     var label = $.trim($target.next().text());
@@ -199,7 +277,8 @@
     }
     else {
       var position = $.inArray(label, this.checkedItems);
-      // Delete the item from the list and make sure that the list doesn't have undefined items left.
+      // Delete the item from the list and make sure that the list doesn't have
+      // undefined items left.
       for (var i = 0; i < this.checkedItems.length; i++) {
         if (i === position) {
           this.checkedItems.splice(i, 1);
@@ -226,9 +305,12 @@
   };
 
   /**
-   * The input field items that add displays must be rendered as <input> elements.
-   * The following behavior detaches the <input> elements from the DOM, wraps them
-   * in an unordered list, then appends them to the list of tabs.
+   * The input field items that add displays must be rendered as `<input>`
+   * elements. The following behavior detaches the `<input>` elements from the
+   * DOM, wraps them in an unordered list, then appends them to the list of
+   * tabs.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewsUiRenderAddViewButton = {
     attach: function (context) {
@@ -242,10 +324,9 @@
       var $displayButtons = $menu.nextAll('input.add-display').detach();
       $displayButtons.appendTo($addDisplayDropdown.find('.action-list')).wrap('<li>')
         .parent().eq(0).addClass('first').end().eq(-1).addClass('last');
-      // Remove the 'Add ' prefix from the button labels since they're being placed
-      // in an 'Add' dropdown.
-      // @todo This assumes English, but so does $addDisplayDropdown above. Add
-      //   support for translation.
+      // Remove the 'Add ' prefix from the button labels since they're being
+      // placed in an 'Add' dropdown. @todo This assumes English, but so does
+      // $addDisplayDropdown above. Add support for translation.
       $displayButtons.each(function () {
         var label = $(this).val();
         if (label.substr(0, 4) === 'Add ') {
@@ -254,7 +335,7 @@
       });
       $addDisplayDropdown.appendTo($menu);
 
-      // Add the click handler for the add display button
+      // Add the click handler for the add display button.
       $menu.find('li.add > a').on('click', function (event) {
         event.preventDefault();
         var $trigger = $(this);
@@ -278,14 +359,22 @@
   };
 
   /**
-   * @note [@jessebeach] I feel like the following should be a more generic function and
-   * not written specifically for this UI, but I'm not sure where to put it.
+   * @param {jQuery} $trigger
+   *
+   *
+   * @note [@jessebeach] I feel like the following should be a more generic
+   *   function and not written specifically for this UI, but I'm not sure
+   *   where to put it.
    */
   Drupal.behaviors.viewsUiRenderAddViewButton.toggleMenu = function ($trigger) {
     $trigger.parent().toggleClass('open');
     $trigger.next().slideToggle('fast');
   };
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.viewsUiSearchOptions = {
     attach: function (context) {
       var $context = $(context);
@@ -305,17 +394,33 @@
    * Constructor for the viewsUi.OptionsSearch object.
    *
    * The OptionsSearch object filters the available options on a form according
-   * to the user's search term. Typing in "taxonomy" will show only those options
-   * containing "taxonomy" in their label.
+   * to the user's search term. Typing in "taxonomy" will show only those
+   * options containing "taxonomy" in their label.
+   *
+   * @constructor
+   *
+   * @param {jQuery} $form
    */
   Drupal.viewsUi.OptionsSearch = function ($form) {
+
+    /**
+     *
+     * @type {jQuery}
+     */
     this.$form = $form;
-    // Add a keyup handler to the search box.
+
+    /**
+     * Add a keyup handler to the search box.
+     */
     this.$searchBox = this.$form.find('#edit-override-controls-options-search');
     this.$searchBox.on('keyup', $.proxy(this.handleKeyup, this));
-    // Get a list of option labels and their corresponding divs and maintain it
-    // in memory, so we have as little overhead as possible at keyup time.
+
+    /**
+     * Get a list of option labels and their corresponding divs and maintain it
+     * in memory, so we have as little overhead as possible at keyup time.
+     */
     this.options = this.getOptions(this.$form.find('.filterable-option'));
+
     // Restripe on initial loading.
     this.handleKeyup();
     // Trap the ENTER key in the search box so that it doesn't submit the form.
@@ -326,13 +431,16 @@
     });
   };
 
-  $.extend(Drupal.viewsUi.OptionsSearch.prototype, {
+  $.extend(Drupal.viewsUi.OptionsSearch.prototype, /** @lends Drupal.viewsUi.OptionsSearch# */{
+
     /**
      * Assemble a list of all the filterable options on the form.
      *
-     * @param $allOptions
-     *   A $ object representing the rows of filterable options to be
+     * @param {jQuery} $allOptions
+     *   A jQuery object representing the rows of filterable options to be
      *   shown and hidden depending on the user's search terms.
+     *
+     * @return {Array}
      */
     getOptions: function ($allOptions) {
       var $label;
@@ -357,15 +465,18 @@
     },
 
     /**
-     * Keyup handler for the search box that hides or shows the relevant options.
+     * Keyup handler for the search box that hides or shows the relevant
+     * options.
+     *
+     * @param {jQuery.Event} event
      */
     handleKeyup: function (event) {
       var found;
       var option;
       var zebraClass;
 
-      // Determine the user's search query. The search text has been converted to
-      // lowercase.
+      // Determine the user's search query. The search text has been converted
+      // to lowercase.
       var search = this.$searchBox.val().toLowerCase();
       var words = search.split(' ');
       var wordsLength = words.length;
@@ -402,6 +513,10 @@
     }
   });
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.viewsUiPreview = {
     attach: function (context) {
       // Only act on the edit view form.
@@ -410,9 +525,10 @@
         return;
       }
 
-      // If the display has no contextual filters, hide the form where you enter
-      // the contextual filters for the live preview. If it has contextual filters,
-      // show the form.
+      // If the display has no contextual filters, hide the form where you
+      // enter
+      // the contextual filters for the live preview. If it has contextual
+      // filters, show the form.
       var $contextualFilters = $contextualFiltersBucket.find('.views-display-setting a');
       if ($contextualFilters.length) {
         $('#preview-args').parent().show();
@@ -428,6 +544,10 @@
     }
   };
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.viewsUiRearrangeFilter = {
     attach: function (context) {
       // Only act on the rearrange filter form.
@@ -445,19 +565,49 @@
 
   /**
    * Improve the UI of the rearrange filters dialog box.
+   *
+   * @constructor
+   *
+   * @param {jQuery} $table
+   * @param {jQuery} $operator
    */
   Drupal.viewsUi.RearrangeFilterHandler = function ($table, $operator) {
-    // Keep a reference to the <table> being altered and to the div containing
-    // the filter groups operator dropdown (if it exists).
+
+    /**
+     * Keep a reference to the `<table>` being altered and to the div containing
+     * the filter groups operator dropdown (if it exists).
+     */
     this.table = $table;
+
+    /**
+     *
+     * @type {jQuery}
+     */
     this.operator = $operator;
+
+    /**
+     *
+     * @type {bool}
+     */
     this.hasGroupOperator = this.operator.length > 0;
 
-    // Keep a reference to all draggable rows within the table.
+    /**
+     * Keep a reference to all draggable rows within the table.
+     *
+     * @type {jQuery}
+     */
     this.draggableRows = $table.find('.draggable');
 
-    // Keep a reference to the buttons for adding and removing filter groups.
+    /**
+     * Keep a reference to the buttons for adding and removing filter groups.
+     *
+     * @type {jQuery}
+     */
     this.addGroupButton = $('input#views-add-group');
+
+    /**
+     * @type {jQuery}
+     */
     this.removeGroupButtons = $table.find('input.views-remove-group');
 
     // Add links that duplicate the functionality of the (hidden) add and remove
@@ -467,14 +617,17 @@
     // When there is a filter groups operator dropdown on the page, create
     // duplicates of the dropdown between each pair of filter groups.
     if (this.hasGroupOperator) {
+      /**
+       * @type {jQuery}
+       */
       this.dropdowns = this.duplicateGroupsOperator();
       this.syncGroupsOperators();
     }
 
-    // Add methods to the tableDrag instance to account for operator cells (which
-    // span multiple rows), the operator labels next to each filter (e.g., "And"
-    // or "Or"), the filter groups, and other special aspects of this tableDrag
-    // instance.
+    // Add methods to the tableDrag instance to account for operator cells
+    // (which span multiple rows), the operator labels next to each filter
+    // (e.g., "And" or "Or"), the filter groups, and other special aspects of
+    // this tableDrag instance.
     this.modifyTableDrag();
 
     // Initialize the operator labels (e.g., "And" or "Or") that are displayed
@@ -486,36 +639,37 @@
       .on('change.views-rearrange-filter-handler', $.proxy(this, 'redrawOperatorLabels'));
 
     // Bind handlers so that when a "Remove" link is clicked, we:
-    // - Update the rowspans of cells containing an operator dropdown (since they
-    //   need to change to reflect the number of rows in each group).
-    // - Redraw the operator labels next to the filters in the group (since the
-    //   filter that is currently displayed last in each group is not supposed to
-    //   have a label display next to it).
+    // - Update the rowspans of cells containing an operator dropdown (since
+    // they need to change to reflect the number of rows in each group). -
+    // Redraw the operator labels next to the filters in the group (since the
+    // filter that is currently displayed last in each group is not supposed to
+    // have a label display next to it).
     $table.find('a.views-groups-remove-link')
       .once('views-rearrange-filter-handler')
       .on('click.views-rearrange-filter-handler', $.proxy(this, 'updateRowspans'))
       .on('click.views-rearrange-filter-handler', $.proxy(this, 'redrawOperatorLabels'));
   };
 
-  $.extend(Drupal.viewsUi.RearrangeFilterHandler.prototype, {
+  $.extend(Drupal.viewsUi.RearrangeFilterHandler.prototype, /** @lends Drupal.viewsUi.RearrangeFilterHandler# */{
+
     /**
      * Insert links that allow filter groups to be added and removed.
      */
     insertAddRemoveFilterGroupLinks: function () {
 
-      // Insert a link for adding a new group at the top of the page, and make it
-      // match the action link styling used in a typical page.html.twig. Since
-      // Drupal does not provide a theme function for this markup this is the best
-      // we can do.
+      // Insert a link for adding a new group at the top of the page, and make
+      // it match the action link styling used in a typical page.html.twig.
+      // Since Drupal does not provide a theme function for this markup this is
+      // the best we can do.
       $('<ul class="action-links"><li><a id="views-add-group-link" href="#">' + this.addGroupButton.val() + '</a></li></ul>')
         .prependTo(this.table.parent())
-        // When the link is clicked, dynamically click the hidden form button for
-        // adding a new filter group.
+        // When the link is clicked, dynamically click the hidden form button
+        // for adding a new filter group.
         .once('views-rearrange-filter-handler')
         .on('click.views-rearrange-filter-handler', $.proxy(this, 'clickAddGroupButton'));
 
-      // Find each (visually hidden) button for removing a filter group and insert
-      // a link next to it.
+      // Find each (visually hidden) button for removing a filter group and
+      // insert a link next to it.
       var length = this.removeGroupButtons.length;
       var i;
       for (i = 0; i < length; i++) {
@@ -532,11 +686,13 @@
 
     /**
      * Dynamically click the button that adds a new filter group.
+     *
+     * @param {jQuery.Event} event
      */
     clickAddGroupButton: function (event) {
       // Due to conflicts between Drupal core's AJAX system and the Views AJAX
-      // system, the only way to get this to work seems to be to trigger both the
-      // mousedown and submit events.
+      // system, the only way to get this to work seems to be to trigger both
+      // the mousedown and submit events.
       this.addGroupButton
         .trigger('mousedown')
         .trigger('submit');
@@ -546,7 +702,7 @@
     /**
      * Dynamically click a button for removing a filter group.
      *
-     * @param event
+     * @param {jQuery.Event} event
      *   Event being triggered, with event.data.buttonId set to the ID of the
      *   form button that should be clicked.
      */
@@ -561,6 +717,8 @@
     /**
      * Move the groups operator so that it's between the first two groups, and
      * duplicate it between any subsequent groups.
+     *
+     * @return {jQuery}
      */
     duplicateGroupsOperator: function () {
       var dropdowns;
@@ -574,7 +732,8 @@
       this.operator.find('label').add('div.description').addClass('visually-hidden');
       this.operator.find('select').addClass('form-select');
 
-      // Keep a list of the operator dropdowns, so we can sync their behavior later.
+      // Keep a list of the operator dropdowns, so we can sync their behavior
+      // later.
       dropdowns = this.operator;
 
       // Move the operator to a new row just above the second group.
@@ -582,7 +741,8 @@
       this.operator.find('label').add('div.description').addClass('visually-hidden');
       this.operator.find('select').addClass('form-select');
 
-      // Keep a list of the operator dropdowns, so we can sync their behavior later.
+      // Keep a list of the operator dropdowns, so we can sync their behavior
+      // later.
       dropdowns = this.operator;
 
       // Move the operator to a new row just above the second group.
@@ -612,7 +772,8 @@
      */
     syncGroupsOperators: function () {
       if (this.dropdowns.length < 2) {
-        // We only have one dropdown (or none at all), so there's nothing to sync.
+        // We only have one dropdown (or none at all), so there's nothing to
+        // sync.
         return;
       }
 
@@ -623,6 +784,8 @@
      * Click handler for the operators that appear between filter groups.
      *
      * Forces all operator dropdowns to have the same value.
+     *
+     * @param {jQuery.Event} event
      */
     operatorChangeHandler: function (event) {
       var $target = $(event.target);
@@ -632,6 +795,9 @@
       operators.val($target.val());
     },
 
+    /**
+     * @method
+     */
     modifyTableDrag: function () {
       var tableDrag = Drupal.tableDrag['views-rearrange-filters'];
       var filterHandler = this;
@@ -639,19 +805,22 @@
       /**
        * Override the row.onSwap method from tabledrag.js.
        *
-       * When a row is dragged to another place in the table, several things need
-       * to occur.
-       * - The row needs to be moved so that it's within one of the filter groups.
-       * - The operator cells that span multiple rows need their rowspan attributes
-       *   updated to reflect the number of rows in each group.
-       * - The operator labels that are displayed next to each filter need to be
+       * When a row is dragged to another place in the table, several things
+       * need to occur.
+       * - The row needs to be moved so that it's within one of the filter
+       * groups.
+       * - The operator cells that span multiple rows need their rowspan
+       * attributes updated to reflect the number of rows in each group.
+       * - The operator labels that are displayed next to each filter need to
+       * be
        *   redrawn, to account for the row's new location.
        */
       tableDrag.row.prototype.onSwap = function () {
         if (filterHandler.hasGroupOperator) {
-          // Make sure the row that just got moved (this.group) is inside one of
-          // the filter groups (i.e. below an empty marker row or a draggable). If
-          // it isn't, move it down one.
+          // Make sure the row that just got moved (this.group) is inside one
+          // of
+          // the filter groups (i.e. below an empty marker row or a draggable).
+          // If it isn't, move it down one.
           var thisRow = $(this.group);
           var previousRow = thisRow.prev('tr');
           if (previousRow.length && !previousRow.hasClass('group-message') && !previousRow.hasClass('draggable')) {
@@ -672,22 +841,22 @@
        * Override the onDrop method from tabledrag.js.
        */
       tableDrag.onDrop = function () {
-        // If the tabledrag change marker (i.e., the "*") has been inserted inside
-        // a row after the operator label (i.e., "And" or "Or") rearrange the items
-        // so the operator label continues to appear last.
+        // If the tabledrag change marker (i.e., the "*") has been inserted
+        // inside a row after the operator label (i.e., "And" or "Or")
+        // rearrange the items so the operator label continues to appear last.
         var changeMarker = $(this.oldRowElement).find('.tabledrag-changed');
         if (changeMarker.length) {
-          // Search for occurrences of the operator label before the change marker,
-          // and reverse them.
+          // Search for occurrences of the operator label before the change
+          // marker, and reverse them.
           var operatorLabel = changeMarker.prevAll('.views-operator-label');
           if (operatorLabel.length) {
             operatorLabel.insertAfter(changeMarker);
           }
         }
 
-        // Make sure the "group" dropdown is properly updated when rows are dragged
-        // into an empty filter group. This is borrowed heavily from the block.js
-        // implementation of tableDrag.onDrop().
+        // Make sure the "group" dropdown is properly updated when rows are
+        // dragged into an empty filter group. This is borrowed heavily from
+        // the block.js implementation of tableDrag.onDrop().
         var groupRow = $(this.rowObject.element).prevAll('tr.group-message').get(0);
         var groupName = groupRow.className.replace(/([^ ]+[ ]+)*group-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
         var groupField = $('select.views-group-select', this.rowObject.element);
@@ -704,29 +873,31 @@
      */
     redrawOperatorLabels: function () {
       for (var i = 0; i < this.draggableRows.length; i++) {
-        // Within the row, the operator labels are displayed inside the first table
-        // cell (next to the filter name).
+        // Within the row, the operator labels are displayed inside the first
+        // table cell (next to the filter name).
         var $draggableRow = $(this.draggableRows[i]);
         var $firstCell = $draggableRow.find('td').eq(0);
         if ($firstCell.length) {
           // The value of the operator label ("And" or "Or") is taken from the
-          // first operator dropdown we encounter, going backwards from the current
-          // row. This dropdown is the one associated with the current row's filter
-          // group.
+          // first operator dropdown we encounter, going backwards from the
+          // current row. This dropdown is the one associated with the current
+          // row's filter group.
           var operatorValue = $draggableRow.prevAll('.views-group-title').find('option:selected').html();
           var operatorLabel = '<span class="views-operator-label">' + operatorValue + '</span>';
           // If the next visible row after this one is a draggable filter row,
           // display the operator label next to the current row. (Checking for
-          // visibility is necessary here since the "Remove" links hide the removed
-          // row but don't actually remove it from the document).
+          // visibility is necessary here since the "Remove" links hide the
+          // removed row but don't actually remove it from the document).
           var $nextRow = $draggableRow.nextAll(':visible').eq(0);
           var $existingOperatorLabel = $firstCell.find('.views-operator-label');
           if ($nextRow.hasClass('draggable')) {
-            // If an operator label was already there, replace it with the new one.
+            // If an operator label was already there, replace it with the new
+            // one.
             if ($existingOperatorLabel.length) {
               $existingOperatorLabel.replaceWith(operatorLabel);
             }
-            // Otherwise, append the operator label to the end of the table cell.
+            // Otherwise, append the operator label to the end of the table
+            // cell.
             else {
               $firstCell.append(operatorLabel);
             }
@@ -744,7 +915,8 @@
     },
 
     /**
-     * Update the rowspan attribute of each cell containing an operator dropdown.
+     * Update the rowspan attribute of each cell containing an operator
+     * dropdown.
      */
     updateRowspans: function () {
       var $row;
@@ -768,7 +940,8 @@
           $operatorCell.attr('rowspan', 2);
         }
         else if ($row.hasClass('draggable') && $row.is(':visible')) {
-          // We've found a visible filter row, so we now know the group isn't empty.
+          // We've found a visible filter row, so we now know the group isn't
+          // empty.
           draggableCount++;
           $currentEmptyRow.removeClass('group-empty').addClass('group-populated');
           // The operator cell should span all draggable rows, plus the title.
@@ -780,6 +953,8 @@
 
   /**
    * Add a select all checkbox, which checks each checkbox at once.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewsFilterConfigSelectAll = {
     attach: function (context) {
@@ -807,6 +982,8 @@
 
   /**
    * Remove icon class from elements that are themed as buttons or dropbuttons.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewsRemoveIconClass = {
     attach: function (context) {
@@ -816,6 +993,8 @@
 
   /**
    * Change "Expose filter" buttons into checkboxes.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewsUiCheckboxify = {
     attach: function (context, settings) {
@@ -831,6 +1010,8 @@
   /**
    * Change the default widget to select the default group according to the
    * selected widget for the exposed group.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewsUiChangeDefaultWidget = {
     attach: function () {
@@ -856,9 +1037,12 @@
   };
 
   /**
-   * Attaches an expose filter button to a checkbox that triggers its click event.
+   * Attaches an expose filter button to a checkbox that triggers its click
+   * event.
+   *
+   * @constructor
    *
-   * @param button
+   * @param {HTMLElement} button
    *   The DOM object representing the button to be checkboxified.
    */
   Drupal.viewsUi.Checkboxifier = function (button) {
@@ -875,6 +1059,8 @@
 
   /**
    * When the checkbox is checked or unchecked, simulate a button press.
+   *
+   * @param {jQuery.Event} e
    */
   Drupal.viewsUi.Checkboxifier.prototype.clickHandler = function (e) {
     this.$button
@@ -884,6 +1070,8 @@
 
   /**
    * Change the Apply button text based upon the override select state.
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewsUiOverrideSelect = {
     attach: function (context) {
@@ -919,11 +1107,15 @@
     }
   };
 
+  /**
+   *
+   * @type {Drupal~behavior}
+   */
   Drupal.behaviors.viewsUiHandlerRemoveLink = {
     attach: function (context) {
       var $context = $(context);
-      // Handle handler deletion by looking for the hidden checkbox and hiding the
-      // row.
+      // Handle handler deletion by looking for the hidden checkbox and hiding
+      // the row.
       $context.find('a.views-remove-link').once('views').on('click', function (event) {
         var id = $(this).attr('id').replace('views-remove-link-', '');
         $context.find('#views-row-' + id).hide();
@@ -931,8 +1123,8 @@
         event.preventDefault();
       });
 
-      // Handle display deletion by looking for the hidden checkbox and hiding the
-      // row.
+      // Handle display deletion by looking for the hidden checkbox and hiding
+      // the row.
       $context.find('a.display-remove-link').once('display').on('click', function (event) {
         var id = $(this).attr('id').replace('display-remove-link-', '');
         $context.find('#display-row-' + id).hide();
diff --git a/core/modules/views_ui/js/views_ui.listing.js b/core/modules/views_ui/js/views_ui.listing.js
index 0374891..4c13d79 100644
--- a/core/modules/views_ui/js/views_ui.listing.js
+++ b/core/modules/views_ui/js/views_ui.listing.js
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * Views listing behaviors.
+ */
+
 (function ($, Drupal) {
 
   "use strict";
@@ -8,6 +13,8 @@
    * Text search input: input.views-filter-text
    * Target table:      input.views-filter-text[data-table]
    * Source text:       .views-table-filter-text-source
+   *
+   * @type {Drupal~behavior}
    */
   Drupal.behaviors.viewTableFilterByText = {
     attach: function (context, settings) {
