|
|
@@ -33,6 +33,8 @@
|
|
|
// The flag to indicate that the form is ready to submit when a remote/callback validator returns
|
|
|
this._submitIfValid = null;
|
|
|
|
|
|
+ this._cacheFields = {};
|
|
|
+
|
|
|
this._init();
|
|
|
};
|
|
|
|
|
|
@@ -218,8 +220,6 @@
|
|
|
for (var field in this.options.fields) {
|
|
|
this._initField(field);
|
|
|
}
|
|
|
-
|
|
|
- this.setLiveMode(this.options.live);
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
@@ -235,7 +235,7 @@
|
|
|
var fields = this.getFieldElements(field);
|
|
|
|
|
|
// We don't need to validate non-existing fields
|
|
|
- if (fields == null) {
|
|
|
+ if (fields == []) {
|
|
|
delete this.options.fields[field];
|
|
|
return;
|
|
|
}
|
|
|
@@ -244,65 +244,91 @@
|
|
|
delete this.options.fields[field].validators[validatorName];
|
|
|
}
|
|
|
}
|
|
|
+ if (this.options.fields[field]['enabled'] == null) {
|
|
|
+ this.options.fields[field]['enabled'] = true;
|
|
|
+ }
|
|
|
|
|
|
- var that = this,
|
|
|
- type = fields.attr('type'),
|
|
|
- event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent,
|
|
|
- total = fields.length,
|
|
|
- updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type);
|
|
|
-
|
|
|
- for (var i = 0; i < total; i++) {
|
|
|
- var $field = $(fields[i]),
|
|
|
- $parent = $field.parents('.form-group'),
|
|
|
- // Allow user to indicate where the error messages are shown
|
|
|
- $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field);
|
|
|
-
|
|
|
- // Set the attribute to indicate the fields which are defined by selector
|
|
|
- if (!$field.attr('data-bv-field')) {
|
|
|
- $field.attr('data-bv-field', field);
|
|
|
- }
|
|
|
+ for (var i = 0; i < fields.length; i++) {
|
|
|
+ this._initFieldElement($(fields[i]));
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- // Whenever the user change the field value, mark it as not validated yet
|
|
|
- $field.on(event + '.update.bv', function() {
|
|
|
- // Reset the flag
|
|
|
- that._submitIfValid = false;
|
|
|
- updateAll ? that.updateStatus(field, that.STATUS_NOT_VALIDATED)
|
|
|
- : that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED);
|
|
|
- });
|
|
|
+ _initFieldElement: function($field) {
|
|
|
+ var that = this,
|
|
|
+ field = $field.attr('name') || $field.attr('data-bv-field'),
|
|
|
+ fields = this.getFieldElements(field),
|
|
|
+ index = fields.index($field),
|
|
|
+ type = $field.attr('type'),
|
|
|
+ total = fields.length,
|
|
|
+ updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type),
|
|
|
+ $parent = $field.parents('.form-group'),
|
|
|
+ // Allow user to indicate where the error messages are shown
|
|
|
+ $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field);
|
|
|
+
|
|
|
+ // Remove all error messages and feedback icons
|
|
|
+ //$message.find('.help-block[data-bv-validator]').remove();
|
|
|
+ //$parent.find('i[data-bv-field]').remove();
|
|
|
+
|
|
|
+ // Set the attribute to indicate the fields which are defined by selector
|
|
|
+ if (!$field.attr('data-bv-field')) {
|
|
|
+ $field.attr('data-bv-field', field);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Whenever the user change the field value, mark it as not validated yet
|
|
|
+ var event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == $field.get(0).tagName) ? 'change' : this._changeEvent;
|
|
|
+ $field.on(event + '.update.bv', function() {
|
|
|
+ // Reset the flag
|
|
|
+ that._submitIfValid = false;
|
|
|
+ that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED);
|
|
|
+ });
|
|
|
|
|
|
- // Create help block elements for showing the error messages
|
|
|
- $field.data('bv.messages', $message);
|
|
|
- for (validatorName in this.options.fields[field].validators) {
|
|
|
- $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED);
|
|
|
-
|
|
|
- if (!updateAll || i == total - 1) {
|
|
|
- $('<small/>')
|
|
|
- .css('display', 'none')
|
|
|
- .attr('data-bv-validator', validatorName)
|
|
|
- .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message)
|
|
|
- .addClass('help-block')
|
|
|
- .appendTo($message);
|
|
|
- }
|
|
|
+ // Create help block elements for showing the error messages
|
|
|
+ $field.data('bv.messages', $message);
|
|
|
+ for (var validatorName in this.options.fields[field].validators) {
|
|
|
+ $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED);
|
|
|
+
|
|
|
+ if (!updateAll || index == total - 1) {
|
|
|
+ $('<small/>')
|
|
|
+ .css('display', 'none')
|
|
|
+ .attr('data-bv-validator', validatorName)
|
|
|
+ .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message)
|
|
|
+ .addClass('help-block')
|
|
|
+ .appendTo($message);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- // Prepare the feedback icons
|
|
|
- // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation)
|
|
|
- if (this.options.feedbackIcons
|
|
|
- && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid
|
|
|
- && (!updateAll || i == total - 1))
|
|
|
- {
|
|
|
- $parent.addClass('has-feedback');
|
|
|
- var $icon = $('<i/>').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field);
|
|
|
- // The feedback icon does not render correctly if there is no label
|
|
|
- // https://github.com/twbs/bootstrap/issues/12873
|
|
|
- if ($parent.find('label').length == 0) {
|
|
|
- $icon.css('top', 0);
|
|
|
- }
|
|
|
+ // Prepare the feedback icons
|
|
|
+ // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation)
|
|
|
+ if (this.options.feedbackIcons
|
|
|
+ && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid
|
|
|
+ && (!updateAll || index == total - 1))
|
|
|
+ {
|
|
|
+ $parent.addClass('has-feedback');
|
|
|
+ var $icon = $('<i/>').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field);
|
|
|
+ // The feedback icon does not render correctly if there is no label
|
|
|
+ // https://github.com/twbs/bootstrap/issues/12873
|
|
|
+ if ($parent.find('label').length == 0) {
|
|
|
+ $icon.css('top', 0);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (this.options.fields[field]['enabled'] == null) {
|
|
|
- this.options.fields[field]['enabled'] = true;
|
|
|
+ // Set live mode
|
|
|
+ var trigger = this.options.fields[field].trigger || this.options.trigger || event,
|
|
|
+ events = $.map(trigger.split(' '), function(item) {
|
|
|
+ return item + '.live.bv';
|
|
|
+ }).join(' ');
|
|
|
+ switch (this.options.live) {
|
|
|
+ case 'submitted':
|
|
|
+ break;
|
|
|
+ case 'disabled':
|
|
|
+ $field.off(events);
|
|
|
+ break;
|
|
|
+ case 'enabled':
|
|
|
+ default:
|
|
|
+ $field.off(events).on(events, function() {
|
|
|
+ that.validateFieldElement($(this));
|
|
|
+ });
|
|
|
+ break;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
@@ -340,7 +366,28 @@
|
|
|
_submit: function() {
|
|
|
if (!this.isValid()) {
|
|
|
if ('submitted' == this.options.live) {
|
|
|
- this.setLiveMode('enabled');
|
|
|
+ // Enable live mode
|
|
|
+ this.options.live = 'enabled';
|
|
|
+ var that = this;
|
|
|
+ for (var field in this.options.fields) {
|
|
|
+ (function(f) {
|
|
|
+ var fields = that.getFieldElements(f);
|
|
|
+ if (fields.length) {
|
|
|
+ var type = $(fields[0]).attr('type'),
|
|
|
+ event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == $(fields[0]).get(0).tagName) ? 'change' : that._changeEvent,
|
|
|
+ trigger = that.options.fields[field].trigger || that.options.trigger || event,
|
|
|
+ events = $.map(trigger.split(' '), function(item) {
|
|
|
+ return item + '.live.bv';
|
|
|
+ }).join(' ');
|
|
|
+
|
|
|
+ for (var i = 0; i < fields.length; i++) {
|
|
|
+ $(fields[i]).off(events).on(events, function() {
|
|
|
+ that.validateFieldElement($(this));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })(field);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Focus to the first invalid field
|
|
|
@@ -397,48 +444,13 @@
|
|
|
* @returns {null|jQuery[]}
|
|
|
*/
|
|
|
getFieldElements: function(field) {
|
|
|
- var fields = this.options.fields[field].selector ? $(this.options.fields[field].selector) : this.$form.find('[name="' + field + '"]');
|
|
|
- return (fields.length == 0) ? null : fields;
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * Set live validating mode
|
|
|
- *
|
|
|
- * @param {String} mode Live validating mode. Can be 'enabled', 'disabled', 'submitted'
|
|
|
- * @returns {BootstrapValidator}
|
|
|
- */
|
|
|
- setLiveMode: function(mode) {
|
|
|
- this.options.live = mode;
|
|
|
- if ('submitted' == mode) {
|
|
|
- return this;
|
|
|
+ if (!this._cacheFields[field]) {
|
|
|
+ this._cacheFields[field] = this.options.fields[field].selector
|
|
|
+ ? $(this.options.fields[field].selector)
|
|
|
+ : this.$form.find('[name="' + field + '"]');
|
|
|
}
|
|
|
|
|
|
- var that = this;
|
|
|
- for (var field in this.options.fields) {
|
|
|
- (function(f) {
|
|
|
- var fields = that.getFieldElements(f);
|
|
|
- if (fields) {
|
|
|
- var type = fields.attr('type'),
|
|
|
- total = fields.length,
|
|
|
- trigger = that.options.fields[field].trigger
|
|
|
- || that.options.trigger
|
|
|
- || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent),
|
|
|
- events = $.map(trigger.split(' '), function(item) {
|
|
|
- return item + '.live.bv';
|
|
|
- }).join(' ');
|
|
|
-
|
|
|
- for (var i = 0; i < total; i++) {
|
|
|
- ('enabled' == mode)
|
|
|
- ? $(fields[i]).on(events, function() {
|
|
|
- that.validateFieldElement($(this));
|
|
|
- })
|
|
|
- : $(fields[i]).off(events);
|
|
|
- }
|
|
|
- }
|
|
|
- })(field);
|
|
|
- }
|
|
|
-
|
|
|
- return this;
|
|
|
+ return this._cacheFields[field];
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
@@ -717,10 +729,15 @@
|
|
|
// Useful APIs which aren't used internally
|
|
|
|
|
|
addFieldElement: function($field, options) {
|
|
|
+ var field = $field.attr('name') || $field.attr('data-bv-field');
|
|
|
+ this._cacheFields[field].push($field);
|
|
|
+ this._initFieldElement($field);
|
|
|
return this;
|
|
|
},
|
|
|
|
|
|
removeFieldElement: function($field) {
|
|
|
+ var field = $field.attr('name') || $field.attr('data-bv-field');
|
|
|
+ delete this._cacheFields[field];
|
|
|
return this;
|
|
|
},
|
|
|
|