Code:
Ext.namespace('Ext.ux.form.field');
/**
* Password Field.
*
* @class Ext.ux.form.field.PasswordField
* @extends Ext.form.Field
*
* Associated CSS:
.j-password-field h4 {margin-bottom: 3px;}
.j-password-field .containerBar {height: 6px; width: 170px; margin-bottom: 15px; background-color: #E6E6E6;}
.j-password-field .percentage {height: 6px;}
.j-password-field .strong .percentage {background-color: green;}
.j-password-field .strong span {color: green;}
.j-password-field .good .percentage {background-color: #6699FF;}
.j-password-field .good span {color: #6699FF;}
.j-password-field .fair .percentage {background-color: #FFCC00;}
.j-password-field .fair span {color: #FFCC00;}
.j-password-field .matches {color:green;background-image:url(../../../img/16/green_check_mark.png) !important; background-repeat: no-repeat; padding-left:22px; line-height:16px; display:block; font-size:10pt;}
.j-password-field .doesnt-match {color:red; background-image:url(../../../img/16/cross.png) !important; background-repeat: no-repeat; padding-left:22px; line-height:16px; display:block; font-size:10pt;}
*/
Ext.ux.form.field.PasswordField = Ext.extend(Ext.form.Field, {
width: 500,
validateOnBlur: true,
fieldLabel: 'Password:<br/><br/>Confirm Password',//Very Hacky
constructor: function(config) {
if(config.name) {
this.passwordFieldName = config.name;
config.name = null;
}
Ext.apply(this, config);
Ext.ux.form.field.PasswordField.superclass.constructor.apply(this, config);
},
initComponent: function() {
Ext.applyIf(this, {
minLength: 6,
maxLength: 64,
regexText: "Invalid Password"
});
Ext.apply(this, {
regex: new RegExp('^[A-Za-z0-9!@#$%^&\*_]{'+this.minLength+','+this.maxLength+'}$','i')
});
Ext.ux.form.field.PasswordField.superclass.initComponent.apply(this);
},
getName: function() {
return this.passwordFieldName;
},
onPasswordKeyUp: function(event, el) {
var pwd = this.passwordField.getValue();
var strength = this.getPasswordStrength(pwd);
var labelConfig;
switch(strength)
{
case 1:
labelConfig = {
pClass: "fair",
pLabel: 'Fair',
width: 50,
};
break;
case 2:
labelConfig = {
pClass: "good",
pLabel: 'Good',
width: 75,
};
break;
case 3:
labelConfig = {
pClass: "strong",
pLabel: 'Strong',
width: 100,
};
break;
case 0:
default:
labelConfig = {
pClass: "",
pLabel: 'Too short',
width: 0,
};
break;
}
this.passwordStrengthLabel.update(labelConfig);
if(this.repeatPasswordField.getValue()) {
this.updateRepeatMatch(pwd);
}
},
onRepeatKeyUp: function(event, el) {
var pwd = this.passwordField.getValue();
this.updateRepeatMatch(pwd);
},
updateRepeatMatch: function(pwd) {
var repeatedPwd = this.repeatPasswordField.getValue();
this.repeatPasswordCorrectLabel.removeClass('matches');
this.repeatPasswordCorrectLabel.removeClass('doesnt-match');
if(!repeatedPwd || repeatedPwd.length == 0) {
this.repeatPasswordCorrectLabel.update('');
} else if (repeatedPwd == pwd) {
this.repeatPasswordCorrectLabel.addClass('matches');
this.repeatPasswordCorrectLabel.update(' ');
} else {
this.repeatPasswordCorrectLabel.addClass('doesnt-match');
this.repeatPasswordCorrectLabel.update("Doesn't match");
}
},
getPasswordStrength: function(password) {
//RegExes from http://www.marketingtechblog.com/javascript-password-strength/
var strongRegex = new RegExp('^(?=.{'+(this.minLength+4)+',})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$', 'g');
var mediumRegex = new RegExp('^(?=.{'+(this.minLength+2)+',})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$', 'g');
var strength;
if (password.length < this.minLength) {
strength=0;
} else if (strongRegex.test(password)) {
strength=3;
} else if (mediumRegex.test(password)) {
strength=2;
} else {
strength = 1;
}
return strength;
},
getValue : function() {
if(this.repeatPasswordField.getValue() == this.passwordField.getValue()) {
return this.passwordField.getValue();
}
return '';
},
setValue : function(v) {
this.passwordField.setValue(v);
return this;
},
isDirty: function() {
if (this.rendered && !this.disabled) {
if(this.passwordField.isDirty() || this.repeatPasswordFIeld.isDirty()) {
return true;
}
}
return false;
},
getErrors: function() {
var errors = [];
var pwd = this.passwordField.getValue();
if(!pwd || pwd.length < this.minLength) {
errors.push('Password must be at least ' + this.minLength + ' charaters');
}
if(this.repeatPasswordField.getValue() != pwd) {
errors.push('Password confirmation incorrect');
}
return errors;
},
onRender: function(ct, position){
if(!this.el) {
this.panel = new Ext.Container({
layout: 'form',
width: 400,
renderTo: ct,
border: false,
autoWidth: true,
items: [
{
xtype: 'container',
layout:'column',
border: false,
cls: 'j-password-field',
width: 400,
items:[
{
xtype: 'container',
columnWidth: .5,
layout: {
type: 'form',
fieldTpl: new Ext.Template(
'<div class="x-form-item {itemCls}" tabIndex="-1">',//Overriding the default fieldTpl to remove the label
'<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle};padding-left:0px;">',
'</div><div class="{clearCls}"></div>',
'</div>'
)
},
border: false,
style: 'margin-right:10px;',
items: [
this.passwordField = new Ext.form.TextField({
fieldLabel: i18n.g('j.l.password'),
regex: this.regex,
regexText: this.regexText,
name: this.passwordFieldName,
allowBlank: false,
width: 115,
enableKeyEvents: true,
inputType: 'password',
listeners: {
afterrender: function(pwdField) {
pwdField.getEl().on('keyup', this.onPasswordKeyUp, this);
},
scope: this
}
}),
this.repeatPasswordField = new Ext.form.TextField({
fieldLabel: i18n.g('j.l.confirmPassword'),
regex: this.regex,
regexText: this.regexText,
submitValue: false,
allowBlank: false,
inputType: 'password',
width: 115,
enableKeyEvents: true,
listeners: {
afterrender: function() {
this.repeatPasswordField.getEl().on('keyup', this.onRepeatKeyUp, this);
},
scope: this
}
})
]
},{
xtype: 'container',
columnWidth: .5,
layout: 'form',
border: false,
items: [
this.passwordStrengthLabel = new Ext.form.Label({
width: 200,
tpl: new Ext.XTemplate(
'<div ext:qtip="{[this.getQtipText()]}" class="{pClass}">' +
'<h4>Password Strength: <span>{pLabel}</span></h4>' +
'<div class="containerBar">' +
'<div class="percentage" style="width: {width}%"></div>' +
'</div>' +
'</div>', {
getQtipText: function() {
return 'Strong passwords contain at least '+this.minLength+ ' characters, ' +
'do not include common words or names, and combine uppercase letters, ' +
'lowercase letters, numbers and symbols (!@#$%^&*_).';
}.createDelegate(this)
}),
listeners: {
afterrender: function(pwdStrengthLabel) {
pwdStrengthLabel.update({
pClass: "",
pLabel: 'Too short',
width: 0,
});
},
scope: this
}
}),
this.repeatPasswordCorrectLabel = new Ext.form.Label({
text: ''
})
]
}]
}
]
});
this.el = this.panel.getEl();
}
Ext.ux.form.field.PasswordField.superclass.onRender.call(this, ct, position);
},
onDisable: function() {
this.delegateFn('disable');
},
onEnable: function() {
this.delegateFn('enable');
},
reset: function() {
this.delegateFn('reset');
},
delegateFn: function(fn) {
this.passwordField[fn]();
this.repeatPasswordField[fn]();
},
beforeDestroy: function() {
Ext.destroy(this.panel);
Ext.ux.form.field.PasswordField.superclass.beforeDestroy.call(this);
},
getRawValue: Ext.emptyFn,
setRawValue: Ext.emptyFn
});