325 lines
10 KiB
JavaScript
325 lines
10 KiB
JavaScript
//>>built
|
|
require({cache:{
|
|
'url:dojox/form/resources/PasswordValidator.html':"<div dojoAttachPoint=\"containerNode\">\n\t<input type=\"hidden\" name=\"${name}\" value=\"\" dojoAttachPoint=\"focusNode\" />\n</div>"}});
|
|
define("dojox/form/PasswordValidator", [
|
|
"dojo/_base/array",
|
|
"dojo/_base/lang",
|
|
"dojo/dom-attr",
|
|
"dojo/i18n",
|
|
"dojo/query",
|
|
"dojo/keys",
|
|
"dijit/form/_FormValueWidget",
|
|
"dijit/form/ValidationTextBox",
|
|
"dojo/text!./resources/PasswordValidator.html",
|
|
"dojo/i18n!./nls/PasswordValidator",
|
|
"dojo/_base/declare"
|
|
], function(array, lang, domAttr, i18n, query, keys, FormValueWidget, ValidationTextBox, template, formNlsPasswordValidator, declare){
|
|
|
|
/*=====
|
|
FormValueWidget = dijit.form._FormValueWidget;
|
|
ValidationTextBox = dijit.form.ValidationTextBox;
|
|
=====*/
|
|
var _ChildTextBox = declare("dojox.form._ChildTextBox", ValidationTextBox, {
|
|
// summary:
|
|
// A class that is shared between all our children - extends
|
|
// ValidationTextBox and provides some shared functionality
|
|
//
|
|
// containerWidget: widget
|
|
// Our parent (the PasswordValidator)
|
|
containerWidget: null,
|
|
|
|
// type: string
|
|
// Don't override this - we are all "password" types
|
|
type: "password",
|
|
|
|
reset: function(){
|
|
// summary:
|
|
// Force-set to empty string (we don't save passwords EVER)...and
|
|
// since _OldPWBox overrides _setValueAttr to check for empty string,
|
|
// call our parent class directly (not this.inherited())
|
|
ValidationTextBox.prototype._setValueAttr.call(this, "", true);
|
|
this._hasBeenBlurred = false;
|
|
},
|
|
|
|
postCreate: function(){
|
|
// summary:
|
|
// We want to remove the "name" attribute from our focus node if
|
|
// we don't have one set - this prevents all our extra values
|
|
// from being posted on submit
|
|
this.inherited(arguments);
|
|
if(!this.name){
|
|
domAttr.remove(this.focusNode, "name");
|
|
}
|
|
this.connect(this.focusNode, "onkeypress", "_onChildKeyPress");
|
|
},
|
|
|
|
_onChildKeyPress: function(e){
|
|
// Check if we pressed <enter> - if so, set our blur value so that
|
|
// the parent widget will be updated correctly.
|
|
if(e && e.keyCode == keys.ENTER){
|
|
this._setBlurValue();
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
|
|
var _OldPWBox = declare("dojox.form._OldPWBox", _ChildTextBox, {
|
|
// summary:
|
|
// A class representing our "old password" box.
|
|
//
|
|
// _isPWValid: boolean
|
|
// Whether or not the password is valid
|
|
_isPWValid: false,
|
|
|
|
_setValueAttr: function(/* anything */ newVal, /* boolean? */ priority){
|
|
// summary:
|
|
// Updates _isPWValid if this isn't our initial update by calling
|
|
// our PasswordValidator's pwCheck function
|
|
if(newVal === ""){
|
|
newVal = _OldPWBox.superclass.attr.call(this, "value");
|
|
}
|
|
if(priority !== null){
|
|
// Priority is passed in as null, explicitly when this is an
|
|
// update (not initially set). We want to check our password now.
|
|
this._isPWValid = this.containerWidget.pwCheck(newVal);
|
|
}
|
|
this.inherited(arguments);
|
|
// Trigger the containerWidget to recheck its value, if needed
|
|
this.containerWidget._childValueAttr(this.containerWidget._inputWidgets[1].get("value"));
|
|
},
|
|
|
|
isValid: function(/* boolean */ isFocused){
|
|
// Take into account the isPWValid setting
|
|
return this.inherited("isValid", arguments) && this._isPWValid;
|
|
},
|
|
|
|
_update: function(/* event */ e){
|
|
// Only call validate() if we've been blurred or else we get popups
|
|
// too early.
|
|
if(this._hasBeenBlurred){ this.validate(true); }
|
|
this._onMouse(e);
|
|
},
|
|
|
|
_getValueAttr: function(){
|
|
if(this.containerWidget._started && this.containerWidget.isValid()){
|
|
return this.inherited(arguments);
|
|
}
|
|
return "";
|
|
},
|
|
|
|
_setBlurValue: function(){
|
|
// TextBox._setBlurValue calls this._setValueAttr(this.get('value'), ...)
|
|
// Because we are overridding _getValueAttr to return "" when the containerWidget
|
|
// is not valid, TextBox._setBlurValue will cause OldPWBox's value to be set to ""
|
|
//
|
|
// So, we directly call ValidationTextBox._getValueAttr to bypass our _getValueAttr
|
|
var value = ValidationTextBox.prototype._getValueAttr.call(this);
|
|
this._setValueAttr(value, (this.isValid ? this.isValid() : true));
|
|
}
|
|
});
|
|
|
|
|
|
var _NewPWBox = declare("dojox.form._NewPWBox", _ChildTextBox, {
|
|
// summary:
|
|
// A class representing our new password textbox
|
|
|
|
// required: boolean
|
|
// Whether or not this widget is required (default: true)
|
|
required: true,
|
|
|
|
onChange: function(){
|
|
// summary:
|
|
// Validates our verify box - to make sure that a change to me is
|
|
// reflected there
|
|
this.containerWidget._inputWidgets[2].validate(false);
|
|
this.inherited(arguments);
|
|
}
|
|
});
|
|
|
|
var _VerifyPWBox = declare("dojox.form._VerifyPWBox", _ChildTextBox, {
|
|
// summary:
|
|
// A class representing our verify textbox
|
|
|
|
isValid: function(isFocused){
|
|
// summary:
|
|
// Validates that we match the "real" password
|
|
return this.inherited("isValid", arguments) &&
|
|
(this.get("value") == this.containerWidget._inputWidgets[1].get("value"));
|
|
}
|
|
});
|
|
|
|
return declare("dojox.form.PasswordValidator", FormValueWidget, {
|
|
// summary:
|
|
// A password validation widget that simplifies the "old/new/verify"
|
|
// style of requesting passwords. You will probably want to override
|
|
// this class and implement your own pwCheck function.
|
|
|
|
// required: boolean
|
|
// Whether or not it is required for form submission
|
|
required: true,
|
|
|
|
// inputWidgets: TextBox[]
|
|
// An array of text boxes that are our components
|
|
_inputWidgets: null,
|
|
|
|
// oldName: string?
|
|
// The name to send our old password as (when form is posted)
|
|
oldName: "",
|
|
|
|
templateString: template,
|
|
|
|
_hasBeenBlurred: false,
|
|
|
|
isValid: function(/* boolean */ isFocused){
|
|
// summary: we are valid if ALL our children are valid
|
|
return array.every(this._inputWidgets, function(i){
|
|
if(i && i._setStateClass){ i._setStateClass(); }
|
|
return (!i || i.isValid());
|
|
});
|
|
},
|
|
|
|
validate: function(/* boolean */ isFocused){
|
|
// summary: Validating this widget validates all our children
|
|
return array.every(array.map(this._inputWidgets, function(i){
|
|
if(i && i.validate){
|
|
i._hasBeenBlurred = (i._hasBeenBlurred || this._hasBeenBlurred);
|
|
return i.validate();
|
|
}
|
|
return true;
|
|
}, this), function(item){ return item; });
|
|
},
|
|
|
|
reset: function(){
|
|
// summary: Resetting this widget resets all our children
|
|
this._hasBeenBlurred = false;
|
|
array.forEach(this._inputWidgets, function(i){
|
|
if(i && i.reset){ i.reset(); }
|
|
}, this);
|
|
},
|
|
|
|
_createSubWidgets: function(){
|
|
// summary:
|
|
// Turns the inputs inside this widget into "real" validation
|
|
// widgets - and sets up the needed connections.
|
|
var widgets = this._inputWidgets,
|
|
msg = i18n.getLocalization("dojox.form", "PasswordValidator", this.lang);
|
|
array.forEach(widgets, function(i, idx){
|
|
if(i){
|
|
var p = {containerWidget: this}, c;
|
|
if(idx === 0){
|
|
p.name = this.oldName;
|
|
p.invalidMessage = msg.badPasswordMessage;
|
|
c = _OldPWBox;
|
|
}else if(idx === 1){
|
|
p.required = this.required;
|
|
c = _NewPWBox;
|
|
}else if(idx === 2){
|
|
p.invalidMessage = msg.nomatchMessage;
|
|
c = _VerifyPWBox;
|
|
}
|
|
widgets[idx] = new c(p, i);
|
|
}
|
|
}, this);
|
|
},
|
|
|
|
pwCheck: function(/* string */ password){
|
|
// summary:
|
|
// Overridable function for validation of the old password box.
|
|
//
|
|
// This function is called and passed the old password. Return
|
|
// true if it's OK to continue, and false if it is not.
|
|
//
|
|
// IMPORTANT SECURITY NOTE: Do NOT EVER EVER EVER check this in
|
|
// HTML or JavaScript!!!
|
|
//
|
|
// You will probably want to override this function to callback
|
|
// to a server to verify the password (the callback will need to
|
|
// be syncronous) - and it's probably a good idea to validate
|
|
// it again on form submission before actually doing
|
|
// anything destructive - that's why the "oldName" value
|
|
// is available.
|
|
//
|
|
// And don't just fetch the password from the server
|
|
// either :) Send the test password (probably hashed, for
|
|
// security) and return from the server a status instead.
|
|
//
|
|
// Again - DON'T BE INSECURE!!! Security is left as an exercise
|
|
// for the reader :)
|
|
return false;
|
|
},
|
|
|
|
postCreate: function(){
|
|
// summary:
|
|
// Sets up the correct widgets. You *MUST* specify one child
|
|
// text box (a simple HTML <input> element) with pwType="new"
|
|
// *and* one child text box with pwType="verify". You *MAY*
|
|
// specify a third child text box with pwType="old" in order to
|
|
// prompt the user to enter in their old password before the
|
|
// widget returns that it is valid.
|
|
|
|
this.inherited(arguments);
|
|
|
|
// Turn my inputs into the correct stuff....
|
|
var widgets = this._inputWidgets = [];
|
|
array.forEach(["old","new","verify"], function(i){
|
|
widgets.push(query("input[pwType=" + i + "]", this.containerNode)[0]);
|
|
}, this);
|
|
if(!widgets[1] || !widgets[2]){
|
|
throw new Error("Need at least pwType=\"new\" and pwType=\"verify\"");
|
|
}
|
|
if(this.oldName && !widgets[0]){
|
|
throw new Error("Need to specify pwType=\"old\" if using oldName");
|
|
}
|
|
this.containerNode = this.domNode;
|
|
this._createSubWidgets();
|
|
this.connect(this._inputWidgets[1], "_setValueAttr", "_childValueAttr");
|
|
this.connect(this._inputWidgets[2], "_setValueAttr", "_childValueAttr");
|
|
},
|
|
|
|
_childValueAttr: function(v){
|
|
this.set("value", this.isValid() ? v : "");
|
|
},
|
|
|
|
_setDisabledAttr: function(value){
|
|
this.inherited(arguments);
|
|
array.forEach(this._inputWidgets, function(i){
|
|
if(i && i.set){ i.set("disabled", value);}
|
|
});
|
|
},
|
|
|
|
_setRequiredAttribute: function(value){
|
|
this.required = value;
|
|
domAttr.set(this.focusNode, "required", value);
|
|
this.focusNode.setAttribute("aria-required", value);
|
|
this._refreshState();
|
|
array.forEach(this._inputWidgets, function(i){
|
|
if(i && i.set){ i.set("required", value);}
|
|
});
|
|
},
|
|
|
|
_setValueAttr: function(v){
|
|
this.inherited(arguments);
|
|
domAttr.set(this.focusNode, "value", v);
|
|
},
|
|
|
|
_getValueAttr: function(){
|
|
// Make sure we don't return undefined.... maybe should do conversion in _setValueAttr() instead?
|
|
return this.value||"";
|
|
},
|
|
|
|
focus: function(){
|
|
// summary:
|
|
// places focus on the first invalid input widget - if all
|
|
// input widgets are valid, the first widget is focused.
|
|
var f = false;
|
|
array.forEach(this._inputWidgets, function(i){
|
|
if(i && !i.isValid() && !f){
|
|
i.focus();
|
|
f = true;
|
|
}
|
|
});
|
|
if(!f){ this._inputWidgets[1].focus(); }
|
|
}
|
|
});
|
|
}); |