]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-admin/js/user-profile.js
WordPress 4.7.1-scripts
[autoinstalls/wordpress.git] / wp-admin / js / user-profile.js
1 /* global ajaxurl, pwsL10n, userProfileL10n */
2 (function($) {
3         var updateLock = false,
4
5                 $pass1Row,
6                 $pass1Wrap,
7                 $pass1,
8                 $pass1Text,
9                 $pass1Label,
10                 $pass2,
11                 $weakRow,
12                 $weakCheckbox,
13                 $toggleButton,
14                 $submitButtons,
15                 $submitButton,
16                 currentPass,
17                 inputEvent;
18
19         /*
20          * Use feature detection to determine whether password inputs should use
21          * the `keyup` or `input` event. Input is preferred but lacks support
22          * in legacy browsers.
23          */
24         if ( 'oninput' in document.createElement( 'input' ) ) {
25                 inputEvent = 'input';
26         } else {
27                 inputEvent = 'keyup';
28         }
29
30         function generatePassword() {
31                 if ( typeof zxcvbn !== 'function' ) {
32                         setTimeout( generatePassword, 50 );
33                         return;
34                 } else if ( ! $pass1.val() ) {
35                         // zxcvbn loaded before user entered password.
36                         $pass1.val( $pass1.data( 'pw' ) );
37                         $pass1.trigger( 'pwupdate' );
38                         showOrHideWeakPasswordCheckbox();
39                 }
40                 else {
41                         // zxcvbn loaded after the user entered password, check strength.
42                         check_pass_strength();
43                         showOrHideWeakPasswordCheckbox();
44                 }
45
46                 if ( 1 !== parseInt( $toggleButton.data( 'start-masked' ), 10 ) ) {
47                         $pass1Wrap.addClass( 'show-password' );
48                 } else {
49                         $toggleButton.trigger( 'click' );
50                 }
51
52                 // Once zxcvbn loads, passwords strength is known.
53                 $( '#pw-weak-text-label' ).html( userProfileL10n.warnWeak );
54         }
55
56         function bindPass1() {
57                 currentPass = $pass1.val();
58
59                 $pass1Wrap = $pass1.parent();
60
61                 $pass1Text = $( '<input type="text"/>' )
62                         .attr( {
63                                 'id':           'pass1-text',
64                                 'name':         'pass1-text',
65                                 'autocomplete': 'off'
66                         } )
67                         .addClass( $pass1[0].className )
68                         .data( 'pw', $pass1.data( 'pw' ) )
69                         .val( $pass1.val() )
70                         .on( inputEvent, function () {
71                                 if ( $pass1Text.val() === currentPass ) {
72                                         return;
73                                 }
74                                 $pass2.val( $pass1Text.val() );
75                                 $pass1.val( $pass1Text.val() ).trigger( 'pwupdate' );
76                                 currentPass = $pass1Text.val();
77                         } );
78
79                 $pass1.after( $pass1Text );
80
81                 if ( 1 === parseInt( $pass1.data( 'reveal' ), 10 ) ) {
82                         generatePassword();
83                 }
84
85                 $pass1.on( inputEvent + ' pwupdate', function () {
86                         if ( $pass1.val() === currentPass ) {
87                                 return;
88                         }
89
90                         currentPass = $pass1.val();
91                         if ( $pass1Text.val() !== currentPass ) {
92                                 $pass1Text.val( currentPass );
93                         }
94                         $pass1.add( $pass1Text ).removeClass( 'short bad good strong' );
95                         showOrHideWeakPasswordCheckbox();
96                 } );
97         }
98
99         function resetToggle() {
100                 $toggleButton
101                         .data( 'toggle', 0 )
102                         .attr({
103                                 'aria-label': userProfileL10n.ariaHide
104                         })
105                         .find( '.text' )
106                                 .text( userProfileL10n.hide )
107                         .end()
108                         .find( '.dashicons' )
109                                 .removeClass( 'dashicons-visibility' )
110                                 .addClass( 'dashicons-hidden' );
111
112                 $pass1Text.focus();
113
114                 $pass1Label.attr( 'for', 'pass1-text' );
115         }
116
117         function bindToggleButton() {
118                 $toggleButton = $pass1Row.find('.wp-hide-pw');
119                 $toggleButton.show().on( 'click', function () {
120                         if ( 1 === parseInt( $toggleButton.data( 'toggle' ), 10 ) ) {
121                                 $pass1Wrap.addClass( 'show-password' );
122
123                                 resetToggle();
124
125                                 if ( ! _.isUndefined( $pass1Text[0].setSelectionRange ) ) {
126                                         $pass1Text[0].setSelectionRange( 0, 100 );
127                                 }
128                         } else {
129                                 $pass1Wrap.removeClass( 'show-password' );
130                                 $toggleButton
131                                         .data( 'toggle', 1 )
132                                         .attr({
133                                                 'aria-label': userProfileL10n.ariaShow
134                                         })
135                                         .find( '.text' )
136                                                 .text( userProfileL10n.show )
137                                         .end()
138                                         .find( '.dashicons' )
139                                                 .removeClass('dashicons-hidden')
140                                                 .addClass('dashicons-visibility');
141
142                                 $pass1.focus();
143
144                                 $pass1Label.attr( 'for', 'pass1' );
145
146                                 if ( ! _.isUndefined( $pass1[0].setSelectionRange ) ) {
147                                         $pass1[0].setSelectionRange( 0, 100 );
148                                 }
149                         }
150                 });
151         }
152
153         function bindPasswordForm() {
154                 var $passwordWrapper,
155                         $generateButton,
156                         $cancelButton;
157
158                 $pass1Row = $('.user-pass1-wrap');
159                 $pass1Label = $pass1Row.find('th label').attr( 'for', 'pass1-text' );
160
161                 // hide this
162                 $('.user-pass2-wrap').hide();
163
164                 $submitButton = $( '#submit' ).on( 'click', function () {
165                         updateLock = false;
166                 });
167
168                 $submitButtons = $submitButton.add( ' #createusersub' );
169
170                 $weakRow = $( '.pw-weak' );
171                 $weakCheckbox = $weakRow.find( '.pw-checkbox' );
172                 $weakCheckbox.change( function() {
173                         $submitButtons.prop( 'disabled', ! $weakCheckbox.prop( 'checked' ) );
174                 } );
175
176                 $pass1 = $('#pass1');
177                 if ( $pass1.length ) {
178                         bindPass1();
179                 }
180
181                 /**
182                  * Fix a LastPass mismatch issue, LastPass only changes pass2.
183                  *
184                  * This fixes the issue by copying any changes from the hidden
185                  * pass2 field to the pass1 field, then running check_pass_strength.
186                  */
187                 $pass2 = $('#pass2').on( inputEvent, function () {
188                         if ( $pass2.val().length > 0 ) {
189                                 $pass1.val( $pass2.val() );
190                                 $pass2.val('');
191                                 currentPass = '';
192                                 $pass1.trigger( 'pwupdate' );
193                         }
194                 } );
195
196                 // Disable hidden inputs to prevent autofill and submission.
197                 if ( $pass1.is( ':hidden' ) ) {
198                         $pass1.prop( 'disabled', true );
199                         $pass2.prop( 'disabled', true );
200                         $pass1Text.prop( 'disabled', true );
201                 }
202
203                 $passwordWrapper = $pass1Row.find( '.wp-pwd' );
204                 $generateButton  = $pass1Row.find( 'button.wp-generate-pw' );
205
206                 bindToggleButton();
207
208                 if ( $generateButton.length ) {
209                         $passwordWrapper.hide();
210                 }
211
212                 $generateButton.show();
213                 $generateButton.on( 'click', function () {
214                         updateLock = true;
215
216                         $generateButton.hide();
217                         $passwordWrapper.show();
218
219                         // Enable the inputs when showing.
220                         $pass1.attr( 'disabled', false );
221                         $pass2.attr( 'disabled', false );
222                         $pass1Text.attr( 'disabled', false );
223
224                         if ( $pass1Text.val().length === 0 ) {
225                                 generatePassword();
226                         }
227
228                         _.defer( function() {
229                                 $pass1Text.focus();
230                                 if ( ! _.isUndefined( $pass1Text[0].setSelectionRange ) ) {
231                                         $pass1Text[0].setSelectionRange( 0, 100 );
232                                 }
233                         }, 0 );
234                 } );
235
236                 $cancelButton = $pass1Row.find( 'button.wp-cancel-pw' );
237                 $cancelButton.on( 'click', function () {
238                         updateLock = false;
239
240                         // Clear any entered password.
241                         $pass1Text.val( '' );
242
243                         // Generate a new password.
244                         wp.ajax.post( 'generate-password' )
245                                 .done( function( data ) {
246                                         $pass1.data( 'pw', data );
247                                 } );
248
249                         $generateButton.show();
250                         $passwordWrapper.hide();
251
252                         $weakRow.hide( 0, function () {
253                                 $weakCheckbox.removeProp( 'checked' );
254                         } );
255
256                         // Disable the inputs when hiding to prevent autofill and submission.
257                         $pass1.prop( 'disabled', true );
258                         $pass2.prop( 'disabled', true );
259                         $pass1Text.prop( 'disabled', true );
260
261                         resetToggle();
262
263                         if ( $pass1Row.closest( 'form' ).is( '#your-profile' ) ) {
264                                 // Clear password field to prevent update
265                                 $pass1.val( '' ).trigger( 'pwupdate' );
266                                 $submitButtons.prop( 'disabled', false );
267                         }
268                 } );
269
270                 $pass1Row.closest( 'form' ).on( 'submit', function () {
271                         updateLock = false;
272
273                         $pass1.prop( 'disabled', false );
274                         $pass2.prop( 'disabled', false );
275                         $pass2.val( $pass1.val() );
276                         $pass1Wrap.removeClass( 'show-password' );
277                 });
278         }
279
280         function check_pass_strength() {
281                 var pass1 = $('#pass1').val(), strength;
282
283                 $('#pass-strength-result').removeClass('short bad good strong');
284                 if ( ! pass1 ) {
285                         $('#pass-strength-result').html( '&nbsp;' );
286                         return;
287                 }
288
289                 strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputBlacklist(), pass1 );
290
291                 switch ( strength ) {
292                         case -1:
293                                 $( '#pass-strength-result' ).addClass( 'bad' ).html( pwsL10n.unknown );
294                                 break;
295                         case 2:
296                                 $('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
297                                 break;
298                         case 3:
299                                 $('#pass-strength-result').addClass('good').html( pwsL10n.good );
300                                 break;
301                         case 4:
302                                 $('#pass-strength-result').addClass('strong').html( pwsL10n.strong );
303                                 break;
304                         case 5:
305                                 $('#pass-strength-result').addClass('short').html( pwsL10n.mismatch );
306                                 break;
307                         default:
308                                 $('#pass-strength-result').addClass('short').html( pwsL10n['short'] );
309                 }
310         }
311
312         function showOrHideWeakPasswordCheckbox() {
313                 var passStrength = $('#pass-strength-result')[0];
314
315                 if ( passStrength.className ) {
316                         $pass1.add( $pass1Text ).addClass( passStrength.className );
317                         if ( 'short' === passStrength.className || 'bad' === passStrength.className ) {
318                                 if ( ! $weakCheckbox.prop( 'checked' ) ) {
319                                         $submitButtons.prop( 'disabled', true );
320                                 }
321                                 $weakRow.show();
322                         } else {
323                                 $submitButtons.prop( 'disabled', false );
324                                 $weakRow.hide();
325                         }
326                 }
327         }
328
329         $(document).ready( function() {
330                 var $colorpicker, $stylesheet, user_id, current_user_id,
331                         select = $( '#display_name' );
332
333                 $('#pass1').val('').on( inputEvent + ' pwupdate', check_pass_strength );
334                 $('#pass-strength-result').show();
335                 $('.color-palette').click( function() {
336                         $(this).siblings('input[name="admin_color"]').prop('checked', true);
337                 });
338
339                 if ( select.length ) {
340                         $('#first_name, #last_name, #nickname').bind( 'blur.user_profile', function() {
341                                 var dub = [],
342                                         inputs = {
343                                                 display_nickname  : $('#nickname').val() || '',
344                                                 display_username  : $('#user_login').val() || '',
345                                                 display_firstname : $('#first_name').val() || '',
346                                                 display_lastname  : $('#last_name').val() || ''
347                                         };
348
349                                 if ( inputs.display_firstname && inputs.display_lastname ) {
350                                         inputs.display_firstlast = inputs.display_firstname + ' ' + inputs.display_lastname;
351                                         inputs.display_lastfirst = inputs.display_lastname + ' ' + inputs.display_firstname;
352                                 }
353
354                                 $.each( $('option', select), function( i, el ){
355                                         dub.push( el.value );
356                                 });
357
358                                 $.each(inputs, function( id, value ) {
359                                         if ( ! value ) {
360                                                 return;
361                                         }
362
363                                         var val = value.replace(/<\/?[a-z][^>]*>/gi, '');
364
365                                         if ( inputs[id].length && $.inArray( val, dub ) === -1 ) {
366                                                 dub.push(val);
367                                                 $('<option />', {
368                                                         'text': val
369                                                 }).appendTo( select );
370                                         }
371                                 });
372                         });
373                 }
374
375                 $colorpicker = $( '#color-picker' );
376                 $stylesheet = $( '#colors-css' );
377                 user_id = $( 'input#user_id' ).val();
378                 current_user_id = $( 'input[name="checkuser_id"]' ).val();
379
380                 $colorpicker.on( 'click.colorpicker', '.color-option', function() {
381                         var colors,
382                                 $this = $(this);
383
384                         if ( $this.hasClass( 'selected' ) ) {
385                                 return;
386                         }
387
388                         $this.siblings( '.selected' ).removeClass( 'selected' );
389                         $this.addClass( 'selected' ).find( 'input[type="radio"]' ).prop( 'checked', true );
390
391                         // Set color scheme
392                         if ( user_id === current_user_id ) {
393                                 // Load the colors stylesheet.
394                                 // The default color scheme won't have one, so we'll need to create an element.
395                                 if ( 0 === $stylesheet.length ) {
396                                         $stylesheet = $( '<link rel="stylesheet" />' ).appendTo( 'head' );
397                                 }
398                                 $stylesheet.attr( 'href', $this.children( '.css_url' ).val() );
399
400                                 // repaint icons
401                                 if ( typeof wp !== 'undefined' && wp.svgPainter ) {
402                                         try {
403                                                 colors = $.parseJSON( $this.children( '.icon_colors' ).val() );
404                                         } catch ( error ) {}
405
406                                         if ( colors ) {
407                                                 wp.svgPainter.setColors( colors );
408                                                 wp.svgPainter.paint();
409                                         }
410                                 }
411
412                                 // update user option
413                                 $.post( ajaxurl, {
414                                         action:       'save-user-color-scheme',
415                                         color_scheme: $this.children( 'input[name="admin_color"]' ).val(),
416                                         nonce:        $('#color-nonce').val()
417                                 }).done( function( response ) {
418                                         if ( response.success ) {
419                                                 $( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme );
420                                         }
421                                 });
422                         }
423                 });
424
425                 bindPasswordForm();
426         });
427
428         $( '#destroy-sessions' ).on( 'click', function( e ) {
429                 var $this = $(this);
430
431                 wp.ajax.post( 'destroy-sessions', {
432                         nonce: $( '#_wpnonce' ).val(),
433                         user_id: $( '#user_id' ).val()
434                 }).done( function( response ) {
435                         $this.prop( 'disabled', true );
436                         $this.siblings( '.notice' ).remove();
437                         $this.before( '<div class="notice notice-success inline"><p>' + response.message + '</p></div>' );
438                 }).fail( function( response ) {
439                         $this.siblings( '.notice' ).remove();
440                         $this.before( '<div class="notice notice-error inline"><p>' + response.message + '</p></div>' );
441                 });
442
443                 e.preventDefault();
444         });
445
446         window.generatePassword = generatePassword;
447
448         /* Warn the user if password was generated but not saved */
449         $( window ).on( 'beforeunload', function () {
450                 if ( true === updateLock ) {
451                         return userProfileL10n.warn;
452                 }
453         } );
454
455 })(jQuery);