SMPF - Simple Multi Page Forms Logo

Description

SMPF is a small Javascript library that makes adding multi page forms to your webpages easy. Very little Javascript experience is required to use this library.

The sight of a long form with lots of questions can look intimidating, quickly become boring and cause you to lose users.

SMPF can easily be used to break up existing forms into individual pages or create new forms from scratch. It is compatible with front-end frameworks such as Bootstrap.

Some simple features that out of the box:

SMPF works with all standard HTML form elements and can look in keeping with any themes or styles your website uses.

Don't hesitate to drop me a message with any feedback, ideas or if I can answer any questions info@smpf.online

Examples

The following example is a simple mock user signup form that also utilises the Bootstrap framework.

Try filling out the form with required bits missing or entered incorrectly:

Please Note: Your username can only contain numbers and letters

The following example includes a navigation section that can be used instead of (or alongside) navigation buttons:

Favourite Sci-Fi

Please select 1 - the images are also clickable







The navigation section on the left won't let you skip over any pages that have inputs requiring a value.

Try going back to page 2, unticking the required tick and then see if you can jump from page 1 to page 3.

This page is missing a submit button.

You would add your own submit button and trigger the submission action for your form.

Setup

Add the following code into the head section of your webpage:

<script src="https://cdn.jsdelivr.net/gh/hairlesscoder/smpf@1.1/smpf.min.js"></script>

All versions of SMPF can be found on GitHub: https://github.com/HairlessCoder/smpf.

An optional smpf.css file is available but you're strongly advised to either modify this or create a new one to better fit your current theme or style (see CSS Class Reference for more details):

<link href="https://cdn.jsdelivr.net/gh/hairlesscoder/smpf@1.1/smpf.css" rel="stylesheet">

Add the following right before your close the body section of your page, the parameter 'exampleForm' used below should match your html form element ID:

<script type="text/javascript">
 const formExample=new SMPF(exampleForm);
</script>

Your HTML form element section that should exist somewhere in your webpage before running the above code:

<form id="exampleForm">
</form>

Starting Out

All of your form elements (between <form> and </form>) need to be wrapped up in a container element that has the CSS class 'formPages' added.

<form id="exampleForm">
<div class="formPages">
</div>
</form>

However you decide to divide up your form sections, the elements will need to be inside a container that has the CSS class 'formPage' added.

<form id="exampleForm">
<div class="formPages">
  <div class="formPage">
   <p>First page/step</p>
  </div>
  <div class="formPage">
   <p>Second page/step</p>
  </div>
  <div class="formPage">
   <p>Third page/step</p>
  </div>
</div>
</form>

If you only did these steps and reloaded your page, you'll notice that only the first step/page of your form is shown.

The easiest way to add the ability to proceed through the form is to add a button element within the form page element with the attribute data-nav="next".

You can add a button that allows the user to go to the previous page by adding a button element within the form page element with the attribute data-nav="prev".

<form id="exampleForm">
<div class="formPages">
  <div class="formPage">
   <p>First page/step</p>
   <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Second page/step</p>
   <button data-nav="prev">Previous</button> <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Third page/step</p>
   <button data-nav="prev">Previous</button>
  </div>
</div>
</form>

Any unpopulated input elements you have with the attribute 'required' prevents the user from navigating forward (they can go to previous steps/pages).

<form id="exampleForm">
<div class="formPages">
  <div class="formPage">
   <p>First page/step</p>
   <input type="text" required>
   <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Second page/step</p>
   <button data-nav="prev">Previous</button> <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Third page/step</p>
   <button data-nav="prev">Previous</button>
  </div>
</div>
</form>

Any input elements with the attribute 'disabled' are ignored from any kind of validation.

<form id="exampleForm">
<div class="formPages">
  <div class="formPage">
   <p>First page/step</p>
   <input type="text" required disabled>
   <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Second page/step</p>
   <button data-nav="prev">Previous</button> <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Third page/step</p>
   <button data-nav="prev">Previous</button>
  </div>
</div>
</form>

Inputs that can have the attribute 'pattern' can also be used to control a users progress through the form pages. The attribute 'pattern' can be mixed/matched with the attribute 'required'.

<form id="exampleForm">
<div class="formPages">
  <div class="formPage">
   <p>First page/step</p>
   <input type="text" pattern="[A-Za-z]{3}" >
   <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Second page/step</p>
   <button data-nav="prev">Previous</button> <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Third page/step</p>
   <button data-nav="prev">Previous</button>
  </div>
</div>
</form>

The same goes for input elements that request a specific piece of information like email address.

<form id="exampleForm">
<div class="formPages">
  <div class="formPage">
   <p>First page/step</p>
   <input type="email">
   <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Second page/step</p>
   <button data-nav="prev">Previous</button> <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Third page/step</p>
   <button data-nav="prev">Previous</button>
  </div>
</div>
</form>

If the last page of your form contains required inputs you'll need to use some Javascript and the 'checkPage' function (see Functions & Callbacks Reference) to validate it before triggering the submission process.

One way of doing this is to add an event listener that triggers on the forms submission (we've added a new button on the last page that natively will submit the form):

<form id="exampleForm">
<div class="formPages">
  <div class="formPage">
   <p>First page/step</p>
   <input type="email">
   <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Second page/step</p>
   <button data-nav="prev">Previous</button> <button data-nav="next">Next</button>
  </div>
  <div class="formPage">
   <p>Third page/step</p>
   <button data-nav="prev">Previous</button> <button>Submit</button>
  </div>
</div>
</form>

//Add the following to your Javascript section -
//Where 'exampleForm' is the value of the attribute 'id' on your form
exampleForm.addEventListener("submit",function(event){
 event.preventDefault(); //This stops the page from submitting
 if(formExample.checkPage()==true){ //This is checking if the current page has been filled in correctly
  event.target.submit(); //If the page is OK, this continues with submitting the form
 }
});

Navigation/Progress

As well as using the navigation buttons within the form pages, users can be given links to every page of the form.

Within the form element but outside of the container with the class 'formPages', add a nav element. Within this nav element, create anchor (a) elements with the attribute href=# - one anchor element for each form page. The order of these tags need to be in the same order as your form steps - as they link sequentially, the 1st takes users to the 1st form page, the 2nd link takes users to the 2nd form page etc...

<nav>
<a href=#>1st page link</a>
<a href=#>2nd page link</a>
<a href=#>3rd page link</a>
</nav>

Whichever step is currently shown, the corresponding navigation link gains the CSS class 'navActive'.

For the steps that have been completed, the corresponding navigation links gain the CSS class 'navCompleted'.

To prevent users from being able to use the naviation links and have them act more like a progress indicator, remove the attribute 'href' from each link.

<nav>
<a>1st page link</a>
<a>2nd page link</a>
<a>3rd page link</a>
</nav>

CSS Class Reference

Some of the elements within your form will gain or lose CSS classes as it is being used. This allows you to highlight important bits of information to your users.

requiredMissing

Form elements that have the attribute 'required' but are left empty gain this CSS class.

Associated labels (where the attribute 'for' matches the form element ID) also gain this CSS class.

patternInvalid

Form elements that have the attribute 'pattern' or request a special input format (date, email, telephone number etc) but are filled incorrectly gain this CSS class.

Associated labels (where the attribute 'for' matches the form element ID) also gain this CSS class.

navActive

If you're using the HTML element 'nav' within your form - the current pages corresponding 'a' (anchor) element will gain this CSS class.

navCompleted

If you're using the HTML element 'nav' within your form - completed pages corresponding 'a' (anchor) element will gain this CSS class.

Functions & Callbacks

The following functions & callbacks are available for those that want to develop advanced checks or behaviours with their forms.

Function: reset

SMPF.reset(page_number): void

Resets all form elements on page_number to empty, eg: exampleForm.reset(0) resets all inputs on the first step of the form. If the parameter page_number is omitted then the current page is reset.

There are 2 important things to keep in mind, first: form steps are counted from 0, second: to act in keeping with how the vanilla form method reset works, the method reset() doesn't reset hidden input items.

Function: checkPage

SMPF.checkPage(page_number): boolean

Checks if all form elements on page_number have been filled in as expected and are valid. If the parameter page_number is omitted then the current page is validated.

This function returns true or false on wether the page has been filled is valid. The function applies/removes all relevant CSS classes to the form elements.

Function: navigate

SMPF.navigate(page_number): void

This function takes the user to a specific page (remember, pages start at 0).

No validation checks are performed.

Callback: postCheck

SMPF.postCheck=function(page_number,current_check_status): boolean

This function is run after checkPage has finished its validation routine.

The page_number parameter tells you which page has been checked. The parameter current_check_status tells you the validation status of the checked page.

Your function needs to return a boolean value. This function gives you a chance to come up with more advanced checks - like comparing if the values of a password input element and a confirmation input element match.