]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-admin/js/user-profile.js
WordPress 4.4
[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                         // Disable the inputs when hiding to prevent autofill and submission.
255                         $pass1.prop( 'disabled', true );
256                         $pass2.prop( 'disabled', true );
257                         $pass1Text.prop( 'disabled', true );
258
259                         resetToggle();
260
261                         // Clear password field to prevent update
262                         $pass1.val( '' ).trigger( 'pwupdate' );
263                         $submitButtons.prop( 'disabled', false );
264                 } );
265
266                 $pass1Row.closest('form').on( 'submit', function () {
267                         updateLock = false;
268
269                         $pass1.prop( 'disabled', false );
270                         $pass2.prop( 'disabled', false );
271                         $pass2.val( $pass1.val() );
272                         $pass1Wrap.removeClass( 'show-password' );
273                 });
274         }
275
276         function check_pass_strength() {
277                 var pass1 = $('#pass1').val(), strength;
278
279                 $('#pass-strength-result').removeClass('short bad good strong');
280                 if ( ! pass1 ) {
281                         $('#pass-strength-result').html( '&nbsp;' );
282                         return;
283                 }
284
285                 strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputBlacklist(), pass1 );
286
287                 switch ( strength ) {
288                         case 2:
289                                 $('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
290                                 break;
291                         case 3:
292                                 $('#pass-strength-result').addClass('good').html( pwsL10n.good );
293                                 break;
294                         case 4:
295                                 $('#pass-strength-result').addClass('strong').html( pwsL10n.strong );
296                                 break;
297                         case 5:
298                                 $('#pass-strength-result').addClass('short').html( pwsL10n.mismatch );
299                                 break;
300                         default:
301                                 $('#pass-strength-result').addClass('short').html( pwsL10n['short'] );
302                 }
303         }
304
305         $(document).ready( function() {
306                 var $colorpicker, $stylesheet, user_id, current_user_id,
307                         select = $( '#display_name' );
308
309                 $('#pass1').val('').on( inputEvent + ' pwupdate', check_pass_strength );
310                 $('#pass-strength-result').show();
311                 $('.color-palette').click( function() {
312                         $(this).siblings('input[name="admin_color"]').prop('checked', true);
313                 });
314
315                 if ( select.length ) {
316                         $('#first_name, #last_name, #nickname').bind( 'blur.user_profile', function() {
317                                 var dub = [],
318                                         inputs = {
319                                                 display_nickname  : $('#nickname').val() || '',
320                                                 display_username  : $('#user_login').val() || '',
321                                                 display_firstname : $('#first_name').val() || '',
322                                                 display_lastname  : $('#last_name').val() || ''
323                                         };
324
325                                 if ( inputs.display_firstname && inputs.display_lastname ) {
326                                         inputs.display_firstlast = inputs.display_firstname + ' ' + inputs.display_lastname;
327                                         inputs.display_lastfirst = inputs.display_lastname + ' ' + inputs.display_firstname;
328                                 }
329
330                                 $.each( $('option', select), function( i, el ){
331                                         dub.push( el.value );
332                                 });
333
334                                 $.each(inputs, function( id, value ) {
335                                         if ( ! value ) {
336                                                 return;
337                                         }
338
339                                         var val = value.replace(/<\/?[a-z][^>]*>/gi, '');
340
341                                         if ( inputs[id].length && $.inArray( val, dub ) === -1 ) {
342                                                 dub.push(val);
343                                                 $('<option />', {
344                                                         'text': val
345                                                 }).appendTo( select );
346                                         }
347                                 });
348                         });
349                 }
350
351                 $colorpicker = $( '#color-picker' );
352                 $stylesheet = $( '#colors-css' );
353                 user_id = $( 'input#user_id' ).val();
354                 current_user_id = $( 'input[name="checkuser_id"]' ).val();
355
356                 $colorpicker.on( 'click.colorpicker', '.color-option', function() {
357                         var colors,
358                                 $this = $(this);
359
360                         if ( $this.hasClass( 'selected' ) ) {
361                                 return;
362                         }
363
364                         $this.siblings( '.selected' ).removeClass( 'selected' );
365                         $this.addClass( 'selected' ).find( 'input[type="radio"]' ).prop( 'checked', true );
366
367                         // Set color scheme
368                         if ( user_id === current_user_id ) {
369                                 // Load the colors stylesheet.
370                                 // The default color scheme won't have one, so we'll need to create an element.
371                                 if ( 0 === $stylesheet.length ) {
372                                         $stylesheet = $( '<link rel="stylesheet" />' ).appendTo( 'head' );
373                                 }
374                                 $stylesheet.attr( 'href', $this.children( '.css_url' ).val() );
375
376                                 // repaint icons
377                                 if ( typeof wp !== 'undefined' && wp.svgPainter ) {
378                                         try {
379                                                 colors = $.parseJSON( $this.children( '.icon_colors' ).val() );
380                                         } catch ( error ) {}
381
382                                         if ( colors ) {
383                                                 wp.svgPainter.setColors( colors );
384                                                 wp.svgPainter.paint();
385                                         }
386                                 }
387
388                                 // update user option
389                                 $.post( ajaxurl, {
390                                         action:       'save-user-color-scheme',
391                                         color_scheme: $this.children( 'input[name="admin_color"]' ).val(),
392                                         nonce:        $('#color-nonce').val()
393                                 }).done( function( response ) {
394                                         if ( response.success ) {
395                                                 $( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme );
396                                         }
397                                 });
398                         }
399                 });
400
401                 bindPasswordForm();
402         });
403
404         $( '#destroy-sessions' ).on( 'click', function( e ) {
405                 var $this = $(this);
406
407                 wp.ajax.post( 'destroy-sessions', {
408                         nonce: $( '#_wpnonce' ).val(),
409                         user_id: $( '#user_id' ).val()
410                 }).done( function( response ) {
411                         $this.prop( 'disabled', true );
412                         $this.siblings( '.notice' ).remove();
413                         $this.before( '<div class="notice notice-success inline"><p>' + response.message + '</p></div>' );
414                 }).fail( function( response ) {
415                         $this.siblings( '.notice' ).remove();
416                         $this.before( '<div class="notice notice-error inline"><p>' + response.message + '</p></div>' );
417                 });
418
419                 e.preventDefault();
420         });
421
422         window.generatePassword = generatePassword;
423
424         /* Warn the user if password was generated but not saved */
425         $( window ).on( 'beforeunload', function () {
426                 if ( true === updateLock ) {
427                         return userProfileL10n.warn;
428                 }
429         } );
430
431 })(jQuery);