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