From cbd01844a2d12ecb4231067b48c2724e34495dde Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Mon, 23 Mar 2015 10:29:17 +0000
Subject: [PATCH] Issue #2348321 by RobLoach, nod_: Upgrade to jQuery Once 2.x

---
 core/assets/vendor/jquery-once/jquery.once.js | 229 ++++++++++++------
 core/core.libraries.yml                       |   4 +-
 core/misc/ajax.js                             |   6 +-
 core/misc/collapse.js                         |   2 +-
 core/misc/drupal.js                           |   8 +-
 core/misc/tabledrag.js                        |   6 +-
 core/misc/tableselect.js                      |   2 +-
 core/misc/vertical-tabs.js                    |   2 +-
 core/modules/block/js/block.admin.js          |   2 +-
 core/modules/block/js/block.js                |   2 +-
 core/modules/ckeditor/js/ckeditor.admin.js    |   6 +-
 .../content_translation.admin.js              |   2 +-
 core/modules/editor/js/editor.admin.js        |   2 +-
 core/modules/editor/js/editor.js              |   4 +-
 core/modules/field_ui/field_ui.js             |   2 +-
 core/modules/file/file.js                     |   4 +-
 core/modules/filter/filter.admin.js           |   2 +-
 .../filter/filter.filter_html.admin.js        |   2 +-
 core/modules/menu_ui/menu_ui.admin.js         |   6 +-
 core/modules/quickedit/js/quickedit.js        |   2 +-
 core/modules/simpletest/simpletest.js         |   4 +-
 core/modules/text/text.js                     |   2 +-
 core/modules/toolbar/js/toolbar.js            |   2 +-
 core/modules/tour/js/tour.js                  |   3 +-
 core/modules/user/user.js                     |   2 +-
 core/modules/user/user.permissions.js         |   2 +-
 core/modules/views/js/ajax_view.js            |   4 +-
 core/modules/views_ui/js/views-admin.js       |   8 +-
 28 files changed, 200 insertions(+), 122 deletions(-)

diff --git a/core/assets/vendor/jquery-once/jquery.once.js b/core/assets/vendor/jquery-once/jquery.once.js
index 5363945b591b..71adb8a57d78 100644
--- a/core/assets/vendor/jquery-once/jquery.once.js
+++ b/core/assets/vendor/jquery-once/jquery.once.js
@@ -1,92 +1,173 @@
-/**
- * jQuery Once Plugin 1.2.3
- * http://plugins.jquery.com/once/
- *
- * Dual licensed under the MIT and GPL licenses:
- *   http://www.opensource.org/licenses/mit-license.php
- *   http://www.gnu.org/licenses/gpl.html
- */
+/*!
+* jQuery Once v2.0.0 - http://github.com/robloach/jquery-once
+* @license MIT, GPL-2.0
+*   http://opensource.org/licenses/MIT
+*   http://opensource.org/licenses/GPL-2.0
+*/
 
+/**
+* Universal Module Definition
+*
+* jQuery Once has a dependency on jQuery, so we wrap the code with a UMD
+* pattern in order to allow loading jQuery and jQuery Once through a module
+* definition like CommonJS, AMD, or through a global object.
+*
+* @see {@link http://github.com/umdjs/umd}
+*/
 (function (factory) {
   "use strict";
-  if (typeof exports === 'object') {
-    factory(require('jquery'));
-  } else if (typeof define === 'function' && define.amd) {
-    define(['jquery'], factory);
+  if (typeof exports === "object") {
+    // CommonJS
+    factory(require("jquery"));
+  } else if (typeof define === "function" && define.amd) {
+    // AMD
+    define(["jquery"], factory);
   } else {
+    // Global object
     factory(jQuery);
   }
 }(function ($) {
   "use strict";
-  var cache = {}, uuid = 0;
 
   /**
-   * Filters elements by whether they have not yet been processed.
-   *
-   * @param id
-   *   (Optional) If this is a string, then it will be used as the CSS class
-   *   name that is applied to the elements for determining whether it has
-   *   already been processed. The elements will get a class in the form of
-   *   "id-processed".
-   *
-   *   If the id parameter is a function, it will be passed off to the fn
-   *   parameter and the id will become a unique identifier, represented as a
-   *   number.
-   *
-   *   When the id is neither a string or a function, it becomes a unique
-   *   identifier, depicted as a number. The element's class will then be
-   *   represented in the form of "jquery-once-#-processed".
-   *
-   *   Take note that the id must be valid for usage as an element's class name.
-   * @param fn
-   *   (Optional) If given, this function will be called for each element that
-   *   has not yet been processed. The function's return value follows the same
-   *   logic as $.each(). Returning true will continue to the next matched
-   *   element in the set, while returning false will entirely break the
-   *   iteration.
-   *
-   * @api public
-   */
-  $.fn.once = function (id, fn) {
-    if (typeof id !== 'string') {
-      // Generate a numeric ID if the id passed can't be used as a CSS class.
-      if (!(id in cache)) {
-        cache[id] = ++uuid;
-      }
-      // When the fn parameter is not passed, we interpret it from the id.
-      if (!fn) {
-        fn = id;
-      }
-      id = 'jquery-once-' + cache[id];
+  * Ensures that the given ID is valid, returning "once" if one is not given.
+  *
+  * @param {string} [id="once"]
+  *   A string representing the ID to check. Defaults to `"once"`.
+  *
+  * @returns The valid ID name.
+  *
+  * @throws Error when an ID is provided, but not a string.
+  * @private
+  */
+  var checkId = function(id) {
+    id = id || "once";
+    if (typeof id !== "string") {
+      throw new Error("The jQuery Once id parameter must be a string");
     }
-    // Remove elements from the set that have already been processed.
-    var name = id + '-processed';
-    var elements = this.not('.' + name).addClass(name);
+    return id;
+  };
+
+  /**
+  * Filter elements that have yet to be processed by the given data ID.
+  *
+  * @param {string} [id="once"]
+  *   The data ID used to determine whether the given elements have already
+  *   been processed or not. Defaults to `"once"`.
+  *
+  * @returns jQuery collection of elements that have now run once by
+  *   the given ID.
+  *
+  * @example
+  * ``` javascript
+  * // The following will change the color of each paragraph to red, just once
+  * // for the "changecolor" key.
+  * $('p').once('changecolor').css('color', 'red');
+  *
+  * // .once() will return a set of elements that yet to have the once ID
+  * // associated with them. You can return to the original collection set by
+  * // using .end().
+  * $('p')
+  *   .once("changecolorblue")
+  *     .css("color", "blue")
+  *   .end()
+  *   .css("color", "red");
+  *
+  * // To execute a function on the once set, you can use jQuery's each().
+  * $('div.calendar').once().each(function() {
+  *   // Since there is no once ID provided here, the key will be "once".
+  * });
+  * ```
+  *
+  * @see removeOnce
+  * @see findOnce
+  * @this jQuery
+  *
+  * @global
+  * @public
+  */
+  $.fn.once = function (id) {
+    // Build the jQuery Once data name from the provided ID.
+    var name = "jquery-once-" + checkId(id);
+
+    // Find elements that don't have the jQuery Once data applied to them yet.
+    return this.filter(function() {
+      return $(this).data(name) !== true;
+    }).data(name, true);
+  };
 
-    return $.isFunction(fn) ? elements.each(fn) : elements;
+  /**
+  * Removes the once data from elements, based on the given ID.
+  *
+  * @param {string} [id="once"]
+  *   A string representing the name of the data ID which should be used when
+  *   filtering the elements. This only filters elements that have already been
+  *   processed by the once function. The ID should be the same ID that was
+  *   originally passed to the once() function. Defaults to `"once"`.
+  *
+  * @returns jQuery collection of elements that were acted upon to remove their
+  *    once data.
+  *
+  * @example
+  * ``` javascript
+  * // Remove once data with the "changecolor" ID. The result set is the
+  * // elements that had their once data removed.
+  * $('p').removeOnce("changecolor").css("color", "");
+  *
+  * // Any jQuery function can be performed on the result set.
+  * $("div.calendar").removeOnce().each(function() {
+  *   // Remove the calendar behavior.
+  * });
+  * ```
+  *
+  * @see once
+  * @this jQuery
+  *
+  * @global
+  * @public
+  */
+  $.fn.removeOnce = function (id) {
+    // Filter through the elements to find the once'd elements.
+    return this.findOnce(id).removeData("jquery-once-" + checkId(id));
   };
 
   /**
-   * Filters elements that have been processed once already.
-   *
-   * @param id
-   *   A required string representing the name of the class which should be used
-   *   when filtering the elements. This only filters elements that have already
-   *   been processed by the once function. The id should be the same id that
-   *   was originally passed to the once() function.
-   * @param fn
-   *   (Optional) If given, this function will be called for each element that
-   *   has not yet been processed. The function's return value follows the same
-   *   logic as $.each(). Returning true will continue to the next matched
-   *   element in the set, while returning false will entirely break the
-   *   iteration.
-   *
-   * @api public
-   */
-  $.fn.removeOnce = function (id, fn) {
-    var name = id + '-processed';
-    var elements = this.filter('.' + name).removeClass(name);
+  * Filters elements that have already been processed once.
+  *
+  * @param {string} [id="once"]
+  *   A string representing the name of the data id which should be used when
+  *   filtering the elements. This only filters elements that have already
+  *   been processed by the once function. The id should be the same id that
+  *   was originally passed to the once() function. Defaults to "once".
+  *
+  * @returns jQuery collection of elements that have been run once.
+  *
+  * @example
+  * ``` javascript
+  * // Find all elements that have been changecolor'ed once.
+  * $('p').findOnce('changecolor').each(function() {
+  *   // This function is called for all elements that has already once'd.
+  * });
+  *
+  * // Find all elements that have been acted on with the default "once" key.
+  * $('p').findOnce().each(function() {
+  *   // This function is called for all elements that have been acted on with
+  *   // a "once" action.
+  * });
+  * ```
+  *
+  * @see once
+  * @this jQuery
+  *
+  * @global
+  * @public
+  */
+  $.fn.findOnce = function (id) {
+    // Filter the elements by which do have the data.
+    var name = "jquery-once-" + checkId(id);
 
-    return $.isFunction(fn) ? elements.each(fn) : elements;
+    return this.filter(function() {
+      return $(this).data(name) === true;
+    });
   };
 }));
diff --git a/core/core.libraries.yml b/core/core.libraries.yml
index a6d963c2c3b0..c8ab09ef66ae 100644
--- a/core/core.libraries.yml
+++ b/core/core.libraries.yml
@@ -391,10 +391,10 @@ jquery.joyride:
 
 jquery.once:
   remote: https://github.com/RobLoach/jquery-once
-  version: 1.2.3
+  version: 2.0.0
   license:
     name: GNU-GPL-2.0-or-later
-    url: https://github.com/RobLoach/jquery-once/blob/1.2.3/LICENSE
+    url: https://github.com/RobLoach/jquery-once/blob/master/LICENSE.md
     gpl-compatible: true
   js:
     assets/vendor/jquery-once/jquery.once.js: { weight: -19 }
diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index 8fe1dcf7ab6c..91e8e1c5ccfc 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -27,7 +27,7 @@
         if (typeof element_settings.selector === 'undefined') {
           element_settings.selector = '#' + base;
         }
-        $(element_settings.selector).once('drupal-ajax', function () {
+        $(element_settings.selector).once('drupal-ajax').each(function () {
           element_settings.element = this;
           Drupal.ajax[element_settings.selector] = new Drupal.ajax(base, this, element_settings);
         });
@@ -41,7 +41,7 @@
       }
 
       // Bind Ajax behaviors to all items showing the class.
-      $('.use-ajax').once('ajax', function () {
+      $('.use-ajax').once('ajax').each(function () {
         var element_settings = {};
         // Clicked links look better with the throbber than the progress bar.
         element_settings.progress = {'type': 'throbber'};
@@ -59,7 +59,7 @@
       });
 
       // This class means to submit the form to the action using Ajax.
-      $('.use-ajax-submit').once('ajax', function () {
+      $('.use-ajax-submit').once('ajax').each(function () {
         var element_settings = {};
 
         // Ajax submits specified in this manner automatically submit to the
diff --git a/core/misc/collapse.js b/core/misc/collapse.js
index 9115dd662d20..1a98e546be8d 100644
--- a/core/misc/collapse.js
+++ b/core/misc/collapse.js
@@ -98,7 +98,7 @@
       if (Modernizr.details) {
         return;
       }
-      var $collapsibleDetails = $(context).find('details').once('collapse');
+      var $collapsibleDetails = $(context).find('details').once('collapse').addClass('collapse-processed');
       if ($collapsibleDetails.length) {
         for (var i = 0; i < $collapsibleDetails.length; i++) {
           CollapsibleDetails.instances.push(new CollapsibleDetails($collapsibleDetails[i]));
diff --git a/core/misc/drupal.js b/core/misc/drupal.js
index 61d329991b4d..70ac77dd94e3 100644
--- a/core/misc/drupal.js
+++ b/core/misc/drupal.js
@@ -111,10 +111,10 @@ if (window.jQuery) {
    * to be processed, in order to allow special behaviors to detach from the
    * content.
    *
-   * Such implementations should look for the class name that was added in their
-   * corresponding Drupal.behaviors.behaviorName.attach implementation, i.e.
-   * behaviorName-processed, to ensure the behavior is detached only from
-   * previously processed elements.
+   * 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
diff --git a/core/misc/tabledrag.js b/core/misc/tabledrag.js
index 9717354277ac..d0c6241a232e 100644
--- a/core/misc/tabledrag.js
+++ b/core/misc/tabledrag.js
@@ -225,7 +225,7 @@
     }
     // Trigger an event to allow other scripts to react to this display change.
     // Force the extra parameter as a bool.
-    $('table.tabledrag-processed').trigger('columnschange', !!displayWeight);
+    $('table').findOnce('tabledrag').trigger('columnschange', !!displayWeight);
   };
 
   /**
@@ -250,7 +250,7 @@
    * Undo showColumns().
    */
   Drupal.tableDrag.prototype.hideColumns = function () {
-    var $tables = $('table.tabledrag-processed');
+    var $tables = $('table').findOnce('tabledrag');
     // Hide weight/parent cells and headers.
     $tables.find('.tabledrag-hide').css('display', 'none');
     // Show TableDrag handles.
@@ -268,7 +268,7 @@
    * Undo hideColumns().
    */
   Drupal.tableDrag.prototype.showColumns = function () {
-    var $tables = $('table.tabledrag-processed');
+    var $tables = $('table').findOnce('tabledrag');
     // Show weight/parent cells and headers.
     $tables.find('.tabledrag-hide').css('display', '');
     // Hide TableDrag handles.
diff --git a/core/misc/tableselect.js b/core/misc/tableselect.js
index 60bb0e173c08..8f91d5e3585d 100644
--- a/core/misc/tableselect.js
+++ b/core/misc/tableselect.js
@@ -5,7 +5,7 @@
   Drupal.behaviors.tableSelect = {
     attach: function (context, settings) {
       // Select the inner-most table in case of nested tables.
-      $(context).find('th.select-all').closest('table').once('table-select', Drupal.tableSelect);
+      $(context).find('th.select-all').closest('table').once('table-select').each(Drupal.tableSelect);
     }
   };
 
diff --git a/core/misc/vertical-tabs.js b/core/misc/vertical-tabs.js
index 11fca707c69e..89b123a7e3ad 100644
--- a/core/misc/vertical-tabs.js
+++ b/core/misc/vertical-tabs.js
@@ -20,7 +20,7 @@
         return;
       }
 
-      $(context).find('[data-vertical-tabs-panes]').once('vertical-tabs', function () {
+      $(context).find('[data-vertical-tabs-panes]').once('vertical-tabs').each(function () {
         var $this = $(this).addClass('vertical-tabs-panes');
         var focusID = $this.find(':hidden.vertical-tabs-active-tab').val();
         var tab_focus;
diff --git a/core/modules/block/js/block.admin.js b/core/modules/block/js/block.admin.js
index 422a83ac6ed5..89739c7caf0f 100644
--- a/core/modules/block/js/block.admin.js
+++ b/core/modules/block/js/block.admin.js
@@ -74,7 +74,7 @@
   Drupal.behaviors.blockHighlightPlacement = {
     attach: function (context, settings) {
       if (settings.blockPlacement) {
-        $('#blocks').once('block-highlight', function () {
+        $('#blocks').once('block-highlight').each(function () {
           var $container = $(this);
           // Just scrolling the document.body will not work in Firefox. The html
           // element is needed as well.
diff --git a/core/modules/block/js/block.js b/core/modules/block/js/block.js
index c25842f20235..2b727c431965 100644
--- a/core/modules/block/js/block.js
+++ b/core/modules/block/js/block.js
@@ -91,7 +91,7 @@
       };
 
       // Add the behavior to each region select list.
-      $(context).find('select.block-region-select').once('block-region-select', function () {
+      $(context).find('select.block-region-select').once('block-region-select').each(function () {
         $(this).on('change', function (event) {
           // Make our new row and select field.
           var row = $(this).closest('tr');
diff --git a/core/modules/ckeditor/js/ckeditor.admin.js b/core/modules/ckeditor/js/ckeditor.admin.js
index e3dbf2b258ac..ff7554160171 100644
--- a/core/modules/ckeditor/js/ckeditor.admin.js
+++ b/core/modules/ckeditor/js/ckeditor.admin.js
@@ -11,8 +11,8 @@
   Drupal.behaviors.ckeditorAdmin = {
     attach: function (context) {
       // Process the CKEditor configuration fragment once.
-      var $configurationForm = $(context).find('.ckeditor-toolbar-configuration');
-      if ($configurationForm.once('ckeditor-configuration').length) {
+      var $configurationForm = $(context).find('.ckeditor-toolbar-configuration').once('ckeditor-configuration');
+      if ($configurationForm.length) {
         var $textarea = $configurationForm
           // Hide the textarea that contains the serialized representation of the
           // CKEditor configuration.
@@ -55,7 +55,7 @@
       // really means that all CKEditor toolbar buttons have been removed. Hence,
       // all editor features will be removed, so any reactions from filters will
       // be undone.
-      var $configurationForm = $(context).find('.ckeditor-toolbar-configuration.ckeditor-configuration-processed');
+      var $configurationForm = $(context).find('.ckeditor-toolbar-configuration').findOnce('ckeditor-configuration');
       if ($configurationForm.length && Drupal.ckeditor.models && Drupal.ckeditor.models.Model) {
         var config = Drupal.ckeditor.models.Model.toJSON().activeEditorConfig;
         var buttons = Drupal.ckeditor.views.controller.getButtonList(config);
diff --git a/core/modules/content_translation/content_translation.admin.js b/core/modules/content_translation/content_translation.admin.js
index c10efa1bfe38..1f4224befe0e 100644
--- a/core/modules/content_translation/content_translation.admin.js
+++ b/core/modules/content_translation/content_translation.admin.js
@@ -70,7 +70,7 @@
     attach: function (context) {
       // Initially hide all field rows for non translatable bundles and all column
       // rows for non translatable fields.
-      $(context).find('table .bundle-settings .translatable :input').once('translation-entity-admin-hide', function () {
+      $(context).find('table .bundle-settings .translatable :input').once('translation-entity-admin-hide').each(function () {
         var $input = $(this);
         var $bundleSettings = $input.closest('.bundle-settings');
         if (!$input.is(':checked')) {
diff --git a/core/modules/editor/js/editor.admin.js b/core/modules/editor/js/editor.admin.js
index 74a38b223433..cbd15103a511 100644
--- a/core/modules/editor/js/editor.admin.js
+++ b/core/modules/editor/js/editor.admin.js
@@ -714,7 +714,7 @@
     attach: function (context, settings) {
       var $context = $(context);
 
-      $context.find('#filters-status-wrapper input.form-checkbox').once('filter-editor-status', function () {
+      $context.find('#filters-status-wrapper input.form-checkbox').once('filter-editor-status').each(function () {
         var $checkbox = $(this);
         var nameAttribute = $checkbox.attr('name');
 
diff --git a/core/modules/editor/js/editor.js b/core/modules/editor/js/editor.js
index 022bc9f7c07d..c6bbfd61157d 100644
--- a/core/modules/editor/js/editor.js
+++ b/core/modules/editor/js/editor.js
@@ -140,7 +140,7 @@
         return;
       }
 
-      $(context).find('.editor').once('editor', function () {
+      $(context).find('.editor').once('editor').each(function () {
         var $this = $(this);
         var activeFormatID = $this.val();
         $this.attr('data-editor-active-text-format', activeFormatID);
@@ -188,7 +188,7 @@
       if (trigger === 'serialize') {
         // Removing the editor-processed class guarantees that the editor will
         // be reattached. Only do this if we're planning to destroy the editor.
-        editors = $(context).find('.editor-processed');
+        editors = $(context).find('.editor').findOnce('editor');
       }
       else {
         editors = $(context).find('.editor').removeOnce('editor');
diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js
index 1167fcc1be1e..3ee0dabff485 100644
--- a/core/modules/field_ui/field_ui.js
+++ b/core/modules/field_ui/field_ui.js
@@ -54,7 +54,7 @@
 
   Drupal.behaviors.fieldUIDisplayOverview = {
     attach: function (context, settings) {
-      $(context).find('table#field-display-overview').once('field-display-overview', function () {
+      $(context).find('table#field-display-overview').once('field-display-overview').each(function () {
         Drupal.fieldUIOverview.attach(this, settings.fieldUIRowsData, Drupal.fieldUIDisplayOverview);
       });
     }
diff --git a/core/modules/file/file.js b/core/modules/file/file.js
index fcefad189aba..b704542bddd4 100644
--- a/core/modules/file/file.js
+++ b/core/modules/file/file.js
@@ -134,10 +134,10 @@
      * Prevent file uploads when using buttons not intended to upload.
      */
     disableFields: function (event) {
-      var $clickedButton = $(this);
+      var $clickedButton = $(this).findOnce('ajax');
 
       // Only disable upload fields for Ajax buttons.
-      if (!$clickedButton.hasClass('ajax-processed')) {
+      if (!$clickedButton.length) {
         return;
       }
 
diff --git a/core/modules/filter/filter.admin.js b/core/modules/filter/filter.admin.js
index 959442a8e78e..ba650c8ec6b3 100644
--- a/core/modules/filter/filter.admin.js
+++ b/core/modules/filter/filter.admin.js
@@ -10,7 +10,7 @@
   Drupal.behaviors.filterStatus = {
     attach: function (context, settings) {
       var $context = $(context);
-      $context.find('#filters-status-wrapper input.form-checkbox').once('filter-status', function () {
+      $context.find('#filters-status-wrapper input.form-checkbox').once('filter-status').each(function () {
         var $checkbox = $(this);
         // Retrieve the tabledrag row belonging to this filter.
         var $row = $context.find('#' + $checkbox.attr('id').replace(/-status$/, '-weight')).closest('tr');
diff --git a/core/modules/filter/filter.filter_html.admin.js b/core/modules/filter/filter.filter_html.admin.js
index a11fca5f1651..a74b938e7c63 100644
--- a/core/modules/filter/filter.filter_html.admin.js
+++ b/core/modules/filter/filter.filter_html.admin.js
@@ -55,7 +55,7 @@
 
     attach: function (context, settings) {
       var that = this;
-      $(context).find('[name="filters[filter_html][settings][allowed_html]"]').once('filter-filter_html-updating', function () {
+      $(context).find('[name="filters[filter_html][settings][allowed_html]"]').once('filter-filter_html-updating').each(function () {
         that.$allowedHTMLFormItem = $(this);
         that.$allowedHTMLDescription = that.$allowedHTMLFormItem.closest('.form-item').find('.description');
         that.userTags = that._parseSetting(this.value);
diff --git a/core/modules/menu_ui/menu_ui.admin.js b/core/modules/menu_ui/menu_ui.admin.js
index 4a04ab0a878c..06a9f3472d21 100644
--- a/core/modules/menu_ui/menu_ui.admin.js
+++ b/core/modules/menu_ui/menu_ui.admin.js
@@ -4,15 +4,15 @@
 
   Drupal.behaviors.menuUiChangeParentItems = {
     attach: function (context, settings) {
-      var $menu = $('#edit-menu');
-      $menu.once('menu-parent', function () {
+      var $menu = $('#edit-menu').once('menu-parent');
+      if ($menu.length) {
         // Update the list of available parent menu items to match the initial
         // available menus.
         Drupal.menuUiUpdateParentList();
 
         // Update list of available parent menu items.
         $menu.on('change', 'input', Drupal.menuUiUpdateParentList);
-      });
+      }
     }
   };
 
diff --git a/core/modules/quickedit/js/quickedit.js b/core/modules/quickedit/js/quickedit.js
index 539fc3e9abdb..238ba0d10ddd 100644
--- a/core/modules/quickedit/js/quickedit.js
+++ b/core/modules/quickedit/js/quickedit.js
@@ -66,7 +66,7 @@
   Drupal.behaviors.quickedit = {
     attach: function (context) {
       // Initialize the Quick Edit app once per page load.
-      $('body').once('quickedit-init', initQuickEdit);
+      $('body').once('quickedit-init').each(initQuickEdit);
 
       // Find all in-place editable fields, if any.
       var $fields = $(context).find('[data-quickedit-field-id]').once('quickedit');
diff --git a/core/modules/simpletest/simpletest.js b/core/modules/simpletest/simpletest.js
index 7e365bd3d650..b1c63de9bc23 100644
--- a/core/modules/simpletest/simpletest.js
+++ b/core/modules/simpletest/simpletest.js
@@ -7,7 +7,7 @@
    */
   Drupal.behaviors.simpleTestGroupCollapse = {
     attach: function (context) {
-      $(context).find('.simpletest-group').once('simpletest-group-collapse', function () {
+      $(context).find('.simpletest-group').once('simpletest-group-collapse').each(function () {
         var $group = $(this);
         var $image = $group.find('.simpletest-image');
         $image
@@ -28,7 +28,7 @@
    */
   Drupal.behaviors.simpleTestSelectAll = {
     attach: function (context) {
-      $(context).find('.simpletest-group').once('simpletest-group-select-all', function () {
+      $(context).find('.simpletest-group').once('simpletest-group-select-all').each(function () {
         var $group = $(this);
         var $cell = $group.find('.simpletest-group-select-all');
         var $groupCheckbox = $('<input type="checkbox" id="' + $cell.attr('id') + '-group-select-all" class="form-checkbox" />');
diff --git a/core/modules/text/text.js b/core/modules/text/text.js
index 10aed14bbe08..0895415faf6c 100644
--- a/core/modules/text/text.js
+++ b/core/modules/text/text.js
@@ -7,7 +7,7 @@
    */
   Drupal.behaviors.textSummary = {
     attach: function (context, settings) {
-      $(context).find('.text-summary').once('text-summary', function () {
+      $(context).find('.text-summary').once('text-summary').each(function () {
         var $widget = $(this).closest('.text-format-wrapper');
 
         var $summary = $widget.find('.text-summary-wrapper');
diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js
index dcfbb2ae798a..efbad03cf0be 100644
--- a/core/modules/toolbar/js/toolbar.js
+++ b/core/modules/toolbar/js/toolbar.js
@@ -43,7 +43,7 @@
         return;
       }
       // Process the administrative toolbar.
-      $(context).find('#toolbar-administration').once('toolbar', function () {
+      $(context).find('#toolbar-administration').once('toolbar').each(function () {
 
         // Establish the toolbar models and views.
         var model = Drupal.toolbar.models.toolbarModel = new Drupal.toolbar.ToolbarModel({
diff --git a/core/modules/tour/js/tour.js b/core/modules/tour/js/tour.js
index cee9feba33f3..f8bc85f452f1 100644
--- a/core/modules/tour/js/tour.js
+++ b/core/modules/tour/js/tour.js
@@ -23,7 +23,7 @@
    */
   Drupal.behaviors.tour = {
     attach: function (context) {
-      $('body').once('tour', function (index, element) {
+      $('body').once('tour').each(function() {
         var model = new Drupal.tour.models.StateModel();
         new Drupal.tour.views.ToggleTourView({
           el: $(context).find('#toolbar-tab-tour'),
@@ -42,7 +42,6 @@
         if (/tour=?/i.test(queryString)) {
           model.set('isActive', true);
         }
-
       });
     }
   };
diff --git a/core/modules/user/user.js b/core/modules/user/user.js
index ded4c0a21628..45f554cf8c05 100644
--- a/core/modules/user/user.js
+++ b/core/modules/user/user.js
@@ -9,7 +9,7 @@
   Drupal.behaviors.password = {
     attach: function (context, settings) {
       var translate = settings.password;
-      $(context).find('input.password-field').once('password', function () {
+      $(context).find('input.password-field').once('password').each(function () {
         var passwordInput = $(this);
         var innerWrapper = $(this).parent();
         var outerWrapper = $(this).parent().parent();
diff --git a/core/modules/user/user.permissions.js b/core/modules/user/user.permissions.js
index 415fc5394380..d47ee9ac568f 100644
--- a/core/modules/user/user.permissions.js
+++ b/core/modules/user/user.permissions.js
@@ -8,7 +8,7 @@
   Drupal.behaviors.permissions = {
     attach: function (context) {
       var self = this;
-      $('table#permissions').once('permissions', function () {
+      $('table#permissions').once('permissions').each(function () {
         // On a site with many roles and permissions, this behavior initially has
         // to perform thousands of DOM manipulations to inject checkboxes and hide
         // them. By detaching the table from the DOM, all operations can be
diff --git a/core/modules/views/js/ajax_view.js b/core/modules/views/js/ajax_view.js
index 3139112f7153..3e0b6800381a 100644
--- a/core/modules/views/js/ajax_view.js
+++ b/core/modules/views/js/ajax_view.js
@@ -63,14 +63,14 @@
 
     // Add the ajax to exposed forms.
     this.$exposed_form = $('form#views-exposed-form-' + settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-'));
-    this.$exposed_form.once('exposed-form', jQuery.proxy(this.attachExposedFormAjax, this));
+    this.$exposed_form.once('exposed-form').each(jQuery.proxy(this.attachExposedFormAjax, this));
 
     // Add the ajax to pagers.
     this.$view
       // Don't attach to nested views. Doing so would attach multiple behaviors
       // to a given element.
       .filter(jQuery.proxy(this.filterNestedViews, this))
-      .once('ajax-pager', jQuery.proxy(this.attachPagerAjax, this));
+      .once('ajax-pager').each(jQuery.proxy(this.attachPagerAjax, this));
 
     // Add a trigger to update this view specifically. In order to trigger a
     // refresh use the following code.
diff --git a/core/modules/views_ui/js/views-admin.js b/core/modules/views_ui/js/views-admin.js
index bdfea7cc72a4..236b746aad94 100644
--- a/core/modules/views_ui/js/views-admin.js
+++ b/core/modules/views_ui/js/views-admin.js
@@ -233,7 +233,7 @@
   Drupal.behaviors.viewsUiRenderAddViewButton = {
     attach: function (context) {
       // Build the add display menu and pull the display input buttons into it.
-      var $menu = $(context).find('#views-display-menu-tabs').once('views-ui-render-add-view-button-processed');
+      var $menu = $(context).find('#views-display-menu-tabs').once('views-ui-render-add-view-button');
       if (!$menu.length) {
         return;
       }
@@ -801,9 +801,7 @@
    */
   Drupal.behaviors.viewsRemoveIconClass = {
     attach: function (context) {
-      $(context).find('.dropbutton').once('dropbutton-icon', function () {
-        $(this).find('.icon').removeClass('icon');
-      });
+      $(context).find('.dropbutton').once('dropbutton-icon').find('.icon').removeClass('icon');
     }
   };
 
@@ -880,7 +878,7 @@
    */
   Drupal.behaviors.viewsUiOverrideSelect = {
     attach: function (context) {
-      $(context).find('#edit-override-dropdown').once('views-ui-override-button-text', function () {
+      $(context).find('#edit-override-dropdown').once('views-ui-override-button-text').each(function () {
         // Closures! :(
         var $context = $(context);
         var $submit = $context.find('[id^=edit-submit]');
-- 
GitLab