Adriano, in your example above, you are trying to develop a Wizard.
Regardless of the number of steps or business rules, we have a basic structure common to this type of component.
Then for the component, you will need the following structure:
HTML Template
<template id="tmplStep">
<div class="step hide">
<div class="title">
</div>
<div class="content">
</div>
<div class="actions">
<input class="prev" type="button" value="Anterior" />
<input class="next" type="button" value="Proximo" />
</div>
</div>
</template>
CSS
.hide {
display: none;
}
JavaScript
var Wizard = function (element) {
var that = this;
this.dom = {};
this.dom.wrapper = element;
this.dom.steps = this.dom.wrapper.querySelectorAll("[data-step]");
this.steps = [];
[].forEach.call(this.dom.steps, function (element, indice) {
var step = new Step(that, element);
});
this.steps[0].Show();
}
var Step = function (wizard, element) {
var that = this;
this.wizard = wizard;
this.indice = this.wizard.steps.length;
this.wizard.steps.push(this);
this.dom = {};
this.dom.fragment = document.importNode(this.template, true);
this.dom.wrapper = this.dom.fragment.querySelector(".step");
this.dom.title = this.dom.wrapper.querySelector(".title");
this.dom.content = this.dom.wrapper.querySelector(".content");
this.dom.actions = this.dom.wrapper.querySelector(".actions");
this.dom.prev = this.dom.actions.querySelector(".prev");
this.dom.next = this.dom.actions.querySelector(".next");
this.dom.content.appendChild(element);
this.wizard.dom.wrapper.appendChild(this.dom.wrapper);
this.dom.prev.addEventListener("click", function (event) {
that.onPrevClick();
});
this.dom.next.addEventListener("click", function (event) {
that.onNextClick();
})
}
Step.prototype.template = document.getElementById("tmplStep").content;
Step.prototype.Show = function () {
this.dom.wrapper.classList.remove("hide");
this.dom.prev.disabled = this.isPrimeiro;
this.dom.next.value = this.isUltimo ? "Finalizar" : "Proximo";
}
Step.prototype.Hide = function () {
this.dom.wrapper.classList.add("hide");
}
Step.prototype.onPrevClick = function () {
this.Hide();
this.prev.Show();
};
Step.prototype.onNextClick = function () {
var isValid = true;
if (this.onValida)
isValid = this.onValida();
if (isValid) {
if (this.isUltimo) {
if (this.wizard.onFinaliza)
this.wizard.onFinaliza();
} else {
this.Hide();
this.next.Show();
}
}
};
Object.defineProperty(Step.prototype, "prev", {
get: function() { return this.wizard.steps[this.indice - 1]; }
});
Object.defineProperty(Step.prototype, "next", {
get: function() { return this.wizard.steps[this.indice + 1]; }
});
Object.defineProperty(Step.prototype, "isPrimeiro", {
get: function() { return this.indice == 0; }
});
Object.defineProperty(Step.prototype, "isUltimo", {
get: function() { return this.indice == this.wizard.steps.length - 1; }
});
You can use the script above whenever you need to mount a "Wizard", however it is interesting that you load it into a separate file, if you prefer you can even mount a module for curljs
or requirejs
. >
Once this is done, just use it as follows:
** Markup HTML **
<div data-wizard="">
<div data-step="Titulo 1">
<label>
Input 1:
<input id="input1" type="text" required/>
</label>
</div>
<div data-step="Titulo 2">
<label>
Input 2:
<input id="input2" type="number" required/>
</label>
</div>
<div data-step="Titulo 3">
<label>
Input 3:
<input id="input3" type="date" required/>
</label>
</div>
</div>
JavaScript
var element = document.querySelector("[data-wizard]");
var wizard = new Wizard(element);
wizard.steps[0].onValida = function () {
var input1 = document.getElementById("input1");
var texto = input1.value.trim();
if (!texto) alert("infore um texto não vazio!");
return texto;
}
wizard.steps[1].onValida = function () {
var input2 = document.getElementById("input2");
var numero = input2.valueAsNumber;
if (!numero) alert("infore um numero e que seja diferente de zero!");
return numero;
}
wizard.steps[2].onValida = function () {
var input3 = document.getElementById("input3");
var data = input3.valueAsDate;
if (!data) alert("infore uma data!");
return data;
}
wizard.onFinaliza = function () {
alert("Wizard Finalizado!");
}
Now the complete example:
var Wizard = function (element) {
var that = this;
this.dom = {};
this.dom.wrapper = element;
this.dom.steps = this.dom.wrapper.querySelectorAll("[data-step]");
this.steps = [];
[].forEach.call(this.dom.steps, function (element, indice) {
var step = new Step(that, element);
});
this.steps[0].Show();
}
var Step = function (wizard, element) {
var that = this;
this.wizard = wizard;
this.indice = this.wizard.steps.length;
this.wizard.steps.push(this);
this.dom = {};
this.dom.fragment = document.importNode(this.template, true);
this.dom.wrapper = this.dom.fragment.querySelector(".step");
this.dom.title = this.dom.wrapper.querySelector(".title");
this.dom.content = this.dom.wrapper.querySelector(".content");
this.dom.actions = this.dom.wrapper.querySelector(".actions");
this.dom.prev = this.dom.actions.querySelector(".prev");
this.dom.next = this.dom.actions.querySelector(".next");
this.dom.content.appendChild(element);
this.wizard.dom.wrapper.appendChild(this.dom.wrapper);
this.dom.prev.addEventListener("click", function (event) {
that.onPrevClick();
});
this.dom.next.addEventListener("click", function (event) {
that.onNextClick();
})
}
Step.prototype.template = document.getElementById("tmplStep").content;
Step.prototype.Show = function () {
this.dom.wrapper.classList.remove("hide");
this.dom.prev.disabled = this.isPrimeiro;
this.dom.next.value = this.isUltimo ? "Finalizar" : "Proximo";
}
Step.prototype.Hide = function () {
this.dom.wrapper.classList.add("hide");
}
Step.prototype.onPrevClick = function () {
this.Hide();
this.prev.Show();
};
Step.prototype.onNextClick = function () {
var isValid = true;
if (this.onValida)
isValid = this.onValida();
if (isValid) {
if (this.isUltimo) {
if (this.wizard.onFinaliza)
this.wizard.onFinaliza();
} else {
this.Hide();
this.next.Show();
}
}
};
Object.defineProperty(Step.prototype, "prev", {
get: function() { return this.wizard.steps[this.indice - 1]; }
});
Object.defineProperty(Step.prototype, "next", {
get: function() { return this.wizard.steps[this.indice + 1]; }
});
Object.defineProperty(Step.prototype, "isPrimeiro", {
get: function() { return this.indice == 0; }
});
Object.defineProperty(Step.prototype, "isUltimo", {
get: function() { return this.indice == this.wizard.steps.length - 1; }
});
var element = document.querySelector("[data-wizard]");
var wizard = new Wizard(element);
wizard.steps[0].onValida = function () {
var input1 = document.getElementById("input1");
var texto = input1.value.trim();
if (!texto) alert("infore um texto não vazio!");
return texto;
}
wizard.steps[1].onValida = function () {
var input2 = document.getElementById("input2");
var numero = input2.valueAsNumber;
if (!numero) alert("infore um numero e que seja diferente de zero!");
return numero;
}
wizard.steps[2].onValida = function () {
var input3 = document.getElementById("input3");
var data = input3.valueAsDate;
if (!data) alert("infore uma data!");
return data;
}
wizard.onFinaliza = function () {
alert("Wizard Finalizado!");
}
.hide {
display: none;
}
<div data-wizard="">
<div data-step="Titulo 1">
<label>
Input 1:
<input id="input1" type="text" required/>
</label>
</div>
<div data-step="Titulo 2">
<label>
Input 2:
<input id="input2" type="number" required/>
</label>
</div>
<div data-step="Titulo 3">
<label>
Input 3:
<input id="input3" type="date" required/>
</label>
</div>
</div>
<template id="tmplStep">
<div class="step hide">
<div class="title">
</div>
<div class="content">
</div>
<div class="actions">
<input class="prev" type="button" value="Anterior" />
<input class="next" type="button" value="Proximo" />
</div>
</div>
</template>