root / drupal7 / modules / user / user.js @ 6d8023f2
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); |