PageSourceSearch

https://www.miamitodaynews.com/wp-admin/js/user-profile.js?ver=6.9.9

js miamitodaynews.com collected 2026-10-02 03:28:52 UTC 18,343 bytes, 625 lines download raw bytes

1/**
2 * @output wp-admin/js/user-profile.js
3 */
4
5/* global ajaxurl, pwsL10n, userProfileL10n, ClipboardJS */
6(function($) {
7	var updateLock = false,
8		isSubmitting = false,
9		__ = wp.i18n.__,
10		clipboard = new ClipboardJS( '.application-password-display .copy-button' ),
11		$pass1Row,
12		$pass1,
13		$pass2,
14		$weakRow,
15		$weakCheckbox,
16		$toggleButton,
17		$submitButtons,
18		$submitButton,
19		currentPass,
20		$form,
21		originalFormContent,
22		$passwordWrapper,
23		successTimeout,
24		isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false, 
25		ua = navigator.userAgent.toLowerCase(),
26		isSafari = window.safari !== 'undefined' && typeof window.safari === 'object',
27		isFirefox = ua.indexOf( 'firefox' ) !== -1;
28
29	function generatePassword() {
30		if ( typeof zxcvbn !== 'function' ) {
31			setTimeout( generatePassword, 50 );
32			return;
33		} else if ( ! $pass1.val() || $passwordWrapper.hasClass( 'is-open' ) ) {
34			// zxcvbn loaded before user entered password, or generating new password.
35			$pass1.val( $pass1.data( 'pw' ) );
36			$pass1.trigger( 'pwupdate' );
37			showOrHideWeakPasswordCheckbox();
38		} else {
39			// zxcvbn loaded after the user entered password, check strength.
40			check_pass_strength();
41			showOrHideWeakPasswordCheckbox();
42		}
43
44		/*
45		 * This works around a race condition when zxcvbn loads quickly and
46		 * causes `generatePassword()` to run prior to the toggle button being
47		 * bound.
48		 */
49		bindToggleButton();
50
51		// Install screen.
52		if ( 1 !== parseInt( $toggleButton.data( 'start-masked' ), 10 ) ) {
53			// Show the password not masked if admin_password hasn't been posted yet.
54			$pass1.attr( 'type', 'text' );
55		} else {
56			// Otherwise, mask the password.
57			$toggleButton.trigger( 'click' );
58		}
59
60		// Once zxcvbn loads, passwords strength is known.
61		$( '#pw-weak-text-label' ).text( __( 'Confirm use of weak password' ) );
62
63		// Focus the password field if not the install screen.
64		if ( 'mailserver_pass' !== $pass1.prop('id' ) && ! $('#weblog_title').length ) {
65			$( $pass1 ).trigger( 'focus' );
66		}
67	}
68
69	function bindPass1() {
70		currentPass = $pass1.val();
71
72		if ( 1 === parseInt( $pass1.data( 'reveal' ), 10 ) ) {
73			generatePassword();
74		}
75
76		$pass1.on( 'input' + ' pwupdate', function () {
77			if ( $pass1.val() === currentPass ) {
78				return;
79			}
80
81			currentPass = $pass1.val();
82
83			// Refresh password strength area.
84			$pass1.removeClass( 'short bad good strong' );
85			showOrHideWeakPasswordCheckbox();
86		} );
87
88		bindCapsLockWarning( $pass1 );
89	}
90
91	function resetToggle( show ) {
92		$toggleButton
93			.attr({
94				'aria-label': show ? __( 'Show password' ) : __( 'Hide password' )
95			})
96			.find( '.text' )
97				.text( show ? __( 'Show' ) : __( 'Hide' ) )
98			.end()
99			.find( '.dashicons' )
100				.removeClass( show ? 'dashicons-hidden' : 'dashicons-visibility' )
101				.addClass( show ? 'dashicons-visibility' : 'dashicons-hidden' );
102	}
103
104	function bindToggleButton() {
105		if ( !! $toggleButton ) {
106			// Do not rebind.
107			return;
108		}
109		$toggleButton = $pass1Row.find('.wp-hide-pw');
110
111		// Toggle between showing and hiding the password.
112		$toggleButton.show().on( 'click', function () {
113			if ( 'password' === $pass1.attr( 'type' ) ) {
114				$pass1.attr( 'type', 'text' );
115				resetToggle( false );
116			} else {
117				$pass1.attr( 'type', 'password' );
118				resetToggle( true );
119			}
120		});
121
122		// Ensure the password input type is set to password when the form is submitted.
123		$pass1Row.closest( 'form' ).on( 'submit', function() {
124			if ( $pass1.attr( 'type' ) === 'text' ) {
125				$pass1.attr( 'type', 'password' );
126				resetToggle( true );
127			}
128		} );
129	}
130
131	/**
132	 * Handle the password reset button. Sets up an ajax callback to trigger sending
133	 * a password reset email.
134	 */
135	function bindPasswordResetLink() {
136		$( '#generate-reset-link' ).on( 'click', function() {
137			var $this  = $(this),
138				data = {
139					'user_id': userProfileL10n.user_id, // The user to send a reset to.
140					'nonce':   userProfileL10n.nonce    // Nonce to validate the action.
141				};
142
143				// Remove any previous error messages.
144				$this.parent().find( '.notice-error' ).remove();
145
146				// Send the reset request.
147				var resetAction =  wp.ajax.post( 'send-password-reset', data );
148
149				// Handle reset success.
150				resetAction.done( function( response ) {
151					addInlineNotice( $this, true, response );
152				} );
153
154				// Handle reset failure.
155				resetAction.fail( function( response ) {
156					addInlineNotice( $this, false, response );
157				} );
158
159		});
160
161	}
162
163	/**
164	 * Helper function to insert an inline notice of success or failure.
165	 *
166	 * @param {jQuery Object} $this   The button element: the message will be inserted
167	 *                                above this button
168	 * @param {bool}          success Whether the message is a success message.
169	 * @param {string}        message The message to insert.
170	 */
171	function addInlineNotice( $this, success, message ) {
172		var resultDiv = $( '<div />', {
173			role: 'alert'
174		} );
175
176		// Set up the notice div.
177		resultDiv.addClass( 'notice inline' );
178
179		// Add a class indicating success or failure.
180		resultDiv.addClass( 'notice-' + ( success ? 'success' : 'error' ) );
181
182		// Add the message, wrapping in a p tag, with a fadein to highlight each message.
183		resultDiv.text( $( $.parseHTML( message ) ).text() ).wrapInner( '<p />');
184
185		// Disable the button when the callback has succeeded.
186		$this.prop( 'disabled', success );
187
188		// Remove any previous notices.
189		$this.siblings( '.notice' ).remove();
190
191		// Insert the notice.
192		$this.before( resultDiv );
193	}
194
195	function bindPasswordForm() {
196		var $generateButton,
197			$cancelButton;
198
199		$pass1Row = $( '.user-pass1-wrap, .user-pass-wrap, .mailserver-pass-wrap, .reset-pass-submit' );
200
201		// Hide the confirm password field when JavaScript support is enabled.
202		$('.user-pass2-wrap').hide();
203
204		$submitButton = $( '#submit, #wp-submit' ).on( 'click', function () {
205			updateLock = false;
206		});
207
208		$submitButtons = $submitButton.add( ' #createusersub' );
209
210		$weakRow = $( '.pw-weak' );
211		$weakCheckbox = $weakRow.find( '.pw-checkbox' );
212		$weakCheckbox.on( 'change', function() {
213			$submitButtons.prop( 'disabled', ! $weakCheckbox.prop( 'checked' ) );
214		} );
215
216		$pass1 = $('#pass1, #mailserver_pass');
217		if ( $pass1.length ) {
218			bindPass1();
219		} else {
220			// Password field for the login form.
221			$pass1 = $( '#user_pass' );
222
223			bindCapsLockWarning( $pass1 );
224		}
225
226		/*
227		 * Fix a LastPass mismatch issue, LastPass only changes pass2.
228		 *
229		 * This fixes the issue by copying any changes from the hidden
230		 * pass2 field to the pass1 field, then running check_pass_strength.
231		 */
232		$pass2 = $( '#pass2' ).on( 'input', function () {
233			if ( $pass2.val().length > 0 ) {
234				$pass1.val( $pass2.val() );
235				$pass2.val('');
236				currentPass = '';
237				$pass1.trigger( 'pwupdate' );
238			}
239		} );
240
241		// Disable hidden inputs to prevent autofill and submission.
242		if ( $pass1.is( ':hidden' ) ) {
243			$pass1.prop( 'disabled', true );
244			$pass2.prop( 'disabled', true );
245		}
246
247		$passwordWrapper = $pass1Row.find( '.wp-pwd' );
248		$generateButton  = $pass1Row.find( 'button.wp-generate-pw' );
249
250		bindToggleButton();
251
252		$generateButton.show();
253		$generateButton.on( 'click', function () {
254			updateLock = true;
255
256			// Make sure the password fields are shown.
257			$generateButton.not( '.skip-aria-expanded' ).attr( 'aria-expanded', 'true' );
258			$passwordWrapper
259				.show()
260				.addClass( 'is-open' );
261
262			// Enable the inputs when showing.
263			$pass1.attr( 'disabled', false );
264			$pass2.attr( 'disabled', false );
265
266			// Set the password to the generated value.
267			generatePassword();
268
269			// Show generated password in plaintext by default.
270			resetToggle ( false );
271
272			// Generate the next password and cache.
273			wp.ajax.post( 'generate-password' )
274				.done( function( data ) {
275					$pass1.data( 'pw', data );
276				} );
277		} );
278
279		$cancelButton = $pass1Row.find( 'button.wp-cancel-pw' );
280		$cancelButton.on( 'click', function () {
281			updateLock = false;
282
283			// Disable the inputs when hiding to prevent autofill and submission.
284			$pass1.prop( 'disabled', true );
285			$pass2.prop( 'disabled', true );
286
287			// Clear password field and update the UI.
288			$pass1.val( '' ).trigger( 'pwupdate' );
289			resetToggle( false );
290
291			// Hide password controls.
292			$passwordWrapper
293				.hide()
294				.removeClass( 'is-open' );
295
296			// Stop an empty password from being submitted as a change.
297			$submitButtons.prop( 'disabled', false );
298
299			$generateButton.attr( 'aria-expanded', 'false' );
300		} );
301
302		$pass1Row.closest( 'form' ).on( 'submit', function () {
303			updateLock = false;
304
305			$pass1.prop( 'disabled', false );
306			$pass2.prop( 'disabled', false );
307			$pass2.val( $pass1.val() );
308		});
309	}
310
311	function check_pass_strength() {
312		var pass1 = $('#pass1').val(), strength;
313
314		$('#pass-strength-result').removeClass('short bad good strong empty');
315		if ( ! pass1 || '' ===  pass1.trim() ) {
316			$( '#pass-strength-result' ).addClass( 'empty' ).html( '&nbsp;' );
317			return;
318		}
319
320		strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputDisallowedList(), pass1 );
321
322		switch ( strength ) {
323			case -1:
324				$( '#pass-strength-result' ).addClass( 'bad' ).html( pwsL10n.unknown );
325				break;
326			case 2:
327				$('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
328				break;
329			case 3:
330				$('#pass-strength-result').addClass('good').html( pwsL10n.good );
331				break;
332			case 4:
333				$('#pass-strength-result').addClass('strong').html( pwsL10n.strong );
334				break;
335			case 5:
336				$('#pass-strength-result').addClass('short').html( pwsL10n.mismatch );
337				break;
338			default:
339				$('#pass-strength-result').addClass('short').html( pwsL10n.short );
340		}
341	}
342
343	/**
344	 * Bind Caps Lock detection to a password input field.
345	 *
346	 * @param {jQuery} $input The password input field.
347	 */
348	function bindCapsLockWarning( $input ) {
349		var $capsWarning,
350			$capsIcon,
351			$capsText,
352			capsLockOn = false;
353
354		// Skip warning on macOS Safari + Firefox (they show native indicators).
355		if ( isMac && ( isSafari || isFirefox ) ) {
356			return;
357		}
358
359		$capsWarning = $( '<div id="caps-warning" class="caps-warning"></div>' );
360		$capsIcon    = $( '<span class="caps-icon" aria-hidden="true"><svg viewBox="0 0 24 26" xmlns="http://www.w3.org/2000/svg" fill="#3c434a" stroke="#3c434a" stroke-width="0.5"><path d="M12 5L19 15H16V19H8V15H5L12 5Z"/><rect x="8" y="21" width="8" height="1.5" rx="0.75"/></svg></span>' );
361		$capsText    = $( '<span>', { 'class': 'caps-warning-text', text: __( 'Caps lock is on.' ) } );
362		$capsWarning.append( $capsIcon, $capsText );
363
364		$input.parent( 'div' ).append( $capsWarning );
365
366		$input.on( 'keydown', function( jqEvent ) {
367			var event = jqEvent.originalEvent;
368
369			// Skip if key is not a printable character.
370			// Key length > 1 usually means non-printable (e.g., "Enter", "Tab").
371			if ( event.ctrlKey || event.metaKey || event.altKey || ! event.key || event.key.length !== 1 ) {
372				return;
373			}
374
375			var state = isCapsLockOn( event );
376
377			// React when the state changes or if caps lock is on when the user starts typing.
378			if ( state !== capsLockOn ) {
379				capsLockOn = state;
380
381				if ( capsLockOn ) {
382					$capsWarning.show();
383					// Don't duplicate existing screen reader Caps lock notifications.
384					if ( event.key !== 'CapsLock' ) {
385						wp.a11y.speak( __( 'Caps lock is on.' ), 'assertive' );
386					}
387				} else {
388					$capsWarning.hide();
389				}
390			}
391		} );
392
393		$input.on( 'blur', function() {
394			if ( ! document.hasFocus() ) {
395				return;
396			}
397			capsLockOn = false;
398			$capsWarning.hide();
399		} );
400	}
401
402	/**
403	 * Determines if Caps Lock is currently enabled.
404	 *
405	 * On macOS Safari and Firefox, the native warning is preferred,
406	 * so this function returns false to suppress custom warnings.
407	 *
408	 * @param {KeyboardEvent} e The keydown event object.
409	 *
410	 * @return {boolean} True if Caps Lock is on, false otherwise. 
411	 */
412	function isCapsLockOn( event ) {
413		return event.getModifierState( 'CapsLock' );
414	}
415
416	function showOrHideWeakPasswordCheckbox() {
417		var passStrengthResult = $('#pass-strength-result');
418
419		if ( passStrengthResult.length ) {
420			var passStrength = passStrengthResult[0];
421
422			if ( passStrength.className ) {
423				$pass1.addClass( passStrength.className );
424				if ( $( passStrength ).is( '.short, .bad' ) ) {
425					if ( ! $weakCheckbox.prop( 'checked' ) ) {
426						$submitButtons.prop( 'disabled', true );
427					}
428					$weakRow.show();
429				} else {
430					if ( $( passStrength ).is( '.empty' ) ) {
431						$submitButtons.prop( 'disabled', true );
432						$weakCheckbox.prop( 'checked', false );
433					} else {
434						$submitButtons.prop( 'disabled', false );
435					}
436					$weakRow.hide();
437				}
438			}
439		}
440	}
441
442	// Debug information copy section.
443	clipboard.on( 'success', function( e ) {
444		var triggerElement = $( e.trigger ),
445			successElement = $( '.success', triggerElement.closest( '.application-password-display' ) );
446
447		// Clear the selection and move focus back to the trigger.
448		e.clearSelection();
449
450		// Show success visual feedback.
451		clearTimeout( successTimeout );
452		successElement.removeClass( 'hidden' );
453
454		// Hide success visual feedback after 3 seconds since last success.
455		successTimeout = setTimeout( function() {
456			successElement.addClass( 'hidden' );
457		}, 3000 );
458
459		// Handle success audible feedback.
460		wp.a11y.speak( __( 'Application password has been copied to your clipboard.' ) );
461	} );
462
463	$( function() {
464		var $colorpicker, $stylesheet, user_id, current_user_id,
465			select       = $( '#display_name' ),
466			current_name = select.val(),
467			greeting     = $( '#wp-admin-bar-my-account' ).find( '.display-name' );
468
469		$( '#pass1' ).val( '' ).on( 'input' + ' pwupdate', check_pass_strength );
470		$('#pass-strength-result').show();
471		$('.color-palette').on( 'click', function() {
472			$(this).siblings('input[name="admin_color"]').prop('checked', true);
473		});
474
475		if ( select.length ) {
476			$('#first_name, #last_name, #nickname').on( 'blur.user_profile', function() {
477				var dub = [],
478					inputs = {
479						display_nickname  : $('#nickname').val() || '',
480						display_username  : $('#user_login').val() || '',
481						display_firstname : $('#first_name').val() || '',
482						display_lastname  : $('#last_name').val() || ''
483					};
484
485				if ( inputs.display_firstname && inputs.display_lastname ) {
486					inputs.display_firstlast = inputs.display_firstname + ' ' + inputs.display_lastname;
487					inputs.display_lastfirst = inputs.display_lastname + ' ' + inputs.display_firstname;
488				}
489
490				$.each( $('option', select), function( i, el ){
491					dub.push( el.value );
492				});
493
494				$.each(inputs, function( id, value ) {
495					if ( ! value ) {
496						return;
497					}
498
499					var val = value.replace(/<\/?[a-z][^>]*>/gi, '');
500
501					if ( inputs[id].length && $.inArray( val, dub ) === -1 ) {
502						dub.push(val);
503						$('<option />', {
504							'text': val
505						}).appendTo( select );
506					}
507				});
508			});
509
510			/**
511			 * Replaces "Howdy, *" in the admin toolbar whenever the display name dropdown is updated for one's own profile.
512			 */
513			select.on( 'change', function() {
514				if ( user_id !== current_user_id ) {
515					return;
516				}
517
518				var display_name = this.value.trim() || current_name;
519
520				greeting.text( display_name );
521			} );
522		}
523
524		$colorpicker = $( '#color-picker' );
525		$stylesheet = $( '#colors-css' );
526		user_id = $( 'input#user_id' ).val();
527		current_user_id = $( 'input[name="checkuser_id"]' ).val();
528
529		$colorpicker.on( 'click.colorpicker', '.color-option', function() {
530			var colors,
531				$this = $(this);
532
533			if ( $this.hasClass( 'selected' ) ) {
534				return;
535			}
536
537			$this.siblings( '.selected' ).removeClass( 'selected' );
538			$this.addClass( 'selected' ).find( 'input[type="radio"]' ).prop( 'checked', true );
539
540			// Set color scheme.
541			if ( user_id === current_user_id ) {
542				// Load the colors stylesheet.
543				// The default color scheme won't have one, so we'll need to create an element.
544				if ( 0 === $stylesheet.length ) {
545					$stylesheet = $( '<link rel="stylesheet" />' ).appendTo( 'head' );
546				}
547				$stylesheet.attr( 'href', $this.children( '.css_url' ).val() );
548
549				// Repaint icons.
550				if ( typeof wp !== 'undefined' && wp.svgPainter ) {
551					try {
552						colors = JSON.parse( $this.children( '.icon_colors' ).val() );
553					} catch ( error ) {}
554
555					if ( colors ) {
556						wp.svgPainter.setColors( colors );
557						wp.svgPainter.paint();
558					}
559				}
560
561				// Update user option.
562				$.post( ajaxurl, {
563					action:       'save-user-color-scheme',
564					color_scheme: $this.children( 'input[name="admin_color"]' ).val(),
565					nonce:        $('#color-nonce').val()
566				}).done( function( response ) {
567					if ( response.success ) {
568						$( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme );
569					}
570				});
571			}
572		});
573
574		bindPasswordForm();
575		bindPasswordResetLink();
576		$submitButtons.on( 'click', function() {
577			isSubmitting = true;
578		});
579
580		$form = $( '#your-profile, #createuser' );
581		originalFormContent = $form.serialize();
582	});
583
584	$( '#destroy-sessions' ).on( 'click', function( e ) {
585		var $this = $(this);
586
587		wp.ajax.post( 'destroy-sessions', {
588			nonce: $( '#_wpnonce' ).val(),
589			user_id: $( '#user_id' ).val()
590		}).done( function( response ) {
591			$this.prop( 'disabled', true );
592			$this.siblings( '.notice' ).remove();
593			$this.before( '<div class="notice notice-success inline" role="alert"><p>' + response.message + '</p></div>' );
594		}).fail( function( response ) {
595			$this.siblings( '.notice' ).remove();
596			$this.before( '<div class="notice notice-error inline" role="alert"><p>' + response.message + '</p></div>' );
597		});
598
599		e.preventDefault();
600	});
601
602	window.generatePassword = generatePassword;
603
604	// Warn the user if password was generated but not saved.
605	$( window ).on( 'beforeunload', function () {
606		if ( true === updateLock ) {
607			return __( 'Your new password has not been saved.' );
608		}
609		if ( originalFormContent !== $form.serialize() && ! isSubmitting ) {
610			return __( 'The changes you made will be lost if you navigate away from this page.' );
611		}
612	});
613
614	/*
615	 * We need to generate a password as soon as the Reset Password page is loaded,
616	 * to avoid double clicking the button to retrieve the first generated password.
617	 * See ticket #39638.
618	 */
619	$( function() {
620		if ( $( '.reset-pass-submit' ).length ) {
621			$( '.reset-pass-submit button.wp-generate-pw' ).trigger( 'click' );
622		}
623	});
624
625})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.