One of my friends wants me to help him on putting a password strength meter on his registration page. Inspired by
a post on Ext JS 1.x forum, I created a Ext JS 4 compatible one as shown below,
To do this, what you need is 1) the following Ext JS widget extends from
Ext.form.field.Text
. 2) do not forget the CSS file and images used in CSS. To change the appearance of password meter, you can simply change images used in CSS.
JavaScript code:
Ext.define('yiyu.util.PasswordMeter',
{
extend : 'Ext.form.field.Text',
alias : 'widget.passwordMeter',
inputType : 'password',
reset : function() {
this.callParent();
this.updateMeter(this);
},
//private
onRender : function(container, position) {
var me = this;
me.callParent(arguments);
this.objMeter = me.el.createChild({
tag : "div",
'class' : "strengthMeter"
});
me.objMeter.setWidth(me.el.getWidth(true) - 17);
me.scoreBar = me.objMeter.createChild({
tag : "div",
'class' : "scoreBar"
});
me.scoreBar.setWidth(me.objMeter.getWidth(true));
if (Ext.isIE6) { // Fix style for IE6
this.objMeter.setStyle('margin-left', '3px');
}
},
// private
initEvents : function() {
var me = this, el = me.inputEl;
me.callParent();
me.mon(el, {
scope : me,
keyup : me.updateMeter
});
},
/**
* Sets the width of the meter, based on the score
*
* @param {Object} e
* Private function
*/
updateMeter : function() {
var score, p, maxWidth, nScore, scoreWidth;
score = 0;
p = this.getValue();
maxWidth = this.objMeter.getWidth() - 2;
nScore = this.calcStrength(p);
scoreWidth = maxWidth - (maxWidth / 100) * nScore;
this.scoreBar.setWidth(scoreWidth, true);
},
/**
* Calculates the strength of a password
*
* @param {Object} p
* The password that needs to be calculated
* @return {int} intScore The strength score of the password
*/
calcStrength : function(p) {
var intScore = 0;
// PASSWORD LENGTH
intScore += p.length;
if (p.length > 0 && p.length <= 4) { // length 4 or
// less
intScore += p.length;
} else if (p.length >= 5 && p.length <= 7) {
// length between 5 and 7
intScore += 6;
} else if (p.length >= 8 && p.length <= 15) {
// length between 8 and 15
intScore += 12;
} else if (p.length >= 16) { // length 16 or more
intScore += 18;
}
// LETTERS (Not exactly implemented as dictacted above
// because of my limited understanding of Regex)
if (p.match(/[a-z]/)) {
// [verified] at least one lower case letter
intScore += 1;
}
if (p.match(/[A-Z]/)) { // [verified] at least one upper
// case letter
intScore += 5;
}
// NUMBERS
if (p.match(/\d/)) { // [verified] at least one
// number
intScore += 5;
}
if (p.match(new RegExp(".*\\d.*\\d.*\\d"))) {
// [verified] at least three numbers
intScore += 5;
}
// SPECIAL CHAR
if (p.match(new RegExp("[!,@,#,$,%,^,&,*,?,_,~]"))) {
// [verified] at least one special character
intScore += 5;
}
// [verified] at least two special characters
if (p.match(new RegExp(
".*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~]"
))) {
intScore += 5;
}
// COMBOS
if (p.match(new RegExp("(?=.*[a-z])(?=.*[A-Z])"))) {
// [verified] both upper and lower case
intScore += 2;
}
if (p.match(new RegExp(
"(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])"))) {
// [verified] both letters and numbers
intScore += 2;
}
// [verified] letters, numbers, and special characters
if (p
.match(new RegExp(
"(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!,@,#,$,%,^,&,*,?,_,~])"
))) {
intScore += 2;
}
var nRound = Math.round(intScore * 2);
if (nRound > 100) {
nRound = 100;
}
return nRound;
}
})
CSS code:
.strengthMeter {
border: 1px solid #B5B8C8;
margin: 3px 0 3px 0;
background-image: url(images/meter.gif);
height: 10px;
background-size: 100%;
}
.scoreBar {
background-image: url(images/meter_background.gif);
height: 10px;
background-size: 100%;
line-height: 1px;
font-size: 1px;
float: right;
}
Edit: Here is
a better implementation crated by osnoek.