/** * Private methods */ module.exports = { _init: function() { var self = this; this._extend($.idealforms.extensions); this.$form = $(this.el); this.$fields = $(); this.$inputs = $(); this.$form.submit(function(e) { e.preventDefault(); self.focusFirstInvalid(); self.opts.onSubmit.call(self, self.getInvalid().length, e); }); this._inject('_init'); this.addRules(this.opts.rules || {}); 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) { var oldValue = $field.data('idealforms-value'); if (e.which == 9 || e.which == 16) return; if (! $(this).is(':checkbox, :radio') && oldValue == this.value) return; $field.data('idealforms-value', this.value); 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) , valid = true , rule; // 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; } };