# Zangdar Wizard
A JavaScript class to simply generate and handle HTML form wizards.
You can find a very simple [demo](https://codepen.io/betaweb/pen/dLBbbq) at this link, and the [API documentation here](https://betaweb.github.io/zangdar/).
## Getting started
### Installation
To install Zangdar, you just have to download `zangdar.min.js` in the `dist` folder and add a script into your HTML page :
```html
```
Your have to add this basic CSS to your styles too :
```css
.zangdar__wizard .zangdar__step {
display: none;
}
.zangdar__wizard .zangdar__step.zangdar__step__active {
display: block;
}
```
### Basic usage
Here a basic HTML form with sections to separate wizard parts :
```html
```
And you just have to instanciate Zangdar with the selector of the form you wan't to handle :
```javascript
document.addEventListener('DOMContentLoaded', () => {
const wizard = new Zangdar('#my-form')
})
```
And.. voilĂ ! You have a fully functional wizard ! :)
### Options & Events
You can pass an object of options as second class parameter. This is very useful, especially for adding events to the wizard lifecycle.
List of properties here :
Name | Type | Default | Description
--- | --- | --- | ---
**step_selector** | *String* | `[data-step]` | Wizard step section selector
**prev_step_selector** | *String* | `[data-prev]` | Wizard step previous button (or any element) selector
**prev_step_selector** | *String* | `[data-next]` | Wizard step next button (or any element) selector
**submit_selector** | *String* | `[type="submit"]` | Wizard form submit button selector
**active_step_index** | *Number* | `0` | Wizard active step index (useful to define active step on wizard instanciation)
**classes.form** | *String* | `zangdar__wizard` | Wizard form CSS class
**classes.prev_button** | *String* | `zangdar__prev` | Wizard previous button (or any element) CSS class
**classes.next_button** | *String* | `zangdar__next` | Wizard next button (or any element) CSS class
**classes.step** | *String* | `zangdar__step` | Wizard step section CSS class
**classes.step_active** | *String* | `zangdar__step__active` | Wizard active step section CSS class
**bypass_validation** | *Boolean* | `false` | Bypass native browser validation or user custom validation
List of events here :
Name | Type | Default | Parameters | Description
--- | --- | --- | --- | ---
**onSubmit** | *Function* | `null` | `{Event} e` | Wizard form custom submit handler (see example below)
**onStepChange** | *Function* | `null` | `{WizardStep} step`
`{Object} oldStep`
`{Number} direction`
`{HTMLFormElement} form` | method triggered when a step changes (see example below)
**onValidation** | *Function* | `null` | `{WizardStep} step`
`{NodeListOf} fields`
`{HTMLFormElement} form` | method triggered on wizard step HTML validation (see example below)
**customValidation** | *Function* | `null` | `{WizardStep} step`
`{NodeListOf} fields`
`{HTMLFormElement} form` | method triggered on wizard step HTML validation (see example below)
Here there are examples for the events listed above :
```javascript
const wizard = new Zangdar('#my-form', {
onSubmit(e) {
e.preventDefault()
// Ajax call, custom form processing or anything you wan't to do here...
return false
},
onStepChange(step, oldStep, direction, form) {
const breadcrumb = this.getBreadcrumb() // this refers to Zangdar form wizard instance
},
onValidation(step, fields, form) {
if (step.hasErrors()) {
// ...
}
// Here a treatment after HTML native validation...
},
customValidation(step, fields, form) {
// Use the Formr library to validate fields (https://github.com/betaWeb/formr)
const validator = new Formr(form)
if (step.labeled('...')) {
validator
.required('name', 'email', 'password', 'confirm_password')
.string('name', 'email', 'password', 'confirm_password')
.email('email')
.length('password', 3, 20)
.length('confirm_password', 3, 20)
.same('password', 'confirm_password')
.validateAll()
if (!validator.isValid()) {
// ...
return false
}
return true
}
//...
}
})
```
## Available methods, getters and setters
You can retrieve all available methods on the [API documentation](https://betaweb.github.io/zangdar/).
### Zangdar object
#### Getters
* `currentIndex: number`
Returns current wizard step index.
```javascript
Zangdar.currentIndex
```
* `steps: WizardStep[]`
Returns an array of wizard steps.
```javascript
const strps = Zangdar.steps
```
* `uniqueId: String`
Returns the wizard instance unique id. Useful if you have more than one instance of the wizard on the page.
```javascript
const wizard_uuid = Zangdar.uniqueId
```
#### Setters
No setters currently available.
#### Methods
* `refresh(): Zangdar`
Refresh the wizard instance. Useful to refresh the DOM (when steps order has changed, for example).
> Fluent method : can be chained with other methods
```javascript
Zangdar.refresh()
```
* `destroy(): Zangdar`
Remove all listeners and destroys the wizard instance.
> Fluent method : can be chained with other methods
```javascript
Zangdar.destroy()
```
* `setOption(key: String, value: any): Zangdar`
Set an instance' option. (you can retrieve the options list above).
> Fluent method : can be chained with other methods
```javascript
Zangdar.setOption('active_step_index', 3)
Zangdar.setOption('bypass_validation', true)
Zangdar.refresh()
```
* `getStep(key: String|Number): WizardStep|null`
Get a WizardStep instance via his index or his label property (data-label attribute).
```javascript
// With step index
const step1 = Zangdar.getStep(1)
// OR with step label
const step_one = Zangdar.getStep('one')
```
* `getFormElement(): HTMLFormElement`
Get wizard HTML form element.
```javascript
const form = Zangdar.getFormElement()
```
* `getCurrentStep(): WizardStep|null`
Get the current WizardStep instance.
```javascript
const currentStep = Zangdar.getCurrentStep()
```
* `removeStep(key: Number|String|WizardStep): WizardStep|null`
Remove a step based on his index, label property (data-label attribute) or WizardStep instance.
```javascript
const step = Zangdar.getStep('step_six')
const removedIndex = Zangdar.removeStep(step)
// you can refresh the wizard after the step removal
Zangdar.refresh()
```
* `first(): Zangdar`
Reveals first step.
> Fluent method : can be chained with other methods
```javascript
Zangdar.first()
```
* `last(): Zangdar`
Reveals last step.
> Fluent method : can be chained with other methods
```javascript
Zangdar.last()
```
* `prev(): Zangdar`
Reveals prev step.
> Fluent method : can be chained with other methods
```javascript
Zangdar.prev()
```
* `next(): Zangdar`
Reveals next step.
> Fluent method : can be chained with other methods
```javascript
Zangdar.next()
```
* `revealStep(key: Number|String|WizardStep): Zangdar`
Reveal a single step based on his index, label property (data-label attribute) or WizardStep instance.
> Fluent method : can be chained with other methods
```javascript
try {
// With his index
Zangdar.revealStep(3)
// OR with his label (data-label attribute)
Zangdar.revealStep('step_three')
// OR event with a WizardStep instance
const step = Zangdar.getStep('step_three')
// ...
Zangdar.revealStep(step)
} catch (e) {
// Step not found
}
```
* `createFromTemplate(template: Object): Zangdar`
Create a wizard from an existing form with a template which is describes it, according to the options passed on wizard instance creation.
Useful to convert programmatically a HTML form into a powerful Zangdar wizard (by keeping only choosen fields).
> Fluent method : can be chained with other methods
```html
```
```javascript
const wizard = new Zangdar('#my_form')
const template = {
'step_one': ['.field__name', '.field__email'],
'step_two': ['.field__password', '.field__password_confirm'],
'step_three': ['.field__genre']
}
wizard.createFromTemplate(template)
```
The generated wizard HTML markup will be :
```html
```
* `getBreadcrumb(): Object`
Returns an object representing the wizard breadcrumb with the label property as key, and the WizardStep as value.
```javascript
const breadcrumb = Zangdar.getBreadcrumb()
```
## TODO
* [x] Finish Zangdar **Available methods, getters and setters** readme section
* [ ] Add WizardStep **Available methods, getters and setters** readme section
* [ ] Update gh-pages API docs