summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/user/user.permissions.js
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/user/user.permissions.js')
-rw-r--r--core/modules/user/user.permissions.js76
1 files changed, 62 insertions, 14 deletions
diff --git a/core/modules/user/user.permissions.js b/core/modules/user/user.permissions.js
index 0188fab2873..ae22cbb5e3d 100644
--- a/core/modules/user/user.permissions.js
+++ b/core/modules/user/user.permissions.js
@@ -1,18 +1,28 @@
/**
-* DO NOT EDIT THIS FILE.
-* See the following change record for more information,
-* https://www.drupal.org/node/2815083
-* @preserve
-**/
+ * @file
+ * User permission page behaviors.
+ */
(function ($, Drupal) {
+ /**
+ * Shows checked and disabled checkboxes for inherited permissions.
+ *
+ * @type {Drupal~behavior}
+ *
+ * @prop {Drupal~behaviorAttach} attach
+ * Attaches functionality to the permissions table.
+ */
Drupal.behaviors.permissions = {
attach(context) {
- once('permissions', 'table#permissions').forEach(table => {
+ once('permissions', 'table#permissions').forEach((table) => {
+ // 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 performed without triggering internal layout and re-rendering
+ // processes in the browser.
const $table = $(table);
let $ancestor;
let method;
-
if ($table.prev().length) {
$ancestor = $table.prev();
method = 'after';
@@ -20,25 +30,63 @@
$ancestor = $table.parent();
method = 'append';
}
-
$table.detach();
- const $dummy = $(Drupal.theme('checkbox')).removeClass('form-checkbox').addClass('dummy-checkbox js-dummy-checkbox').attr('disabled', 'disabled').attr('checked', 'checked').attr('title', Drupal.t('This permission is inherited from the authenticated user role.')).hide();
- $table.find('input[type="checkbox"]').not('.js-rid-anonymous, .js-rid-authenticated').addClass('real-checkbox js-real-checkbox').after($dummy);
- $table.find('input[type=checkbox].js-rid-authenticated').on('click.permissions', this.toggle).each(this.toggle);
+
+ // Create dummy checkboxes. We use dummy checkboxes instead of reusing
+ // the existing checkboxes here because new checkboxes don't alter the
+ // submitted form. If we'd automatically check existing checkboxes, the
+ // permission table would be polluted with redundant entries. This is
+ // deliberate, but desirable when we automatically check them.
+ const $dummy = $(Drupal.theme('checkbox'))
+ .removeClass('form-checkbox')
+ .addClass('dummy-checkbox js-dummy-checkbox')
+ .attr('disabled', 'disabled')
+ .attr('checked', 'checked')
+ .attr(
+ 'title',
+ Drupal.t(
+ 'This permission is inherited from the authenticated user role.',
+ ),
+ )
+ .hide();
+
+ $table
+ .find('input[type="checkbox"]')
+ .not('.js-rid-anonymous, .js-rid-authenticated')
+ .addClass('real-checkbox js-real-checkbox')
+ .after($dummy);
+
+ // Initialize the authenticated user checkbox.
+ $table
+ .find('input[type=checkbox].js-rid-authenticated')
+ .on('click.permissions', this.toggle)
+ // .triggerHandler() cannot be used here, as it only affects the first
+ // element.
+ .each(this.toggle);
+
+ // Re-insert the table into the DOM.
$ancestor[method]($table);
});
},
+ /**
+ * Toggles all dummy checkboxes based on the checkboxes' state.
+ *
+ * If the "authenticated user" checkbox is checked, the checked and disabled
+ * checkboxes are shown, the real checkboxes otherwise.
+ */
toggle() {
const authCheckbox = this;
const $row = $(this).closest('tr');
+ // jQuery performs too many layout calculations for .hide() and .show(),
+ // leading to a major page rendering lag on sites with many roles and
+ // permissions. Therefore, we toggle visibility directly.
$row.find('.js-real-checkbox').each(function () {
this.style.display = authCheckbox.checked ? 'none' : '';
});
$row.find('.js-dummy-checkbox').each(function () {
this.style.display = authCheckbox.checked ? '' : 'none';
});
- }
-
+ },
};
-})(jQuery, Drupal); \ No newline at end of file
+})(jQuery, Drupal);