Jake
Jake

Reputation: 26117

Horizontal Timeline

I have put together a JSFiddle to create a horizontal timeline with CSS and JQuery. The behavior of the timeline is, as under:

When the page loads, the "timelineSlider" always positions itself under "Link 1". Clicking on each list item named "Link", the "timelineSlider" slides towards and under that list item.

Currently, it works sequentially when a user clicks Link1, Link2, Link3 and then Link4. But I would like the user to click on any list item in any order and the "timelineSlider" should either slide right or left or does not change position, depending on the previous position of the "timelineSlider". How can I change my JS code to do this?

JSFiddle

$(document).ready(function() {
  $("li").click(function() {
    //Get Initial timelineSlider Margin
    var timelineSliderMargin = parseInt($('.timelineSlider').css('margin-left'));
    //Slide the box to the link clicked (left or right) depending on box position
    $(".timelineSlider").animate({
      'margin-left': (parseInt(calculate(0)) + parseInt($('.timelineSlider').css('margin-left'))) + 'px'
    });
  });
});

function calculate(i) {
  var sum = 0;
  for (var j = 0; j <= i; j++) {
    sum = sum + $("ul li:eq(" + j + ")").outerWidth(true);
  }
  return sum;
}
div.eventsWrapper {
  height: 75px;
  margin-left: 5px;
  position: absolute;
  width: 800px;
}
.eventsConnector {
  background: #0070c0 none repeat scroll 50% 50%;
  height: 3px;
  left: 0;
  margin-left: 185px;
  margin-top: -31px;
  position: absolute;
  transition: transform 0.4s ease 0s;
  width: 512px;
  z-index: -1;
}
#events {
  z-index: 2;
}
#events ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
}
#events li {
  display: inline-block;
}
#events a {
  display: block;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 5px #0070c0 solid;
  text-transform: uppercase;
  text-decoration: none;
  font-size: 15px;
  text-align: center;
  line-height: 50px;
  margin-left: 125px;
  z-index: 3;
  color: #666666;
  background-color: #0070c0;
}
#events a .event {
  background-color: #ffffff;
  border: 1px solid #ffffff;
  border-radius: 50%;
  color: #666666;
  display: block;
  font-size: 15px;
  height: 48px;
  margin-left: 0;
  margin-top: 0;
  position: relative;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  width: 48px;
  z-index: 4;
}
.timelineSlider {
  width: 110px;
  height: 66px;
  border: 0px;
  margin-left: 95px;
  margin-top: 10px;
  position: absolute;
  z-index: 2;
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="eventsWrapper">
  <div id="events">
    <ul>
      <li>
        <a href="#1">
          <div class="event">LINK1</div>
        </a>
      </li>
      <li>
        <a href="#2">
          <div class="event">LINK2</div>
        </a>
      </li>
      <li>
        <a href="#3">
          <div class="event">LINK3</div>
        </a>
      </li>
      <li>
        <a href="#4">
          <div class="event">LINK4</div>
        </a>
      </li>
    </ul>
  </div>
  <div class="eventsConnector"></div>
  <div class="timelineSlider">Slide this box to the link clicked.</div>
</div>

Upvotes: 2

Views: 1586

Answers (1)

maioman
maioman

Reputation: 18764

you can do it without calculate function,

just check the offset left of $(this), and use that to position the red box:

$(document).ready(function() {
  $("li").click(function() {
    //Get Initial timelineSlider Margin
    var timelineSliderMargin = parseInt($('.timelineSlider').css('margin-left'));
    
    var left = $(this)[0].offsetLeft;
    //Slide the box to the link clicked (left or right) depending on box position
    $(".timelineSlider").animate({
      'left': (left +  'px')
    });
  });
});

/*function calculate(i) {
  var sum = 0;
  for (var j = 0; j <= i; j++) {
    sum = sum + $("ul li:eq(" + j + ")").outerWidth(true);
  }
  return sum;
}*/
div.eventsWrapper {
  height: 75px;
  margin-left: 5px;
  position: absolute;
  width: 800px;
}
.eventsConnector {
  background: #0070c0 none repeat scroll 50% 50%;
  height: 3px;
  left: 0;
  margin-left: 185px;
  margin-top: -31px;
  position: absolute;
  transition: transform 0.4s ease 0s;
  width: 512px;
  z-index: -1;
}
#events {
  z-index: 2;
}
#events ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
}
#events li {
  display: inline-block;
}
#events a {
  display: block;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 5px #0070c0 solid;
  text-transform: uppercase;
  text-decoration: none;
  font-size: 15px;
  text-align: center;
  line-height: 50px;
  margin-left: 125px;
  z-index: 3;
  color: #666666;
  background-color: #0070c0;
}
#events a .event {
  background-color: #ffffff;
  border: 1px solid #ffffff;
  border-radius: 50%;
  color: #666666;
  display: block;
  font-size: 15px;
  height: 48px;
  margin-left: 0;
  margin-top: 0;
  position: relative;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  width: 48px;
  z-index: 4;
}
.timelineSlider {
  width: 110px;
  height: 66px;
  border: 0px;
  margin-left: 95px;
  margin-top: 10px;
  position: absolute;
  z-index: 2;
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="eventsWrapper">
  <div id="events">
    <ul>
      <li>
        <a href="#1">
          <div class="event">LINK1</div>
        </a>
      </li>
      <li>
        <a href="#2">
          <div class="event">LINK2</div>
        </a>
      </li>
      <li>
        <a href="#3">
          <div class="event">LINK3</div>
        </a>
      </li>
      <li>
        <a href="#4">
          <div class="event">LINK4</div>
        </a>
      </li>
    </ul>
  </div>
  <div class="eventsConnector"></div>
  <div class="timelineSlider">Slide this box to the link clicked.</div>
</div>

Upvotes: 1

Related Questions