Skip to content

Instantly share code, notes, and snippets.

@makeusabrew
Created March 11, 2011 14:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save makeusabrew/865948 to your computer and use it in GitHub Desktop.
Save makeusabrew/865948 to your computer and use it in GitHub Desktop.
i just wanted to fork this mother. and everyone loves typoeof
event-proxy.js
groupable-model.js
test.html
// 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 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();
// 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;
}
});
}
@stephenmelrose
Copy link

Jamie already pulled me up on that and I've implemented a different check. Check it out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment