mirror of
https://github.com/silverstripe/silverstripe-userforms.git
synced 2024-10-22 17:05:42 +02:00
246 lines
5.9 KiB
JavaScript
246 lines
5.9 KiB
JavaScript
/**
|
|
* @file Manages the multi-step navigation.
|
|
*/
|
|
jQuery(function ($) {
|
|
|
|
/**
|
|
* @func UserForm
|
|
* @constructor
|
|
* @param object element
|
|
* @return object - The UserForm instance.
|
|
* @desc The form
|
|
*/
|
|
function UserForm(element) {
|
|
var self = this;
|
|
|
|
this.$el = element instanceof jQuery ? element : $(element);
|
|
this.steps = [];
|
|
|
|
// Listen for events triggered my form steps.
|
|
this.$el.on('userform.step.prev', function (e) {
|
|
self.prevStep();
|
|
});
|
|
this.$el.on('userform.step.next', function (e) {
|
|
self.nextStep();
|
|
});
|
|
|
|
// Listen for events triggered by the progress bar.
|
|
$('#userform-progress').on('userform.progress.changestep', function (e, stepNumber) {
|
|
self.jumpToStep(stepNumber - 1);
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @func UserForm.addStep
|
|
* @param object step - An instance of FormStep.
|
|
* @desc Adds a step to the UserForm.
|
|
*/
|
|
UserForm.prototype.addStep = function (step) {
|
|
// Make sure we're dealing with a form step.
|
|
if (!step instanceof FormStep) {
|
|
return;
|
|
}
|
|
|
|
this.steps.push(step);
|
|
};
|
|
|
|
/**
|
|
* @func UserForm.setCurrentStep
|
|
* @param object step - An instance of FormStep.
|
|
* @desc Sets the step the user is currently on.
|
|
*/
|
|
UserForm.prototype.setCurrentStep = function (step) {
|
|
// Make sure we're dealing with a form step.
|
|
if (!step instanceof FormStep) {
|
|
return;
|
|
}
|
|
|
|
this.currentStep = step;
|
|
this.currentStep.show();
|
|
};
|
|
|
|
/**
|
|
* @func UserForm.jumpToStep
|
|
* @param number stepNumber
|
|
* @desc Jumps to a specific form step.
|
|
*/
|
|
UserForm.prototype.jumpToStep = function (stepNumber) {
|
|
var targetStep = this.steps[stepNumber];
|
|
|
|
// Make sure the target step exists.
|
|
if (targetStep === void 0) {
|
|
return;
|
|
}
|
|
|
|
this.currentStep.hide();
|
|
this.setCurrentStep(targetStep);
|
|
|
|
this.$el.trigger('userform.form.changestep', [stepNumber]);
|
|
};
|
|
|
|
/**
|
|
* @func UserForm.nextStep
|
|
* @desc Advances the form to the next step.
|
|
*/
|
|
UserForm.prototype.nextStep = function () {
|
|
this.jumpToStep(this.steps.indexOf(this.currentStep) + 1);
|
|
};
|
|
|
|
/**
|
|
* @func UserForm.prevStep
|
|
* @desc Goes back one step (not bound to browser history).
|
|
*/
|
|
UserForm.prototype.prevStep = function () {
|
|
this.jumpToStep(this.steps.indexOf(this.currentStep) - 1);
|
|
};
|
|
|
|
/**
|
|
* @func FormStep
|
|
* @constructor
|
|
* @param object element
|
|
* @return object - The FormStep instance.
|
|
* @desc Creates a form step.
|
|
*/
|
|
function FormStep(element) {
|
|
var self = this;
|
|
|
|
this.$el = element instanceof jQuery ? element : $(element);
|
|
|
|
// Bind the step navigation event listeners.
|
|
this.$el.find('.step-button-prev').on('click', function (e) {
|
|
e.preventDefault();
|
|
self.$el.trigger('userform.step.prev');
|
|
});
|
|
this.$el.find('.step-button-next').on('click', function (e) {
|
|
e.preventDefault();
|
|
self.$el.trigger('userform.step.next');
|
|
});
|
|
|
|
this.hide();
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @func FormStep.show
|
|
* @desc Show the form step. Looks after aria attributes too.
|
|
*/
|
|
FormStep.prototype.show = function () {
|
|
this.$el.attr('aria-hidden', false).show();
|
|
};
|
|
|
|
/**
|
|
* @func FormStep.hide
|
|
* @desc Hide the form step. Looks after aria attributes too.
|
|
*/
|
|
FormStep.prototype.hide = function () {
|
|
this.$el.attr('aria-hidden', true).hide();
|
|
};
|
|
|
|
/**
|
|
* @func ProgressBar
|
|
* @constructor
|
|
* @param object element
|
|
* @return object - The Progress bar instance.
|
|
* @desc Creates a progress bar.
|
|
*/
|
|
function ProgressBar(element) {
|
|
var self = this;
|
|
|
|
this.$el = element instanceof jQuery ? element : $(element);
|
|
this.$buttons = this.$el.find('.step-button-jump');
|
|
|
|
// 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]);
|
|
});
|
|
});
|
|
|
|
// Update the progress bar when 'prev' and 'next' buttons are clicked.
|
|
$('.userform').on('userform.form.changestep', function (e, newStep) {
|
|
self.update(newStep + 1);
|
|
});
|
|
|
|
this.update(1);
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @func ProgressBar.update
|
|
* @param number newStep
|
|
* @desc Update the progress element to show a new step.
|
|
*/
|
|
ProgressBar.prototype.update = function (newStep) {
|
|
// Update elements that contain the current step number.
|
|
this.$el.find('.current-step-number').each(function (i, element) {
|
|
$(element).text(newStep);
|
|
});
|
|
|
|
// Update aria attributes.
|
|
this.$el.find('[aria-valuenow]').each(function (i, element) {
|
|
$(element).attr('aria-valuenow', newStep);
|
|
});
|
|
|
|
// Update the CSS classes on step buttons.
|
|
this.$buttons.each(function (i, element) {
|
|
var $item = $(element).parent();
|
|
|
|
if (parseInt($(element).text(), 10) === newStep) {
|
|
$item.addClass('current');
|
|
return;
|
|
}
|
|
|
|
$item.removeClass('current');
|
|
});
|
|
|
|
// Update the width of the progress bar.
|
|
this.$el.find('.progress-bar').width(newStep / this.$buttons.length * 100 + '%');
|
|
};
|
|
|
|
/**
|
|
* @func main
|
|
* @desc Bootstraps the front-end.
|
|
*/
|
|
function main() {
|
|
var userform = new UserForm($('.userform')),
|
|
progressBar = new ProgressBar($('#userform-progress'));
|
|
|
|
// 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();
|
|
});
|
|
|
|
// Initialise the form steps.
|
|
userform.$el.find('.form-step').each(function (i, element) {
|
|
var step = new FormStep(element);
|
|
|
|
userform.addStep(step);
|
|
});
|
|
|
|
userform.setCurrentStep(userform.steps[0]);
|
|
|
|
// Hide the form-wide actions on multi-step forms.
|
|
// Because JavaScript is enabled we'll use the actions contained
|
|
// in the final step's navigation.
|
|
if (userform.steps.length > 1) {
|
|
userform.$el.children('.Actions').attr('aria-hidden', true).hide();
|
|
}
|
|
|
|
// Make sure the form doesn't expire on the user. Pings every 3 mins.
|
|
setInterval(function () {
|
|
$.ajax({ url: 'UserDefinedForm_Controller/ping' });
|
|
}, 180 * 1000);
|
|
}
|
|
|
|
main();
|
|
});
|