cms/drupal/modules/user/user.js
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 (function ($) {
       
     2 
       
     3 /**
       
     4  * Attach handlers to evaluate the strength of any password fields and to check
       
     5  * that its confirmation is correct.
       
     6  */
       
     7 Drupal.behaviors.password = {
       
     8   attach: function (context, settings) {
       
     9     var translate = settings.password;
       
    10     $('input.password-field', context).once('password', function () {
       
    11       var passwordInput = $(this);
       
    12       var innerWrapper = $(this).parent();
       
    13       var outerWrapper = $(this).parent().parent();
       
    14 
       
    15       // Add identifying class to password element parent.
       
    16       innerWrapper.addClass('password-parent');
       
    17 
       
    18       // Add the password confirmation layer.
       
    19       $('input.password-confirm', outerWrapper).parent().prepend('<div class="password-confirm">' + translate['confirmTitle'] + ' <span></span></div>').addClass('confirm-parent');
       
    20       var confirmInput = $('input.password-confirm', outerWrapper);
       
    21       var confirmResult = $('div.password-confirm', outerWrapper);
       
    22       var confirmChild = $('span', confirmResult);
       
    23 
       
    24       // Add the description box.
       
    25       var passwordMeter = '<div class="password-strength"><div class="password-strength-text" aria-live="assertive"></div><div class="password-strength-title">' + translate['strengthTitle'] + '</div><div class="password-indicator"><div class="indicator"></div></div></div>';
       
    26       $(confirmInput).parent().after('<div class="password-suggestions description"></div>');
       
    27       $(innerWrapper).prepend(passwordMeter);
       
    28       var passwordDescription = $('div.password-suggestions', outerWrapper).hide();
       
    29 
       
    30       // Check the password strength.
       
    31       var passwordCheck = function () {
       
    32 
       
    33         // Evaluate the password strength.
       
    34         var result = Drupal.evaluatePasswordStrength(passwordInput.val(), settings.password);
       
    35 
       
    36         // Update the suggestions for how to improve the password.
       
    37         if (passwordDescription.html() != result.message) {
       
    38           passwordDescription.html(result.message);
       
    39         }
       
    40 
       
    41         // Only show the description box if there is a weakness in the password.
       
    42         if (result.strength == 100) {
       
    43           passwordDescription.hide();
       
    44         }
       
    45         else {
       
    46           passwordDescription.show();
       
    47         }
       
    48 
       
    49         // Adjust the length of the strength indicator.
       
    50         $(innerWrapper).find('.indicator').css('width', result.strength + '%');
       
    51 
       
    52         // Update the strength indication text.
       
    53         $(innerWrapper).find('.password-strength-text').html(result.indicatorText);
       
    54 
       
    55         passwordCheckMatch();
       
    56       };
       
    57 
       
    58       // Check that password and confirmation inputs match.
       
    59       var passwordCheckMatch = function () {
       
    60 
       
    61         if (confirmInput.val()) {
       
    62           var success = passwordInput.val() === confirmInput.val();
       
    63 
       
    64           // Show the confirm result.
       
    65           confirmResult.css({ visibility: 'visible' });
       
    66 
       
    67           // Remove the previous styling if any exists.
       
    68           if (this.confirmClass) {
       
    69             confirmChild.removeClass(this.confirmClass);
       
    70           }
       
    71 
       
    72           // Fill in the success message and set the class accordingly.
       
    73           var confirmClass = success ? 'ok' : 'error';
       
    74           confirmChild.html(translate['confirm' + (success ? 'Success' : 'Failure')]).addClass(confirmClass);
       
    75           this.confirmClass = confirmClass;
       
    76         }
       
    77         else {
       
    78           confirmResult.css({ visibility: 'hidden' });
       
    79         }
       
    80       };
       
    81 
       
    82       // Monitor keyup and blur events.
       
    83       // Blur must be used because a mouse paste does not trigger keyup.
       
    84       passwordInput.keyup(passwordCheck).focus(passwordCheck).blur(passwordCheck);
       
    85       confirmInput.keyup(passwordCheckMatch).blur(passwordCheckMatch);
       
    86     });
       
    87   }
       
    88 };
       
    89 
       
    90 /**
       
    91  * Evaluate the strength of a user's password.
       
    92  *
       
    93  * Returns the estimated strength and the relevant output message.
       
    94  */
       
    95 Drupal.evaluatePasswordStrength = function (password, translate) {
       
    96   password = $.trim(password);
       
    97 
       
    98   var weaknesses = 0, strength = 100, msg = [];
       
    99 
       
   100   var hasLowercase = /[a-z]+/.test(password);
       
   101   var hasUppercase = /[A-Z]+/.test(password);
       
   102   var hasNumbers = /[0-9]+/.test(password);
       
   103   var hasPunctuation = /[^a-zA-Z0-9]+/.test(password);
       
   104 
       
   105   // If there is a username edit box on the page, compare password to that, otherwise
       
   106   // use value from the database.
       
   107   var usernameBox = $('input.username');
       
   108   var username = (usernameBox.length > 0) ? usernameBox.val() : translate.username;
       
   109 
       
   110   // Lose 5 points for every character less than 6, plus a 30 point penalty.
       
   111   if (password.length < 6) {
       
   112     msg.push(translate.tooShort);
       
   113     strength -= ((6 - password.length) * 5) + 30;
       
   114   }
       
   115 
       
   116   // Count weaknesses.
       
   117   if (!hasLowercase) {
       
   118     msg.push(translate.addLowerCase);
       
   119     weaknesses++;
       
   120   }
       
   121   if (!hasUppercase) {
       
   122     msg.push(translate.addUpperCase);
       
   123     weaknesses++;
       
   124   }
       
   125   if (!hasNumbers) {
       
   126     msg.push(translate.addNumbers);
       
   127     weaknesses++;
       
   128   }
       
   129   if (!hasPunctuation) {
       
   130     msg.push(translate.addPunctuation);
       
   131     weaknesses++;
       
   132   }
       
   133 
       
   134   // Apply penalty for each weakness (balanced against length penalty).
       
   135   switch (weaknesses) {
       
   136     case 1:
       
   137       strength -= 12.5;
       
   138       break;
       
   139 
       
   140     case 2:
       
   141       strength -= 25;
       
   142       break;
       
   143 
       
   144     case 3:
       
   145       strength -= 40;
       
   146       break;
       
   147 
       
   148     case 4:
       
   149       strength -= 40;
       
   150       break;
       
   151   }
       
   152 
       
   153   // Check if password is the same as the username.
       
   154   if (password !== '' && password.toLowerCase() === username.toLowerCase()) {
       
   155     msg.push(translate.sameAsUsername);
       
   156     // Passwords the same as username are always very weak.
       
   157     strength = 5;
       
   158   }
       
   159 
       
   160   // Based on the strength, work out what text should be shown by the password strength meter.
       
   161   if (strength < 60) {
       
   162     indicatorText = translate.weak;
       
   163   } else if (strength < 70) {
       
   164     indicatorText = translate.fair;
       
   165   } else if (strength < 80) {
       
   166     indicatorText = translate.good;
       
   167   } else if (strength <= 100) {
       
   168     indicatorText = translate.strong;
       
   169   }
       
   170 
       
   171   // Assemble the final message.
       
   172   msg = translate.hasWeaknesses + '<ul><li>' + msg.join('</li><li>') + '</li></ul>';
       
   173   return { strength: strength, message: msg, indicatorText: indicatorText };
       
   174 
       
   175 };
       
   176 
       
   177 /**
       
   178  * Field instance settings screen: force the 'Display on registration form'
       
   179  * checkbox checked whenever 'Required' is checked.
       
   180  */
       
   181 Drupal.behaviors.fieldUserRegistration = {
       
   182   attach: function (context, settings) {
       
   183     var $checkbox = $('form#field-ui-field-edit-form input#edit-instance-settings-user-register-form');
       
   184 
       
   185     if ($checkbox.length) {
       
   186       $('input#edit-instance-required', context).once('user-register-form-checkbox', function () {
       
   187         $(this).bind('change', function (e) {
       
   188           if ($(this).attr('checked')) {
       
   189             $checkbox.attr('checked', true);
       
   190           }
       
   191         });
       
   192       });
       
   193 
       
   194     }
       
   195   }
       
   196 };
       
   197 
       
   198 })(jQuery);