user.permissions.js 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /**
  2. * @file
  3. * User permission page behaviors.
  4. */
  5. (function ($, Drupal) {
  6. 'use strict';
  7. /**
  8. * Shows checked and disabled checkboxes for inherited permissions.
  9. *
  10. * @type {Drupal~behavior}
  11. *
  12. * @prop {Drupal~behaviorAttach} attach
  13. * Attaches functionality to the permissions table.
  14. */
  15. Drupal.behaviors.permissions = {
  16. attach: function (context) {
  17. var self = this;
  18. $('table#permissions').once('permissions').each(function () {
  19. // On a site with many roles and permissions, this behavior initially
  20. // has to perform thousands of DOM manipulations to inject checkboxes
  21. // and hide them. By detaching the table from the DOM, all operations
  22. // can be performed without triggering internal layout and re-rendering
  23. // processes in the browser.
  24. var $table = $(this);
  25. var $ancestor;
  26. var method;
  27. if ($table.prev().length) {
  28. $ancestor = $table.prev();
  29. method = 'after';
  30. }
  31. else {
  32. $ancestor = $table.parent();
  33. method = 'append';
  34. }
  35. $table.detach();
  36. // Create dummy checkboxes. We use dummy checkboxes instead of reusing
  37. // the existing checkboxes here because new checkboxes don't alter the
  38. // submitted form. If we'd automatically check existing checkboxes, the
  39. // permission table would be polluted with redundant entries. This
  40. // is deliberate, but desirable when we automatically check them.
  41. var $dummy = $('<input type="checkbox" class="dummy-checkbox js-dummy-checkbox" disabled="disabled" checked="checked" />')
  42. .attr('title', Drupal.t('This permission is inherited from the authenticated user role.'))
  43. .hide();
  44. $table
  45. .find('input[type="checkbox"]')
  46. .not('.js-rid-anonymous, .js-rid-authenticated')
  47. .addClass('real-checkbox js-real-checkbox')
  48. .after($dummy);
  49. // Initialize the authenticated user checkbox.
  50. $table.find('input[type=checkbox].js-rid-authenticated')
  51. .on('click.permissions', self.toggle)
  52. // .triggerHandler() cannot be used here, as it only affects the first
  53. // element.
  54. .each(self.toggle);
  55. // Re-insert the table into the DOM.
  56. $ancestor[method]($table);
  57. });
  58. },
  59. /**
  60. * Toggles all dummy checkboxes based on the checkboxes' state.
  61. *
  62. * If the "authenticated user" checkbox is checked, the checked and disabled
  63. * checkboxes are shown, the real checkboxes otherwise.
  64. */
  65. toggle: function () {
  66. var authCheckbox = this;
  67. var $row = $(this).closest('tr');
  68. // jQuery performs too many layout calculations for .hide() and .show(),
  69. // leading to a major page rendering lag on sites with many roles and
  70. // permissions. Therefore, we toggle visibility directly.
  71. $row.find('.js-real-checkbox').each(function () {
  72. this.style.display = (authCheckbox.checked ? 'none' : '');
  73. });
  74. $row.find('.js-dummy-checkbox').each(function () {
  75. this.style.display = (authCheckbox.checked ? '' : 'none');
  76. });
  77. }
  78. };
  79. })(jQuery, Drupal);