home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress / wp-admin / js / user-profile.js < prev    next >
Encoding:
JavaScript  |  2017-09-21  |  12.2 KB  |  471 lines

  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, #wp-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( ' ' );
  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 ( $( passStrength ).is( '.short, .bad' ) ) {
  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.             current_name = select.val(),
  333.             greeting     = $( '#wp-admin-bar-my-account' ).find( '.display-name' );
  334.  
  335.         $('#pass1').val('').on( inputEvent + ' pwupdate', check_pass_strength );
  336.         $('#pass-strength-result').show();
  337.         $('.color-palette').click( function() {
  338.             $(this).siblings('input[name="admin_color"]').prop('checked', true);
  339.         });
  340.  
  341.         if ( select.length ) {
  342.             $('#first_name, #last_name, #nickname').bind( 'blur.user_profile', function() {
  343.                 var dub = [],
  344.                     inputs = {
  345.                         display_nickname  : $('#nickname').val() || '',
  346.                         display_username  : $('#user_login').val() || '',
  347.                         display_firstname : $('#first_name').val() || '',
  348.                         display_lastname  : $('#last_name').val() || ''
  349.                     };
  350.  
  351.                 if ( inputs.display_firstname && inputs.display_lastname ) {
  352.                     inputs.display_firstlast = inputs.display_firstname + ' ' + inputs.display_lastname;
  353.                     inputs.display_lastfirst = inputs.display_lastname + ' ' + inputs.display_firstname;
  354.                 }
  355.  
  356.                 $.each( $('option', select), function( i, el ){
  357.                     dub.push( el.value );
  358.                 });
  359.  
  360.                 $.each(inputs, function( id, value ) {
  361.                     if ( ! value ) {
  362.                         return;
  363.                     }
  364.  
  365.                     var val = value.replace(/<\/?[a-z][^>]*>/gi, '');
  366.  
  367.                     if ( inputs[id].length && $.inArray( val, dub ) === -1 ) {
  368.                         dub.push(val);
  369.                         $('<option />', {
  370.                             'text': val
  371.                         }).appendTo( select );
  372.                     }
  373.                 });
  374.             });
  375.  
  376.             /**
  377.              * Replaces "Howdy, *" in the admin toolbar whenever the display name dropdown is updated for one's own profile.
  378.              */
  379.             select.on( 'change', function() {
  380.                 if ( user_id !== current_user_id ) {
  381.                     return;
  382.                 }
  383.  
  384.                 var display_name = $.trim( this.value ) || current_name;
  385.  
  386.                 greeting.text( display_name );
  387.             } );
  388.         }
  389.  
  390.         $colorpicker = $( '#color-picker' );
  391.         $stylesheet = $( '#colors-css' );
  392.         user_id = $( 'input#user_id' ).val();
  393.         current_user_id = $( 'input[name="checkuser_id"]' ).val();
  394.  
  395.         $colorpicker.on( 'click.colorpicker', '.color-option', function() {
  396.             var colors,
  397.                 $this = $(this);
  398.  
  399.             if ( $this.hasClass( 'selected' ) ) {
  400.                 return;
  401.             }
  402.  
  403.             $this.siblings( '.selected' ).removeClass( 'selected' );
  404.             $this.addClass( 'selected' ).find( 'input[type="radio"]' ).prop( 'checked', true );
  405.  
  406.             // Set color scheme
  407.             if ( user_id === current_user_id ) {
  408.                 // Load the colors stylesheet.
  409.                 // The default color scheme won't have one, so we'll need to create an element.
  410.                 if ( 0 === $stylesheet.length ) {
  411.                     $stylesheet = $( '<link rel="stylesheet" />' ).appendTo( 'head' );
  412.                 }
  413.                 $stylesheet.attr( 'href', $this.children( '.css_url' ).val() );
  414.  
  415.                 // repaint icons
  416.                 if ( typeof wp !== 'undefined' && wp.svgPainter ) {
  417.                     try {
  418.                         colors = $.parseJSON( $this.children( '.icon_colors' ).val() );
  419.                     } catch ( error ) {}
  420.  
  421.                     if ( colors ) {
  422.                         wp.svgPainter.setColors( colors );
  423.                         wp.svgPainter.paint();
  424.                     }
  425.                 }
  426.  
  427.                 // update user option
  428.                 $.post( ajaxurl, {
  429.                     action:       'save-user-color-scheme',
  430.                     color_scheme: $this.children( 'input[name="admin_color"]' ).val(),
  431.                     nonce:        $('#color-nonce').val()
  432.                 }).done( function( response ) {
  433.                     if ( response.success ) {
  434.                         $( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme );
  435.                     }
  436.                 });
  437.             }
  438.         });
  439.  
  440.         bindPasswordForm();
  441.     });
  442.  
  443.     $( '#destroy-sessions' ).on( 'click', function( e ) {
  444.         var $this = $(this);
  445.  
  446.         wp.ajax.post( 'destroy-sessions', {
  447.             nonce: $( '#_wpnonce' ).val(),
  448.             user_id: $( '#user_id' ).val()
  449.         }).done( function( response ) {
  450.             $this.prop( 'disabled', true );
  451.             $this.siblings( '.notice' ).remove();
  452.             $this.before( '<div class="notice notice-success inline"><p>' + response.message + '</p></div>' );
  453.         }).fail( function( response ) {
  454.             $this.siblings( '.notice' ).remove();
  455.             $this.before( '<div class="notice notice-error inline"><p>' + response.message + '</p></div>' );
  456.         });
  457.  
  458.         e.preventDefault();
  459.     });
  460.  
  461.     window.generatePassword = generatePassword;
  462.  
  463.     /* Warn the user if password was generated but not saved */
  464.     $( window ).on( 'beforeunload', function () {
  465.         if ( true === updateLock ) {
  466.             return userProfileL10n.warn;
  467.         }
  468.     } );
  469.  
  470. })(jQuery);
  471.