1/* 2--- 3 4requires: [AbacusAD, MooTools, Class, Class.Extras, DomReady, Element, Element.Event] 5 6provides: [AbacusAD.PasswordStrength] 7 8... 9*/ 10 11(function($, window, document){ 12 13 $(window).addEvent('domready', function() { 14 $$('.passwordMeter').each(function(element) { 15 new StrongPass(element, { 16 minChar: 8, 17 label: 'Strength', 18 passStrengthZen: 'div.passwordStrength.alignRight', 19 passbarClassZen: 'div.indicator', 20 passbarHintZen: 'p', 21 checkBannedPasswords: false 22 }); 23 }); 24 }); 25 26 (function() { 27 'use strict'; 28 29 var StrongPass = new Class({ 30 31 Implements: [Options, Events], 32 33 options: { 34 minChar: 6, // too short while less than this 35 passIndex: 2, // Weak 36 checkBannedPasswords: true, // prompts when match is found against bannedPassword, set false to disable 37 // output verdicts, colours and bar % 38 label: 'Password strength: ', 39 verdicts: [ 40 ' ', 41 'Very weak', 42 'Weak', 43 'Good', 44 'Strong', 45 'Very strong' 46 ], 47 colors: [ 48 '#F3F3F3', 49 '#B71F38', 50 '#FF8000', 51 '#FFD044', 52 '#008C5C', 53 '#205793' 54 ], 55 width: [ 56 '', 57 '26px', 58 '57px', 59 '88px', 60 '119px', 61 '150px' 62 ], 63 klasses: [ 64 'default', 65 'very-weak', 66 'weak', 67 'good', 68 'strong', 69 'very-strong' 70 ], 71 // tweak scores here 72 scores: [ 73 10, 74 15, 75 25, 76 45 77 ], 78 // when in banned list, verdict is: 79 bannedPass: 'Not allowed', 80 // styles 81 passStrengthZen: 'div.pass-container', 82 passbarClassZen: 'div.pass-bar', // css controls 83 passbarHintZen: 'div.pass-hint', 84 passbarHintZenPlacement: 'top', 85 // output 86 render: true, // it can just report for your own implementation 87 injectTarget: null, 88 injectPlacement: 'after' 89 }, 90 91 bannedPasswords: [ 92 // see study here: http://smrt.io/JlNfrH 93 '123456', 94 '12345', 95 '123456789', 96 'password', 97 'iloveyou', 98 'princess', 99 'rockyou', 100 '1234567', 101 '12345678', 102 'abc123', 103 'nicole', 104 'daniel', 105 'babygirl', 106 'monkey', 107 'jessica', 108 'lovely', 109 'michael', 110 'ashley', 111 '654321', 112 'qwerty', 113 'password1', 114 'welcome', 115 'welcome1', 116 'password2', 117 'password01', 118 'password3', 119 'p@ssw0rd', 120 'passw0rd', 121 'password4', 122 'password123', 123 'summer09', 124 'password6', 125 'password7', 126 'password9', 127 'password8', 128 'welcome2', 129 'welcome01', 130 'winter12', 131 'spring2012', 132 'summer12', 133 'summer2012' 134 ], 135 136 /** 137 * @constructor 138 * @param {DOMElement} element Base element to attach to 139 * @param {Object} options* Options to merge in / attach events from 140 * @fires StrongPass#ready 141 * @returns SrongPass 142 */ 143 initialize: function(element, options) { 144 this.setOptions(options); 145 this.element = document.id(element); 146 if(this.element.getNext('div.passwordStrength')) { 147 this.element.getNext('div.passwordStrength').dispose(); 148 } 149 this.options.render && this.createBox(); 150 this.attachEvents(); 151 this.fireEvent('ready'); 152 }, 153 154 /** 155 * @description Attaches events and saves a reference 156 * @returns {StrongPass} 157 */ 158 attachEvents: function() { 159 var self = this; 160 // only attach events once so freshen 161 this.eventObj && this.element.removeEvents(this.eventObj); 162 this.element.addEvents(this.eventObj = { 163 keyup: this.runPassword.bind(this), 164 focus: function() { 165 self.showStrengthPass(this.value); 166 }, 167 blur: function() { 168 this.getSiblings(self.options.passStrengthZen)[0].setStyle('display', 'none'); 169 } 170 }); 171 172 return this; 173 }, 174 175 /** 176 * @description Attaches pass elements. 177 * @returns {StrongPass} 178 */ 179 createBox: function() { 180 //todo: should be templated 181 var width = this.element.getSize().x, 182 o = this.options; 183 184 this.stbox = new Element(o.passStrengthZen); 185
186 this.stdbar = new Element(o.passbarClassZen, { 187 'html': '<div></div>' 188 }).inject(this.stbox); 189 190 this.txtbox = new Element(o.passbarHintZen, { 191 'html': '<span></span><strong></strong>' 192 }).inject(this.stbox, this.options.passbarHintZenPlacement); 193 this.stbox.inject((document.id(o.injectTarget) || this.element), o.injectPlacement); 194 195 return this; 196 }, 197 198 /** 199 * @description Shows pass strength element. 200 * @returns {StrongPass} 201 */ 202 showStrengthPass: function(field) { 203 if(field.length > 0) { 204 this.element.getSiblings(this.options.passStrengthZen)[0].setStyle('display', 'block'); 205 } 206 return this; 207 }, 208 209 /** 210 * @description Runs a password check on the keyup event 211 * @param {Object} event* 212 * @param {String} password* Optionally pass a string or go to element getter 213 * @fires StrongPass#fail StrongPass#pass 214 * @returns {StrongPass} 215 */ 216 runPassword: function(event, password) { 217 password = password || this.element.get('value'); 218 219 this.showStrengthPass(password); 220 221 var score = this.checkPassword(password), 222 index = 0, 223 o = this.options, 224 s = Array.clone(o.scores), 225 verdict; 226 227 var setscore = function() { 228 if (score < 0 && score > -199) { 229 index = 0; 230 } 231 else { 232 s.push(score); 233 s.sort(function(a, b) { 234 return a - b; 235 }); 236 index = s.indexOf(score) + 1; 237 } 238 239 verdict = o.verdicts[index] || o.verdicts.getLast(); 240 } 241 242 if(this.options.checkBannedPasswords) { 243 if (Array.indexOf(this.bannedPasswords, password.toLowerCase()) !== -1) { 244 this.fireEvent('banned', password); 245 verdict = o.bannedPass; 246 } 247 else { 248 setscore(); 249 } 250 } else { 251 setscore(); 252 } 253 254 if (o.render) { 255 this.txtbox.getElement('span').set('text', o.label); 256 this.txtbox.getElement('strong').set('text', verdict); 257 this.stdbar.getElement('div').setStyles({ 258 'width': o.width[index] || o.width.getLast(), 259 'background-color': o.colors[index] || o.colors.getLast() 260 }); 261 262 this.stdbar 263 .removeClass(o.klasses[0]) 264 .removeClass(o.klasses[1]) 265 .removeClass(o.klasses[2]) 266 .removeClass(o.klasses[3]) 267 .removeClass(o.klasses[4]) 268 .addClass(o.klasses[index]); 269 } 270 271 /** 272 * @event StrongPass#fail,StrongPass#pass 273 */ 274 return this.fireEvent(['fail', 'pass'][+(this.passed = o.verdicts.indexOf(verdict) >= o.passIndex)], [index, verdict, password]); 275 }, 276 277 /** 278 * @type {Array} 279 * @description The collection of regex checks and how much they affect the scoring 280 */ 281 checks: [ 282 /* alphaLower */ { 283 re: /[a-z]/, 284 score: 1 285 }, 286 /* alphaUpper */ { 287 re: /[A-Z]/, 288 score: 5 289 }, 290 /* mixture of upper and lowercase */ { 291 re: /([a-z].*[A-Z])|([A-Z].*[a-z])/, 292 score: 2 293 }, 294 /* threeNumbers */ { 295 re: /(.*[0-9].*[0-9].*[0-9])/, 296 score: 7 297 }, 298 /* special chars */ { 299 re: /.[!@#$%^&*?_~]/, 300 score: 5 301 }, 302 /* multiple special chars */ { 303 re: /(.*[!@#$%^&*?_~].*[!@#$%^&*?_~])/, 304 score: 7 305 }, 306 /* all together now, does it look nice? */ { 307 re: /([a-zA-Z0-9].*[!@#$%^&*?_~])|([!@#$%^&*?_~].*[a-zA-Z0-9])/, 308 score: 3 309 }, 310 /* password of a single char sucks */ { 311 re: /(.)\1+$/, 312 score: 2 313 } 314 ], 315 316 checkPassword: function(pass) { 317 var score = 0, 318 minChar = this.options.minChar, 319 len = pass.length, 320 diff = len - minChar; 321 322 (diff < 0 && (score -= 100)) || (diff >= 5 && (score += 18)) || (diff >= 3 && (score += 12)) || (diff === 2 && (score += 6)); 323 324 Array.each(this.checks, function(check) { 325 pass.match(check.re) && (score += check.score); 326 }); 327 328 // bonus for length per char 329 score && (score += len); 330 return score; 331 } 332 }); 333 334 if (typeof define === 'function' && define.amd) { 335 // return an AMD module 336 define(function(){ 337 return StrongPass; 338 }); 339 } 340 else { 341 // exports to global object 342 this.StrongPass = StrongPass; 343 } 344 345 // change to any object / ns 346 }.call(this)); 347 348})(document.id, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.