Progress bar New

by namlth

HTML

<script src="//code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="//stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://github.com/SteveSanderson/knockout-projections/blob/master/dist/knockout-projections.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js"></script>

<!-- Dynamic -->
<div class="progress-container">
  <div class="scope-progress-bar">
    <div class="scope-progress-bar-top" data-bind="foreach: { data: items, as: 'item' }">
      <div class="top-icon">
        <i class="fa fa-home" data-bind="css: { active: isActive }"></i>
      </div>
      <div class="top-icon-secondary invisible" data-bind="css: { 'd-none': isLastOfType }">
        <i class="fa fa-circle" data-bind="css: { active: isActive }"></i>
      </div>
    </div>
    <div class="scope-progress-bar-main" data-bind="foreach: { data: items, as: 'item' }">
      <div class="step">
        <div class="step-main" role="button"
             data-bind="attr: { id: item.name },
                        click: $parent.stepClick.bind($parent, item),
                        css: { 'first-type': isFirstOfType, 'last-type': isLastOfType,
                        'active': isActive, 'first': isFirstActive, 'last': isLastActive, 'only': isOnly }
                        ">
          <i class="step-icon far" data-bind="css: { 'fa-square': !item.isActive(), 'fa-check-square': item.isActive() }"></i>
        </div>
        <!--<label>some textaaa aaa aaa aaa aaaaa aaaa aaa</label>-->
      </div>
      <div class="secondary-step">
        <div...

SCSS

$background-color-lightyellow: lightyellow;
$active-color: red;
$inactive-color: lightgray;
$element-min-width: 33%;

.progress-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.scope-progress-bar {
  width: 100%;
  padding-top: 1rem;
  padding-bottom: 1rem;
  background: $background-color-lightyellow;
  overflow-x: scroll;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  &::-webkit-scrollbar {
    display: none;
  }
}

.scope-progress-bar-top {
  width: 100%;
  background: lightgreen;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}

.scope-progress-bar-main {
  background: lightcyan;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  min-height: 30px;
}

.step {
  width: 100%;
  min-width: $element-min-width;
  text-align: center;
  flex-direction: column;
  align-items: center;
}

.step-main {
  //background-color: lightyellow;
  text-align: center;
  position: relative;
  display: flex;
  justify-content: center;
  list-style: none;
}

.step-main:before,
.step-main:after{
  content: "";
  top: calc(50% - 2px);
  z-index: 1;
  border: 3px solid $inactive-color;
  position: absolute;
  //-webkit-transition: width 2s, height 4s; /* For Safari 3.1 to 6.0 */
  //transition: width 2s, height 4s;
}

.step-main.active:before {
  content: "";
  top: calc(50% - 2px);
  z-index: 2;
  border: 3px solid $active-color;
  position: absolute;
  //-webkit-transition: width 2s, height 4s; /* For Safari 3.1 to 6.0 */
  //transition: width 2s, height 4s;
}

.step-main:before {
  left: -1px;
  right: 50%;
}

.step-main:after {
  left: 50%;
  right: -1px;
}

.step-main.active:before {
  left: -1px;
  right: 50%;
}

.step-main.first-type:before {
  border: none !important;
}

.step-main.last-type:after {
  border: none !important;
}

.step-main.active.first:before {
  border: 3px solid...

JavaScript

function myModel() {
  var that = this;
  that.items = ko.observableArray([
    { index: 0, name: "item1", isFirstOfType: ko.observable(true),  isLastOfType: ko.observable(false),
     isActive: ko.observable(false), isFirstActive: ko.observable(false), isLastActive: ko.observable(false), isOnly: ko.observable(false) },
    { index: 1, name: "item2", isFirstOfType: ko.observable(false), isLastOfType: ko.observable(false),
     isActive: ko.observable(true),  isFirstActive: ko.observable(true),  isLastActive: ko.observable(false), isOnly: ko.observable(false) },
    { index: 2, name: "item3", isFirstOfType: ko.observable(false), isLastOfType: ko.observable(false),
     isActive: ko.observable(true),  isFirstActive: ko.observable(false), isLastActive: ko.observable(false), isOnly: ko.observable(false) },
    //{ index: 3, name: "item4", isFirstOfType: ko.observable(false), isLastOfType: ko.observable(false), 
     //isActive: ko.observable(true),  isFirstActive: ko.observable(false), isLastActive: ko.observable(true),  isOnly: ko.observable(false) },
    //{ index: 4, name: "item5", isFirstOfType: ko.observable(false), isLastOfType: ko.observable(false), 
     //isActive: ko.observable(false), isFirstActive: ko.observable(false), isLastActive: ko.observable(false), isOnly: ko.observable(false) },
    { index: 3, name: "item6", isFirstOfType: ko.observable(false), isLastOfType: ko.observable(true),  
     isActive: ko.observable(false), isFirstActive: ko.observable(false), isLastActive: ko.observable(false), isOnly: ko.observable(false) }
  ]);
  that.itemsLength = ko.computed(() => {
    return that.items().length;
  });
  that.activeItems = ko.computed(() => {
    var activeItems = that.items().filter((x) => { return x.isActive(); });
    return activeItems;
  });
  that.firstActiveItem = ko.computed(() => {
    if (that.activeItems().length > 0) return that.activeItems()[0];
    else return null;
  });
  that.firstActiveItemName = ko.computed(() => {
    if...