[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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( ' ' ); 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);
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu May 9 08:20:02 2024 | Cross-referenced by PHPXref |