180 lines
4.7 KiB
JavaScript
180 lines
4.7 KiB
JavaScript
/**
|
|
* Private methods
|
|
*/
|
|
module.exports = {
|
|
|
|
_init: function() {
|
|
|
|
var self = this;
|
|
|
|
this._extend($.idealforms.extensions);
|
|
|
|
this.$form = $(this.el);
|
|
this.$fields = $();
|
|
this.$inputs = $();
|
|
|
|
this._inject('_init');
|
|
|
|
this.addRules(this.opts.rules || {});
|
|
|
|
this.$form.submit(function(e) {
|
|
e.preventDefault();
|
|
self._validateAll();
|
|
self.focusFirstInvalid();
|
|
self.opts.onSubmit.call(self, self.getInvalid().length, e);
|
|
});
|
|
|
|
if (! this.opts.silentLoad) this.focusFirstInvalid();
|
|
},
|
|
|
|
_buildField: function(input) {
|
|
|
|
var self = this
|
|
, $field = this._getField(input)
|
|
, $icon;
|
|
|
|
$icon = $(this.opts.iconHtml, {
|
|
class: this.opts.iconClass,
|
|
click: function(){ $(input).focus() }
|
|
});
|
|
|
|
if (! this.$fields.filter($field).length) {
|
|
this.$fields = this.$fields.add($field);
|
|
if (this.opts.iconHtml) $field.append($icon);
|
|
$field.addClass('idealforms-field idealforms-field-'+ input.type);
|
|
}
|
|
|
|
this._addEvents(input);
|
|
|
|
this._inject('_buildField', input);
|
|
},
|
|
|
|
_addEvents: function(input) {
|
|
|
|
var self = this
|
|
, $field = this._getField(input);
|
|
|
|
$(input)
|
|
.on('change keyup', function(e) {
|
|
if (e.which == 9 || e.which == 16) return;
|
|
self._validate(this, true, true);
|
|
})
|
|
.focus(function() {
|
|
|
|
if (self.isValid(this.name)) return false;
|
|
|
|
if (self._isRequired(this) || this.value) {
|
|
$field.find(self.opts.error).show();
|
|
}
|
|
})
|
|
.blur(function() {
|
|
$field.find(self.opts.error).hide();
|
|
});
|
|
},
|
|
|
|
_isRequired: function(input) {
|
|
// We assume non-text inputs with rules are required
|
|
if ($(input).is(':checkbox, :radio, select')) return true;
|
|
return this.opts.rules[input.name].indexOf('required') > -1;
|
|
},
|
|
|
|
_getRelated: function(input) {
|
|
return this._getField(input).find('[name="'+ input.name +'"]');
|
|
},
|
|
|
|
_getField: function(input) {
|
|
return $(input).closest(this.opts.field);
|
|
},
|
|
|
|
_getFirstInvalid: function() {
|
|
return this.getInvalid().first().find('input:first, textarea, select');
|
|
},
|
|
|
|
_handleError: function(input, error, valid) {
|
|
valid = valid || this.isValid(input.name);
|
|
var $error = this._getField(input).find(this.opts.error);
|
|
this.$form.find(this.opts.error).hide();
|
|
if (error) $error.text(error);
|
|
$error.toggle(!valid);
|
|
},
|
|
|
|
_handleStyle: function(input, valid) {
|
|
valid = valid || this.isValid(input.name);
|
|
this._getField(input)
|
|
.removeClass(this.opts.validClass +' '+ this.opts.invalidClass)
|
|
.addClass(valid ? this.opts.validClass : this.opts.invalidClass)
|
|
.find('.'+ this.opts.iconClass).show();
|
|
},
|
|
|
|
_fresh: function(input) {
|
|
this._getField(input)
|
|
.removeClass(this.opts.validClass +' '+ this.opts.invalidClass)
|
|
.find(this.opts.error).hide()
|
|
.end()
|
|
.find('.'+ this.opts.iconClass).toggle(this._isRequired(input));
|
|
},
|
|
|
|
_validate: function(input, handleError, handleStyle) {
|
|
|
|
var self = this
|
|
, $field = this._getField(input)
|
|
, userRules = this.opts.rules[input.name].split($.idealforms.ruleSeparator)
|
|
, oldValue = $field.data('idealforms-value')
|
|
, valid = true
|
|
, rule;
|
|
|
|
// Don't validate input if value hasn't changed
|
|
if (! $(input).is(':checkbox, :radio') && oldValue == input.value) {
|
|
return $field.data('idealforms-valid');
|
|
}
|
|
|
|
$field.data('idealforms-value', input.value);
|
|
|
|
// Non-required input with empty value must pass validation
|
|
if (! input.value && ! this._isRequired(input)) {
|
|
$field.removeData('idealforms-valid');
|
|
this._fresh(input);
|
|
|
|
// Required inputs
|
|
} else {
|
|
|
|
$.each(userRules, function(i, userRule) {
|
|
|
|
userRule = userRule.split($.idealforms.argSeparator);
|
|
|
|
rule = userRule[0];
|
|
|
|
var theRule = $.idealforms.rules[rule]
|
|
, args = userRule.slice(1)
|
|
, error;
|
|
|
|
error = $.idealforms._format.apply(null, [
|
|
$.idealforms._getKey('errors.'+ input.name +'.'+ rule, self.opts) ||
|
|
$.idealforms.errors[rule]
|
|
].concat(args));
|
|
|
|
valid = typeof theRule == 'function'
|
|
? theRule.apply(self, [input, input.value].concat(args))
|
|
: theRule.test(input.value);
|
|
|
|
$field.data('idealforms-valid', valid);
|
|
|
|
if (handleError) self._handleError(input, error, valid);
|
|
if (handleStyle) self._handleStyle(input, valid);
|
|
|
|
self.opts.onValidate.call(self, input, rule, valid);
|
|
|
|
return valid;
|
|
});
|
|
}
|
|
|
|
this._inject('_validate', input, rule, valid);
|
|
|
|
return valid;
|
|
},
|
|
|
|
_validateAll: function() {
|
|
var self = this;
|
|
this.$inputs.each(function(){ self._validate(this, true); });
|
|
}
|
|
};
|