I am trying to make a "timeline". I am doing it to learn more about jquery, so i am trying not to use any "timeline js plugins".
I used a jQuery function to center the Event which the user clicks. I do this by using a transform:
$('.tl-container').css('transform', 'translateX(' + movingDistance + 'px)');
Then i added a couple of arrows so the user could go left and right and see other events which might be out of sight.
How can i make it that that buttons move the timeline on each click by 100px?
I first tried also using the translate idea, but that didn't work. It would translate once, but the second click wouldn't work anymore (because the timeline was already at the "end" of the translate.
Then i tried with .animate(). This works, but with one major problem. It "offsets" the whole timeline, so when i then click on an Event it won't center (it will move to the new "offset center".
Any ideas?
Here is a CodePen showing what i have now: https://codepen.io/anon/pen/bVJQbB
I also have the project on GitHug if you prefer: https://github.com/boguz/chronos
I have forked your pen : https://codepen.io/sodawillow/pen/MaRZLa
In HTML I have added two buttons with next
and prev
ID's (just for test purposes, because your arrows didn't display on Firefox when I first worked on your pen) :
<button id="prev">prev</button>
<button id="next">next</button>
In JS I have added a global variable (activeEventNumber
) to hold the current active event, and used it with your code to mode the cursor one step forwards, or backwards. Of course, this could be improved a little :
$("#prev").on("click", prevEvent);
$("#next").on("click", nextEvent);
function prevEvent() {
var eventSize = $('.tl-event').width(),
windowSize = $(window).width(),
clickedPosition = eventSpacing * --activeEventNumber + eventSize * activeEventNumber,
movingDistance = windowSize / 2 - clickedPosition - eventSpacing / 2 - eventSpacing * 1.7;
$('.tl-container').css('transform', 'translateX(' + movingDistance + 'px)');
activeEvent($(".tl-event").eq(activeEventNumber - 1));
}
function nextEvent() {
var eventSize = $('.tl-event').width(),
windowSize = $(window).width(),
clickedPosition = eventSpacing * ++activeEventNumber + eventSize * activeEventNumber,
movingDistance = windowSize / 2 - clickedPosition - eventSpacing / 2 - eventSpacing * 1.7;
$('.tl-container').css('transform', 'translateX(' + movingDistance + 'px)');
activeEvent($(".tl-event").eq(activeEventNumber - 1));
}
PS : I will try to improve the JS in my pen
EDIT : my pen has both your arrows and mine working, and I tried to DRY the JS as much as possible (less lines than your JS :)). I have added keyboard arrows, too. If you don't understand some/anything, please tell me.
// Use Strict Mode
"use strict";
// GLOBAL variables
var eventSpacing = 50, activeEventNumber = 0, clickedEventNumber, eventSize, windowSize;
// DOCUMENT READY FUNCTION
$(function () {
//set useful values
clickedEventNumber = $(this).index();
eventSize = $('.tl-event').width();
windowSize = $(window).width();
createTimeline();
initEvents();
}); // end of document.ready
function createTimeline() {
var numberOfEvents = $('.tl-event').length;
$('.tl-line').each(function() {
var lineLength = numberOfEvents * (eventSpacing + eventSize);
$('.tl-container').css('width', lineLength + (eventSpacing * 2) +'px');
$('.tl-line').css('left', eventSpacing + 'px');
$('.tl-line').css('width', lineLength + 'px');
});
$('.tl-event').each(function() {
var eventNumber = $(this).index();
var eventHorPosition = eventNumber * eventSpacing + eventSpacing / 2;
$(this).css('left', eventHorPosition + 'px');
});
}
function initEvents() {
//click
$('.tl-event').on('click', function() {
activeEventNumber = $(this).index();
moveCursor(activeEventNumber);
});
//buttons
$('#prev, .arrow-before').on("click", moveToPrevEvent);
$('#next, .arrow-after').on("click", moveToNextEvent);
//keyboard arrows
$(window).on("keydown", function(e) {
switch(e.which) {
case 37: moveToPrevEvent(); break; //left arrow key
case 39: moveToNextEvent(); break; //right arrow key
default: return; // exit this handler for other keys
}
e.preventDefault(); // prevent the default action (scroll / move caret)
});
//next and previous functions
function moveToPrevEvent() { if(activeEventNumber > 1) moveCursor(--activeEventNumber); }
function moveToNextEvent() { if(activeEventNumber < $('.tl-event').length) moveCursor(++activeEventNumber); }
//main function to select an event
function moveCursor(eventNumber) {
var clickedPosition, movingDistance;
//move
clickedPosition = (eventSpacing + eventSize) * eventNumber;
movingDistance = windowSize / 2 - clickedPosition - eventSpacing * 2.2; //magic number ! :) 1.7 + .5
$('.tl-container').css('transform', 'translateX(' + movingDistance + 'px)');
//style
$('.tl-event').css('background-color', 'white');
$($(".tl-event").eq(activeEventNumber - 1)).css('background-color', 'red');
}
}
* {
margin: 0;
padding: 0;
}
body {
background-color: #444;
color: #fff;
max-width: 100%;
overflow: hidden;
text-align: center;
}
.tl-mask {
border: 1px solid red;
height: 200px;
width: 86vw;
margin: 10vh auto 0;
overflow: hidden;
position: relative;
}
.arrow {
height: 40px;
position: absolute;
top: 188px;
opacity: .2;
}
.arrow:hover {
opacity: .75;
cursor: pointer;
}
.arrow-before {
left: 50px;
}
.arrow-after {
right: 50px;
}
.tl-container {
height: 200px;
background-color: #666;
position: relative;
transition: all 2s ease;
min-width: 100%;
}
.tl-line {
background-color: white;
height: 2px;
display: block;
position: relative;
top: 100px;
}
.tl-event {
background-color: white;
height: 10px;
width: 10px;
position: relative;
top: 94px;
border-radius: 50%;
float: left;
}
.tl-event:hover {
cursor: pointer;
}
.center-check {
background-color: white;
width: 3px;
height: 20px;
margin: 10px auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>chronos</h1>
<img src="./img/arrow_before.png" alt="" class="arrow arrow-before">
<div class="tl-mask">
<div class="tl-container">
<div class="tl-line"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
<div class="tl-event"></div>
</div> <!-- end .tl-container -->
</div> <!-- end -tl-mask -->
<img src="./img/arrow_after.png" alt="" class="arrow arrow-after">
<div class="center-check"></div>
<button id="prev">prev</button>
<button id="next">next</button>