mirror of
https://github.com/silverstripe/silverstripe-userforms.git
synced 2024-10-22 17:05:42 +02:00
Initial validation
This commit is contained in:
parent
10c86bcbc1
commit
97eb8b0255
@ -3,6 +3,15 @@
|
||||
*/
|
||||
jQuery(function ($) {
|
||||
|
||||
// Settings that come from the CMS.
|
||||
var CONSTANTS = {
|
||||
ERROR_CONTAINER_ID: '',
|
||||
ENABLE_LIVE_VALIDATION: false,
|
||||
DISPLAY_ERROR_MESSAGES_AT_TOP: false,
|
||||
HIDE_FIELD_LABELS: false,
|
||||
MESSAGES: {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @func UserForm
|
||||
* @constructor
|
||||
@ -59,6 +68,10 @@ jQuery(function ($) {
|
||||
|
||||
this.currentStep = step;
|
||||
this.currentStep.show();
|
||||
|
||||
// Record the user has viewed the step.
|
||||
step.viewed = true;
|
||||
step.$el.addClass('viewed');
|
||||
};
|
||||
|
||||
/**
|
||||
@ -74,6 +87,13 @@ jQuery(function ($) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the current section.
|
||||
// Users can navigate to step's they've already viewed
|
||||
// even if the current step is invalid.
|
||||
if (!this.$el.valid() && targetStep.viewed === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentStep.hide();
|
||||
this.setCurrentStep(targetStep);
|
||||
|
||||
@ -108,6 +128,11 @@ jQuery(function ($) {
|
||||
|
||||
this.$el = element instanceof jQuery ? element : $(element);
|
||||
|
||||
// Has the step been viewed by the user?
|
||||
this.viewed = false;
|
||||
|
||||
this.hide();
|
||||
|
||||
// Bind the step navigation event listeners.
|
||||
this.$el.find('.step-button-prev').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
@ -118,11 +143,50 @@ jQuery(function ($) {
|
||||
self.$el.trigger('userform.step.next');
|
||||
});
|
||||
|
||||
this.hide();
|
||||
// Set up validation for the step.
|
||||
this.$el.validate(this.validationOptions);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default options for step validation. These get extended in main().
|
||||
*/
|
||||
FormStep.prototype.validationOptions = {
|
||||
ignore: ':hidden',
|
||||
errorClass: 'required',
|
||||
errorElement: 'span',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('message');
|
||||
|
||||
if(element.is(':radio') || element.parents('.checkboxset').length > 0) {
|
||||
error.insertAfter(element.closest('ul'));
|
||||
} else {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
|
||||
if (CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP) {
|
||||
// TODO
|
||||
//applyTopErrorMessage(element, error.html());
|
||||
}
|
||||
|
||||
},
|
||||
success: function (error) {
|
||||
error.remove();
|
||||
},
|
||||
messages: CONSTANTS.MESSAGES,
|
||||
rules: {
|
||||
// TODO
|
||||
// <% loop $Fields %>
|
||||
// <% if $Validation %><% if ClassName == EditableCheckboxGroupField %>
|
||||
// '{$Name.JS}[]': {$ValidationJSON.RAW},
|
||||
// <% else %>
|
||||
// '{$Name.JS}': {$ValidationJSON.RAW},
|
||||
// <% end_if %><% end_if %>
|
||||
// <% end_loop %>
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @func FormStep.show
|
||||
* @desc Show the form step. Looks after aria attributes too.
|
||||
@ -155,12 +219,8 @@ jQuery(function ($) {
|
||||
// Update the progress bar when 'step' buttons are clicked.
|
||||
this.$buttons.each(function (i, stepButton) {
|
||||
$(stepButton).on('click', function (e) {
|
||||
var newStepNumber = parseInt($(this).text(), 10);
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
self.update(newStepNumber);
|
||||
self.$el.trigger('userform.progress.changestep', [newStepNumber]);
|
||||
self.$el.trigger('userform.progress.changestep', [parseInt($(this).text(), 10)]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -192,10 +252,13 @@ jQuery(function ($) {
|
||||
|
||||
// Update the CSS classes on step buttons.
|
||||
this.$buttons.each(function (i, element) {
|
||||
var $item = $(element).parent();
|
||||
var $element = $(element),
|
||||
$item = $element.parent();
|
||||
|
||||
if (parseInt($element.text(), 10) === newStep) {
|
||||
$item.addClass('current viewed');
|
||||
$element.removeAttr('disabled');
|
||||
|
||||
if (parseInt($(element).text(), 10) === newStep) {
|
||||
$item.addClass('current');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -214,6 +277,35 @@ jQuery(function ($) {
|
||||
var userform = new UserForm($('.userform')),
|
||||
progressBar = new ProgressBar($('#userform-progress'));
|
||||
|
||||
// Extend the default validation options with conditional options
|
||||
// that are set by the user in the CMS.
|
||||
if (CONSTANTS.ENABLE_LIVE_VALIDATION) {
|
||||
$.extend(FormStep.prototype.validationOptions, {
|
||||
onfocusout: function (element) {
|
||||
this.element(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP) {
|
||||
$.extend(FormStep.prototype.validationOptions, {
|
||||
invalidHandler: function (event, validator) {
|
||||
var errorList = $('#' + CONSTANTS.ERROR_CONTAINER_ID + ' ul');
|
||||
|
||||
// Update the error list with errors from the validator.
|
||||
// We do this because top messages are not part of the regular
|
||||
// error message life cycle, which jquery.validate handles for us.
|
||||
errorList.empty();
|
||||
|
||||
$.each(validator.errorList, function () {
|
||||
// TODO
|
||||
//applyTopErrorMessage($(this.element), this.message);
|
||||
});
|
||||
},
|
||||
onfocusout: false
|
||||
});
|
||||
}
|
||||
|
||||
// Display all the things that are hidden when JavaScript is disabled.
|
||||
$.each(['#userform-progress', '.step-navigation'], function (i, selector) {
|
||||
$(selector).attr('aria-hidden', false).show();
|
||||
|
@ -9,7 +9,7 @@
|
||||
<ul class="step-buttons">
|
||||
<% loop $NumberOfSteps %>
|
||||
<li class="step-button-wrapper<% if $Pos == '1' %> current<% end_if %>">
|
||||
<button class="step-button-jump">$Pos</button>
|
||||
<button class="step-button-jump" disabled="disabled">$Pos</button>
|
||||
</li>
|
||||
<% end_loop %>
|
||||
<ul>
|
||||
|
Loading…
Reference in New Issue
Block a user