Created
March 11, 2011 14:30
-
-
Save makeusabrew/865948 to your computer and use it in GitHub Desktop.
i just wanted to fork this mother. and everyone loves typoeof
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
event-proxy.js | |
groupable-model.js | |
test.html |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Candidate represents candidate data for a given set of fields | |
// The candidate is only valid when all fields have been set and pass validation | |
var Candidate = function(fields) { | |
// Init fields | |
var field; | |
for(field in fields) { | |
if (typeof fields[field].defaultValue != 'undefined') { | |
fields[field].value = fields[field].defaultValue; | |
} | |
if (typeof fields[field].value == 'undefined') { | |
fields[field].value = null; | |
} | |
} | |
// Create Candidate object and return it | |
return { | |
// The field config | |
fields: fields, | |
// Gets the candidate value for the field | |
getFieldValue: function(field) { | |
return this.fields[field].value; | |
}, | |
// Gets the candiate values for all fields | |
getFieldValues: function() { | |
var values = {}; | |
var field; | |
for(field in this.fields) { | |
values[field] = this.getFieldValue(field); | |
} | |
return values; | |
}, | |
// Gets the default candidate value for a field | |
getFieldDefaultValue: function(field) { | |
return this.fields[field].defaultValue; | |
}, | |
// Sets the candidate value for the field. Value is validated and cleaned. | |
setFieldValue: function(field, value) { | |
value = this.fields[field].validator.clean(value); | |
if (value == null) { | |
value = this.getFieldDefaultValue(field); | |
} | |
return this.fields[field].value = value; | |
}, | |
// Determines if the candiate is valid or not | |
isValid: function() { | |
var field; | |
for(field in this.fields) { | |
if (!this.isFieldValid(field)) { | |
return false; | |
} | |
} | |
return true; | |
}, | |
// Determines if a specific field is valid or not | |
isFieldValid: function(field) { | |
var value = this.getFieldValue(field); | |
return value != null; | |
} | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is how you would define a specific Candidate | |
var TestFormCandiateSimple = function() { | |
// Essentially all candidates are an instance of Candidate with different field setups | |
return Candidate({ | |
// This is a specific field of the candidate | |
firstname: { | |
// This is the validator used for the field. | |
// There are MANY combinations to achieve complex validations | |
// Further examples will be given | |
validator: v.String({ min_length: 3, max_length: 20}) | |
}, | |
surname: { | |
// A default value can be set. | |
// If "required" is FALSE on the validator, the default is "" anyway | |
defaultValue: 'Smith', | |
validator: v.String({ required: false, min_length: 3, max_length: 20}) | |
} | |
// etc | |
}); | |
} | |
// The above example is not very extendable, you might do something like... | |
var TestFormCandiate = function(fields) { | |
fields = fields || {}; | |
fields.firstname = fields.firstname || { | |
validator: v.String({ min_length: 3, max_length: 20}) | |
}; | |
fields.surname = fields.firstname || { | |
defaultValue: 'Smith', | |
validator: v.String({ required: false, min_length: 3, max_length: 20}) | |
}; | |
return Candidate(fields); | |
} | |
// So, to create an instance, you would simply do | |
var myCandiate = TestFormCandiate(); | |
// To set a value, you would do the following | |
myCandiate.setFieldValue('firstname', 'value'); | |
// This will also, | |
// 1) Validate the field, firing a specific when a validation fails, | |
// which can be setup in the Candidate | |
// 2) "Clean" the field. So for example, a string is trimmed unless otherwise | |
// specified. The value saved in the Candidate is the clean one | |
// To get the candidate value, which as mentioned is the clean version, | |
myCandiate.getFieldValue('firstname'); | |
// To get all candidate values, | |
myCandiate.getFieldValues(); | |
// Which returns, | |
var exampleReturn = { | |
firstname: null, | |
lastname: 'Smith' | |
}; | |
// To check if a specific field is valid, | |
myCandiate.isFieldValid('firstname'); | |
// To check if all fields are valid, | |
myCandiate.isValid(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The core Validator namespace | |
var Validator = {}; | |
var v = Validator; | |
// =============================================================== | |
// The base Validator all other validators extend | |
Validator.Base = function(config, events) { | |
// Init config | |
config = config || {}; | |
config.required = config.required == undefined ? true : config.required; | |
config.trim = config.trim == undefined ? true : config.trim; | |
// Init events | |
events = events || {}; | |
events.success = events.success || 'validator:base.success'; | |
events.required = events.required || 'validator:base.required'; | |
return { | |
// Params | |
config: config, | |
events: events, | |
// Validates and cleans the passed value | |
clean: function(value) { | |
if (this.config.trim && typeof value === 'string') { | |
value = $.trim(value); | |
} | |
if (this.isEmpty(value)) { | |
if (this.config.required) { | |
return this.triggerEvent('required'); | |
} | |
} else { | |
value = this.doClean(value); | |
} | |
if (value != null) { | |
this.triggerEvent('success') | |
} | |
return value; | |
}, | |
// Validates and cleans the passed value (used by child validators) | |
doClean: function(value) { | |
return value; | |
}, | |
// Determines if a value is "empty" | |
isEmpty: function(value) { | |
return [null, '', []].indexOf(value) != -1; | |
}, | |
// Triggers a proxy event | |
triggerEvent: function(event) { | |
eventProxy.trigger(this.events[event]); | |
return null; | |
} | |
}; | |
} | |
// =============================================================== | |
// Validates a value is a number, meets min/max criteria, etc | |
Validator.Number = function(config, events) { | |
// Init events | |
events = events || {}; | |
events.invalid = events.invalid || 'validator:number.invalid'; | |
events.min = events.min || 'validator:number.min'; | |
events.max = events.max || 'validator:number.max'; | |
// Extend the Base validator | |
return $.extend(Validator.Base(config, events), { | |
// Validates and cleans the passed value | |
doClean: function(value) { | |
value = parseFloat(value); | |
if (isNaN(value)) { | |
return this.triggerEvent('invalid'); | |
} | |
if (this.config.min && value < this.config.min) { | |
return this.triggerEvent('min'); | |
} | |
if (this.config.max && value > this.config.max) { | |
return this.triggerEvent('max'); | |
} | |
return value; | |
} | |
}); | |
} | |
// Validates a value is a string, meets length criterias, etc | |
Validator.String = function(config, events) { | |
// Init events | |
events = events || {}; | |
events.invalid = events.invalid || 'validator:string.invalid'; | |
events.min_length = events.min_length || 'validator:string.min_length'; | |
events.max_length = events.max_length || 'validator:string.max_length'; | |
// Extend the Base validator | |
return $.extend(Validator.Base(config, events), { | |
// Validates and cleans the passed value | |
doClean: function(value) { | |
if (!(typeof value === 'string')) { | |
return this.triggerEvent('invalid'); | |
} | |
if (this.config.min_length && value.length < this.config.min_length) { | |
return this.triggerEvent('min_length'); | |
} | |
if (this.config.max_length && value.length > this.config.max_length) { | |
return this.triggerEvent('max_length'); | |
} | |
return value; | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Jamie already pulled me up on that and I've implemented a different check. Check it out!