annotate modules/user/user.js @ 20:e3d20ebd63d1 tip

Added tag 6.9 for changeset 3edae6ecd6c6
author Franck Deroche <franck@defr.org>
date Thu, 15 Jan 2009 10:16:10 +0100
parents c1f4ac30525a
children
rev   line source
webmaster@1 1 // $Id: user.js,v 1.6 2007/09/12 18:29:32 goba Exp $
webmaster@1 2
webmaster@1 3 /**
webmaster@1 4 * Attach handlers to evaluate the strength of any password fields and to check
webmaster@1 5 * that its confirmation is correct.
webmaster@1 6 */
webmaster@1 7 Drupal.behaviors.password = function(context) {
webmaster@1 8 var translate = Drupal.settings.password;
webmaster@1 9 $("input.password-field:not(.password-processed)", context).each(function() {
webmaster@1 10 var passwordInput = $(this).addClass('password-processed');
webmaster@1 11 var parent = $(this).parent();
webmaster@1 12 // Wait this number of milliseconds before checking password.
webmaster@1 13 var monitorDelay = 700;
webmaster@1 14
webmaster@1 15 // Add the password strength layers.
webmaster@1 16 $(this).after('<span class="password-strength"><span class="password-title">'+ translate.strengthTitle +'</span> <span class="password-result"></span></span>').parent();
webmaster@1 17 var passwordStrength = $("span.password-strength", parent);
webmaster@1 18 var passwordResult = $("span.password-result", passwordStrength);
webmaster@1 19 parent.addClass("password-parent");
webmaster@1 20
webmaster@1 21 // Add the password confirmation layer.
webmaster@1 22 var outerItem = $(this).parent().parent();
webmaster@1 23 $("input.password-confirm", outerItem).after('<span class="password-confirm">'+ translate["confirmTitle"] +' <span></span></span>').parent().addClass("confirm-parent");
webmaster@1 24 var confirmInput = $("input.password-confirm", outerItem);
webmaster@1 25 var confirmResult = $("span.password-confirm", outerItem);
webmaster@1 26 var confirmChild = $("span", confirmResult);
webmaster@1 27
webmaster@1 28 // Add the description box at the end.
webmaster@1 29 $(confirmInput).parent().after('<div class="password-description"></div>');
webmaster@1 30 var passwordDescription = $("div.password-description", $(this).parent().parent()).hide();
webmaster@1 31
webmaster@1 32 // Check the password fields.
webmaster@1 33 var passwordCheck = function () {
webmaster@1 34 // Remove timers for a delayed check if they exist.
webmaster@1 35 if (this.timer) {
webmaster@1 36 clearTimeout(this.timer);
webmaster@1 37 }
webmaster@1 38
webmaster@1 39 // Verify that there is a password to check.
webmaster@1 40 if (!passwordInput.val()) {
webmaster@1 41 passwordStrength.css({ visibility: "hidden" });
webmaster@1 42 passwordDescription.hide();
webmaster@1 43 return;
webmaster@1 44 }
webmaster@1 45
webmaster@1 46 // Evaluate password strength.
webmaster@1 47
webmaster@1 48 var result = Drupal.evaluatePasswordStrength(passwordInput.val());
webmaster@1 49 passwordResult.html(result.strength == "" ? "" : translate[result.strength +"Strength"]);
webmaster@1 50
webmaster@1 51 // Map the password strength to the relevant drupal CSS class.
webmaster@1 52 var classMap = { low: "error", medium: "warning", high: "ok" };
webmaster@1 53 var newClass = classMap[result.strength] || "";
webmaster@1 54
webmaster@1 55 // Remove the previous styling if any exists; add the new class.
webmaster@1 56 if (this.passwordClass) {
webmaster@1 57 passwordResult.removeClass(this.passwordClass);
webmaster@1 58 passwordDescription.removeClass(this.passwordClass);
webmaster@1 59 }
webmaster@1 60 passwordDescription.html(result.message);
webmaster@1 61 passwordResult.addClass(newClass);
webmaster@1 62 if (result.strength == "high") {
webmaster@1 63 passwordDescription.hide();
webmaster@1 64 }
webmaster@1 65 else {
webmaster@1 66 passwordDescription.addClass(newClass);
webmaster@1 67 }
webmaster@1 68 this.passwordClass = newClass;
webmaster@1 69
webmaster@1 70 // Check that password and confirmation match.
webmaster@1 71
webmaster@1 72 // Hide the result layer if confirmation is empty, otherwise show the layer.
webmaster@1 73 confirmResult.css({ visibility: (confirmInput.val() == "" ? "hidden" : "visible") });
webmaster@1 74
webmaster@1 75 var success = passwordInput.val() == confirmInput.val();
webmaster@1 76
webmaster@1 77 // Remove the previous styling if any exists.
webmaster@1 78 if (this.confirmClass) {
webmaster@1 79 confirmChild.removeClass(this.confirmClass);
webmaster@1 80 }
webmaster@1 81
webmaster@1 82 // Fill in the correct message and set the class accordingly.
webmaster@1 83 var confirmClass = success ? "ok" : "error";
webmaster@1 84 confirmChild.html(translate["confirm"+ (success ? "Success" : "Failure")]).addClass(confirmClass);
webmaster@1 85 this.confirmClass = confirmClass;
webmaster@1 86
webmaster@1 87 // Show the indicator and tips.
webmaster@1 88 passwordStrength.css({ visibility: "visible" });
webmaster@1 89 passwordDescription.show();
webmaster@1 90 };
webmaster@1 91
webmaster@1 92 // Do a delayed check on the password fields.
webmaster@1 93 var passwordDelayedCheck = function() {
webmaster@1 94 // Postpone the check since the user is most likely still typing.
webmaster@1 95 if (this.timer) {
webmaster@1 96 clearTimeout(this.timer);
webmaster@1 97 }
webmaster@1 98
webmaster@1 99 // When the user clears the field, hide the tips immediately.
webmaster@1 100 if (!passwordInput.val()) {
webmaster@1 101 passwordStrength.css({ visibility: "hidden" });
webmaster@1 102 passwordDescription.hide();
webmaster@1 103 return;
webmaster@1 104 }
webmaster@1 105
webmaster@1 106 // Schedule the actual check.
webmaster@1 107 this.timer = setTimeout(passwordCheck, monitorDelay);
webmaster@1 108 };
webmaster@1 109 // Monitor keyup and blur events.
webmaster@1 110 // Blur must be used because a mouse paste does not trigger keyup.
webmaster@1 111 passwordInput.keyup(passwordDelayedCheck).blur(passwordCheck);
webmaster@1 112 confirmInput.keyup(passwordDelayedCheck).blur(passwordCheck);
webmaster@1 113 });
webmaster@1 114 };
webmaster@1 115
webmaster@1 116 /**
webmaster@1 117 * Evaluate the strength of a user's password.
webmaster@1 118 *
webmaster@1 119 * Returns the estimated strength and the relevant output message.
webmaster@1 120 */
webmaster@1 121 Drupal.evaluatePasswordStrength = function(value) {
webmaster@1 122 var strength = "", msg = "", translate = Drupal.settings.password;
webmaster@1 123
webmaster@1 124 var hasLetters = value.match(/[a-zA-Z]+/);
webmaster@1 125 var hasNumbers = value.match(/[0-9]+/);
webmaster@1 126 var hasPunctuation = value.match(/[^a-zA-Z0-9]+/);
webmaster@1 127 var hasCasing = value.match(/[a-z]+.*[A-Z]+|[A-Z]+.*[a-z]+/);
webmaster@1 128
webmaster@1 129 // Check if the password is blank.
webmaster@1 130 if (!value.length) {
webmaster@1 131 strength = "";
webmaster@1 132 msg = "";
webmaster@1 133 }
webmaster@1 134 // Check if length is less than 6 characters.
webmaster@1 135 else if (value.length < 6) {
webmaster@1 136 strength = "low";
webmaster@1 137 msg = translate.tooShort;
webmaster@1 138 }
webmaster@1 139 // Check if password is the same as the username (convert both to lowercase).
webmaster@1 140 else if (value.toLowerCase() == translate.username.toLowerCase()) {
webmaster@1 141 strength = "low";
webmaster@1 142 msg = translate.sameAsUsername;
webmaster@1 143 }
webmaster@1 144 // Check if it contains letters, numbers, punctuation, and upper/lower case.
webmaster@1 145 else if (hasLetters && hasNumbers && hasPunctuation && hasCasing) {
webmaster@1 146 strength = "high";
webmaster@1 147 }
webmaster@1 148 // Password is not secure enough so construct the medium-strength message.
webmaster@1 149 else {
webmaster@1 150 // Extremely bad passwords still count as low.
webmaster@1 151 var count = (hasLetters ? 1 : 0) + (hasNumbers ? 1 : 0) + (hasPunctuation ? 1 : 0) + (hasCasing ? 1 : 0);
webmaster@1 152 strength = count > 1 ? "medium" : "low";
webmaster@1 153
webmaster@1 154 msg = [];
webmaster@1 155 if (!hasLetters || !hasCasing) {
webmaster@1 156 msg.push(translate.addLetters);
webmaster@1 157 }
webmaster@1 158 if (!hasNumbers) {
webmaster@1 159 msg.push(translate.addNumbers);
webmaster@1 160 }
webmaster@1 161 if (!hasPunctuation) {
webmaster@1 162 msg.push(translate.addPunctuation);
webmaster@1 163 }
webmaster@1 164 msg = translate.needsMoreVariation +"<ul><li>"+ msg.join("</li><li>") +"</li></ul>";
webmaster@1 165 }
webmaster@1 166
webmaster@1 167 return { strength: strength, message: msg };
webmaster@1 168 };
webmaster@1 169
webmaster@1 170 /**
webmaster@1 171 * Set the client's system timezone as default values of form fields.
webmaster@1 172 */
webmaster@1 173 Drupal.setDefaultTimezone = function() {
webmaster@1 174 var offset = new Date().getTimezoneOffset() * -60;
webmaster@1 175 $("#edit-date-default-timezone, #edit-user-register-timezone").val(offset);
webmaster@1 176 };
webmaster@1 177
webmaster@1 178 /**
webmaster@1 179 * On the admin/user/settings page, conditionally show all of the
webmaster@1 180 * picture-related form elements depending on the current value of the
webmaster@1 181 * "Picture support" radio buttons.
webmaster@1 182 */
webmaster@1 183 Drupal.behaviors.userSettings = function (context) {
webmaster@1 184 $('div.user-admin-picture-radios input[type=radio]:not(.userSettings-processed)', context).addClass('userSettings-processed').click(function () {
webmaster@1 185 $('div.user-admin-picture-settings', context)[['hide', 'show'][this.value]]();
webmaster@1 186 });
webmaster@1 187 };
webmaster@1 188