| CODENOTIFIER | HelpYou are not signed inSign in |
Project: jQuery
Revision: 5832
Author: joern.zaefferer
Date: 19 Aug 2008 13:26:15
Diff at Trac: http://dev.jquery.com/changeset/5832
Changes:validate: first prototype for password validation including password strength meter
Files:| ... | ...@@ -0,0 +1,69 @@ | |
| 1 | (function($) { | |
| 2 | ||
| 3 | var LOWER = /[a-z]/, | |
| 4 | UPPER = /[A-Z]/, | |
| 5 | DIGIT = /[0-9]/, | |
| 6 | DIGITS = /[0-9].*[0-9]/, | |
| 7 | SPECIAL = /[^a-zA-Z0-9]/, | |
| 8 | SAME = /^(.)\1+$/; | |
| 9 | ||
| 10 | function rating(rate, message) { | |
| 11 | return { | |
| 12 | rate: rate, | |
| 13 | messageKey: message | |
| 14 | }; | |
| 15 | } | |
| 16 | ||
| 17 | function uncapitalize(str) { | |
| 18 | return str.substring(0, 1).toLowerCase() + str.substring(1); | |
| 19 | } | |
| 20 | ||
| 21 | $.validator.passwordRating = function(password, username) { | |
| 22 | if (!password || password.length < 8) | |
| 23 | return rating(0, "too-short"); | |
| 24 | if (username && password.toLowerCase().match(username.toLowerCase())) | |
| 25 | return rating(0, "similar-to-username"); | |
| 26 | if (SAME.test(password)) | |
| 27 | return rating(1, "very-weak"); | |
| 28 | ||
| 29 | var lower = LOWER.test(password), | |
| 30 | upper = UPPER.test(uncapitalize(password)), | |
| 31 | digit = DIGIT.test(password), | |
| 32 | digits = DIGITS.test(password), | |
| 33 | special = SPECIAL.test(password); | |
| 34 | ||
| 35 | if (lower && upper && digit || lower && digits || upper && digits || special) | |
| 36 | return rating(4, "strong"); | |
| 37 | if (lower && upper || lower && digit || upper && digit) | |
| 38 | return rating(3, "good"); | |
| 39 | return rating(2, "weak"); | |
| 40 | } | |
| 41 | ||
| 42 | $.validator.passwordRating.messages = { | |
| 43 | "too-short": "Too short", | |
| 44 | "very-weak": "Weak", | |
| 45 | "weak": "Fair", | |
| 46 | "good": "Good", | |
| 47 | "strong": "Strong" | |
| 48 | } | |
| 49 | ||
| 50 | $.validator.addMethod("password", function(value, element, usernameField) { | |
| 51 | // use untrimmed value | |
| 52 | var password = element.value, | |
| 53 | // get username for comparison, if specified | |
| 54 | username = $(typeof usernameField != "boolean" ? usernameField : []); | |
| 55 | ||
| 56 | var rating = $.validator.passwordRating(password, username.val()); | |
| 57 | // update message for this field | |
| 58 | $.extend(this.settings.messages[element.name] || (this.settings.messages[element.name] = {}), { | |
| 59 | password: $.validator.passwordRating.messages[rating.messageKey] | |
| 60 | }) | |
| 61 | $(".password-meter-bar").removeClass().addClass("password-meter-bar").addClass("password-meter-" + rating.messageKey); | |
| 62 | // display process bar instead of error message | |
| 63 | ||
| 64 | return rating.rate > 2; | |
| 65 | }, ""); | |
| 66 | // manually add class rule, to make username param optional | |
| 67 | $.validator.classRuleSettings.password = { password: true }; | |
| 68 | ||
| 69 | })(jQuery); |
| ... | ...@@ -0,0 +1,236 @@ | |
| 1 | /* GENERAL ELEMENTS */ | |
| 2 | ||
| 3 | * { margin: 0; padding: 0; } | |
| 4 | ||
| 5 | body, input, select, textarea { font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; } | |
| 6 | body { color: #333; background-color: #fff; text-align: center; } | |
| 7 | ||
| 8 | a:link { color:#0060BF; text-decoration: underline; } | |
| 9 | a:visited { color:#0060BF; text-decoration: underline; } | |
| 10 | a:active { color:#0060BF; text-decoration: underline; } | |
| 11 | a:hover { color:#000000; text-decoration: underline; } | |
| 12 | ||
| 13 | h1, h2, h3, h4, h5, h6 { font-family: "Lucida Grande", "Lucida Sans Unicode", geneva, verdana, arial, helvetica, sans-serif; font-weight: bold; color: #666; } | |
| 14 | h1 { font-size: 1.8em; margin: 0em 0em 0.6em 0em; color: #EC5800; } | |
| 15 | h2 { font-size: 1.5em; margin: 1.2em 0em 0.4em 0em; } | |
| 16 | h3 { font-size: 1.4em; margin: 1.2em 0em 0.4em 0em; color: #EC5800; } | |
| 17 | h4 { font-size: 1.2em; margin: 1.2em 0em 0.4em 0em; } | |
| 18 | h5 { font-size: 1.0em; margin: 1.2em 0em 0.4em 0em; } | |
| 19 | h6 { font-size: 0.8em; margin: 1.2em 0em 0.4em 0em; } | |
| 20 | ||
| 21 | img { border: 0px; } | |
| 22 | ||
| 23 | p { font-size: 1.0em; line-height: 1.3em; margin: 1.2em 0em 1.2em 0em; } | |
| 24 | li > p { margin-top: 0.2em; } | |
| 25 | pre { font-family: monospace; font-size: 1.0em; } | |
| 26 | strong, b { font-weight: bold; } | |
| 27 | ||
| 28 | /* PAGE ELEMENTS */ | |
| 29 | ||
| 30 | /* Content */ | |
| 31 | ||
| 32 | #content { margin: 0em auto; width: 765px; padding: 10px 0 10px 0; text-align: left; /* Win IE5 */ } | |
| 33 | .content { margin-left: 4.5em; margin-right: 4.5em; } | |
| 34 | .content ol, .content ul, .content li { font-size: 1.0em; line-height: 1.3em; margin: 0.2em 0 0.1em 1.5em; } | |
| 35 | .content ol.terms li { margin-bottom: 1em; } | |
| 36 | ||
| 37 | /* Header */ | |
| 38 | ||
| 39 | #header { padding-bottom: 10em; } | |
| 40 | #headerlogo { float: left; } | |
| 41 | #headerlogo img { width: 188px; height: 83px; } | |
| 42 | #headernav { float: right; } | |
| 43 | ||
| 44 | label { font-weight: bold; } | |
| 45 | #reminders label { font-weight: normal; } | |
| 46 | ||
| 47 | table.tabbedtable { padding-left: 3em; } | |
| 48 | table.tabbedtable td { padding-bottom: 5px; } | |
| 49 | table.tabbedtable label { text-align: right; padding-right: 9px; } | |
| 50 | .hiddenlabel { visibility: hidden; } | |
| 51 | .largelink { border: 1px solid #cacaca; padding: 10px; background-color: #E8EEF7; font-size: 1.2em; font-weight: bold; } | |
| 52 | .largelinkwrap { padding-top: 10px; padding-bottom: 10px; } | |
| 53 | ||
| 54 | ||
| 55 | ||
| 56 | #signuptab { | |
| 57 | float:left; | |
| 58 | width:100%; | |
| 59 | background:#fff url("bg.gif") repeat-x bottom; | |
| 60 | font-size: 1.0em; | |
| 61 | line-height: normal; | |
| 62 | } | |
| 63 | #signuptab ul { | |
| 64 | margin:0; | |
| 65 | padding: 0px 10px 0px 10px; | |
| 66 | list-style:none; | |
| 67 | } | |
| 68 | #signuptab li { | |
| 69 | float:left; | |
| 70 | background:url("left_white.png") no-repeat left top; | |
| 71 | margin:0; | |
| 72 | padding:0 3px 0 9px; | |
| 73 | border-bottom:1px solid #CACACA; | |
| 74 | } | |
| 75 | #signuptab a { | |
| 76 | float:left; | |
| 77 | display:block; | |
| 78 | width:.1em; | |
| 79 | background:url("right_white.png") no-repeat right top; | |
| 80 | padding:2px 15px 0px 6px; | |
| 81 | text-decoration:none; | |
| 82 | font-weight:bold; | |
| 83 | color:#fff; | |
| 84 | white-space: nowrap; | |
| 85 | } | |
| 86 | #signuptab > ul a {width:auto;} | |
| 87 | /* Commented Backslash Hack hides rule from IE5-Mac \*/ | |
| 88 | #signuptab a {float:none;} | |
| 89 | /* End IE5-Mac hack */ | |
| 90 | #signuptab a:hover { | |
| 91 | color:#333; | |
| 92 | } | |
| 93 | #signuptab #signupcurrent { | |
| 94 | background-position:0 -150px; | |
| 95 | border-width:0; | |
| 96 | } | |
| 97 | #signuptab #signupcurrent a { | |
| 98 | background-position:100% -150px; | |
| 99 | padding-bottom:1px; | |
| 100 | color:#000; | |
| 101 | } | |
| 102 | #signuptab li:hover, #signuptab li:hover a { | |
| 103 | background-position:0% -150px; | |
| 104 | color:#000; | |
| 105 | } | |
| 106 | #signuptab li:hover a { | |
| 107 | background-position:100% -150px; | |
| 108 | } | |
| 109 | ||
| 110 | /* Signup box */ | |
| 111 | ||
| 112 | #signupbox { | |
| 113 | width: 100%; | |
| 114 | text-align: center; | |
| 115 | margin: 0em auto; | |
| 116 | } | |
| 117 | ||
| 118 | #signupwrap { | |
| 119 | border: 1px solid #CACACA; | |
| 120 | border-top: 0; | |
| 121 | text-align: left; | |
| 122 | padding: 35px 10px 20px 30px; | |
| 123 | clear: both; | |
| 124 | } | |
| 125 | ||
| 126 | /* Unsupported browsers */ | |
| 127 | ||
| 128 | .orange_rbcontent { padding: 0.4em; } | |
| 129 | .orange_rbroundbox { width: 100%; } | |
| 130 | ||
| 131 | #unsupported { | |
| 132 | font-weight: bold; | |
| 133 | text-align: left; | |
| 134 | } | |
| 135 | ||
| 136 | /*#content { | |
| 137 | padding-top: 15px; | |
| 138 | }*/ | |
| 139 | ||
| 140 | /* Signup form */ | |
| 141 | ||
| 142 | #signupform table { | |
| 143 | border-spacing: 0px; | |
| 144 | border-collapse: collapse; | |
| 145 | empty-cells: show; | |
| 146 | } | |
| 147 | ||
| 148 | #signupform .label { | |
| 149 | padding-top: 2px; | |
| 150 | padding-right: 8px; | |
| 151 | vertical-align: top; | |
| 152 | text-align: right; | |
| 153 | width: 125px; | |
| 154 | white-space: nowrap; | |
| 155 | } | |
| 156 | ||
| 157 | #signupform .field { | |
| 158 | padding-bottom: 10px; | |
| 159 | white-space: nowrap; | |
| 160 | } | |
| 161 | ||
| 162 | #signupform .status { | |
| 163 | padding-top: 2px; | |
| 164 | padding-left: 8px; | |
| 165 | vertical-align: top; | |
| 166 | width: 246px; | |
| 167 | white-space: nowrap; | |
| 168 | } | |
| 169 | ||
| 170 | #signupform .textfield { | |
| 171 | width: 150px; | |
| 172 | } | |
| 173 | ||
| 174 | #signupform label.error { | |
| 175 | background:url("unchecked.gif") no-repeat 0px 0px; | |
| 176 | padding-left: 16px; | |
| 177 | padding-bottom: 2px; | |
| 178 | font-weight: bold; | |
| 179 | color: #EA5200; | |
| 180 | } | |
| 181 | ||
| 182 | #signupform label.checked { | |
| 183 | background:url("checked.gif") no-repeat 0px 0px; | |
| 184 | } | |
| 185 | ||
| 186 | #signupform .success_msg { | |
| 187 | font-weight: bold; | |
| 188 | color: #0060BF; | |
| 189 | margin-left: 19px; | |
| 190 | } | |
| 191 | ||
| 192 | #signupform #dateformatStatus, #signupform #termsStatus { | |
| 193 | margin-left: 6px; | |
| 194 | } | |
| 195 | ||
| 196 | #signupform #dateformat_eu { | |
| 197 | vertical-align: middle; | |
| 198 | } | |
| 199 | ||
| 200 | #signupform #ldateformat_eu { | |
| 201 | font-weight: normal; | |
| 202 | vertical-align: middle; | |
| 203 | } | |
| 204 | ||
| 205 | #signupform #dateformat_am { | |
| 206 | vertical-align: middle; | |
| 207 | } | |
| 208 | ||
| 209 | #signupform #ldateformat_am { | |
| 210 | font-weight: normal; | |
| 211 | vertical-align: middle; | |
| 212 | } | |
| 213 | ||
| 214 | #signupform #termswrap { | |
| 215 | float: left; | |
| 216 | } | |
| 217 | ||
| 218 | #signupform #terms { | |
| 219 | vertical-align: middle; | |
| 220 | float: left; | |
| 221 | display: block; | |
| 222 | margin-right: 5px; | |
| 223 | } | |
| 224 | ||
| 225 | #signupform #lterms { | |
| 226 | font-weight: normal; | |
| 227 | vertical-align: middle; | |
| 228 | float: left; | |
| 229 | display: block; | |
| 230 | width: 350px; | |
| 231 | white-space: normal; | |
| 232 | } | |
| 233 | ||
| 234 | #signupform #lsignupsubmit { | |
| 235 | visibility: hidden; | |
| 236 | } | |
| 0 | 237 | \ No newline at end of file |
| ... | ...@@ -0,0 +1,166 @@ | |
| 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
| 2 | <html> | |
| 3 | <head> | |
| 4 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |
| 5 | <title>jQuery Validation Plugin Password Extension demo</title> | |
| 6 | ||
| 7 | <link rel="stylesheet" type="text/css" media="screen" href="milk.css" /> | |
| 8 | ||
| 9 | <script type="text/javascript" src="../../validate/lib/jquery.js"></script> | |
| 10 | <script type="text/javascript" src="../../validate/jquery.validate.js"></script> | |
| 11 | <script type="text/javascript" src="../jquery.validate.password.js"></script> | |
| 12 | ||
| 13 | <style type="text/css"> | |
| 14 | .password-meter { | |
| 15 | position:relative; | |
| 16 | top: 20px; | |
| 17 | background: #e0e0e0; | |
| 18 | width: 180px; | |
| 19 | } | |
| 20 | .password-meter-bar { | |
| 21 | height: 4px; | |
| 22 | } | |
| 23 | .password-meter-weak { | |
| 24 | background: red; | |
| 25 | width: 20px; | |
| 26 | } | |
| 27 | .password-meter-good { | |
| 28 | background: blue; | |
| 29 | width: 140px; | |
| 30 | } | |
| 31 | .password-meter-strong { | |
| 32 | background: green; | |
| 33 | width: 180px; | |
| 34 | } | |
| 35 | ||
| 36 | </style> | |
| 37 | ||
| 38 | <script id="demo" type="text/javascript"> | |
| 39 | $(document).ready(function() { | |
| 40 | // validate signup form on keyup and submit | |
| 41 | var validator = $("#signupform").validate({ | |
| 42 | rules: { | |
| 43 | username: { | |
| 44 | required: true, | |
| 45 | minlength: 2 | |
| 46 | }, | |
| 47 | password: { | |
| 48 | required: true, | |
| 49 | password: true | |
| 50 | }, | |
| 51 | password_confirm: { | |
| 52 | required: true, | |
| 53 | equalTo: "#password" | |
| 54 | } | |
| 55 | }, | |
| 56 | messages: { | |
| 57 | username: { | |
| 58 | required: "Enter a username", | |
| 59 | minlength: jQuery.format("Enter at least {0} characters") | |
| 60 | }, | |
| 61 | password: { | |
| 62 | required: "Provide a password", | |
| 63 | rangelength: jQuery.format("Enter at least {0} characters") | |
| 64 | }, | |
| 65 | password_confirm: { | |
| 66 | required: "Repeat your password", | |
| 67 | minlength: jQuery.format("Enter at least {0} characters"), | |
| 68 | equalTo: "Enter the same password as above" | |
| 69 | } | |
| 70 | }, | |
| 71 | // the errorPlacement has to take the table layout into account | |
| 72 | errorPlacement: function(error, element) { | |
| 73 | error.appendTo( element.parent().next() ); | |
| 74 | }, | |
| 75 | // specifying a submitHandler prevents the default submit, good for the demo | |
| 76 | submitHandler: function() { | |
| 77 | alert("submitted!"); | |
| 78 | }, | |
| 79 | // set this class to error-labels to indicate valid fields | |
| 80 | success: function(label) { | |
| 81 | // set as text for IE | |
| 82 | label.html(" ").addClass("checked"); | |
| 83 | } | |
| 84 | }); | |
| 85 | ||
| 86 | // propose username by combining first- and lastname | |
| 87 | $("#username").focus(function() { | |
| 88 | var firstname = $("#firstname").val(); | |
| 89 | var lastname = $("#lastname").val(); | |
| 90 | if(firstname && lastname && !this.value) { | |
| 91 | this.value = firstname + "." + lastname; | |
| 92 | } | |
| 93 | }); | |
| 94 | ||
| 95 | }); | |
| 96 | </script> | |
| 97 | ||
| 98 | </head> | |
| 99 | <body> | |
| 100 | ||
| 101 | <h1 id="banner"><a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">jQuery Validation Plugin Password Extension </a> Demo</h1> | |
| 102 | <div id="main"> | |
| 103 | ||
| 104 | <div id="content"> | |
| 105 | ||
| 106 | <div id="header"> | |
| 107 | <div id="headerlogo"><img src="milk.png" alt="Remember The Milk" /></div> | |
| 108 | </div> | |
| 109 | <div style="clear: both;"><div></div></div> | |
| 110 | ||
| 111 | ||
| 112 | <div class="content"> | |
| 113 | <div id="signupbox"> | |
| 114 | <div id="signuptab"> | |
| 115 | <ul> | |
| 116 | <li id="signupcurrent"><a href=" ">Signup</a></li> | |
| 117 | </ul> | |
| 118 | </div> | |
| 119 | <div id="signupwrap"> | |
| 120 | <form id="signupform" autocomplete="off" method="get" action=""> | |
| 121 | <table> | |
| 122 | <tr> | |
| 123 | <td class="label"><label id="lusername" for="username">Username</label></td> | |
| 124 | <td class="field"><input id="username" name="username" type="text" value="" maxlength="50" /></td> | |
| 125 | <td class="status"></td> | |
| 126 | </tr> | |
| 127 | <tr> | |
| 128 | <td class="label"><label id="lpassword" for="password">Password</label></td> | |
| 129 | <td class="field"><input id="password" name="password" type="password" maxlength="50" value="" /></td> | |
| 130 | <td class="status"> | |
| 131 | <div class="password-meter"> | |
| 132 | <div class="password-meter-bar"></div> | |
| 133 | </div> | |
| 134 | </td> | |
| 135 | </tr> | |
| 136 | <tr> | |
| 137 | <td class="label"><label id="lpassword_confirm" for="password_confirm">Confirm Password</label></td> | |
| 138 | <td class="field"><input id="password_confirm" name="password_confirm" type="password" maxlength="50" value="" /></td> | |
| 139 | <td class="status"></td> | |
| 140 | </tr> | |
| 141 | <tr> | |
| 142 | <td class="label"><label id="lsignupsubmit" for="signupsubmit">Signup</label></td> | |
| 143 | <td class="field" colspan="2"> | |
| 144 | <input id="signupsubmit" name="signup" type="submit" value="Signup" /> | |
| 145 | </td> | |
| 146 | </tr> | |
| 147 | ||
| 148 | </table> | |
| 149 | </form> | |
| 150 | </div> | |
| 151 | </div> | |
| 152 | </div> | |
| 153 | ||
| 154 | </div> | |
| 155 | ||
| 156 | </div> | |
| 157 | ||
| 158 | <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> | |
| 159 | </script> | |
| 160 | <script type="text/javascript"> | |
| 161 | _uacct = "UA-2623402-1"; | |
| 162 | urchinTracker(); | |
| 163 | </script> | |
| 164 | ||
| 165 | </body> | |
| 166 | </html> | |
| 0 | 167 | \ No newline at end of file |