[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/js/ -> user-profile.js (source)

   1  /**
   2   * @output wp-admin/js/user-profile.js
   3   */
   4  
   5  /* global ajaxurl, pwsL10n, userProfileL10n */
   6  (function($) {
   7      var updateLock = false,
   8          __ = wp.i18n.__,
   9          $pass1Row,
  10          $pass1,
  11          $pass2,
  12          $weakRow,
  13          $weakCheckbox,
  14          $toggleButton,
  15          $submitButtons,
  16          $submitButton,
  17          currentPass,
  18          $passwordWrapper;
  19  
  20  	function generatePassword() {
  21          if ( typeof zxcvbn !== 'function' ) {
  22              setTimeout( generatePassword, 50 );
  23              return;
  24          } else if ( ! $pass1.val() || $passwordWrapper.hasClass( 'is-open' ) ) {
  25              // zxcvbn loaded before user entered password, or generating new password.
  26              $pass1.val( $pass1.data( 'pw' ) );
  27              $pass1.trigger( 'pwupdate' );
  28              showOrHideWeakPasswordCheckbox();
  29          } else {
  30              // zxcvbn loaded after the user entered password, check strength.
  31              check_pass_strength();
  32              showOrHideWeakPasswordCheckbox();
  33          }
  34  
  35          /*
  36           * This works around a race condition when zxcvbn loads quickly and
  37           * causes `generatePassword()` to run prior to the toggle button being
  38           * bound.
  39           */
  40          bindToggleButton();
  41  
  42          // Install screen.
  43          if ( 1 !== parseInt( $toggleButton.data( 'start-masked' ), 10 ) ) {
  44              // Show the password not masked if admin_password hasn't been posted yet.
  45              $pass1.attr( 'type', 'text' );
  46          } else {
  47              // Otherwise, mask the password.
  48              $toggleButton.trigger( 'click' );
  49          }
  50  
  51          // Once zxcvbn loads, passwords strength is known.
  52          $( '#pw-weak-text-label' ).text( __( 'Confirm use of weak password' ) );
  53  
  54          // Focus the password field.
  55          if ( 'mailserver_pass' !== $pass1.prop('id' ) ) {
  56              $( $pass1 ).trigger( 'focus' );
  57          }
  58      }
  59  
  60  	function bindPass1() {
  61          currentPass = $pass1.val();
  62  
  63          if ( 1 === parseInt( $pass1.data( 'reveal' ), 10 ) ) {
  64              generatePassword();
  65          }
  66  
  67          $pass1.on( 'input' + ' pwupdate', function () {
  68              if ( $pass1.val() === currentPass ) {
  69                  return;
  70              }
  71  
  72              currentPass = $pass1.val();
  73  
  74              // Refresh password strength area.
  75              $pass1.removeClass( 'short bad good strong' );
  76              showOrHideWeakPasswordCheckbox();
  77          } );
  78      }
  79  
  80  	function resetToggle( show ) {
  81          $toggleButton
  82              .attr({
  83                  'aria-label': show ? __( 'Show password' ) : __( 'Hide password' )
  84              })
  85              .find( '.text' )
  86                  .text( show ? __( 'Show' ) : __( 'Hide' ) )
  87              .end()
  88              .find( '.dashicons' )
  89                  .removeClass( show ? 'dashicons-hidden' : 'dashicons-visibility' )
  90                  .addClass( show ? 'dashicons-visibility' : 'dashicons-hidden' );
  91      }
  92  
  93  	function bindToggleButton() {
  94          if ( !! $toggleButton ) {
  95              // Do not rebind.
  96              return;
  97          }
  98          $toggleButton = $pass1Row.find('.wp-hide-pw');
  99          $toggleButton.show().on( 'click', function () {
 100              if ( 'password' === $pass1.attr( 'type' ) ) {
 101                  $pass1.attr( 'type', 'text' );
 102                  resetToggle( false );
 103              } else {
 104                  $pass1.attr( 'type', 'password' );
 105                  resetToggle( true );
 106              }
 107          });
 108      }
 109  
 110      /**
 111       * Handle the password reset button. Sets up an ajax callback to trigger sending
 112       * a password reset email.
 113       */
 114  	function bindPasswordResetLink() {
 115          $( '#generate-reset-link' ).on( 'click', function() {
 116              var $this  = $(this),
 117                  data = {
 118                      'user_id': userProfileL10n.user_id, // The user to send a reset to.
 119                      'nonce':   userProfileL10n.nonce    // Nonce to validate the action.
 120                  };
 121  
 122                  // Remove any previous error messages.
 123                  $this.parent().find( '.notice-error' ).remove();
 124  
 125                  // Send the reset request.
 126                  var resetAction =  wp.ajax.post( 'send-password-reset', data );
 127  
 128                  // Handle reset success.
 129                  resetAction.done( function( response ) {
 130                      addInlineNotice( $this, true, response );
 131                  } );
 132  
 133                  // Handle reset failure.
 134                  resetAction.fail( function( response ) {
 135                      addInlineNotice( $this, false, response );
 136                  } );
 137  
 138          });
 139  
 140      }
 141  
 142      /**
 143       * Helper function to insert an inline notice of success or failure.
 144       *
 145       * @param {jQuery Object} $this   The button element: the message will be inserted
 146       *                                above this button
 147       * @param {bool}          success Whether the message is a success message.
 148       * @param {string}        message The message to insert.
 149       */
 150  	function addInlineNotice( $this, success, message ) {
 151          var resultDiv = $( '<div />' );
 152  
 153          // Set up the notice div.
 154          resultDiv.addClass( 'notice inline' );
 155  
 156          // Add a class indicating success or failure.
 157          resultDiv.addClass( 'notice-' + ( success ? 'success' : 'error' ) );
 158  
 159          // Add the message, wrapping in a p tag, with a fadein to highlight each message.
 160          resultDiv.text( $( $.parseHTML( message ) ).text() ).wrapInner( '<p />');
 161  
 162          // Disable the button when the callback has succeeded.
 163          $this.prop( 'disabled', success );
 164  
 165          // Remove any previous notices.
 166          $this.siblings( '.notice' ).remove();
 167  
 168          // Insert the notice.
 169          $this.before( resultDiv );
 170      }
 171  
 172  	function bindPasswordForm() {
 173          var $generateButton,
 174              $cancelButton;
 175  
 176          $pass1Row = $( '.user-pass1-wrap, .user-pass-wrap, .mailserver-pass-wrap, .reset-pass-submit' );
 177  
 178          // Hide the confirm password field when JavaScript support is enabled.
 179          $('.user-pass2-wrap').hide();
 180  
 181          $submitButton = $( '#submit, #wp-submit' ).on( 'click', function () {
 182              updateLock = false;
 183          });
 184  
 185          $submitButtons = $submitButton.add( ' #createusersub' );
 186  
 187          $weakRow = $( '.pw-weak' );
 188          $weakCheckbox = $weakRow.find( '.pw-checkbox' );
 189          $weakCheckbox.on( 'change', function() {
 190              $submitButtons.prop( 'disabled', ! $weakCheckbox.prop( 'checked' ) );
 191          } );
 192  
 193          $pass1 = $('#pass1, #mailserver_pass');
 194          if ( $pass1.length ) {
 195              bindPass1();
 196          } else {
 197              // Password field for the login form.
 198              $pass1 = $( '#user_pass' );
 199          }
 200  
 201          /*
 202           * Fix a LastPass mismatch issue, LastPass only changes pass2.
 203           *
 204           * This fixes the issue by copying any changes from the hidden
 205           * pass2 field to the pass1 field, then running check_pass_strength.
 206           */
 207          $pass2 = $( '#pass2' ).on( 'input', function () {
 208              if ( $pass2.val().length > 0 ) {
 209                  $pass1.val( $pass2.val() );
 210                  $pass2.val('');
 211                  currentPass = '';
 212                  $pass1.trigger( 'pwupdate' );
 213              }
 214          } );
 215  
 216          // Disable hidden inputs to prevent autofill and submission.
 217          if ( $pass1.is( ':hidden' ) ) {
 218              $pass1.prop( 'disabled', true );
 219              $pass2.prop( 'disabled', true );
 220          }
 221  
 222          $passwordWrapper = $pass1Row.find( '.wp-pwd' );
 223          $generateButton  = $pass1Row.find( 'button.wp-generate-pw' );
 224  
 225          bindToggleButton();
 226  
 227          $generateButton.show();
 228          $generateButton.on( 'click', function () {
 229              updateLock = true;
 230  
 231              // Make sure the password fields are shown.
 232              $generateButton.not( '.skip-aria-expanded' ).attr( 'aria-expanded', 'true' );
 233              $passwordWrapper
 234                  .show()
 235                  .addClass( 'is-open' );
 236  
 237              // Enable the inputs when showing.
 238              $pass1.attr( 'disabled', false );
 239              $pass2.attr( 'disabled', false );
 240  
 241              // Set the password to the generated value.
 242              generatePassword();
 243  
 244              // Show generated password in plaintext by default.
 245              resetToggle ( false );
 246  
 247              // Generate the next password and cache.
 248              wp.ajax.post( 'generate-password' )
 249                  .done( function( data ) {
 250                      $pass1.data( 'pw', data );
 251                  } );
 252          } );
 253  
 254          $cancelButton = $pass1Row.find( 'button.wp-cancel-pw' );
 255          $cancelButton.on( 'click', function () {
 256              updateLock = false;
 257  
 258              // Disable the inputs when hiding to prevent autofill and submission.
 259              $pass1.prop( 'disabled', true );
 260              $pass2.prop( 'disabled', true );
 261  
 262              // Clear password field and update the UI.
 263              $pass1.val( '' ).trigger( 'pwupdate' );
 264              resetToggle( false );
 265  
 266              // Hide password controls.
 267              $passwordWrapper
 268                  .hide()
 269                  .removeClass( 'is-open' );
 270  
 271              // Stop an empty password from being submitted as a change.
 272              $submitButtons.prop( 'disabled', false );
 273  
 274              $generateButton.attr( 'aria-expanded', 'false' );
 275          } );
 276  
 277          $pass1Row.closest( 'form' ).on( 'submit', function () {
 278              updateLock = false;
 279  
 280              $pass1.prop( 'disabled', false );
 281              $pass2.prop( 'disabled', false );
 282              $pass2.val( $pass1.val() );
 283          });
 284      }
 285  
 286  	function check_pass_strength() {
 287          var pass1 = $('#pass1').val(), strength;
 288  
 289          $('#pass-strength-result').removeClass('short bad good strong empty');
 290          if ( ! pass1 || '' ===  pass1.trim() ) {
 291              $( '#pass-strength-result' ).addClass( 'empty' ).html( '&nbsp;' );
 292              return;
 293          }
 294  
 295          strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputDisallowedList(), pass1 );
 296  
 297          switch ( strength ) {
 298              case -1:
 299                  $( '#pass-strength-result' ).addClass( 'bad' ).html( pwsL10n.unknown );
 300                  break;
 301              case 2:
 302                  $('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
 303                  break;
 304              case 3:
 305                  $('#pass-strength-result').addClass('good').html( pwsL10n.good );
 306                  break;
 307              case 4:
 308                  $('#pass-strength-result').addClass('strong').html( pwsL10n.strong );
 309                  break;
 310              case 5:
 311                  $('#pass-strength-result').addClass('short').html( pwsL10n.mismatch );
 312                  break;
 313              default:
 314                  $('#pass-strength-result').addClass('short').html( pwsL10n.short );
 315          }
 316      }
 317  
 318  	function showOrHideWeakPasswordCheckbox() {
 319          var passStrengthResult = $('#pass-strength-result');
 320  
 321          if ( passStrengthResult.length ) {
 322              var passStrength = passStrengthResult[0];
 323  
 324              if ( passStrength.className ) {
 325                  $pass1.addClass( passStrength.className );
 326                  if ( $( passStrength ).is( '.short, .bad' ) ) {
 327                      if ( ! $weakCheckbox.prop( 'checked' ) ) {
 328                          $submitButtons.prop( 'disabled', true );
 329                      }
 330                      $weakRow.show();
 331                  } else {
 332                      if ( $( passStrength ).is( '.empty' ) ) {
 333                          $submitButtons.prop( 'disabled', true );
 334                          $weakCheckbox.prop( 'checked', false );
 335                      } else {
 336                          $submitButtons.prop( 'disabled', false );
 337                      }
 338                      $weakRow.hide();
 339                  }
 340              }
 341          }
 342      }
 343  
 344      $( function() {
 345          var $colorpicker, $stylesheet, user_id, current_user_id,
 346              select       = $( '#display_name' ),
 347              current_name = select.val(),
 348              greeting     = $( '#wp-admin-bar-my-account' ).find( '.display-name' );
 349  
 350          $( '#pass1' ).val( '' ).on( 'input' + ' pwupdate', check_pass_strength );
 351          $('#pass-strength-result').show();
 352          $('.color-palette').on( 'click', function() {
 353              $(this).siblings('input[name="admin_color"]').prop('checked', true);
 354          });
 355  
 356          if ( select.length ) {
 357              $('#first_name, #last_name, #nickname').on( 'blur.user_profile', function() {
 358                  var dub = [],
 359                      inputs = {
 360                          display_nickname  : $('#nickname').val() || '',
 361                          display_username  : $('#user_login').val() || '',
 362                          display_firstname : $('#first_name').val() || '',
 363                          display_lastname  : $('#last_name').val() || ''
 364                      };
 365  
 366                  if ( inputs.display_firstname && inputs.display_lastname ) {
 367                      inputs.display_firstlast = inputs.display_firstname + ' ' + inputs.display_lastname;
 368                      inputs.display_lastfirst = inputs.display_lastname + ' ' + inputs.display_firstname;
 369                  }
 370  
 371                  $.each( $('option', select), function( i, el ){
 372                      dub.push( el.value );
 373                  });
 374  
 375                  $.each(inputs, function( id, value ) {
 376                      if ( ! value ) {
 377                          return;
 378                      }
 379  
 380                      var val = value.replace(/<\/?[a-z][^>]*>/gi, '');
 381  
 382                      if ( inputs[id].length && $.inArray( val, dub ) === -1 ) {
 383                          dub.push(val);
 384                          $('<option />', {
 385                              'text': val
 386                          }).appendTo( select );
 387                      }
 388                  });
 389              });
 390  
 391              /**
 392               * Replaces "Howdy, *" in the admin toolbar whenever the display name dropdown is updated for one's own profile.
 393               */
 394              select.on( 'change', function() {
 395                  if ( user_id !== current_user_id ) {
 396                      return;
 397                  }
 398  
 399                  var display_name = this.value.trim() || current_name;
 400  
 401                  greeting.text( display_name );
 402              } );
 403          }
 404  
 405          $colorpicker = $( '#color-picker' );
 406          $stylesheet = $( '#colors-css' );
 407          user_id = $( 'input#user_id' ).val();
 408          current_user_id = $( 'input[name="checkuser_id"]' ).val();
 409  
 410          $colorpicker.on( 'click.colorpicker', '.color-option', function() {
 411              var colors,
 412                  $this = $(this);
 413  
 414              if ( $this.hasClass( 'selected' ) ) {
 415                  return;
 416              }
 417  
 418              $this.siblings( '.selected' ).removeClass( 'selected' );
 419              $this.addClass( 'selected' ).find( 'input[type="radio"]' ).prop( 'checked', true );
 420  
 421              // Set color scheme.
 422              if ( user_id === current_user_id ) {
 423                  // Load the colors stylesheet.
 424                  // The default color scheme won't have one, so we'll need to create an element.
 425                  if ( 0 === $stylesheet.length ) {
 426                      $stylesheet = $( '<link rel="stylesheet" />' ).appendTo( 'head' );
 427                  }
 428                  $stylesheet.attr( 'href', $this.children( '.css_url' ).val() );
 429  
 430                  // Repaint icons.
 431                  if ( typeof wp !== 'undefined' && wp.svgPainter ) {
 432                      try {
 433                          colors = JSON.parse( $this.children( '.icon_colors' ).val() );
 434                      } catch ( error ) {}
 435  
 436                      if ( colors ) {
 437                          wp.svgPainter.setColors( colors );
 438                          wp.svgPainter.paint();
 439                      }
 440                  }
 441  
 442                  // Update user option.
 443                  $.post( ajaxurl, {
 444                      action:       'save-user-color-scheme',
 445                      color_scheme: $this.children( 'input[name="admin_color"]' ).val(),
 446                      nonce:        $('#color-nonce').val()
 447                  }).done( function( response ) {
 448                      if ( response.success ) {
 449                          $( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme );
 450                      }
 451                  });
 452              }
 453          });
 454  
 455          bindPasswordForm();
 456          bindPasswordResetLink();
 457      });
 458  
 459      $( '#destroy-sessions' ).on( 'click', function( e ) {
 460          var $this = $(this);
 461  
 462          wp.ajax.post( 'destroy-sessions', {
 463              nonce: $( '#_wpnonce' ).val(),
 464              user_id: $( '#user_id' ).val()
 465          }).done( function( response ) {
 466              $this.prop( 'disabled', true );
 467              $this.siblings( '.notice' ).remove();
 468              $this.before( '<div class="notice notice-success inline"><p>' + response.message + '</p></div>' );
 469          }).fail( function( response ) {
 470              $this.siblings( '.notice' ).remove();
 471              $this.before( '<div class="notice notice-error inline"><p>' + response.message + '</p></div>' );
 472          });
 473  
 474          e.preventDefault();
 475      });
 476  
 477      window.generatePassword = generatePassword;
 478  
 479      // Warn the user if password was generated but not saved.
 480      $( window ).on( 'beforeunload', function () {
 481          if ( true === updateLock ) {
 482              return __( 'Your new password has not been saved.' );
 483          }
 484      } );
 485  
 486      /*
 487       * We need to generate a password as soon as the Reset Password page is loaded,
 488       * to avoid double clicking the button to retrieve the first generated password.
 489       * See ticket #39638.
 490       */
 491      $( function() {
 492          if ( $( '.reset-pass-submit' ).length ) {
 493              $( '.reset-pass-submit button.wp-generate-pw' ).trigger( 'click' );
 494          }
 495      });
 496  
 497  })(jQuery);


Generated : Fri Mar 29 08:20:02 2024 Cross-referenced by PHPXref