dojo.provide("dojo.widget.ValidationTextbox");
dojo.require("dojo.widget.Textbox");
dojo.require("dojo.i18n.common");
dojo.widget.defineWidget(
"dojo.widget.ValidationTextbox",
dojo.widget.Textbox,
function() {
// summary:
// A subclass of Textbox.
// Over-ride isValid in subclasses to perform specific kinds of validation.
// this property isn't a primitive and needs to be created on a per-item basis.
this.flags = {};
},
{
// default values for new subclass properties
// required: Boolean
// Can be true or false, default is false.
required: false,
rangeClass: "range",
// invalidClass: String
// Class used to format displayed text in page if necessary to override default class
invalidClass: "invalid",
// missingClass: String
// Override default class used for missing input data
missingClass: "missing",
classPrefix: "dojoValidate",
// size: String
// Basic input tag size declaration.
size: "",
// maxlength: String
// Basic input tag maxlength declaration.
maxlength: "",
// promptMessage: String
// Will not issue invalid message if field is populated with default user-prompt text
promptMessage: "",
// invalidMessage: String
// The message to display if value is invalid.
invalidMessage: "",
// missingMessage: String
// The message to display if value is missing.
missingMessage: "",
rangeMessage: "",
// listenOnKeyPress: Boolean
// Updates messages on each key press. Default is true.
listenOnKeyPress: true,
htmlfloat: "none",
lastCheckedValue: null,
templatePath: dojo.uri.dojoUri("src/widget/templates/ValidationTextbox.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/Validate.css"),
// new DOM nodes
invalidSpan: null,
missingSpan: null,
rangeSpan: null,
getValue: function() {
return this.textbox.value;
},
setValue: function(value) {
this.textbox.value = value;
this.update();
},
isValid: function() {
// summary: Need to over-ride with your own validation code in subclasses
return true;
},
isInRange: function() {
// summary: Need to over-ride with your own validation code in subclasses
return true;
},
isEmpty: function() {
// summary: Checks for whitespace
return ( /^\s*$/.test(this.textbox.value) ); // Boolean
},
isMissing: function() {
// summary: Checks to see if value is required and is whitespace
return ( this.required && this.isEmpty() ); // Boolean
},
update: function() {
// summary:
// Called by oninit, onblur, and onkeypress.
// description:
// Show missing or invalid messages if appropriate, and highlight textbox field.
this.lastCheckedValue = this.textbox.value;
this.missingSpan.style.display = "none";
this.invalidSpan.style.display = "none";
this.rangeSpan.style.display = "none";
var empty = this.isEmpty();
var valid = true;
if(this.promptMessage != this.textbox.value){
valid = this.isValid();
}
var missing = this.isMissing();
// Display at most one error message
if(missing){
this.missingSpan.style.display = "";
}else if( !empty && !valid ){
this.invalidSpan.style.display = "";
}else if( !empty && !this.isInRange() ){
this.rangeSpan.style.display = "";
}
this.highlight();
},
updateClass: function(className){
// summary: used to ensure that only 1 validation class is set at a time
var pre = this.classPrefix;
dojo.html.removeClass(this.textbox,pre+"Empty");
dojo.html.removeClass(this.textbox,pre+"Valid");
dojo.html.removeClass(this.textbox,pre+"Invalid");
dojo.html.addClass(this.textbox,pre+className);
},
highlight: function() {
// summary: by Called oninit, and onblur.
// highlight textbox background
if (this.isEmpty()) {
this.updateClass("Empty");
}else if (this.isValid() && this.isInRange() ){
this.updateClass("Valid");
}else if(this.textbox.value != this.promptMessage){
this.updateClass("Invalid");
}else{
this.updateClass("Empty");
}
},
onfocus: function(evt) {
if ( !this.listenOnKeyPress) {
this.updateClass("Empty");
// this.textbox.style.backgroundColor = "";
}
},
onblur: function(evt) {
this.filter();
this.update();
},
onkeyup: function(evt){
if(this.listenOnKeyPress){
//this.filter(); trim is problem if you have to type two words
this.update();
}else if (this.textbox.value != this.lastCheckedValue){
this.updateClass("Empty");
// this.textbox.style.backgroundColor = "";
}
},
postMixInProperties: function(localProperties, frag) {
dojo.widget.ValidationTextbox.superclass.postMixInProperties.apply(this, arguments);
this.messages = dojo.i18n.getLocalization("dojo.widget", "validate", this.lang);
dojo.lang.forEach(["invalidMessage", "missingMessage", "rangeMessage"], function(prop) {
if(this[prop]){ this.messages[prop] = this[prop]; }
}, this);
},
fillInTemplate: function() {
dojo.widget.ValidationTextbox.superclass.fillInTemplate.apply(this, arguments);
// Attach isMissing and isValid methods to the textbox.
// We may use them later in connection with a submit button widget.
// TODO: this is unorthodox; it seems better to do it another way -- Bill
this.textbox.isValid = function() { this.isValid.call(this); };
this.textbox.isMissing = function() { this.isMissing.call(this); };
this.textbox.isInRange = function() { this.isInRange.call(this); };
dojo.html.setClass(this.invalidSpan,this.invalidClass);
this.update();
// apply any filters to initial value
this.filter();
// set table to be inlined (technique varies by browser)
// TODO: use method in dojo.html that does this
if(dojo.render.html.ie){ dojo.html.addClass(this.domNode, "ie"); }
if(dojo.render.html.moz){ dojo.html.addClass(this.domNode, "moz"); }
if(dojo.render.html.opera){ dojo.html.addClass(this.domNode, "opera"); }
if(dojo.render.html.safari){ dojo.html.addClass(this.domNode, "safari"); }
}
}
);