Demo of the widget: http://jsfiddle.net/slicedtoad/Lywvbsf4/
It's a progress bar that shows a list of steps and which one is being completed as well as allowing previous steps to be revisited.
It will be used to display the user's form completion progress on a web app that favors a client side approach (forms are submitted to the server at the last step).
I'd like feedback specifically on the widget based approached I took. I had the goals:
- simple interface
- low coupling to the rest of the app
- easy to extend the functionality (it should be easy to add more callbacks to handle new functionality, for example)
- no code bloat from
- legacy support (the app is only supported on FF and Chrome)
- unnecessarily portability and safety (i.e. it needs to be safe in this app, not every app)
I ended up making a lot of fairly arbitrary decisions, which I would like critiqued.
Widget:
var progressBar = function(id,options){
this.init(id,options);
};
progressBar.prototype.init = function(options){
this.id = options.id; // ID of the div that will store the progress bar
this.$node;
this.steps = options.steps;
this.current = 0; // current step
this.previousClickedCallback = options.previousClicked;
this.draw(); // populate $node
$(this.id).append(this.$node); // append $node to the DOM
this.$node.on("click",".step-finished .step-number",
$.proxy(this.previousClick,this));
this.next();
};
progressBar.prototype.previousClick = function(e){
this.previousClickedCallback($(e.target).html());
};
progressBar.prototype.draw = function(){
this.$node = $("<ol class='progressbar container'></ol>");
var html = "";
for(var step in this.steps){
html +=
"<li class='step'>" +
"<div class='step-number'>"+(parseInt(step)+1)+"</div>" +
"<div class='step-line'></div>" +
"<div class='step-label-wrap'>" +
"<label class='step-label'>"+this.steps[step]+"</label>" +
"</div>" +
"</li>";
}
this.$node.html(html);
};
progressBar.prototype.goToStep = function(step){
console.log("gotostep: ",step);
if(step>=1 && step<=this.steps.length+1){
this.current = parseInt(step);
// Reset progress bar status
this.$node.find(".step-current").removeClass("step-current");
this.$node.find(".step-finished").removeClass("step-finished");
// Set current step
this.$node.find(".step:nth-child("+this.current+")").addClass("step-current");
// Set all previous steps to finished
for(var i = step-1; i > 0; i--){
this.$node.find(".step:nth-child("+i+")").addClass("step-finished");
}
}
};
progressBar.prototype.next = function(){
if(this.current<this.steps.length+1){
this.goToStep(this.current+1);
}
};
progressBar.prototype.previous = function(){
if(this.current>=2){
this.goToStep(this.current-1);
}
};
Example usage:
var goBack = function(step){
//cache current form or whatever
pbar.goToStep(step);
};
var pbar = new progressBar({
id:"#ProgressBar",
steps:["Date","Items","Preview","Details","Confirm"],
previousClicked:function(step){goBack(step);}
});
$("#next").on("click",function(){pbar.next()});
$("#previous").on("click",function(){pbar.previous()});
CSS (minimal):
ol.progressbar {
list-style-type: none;
padding-left:0;
}
.progressbar.container {
display: flex;
align-items: flex-end;
padding-top: 22px;
}
.progressbar .step {
flex-grow:1;
position:relative;
text-align: center;
z-index:1;
}
.progressbar .step-number {
position:relative;
z-index:10;
width: 20px;
height: 20px;
border-radius: 10px;
background-color:white;
display:inline-block;
text-align: center;
line-height: 20px;
border:1px solid;
}
.progressbar .step-finished .step-number:hover{
background-color: lightblue;
cursor: pointer;
}
.progressbar .step-finished .step-number{
background-color: green;
}
.progressbar .step-current .step-number{
background-color:lightblue;
}
.progressbar .step-label-wrap {
position: absolute;
width:100%;
top: -22px;
}
.progressbar .step-label {
padding: 0px 1px;
}
.progressbar .step-line {
height: 2px;
background-color: black;
width:100%;
position:absolute;
top: 50%;
left:50%;
z-index:5;
}
.progressbar .step:last-of-type .step-line{
display:none;
}
lang-js
. I tried to addjavascript
as the language hint. \$\endgroup\$