Elementor Timeline Slider
November 11, 2024 ยท AI Conversations
<style>
.timeline_section {
display: flex;
gap:24px;
}
.timeline_image img
{
width:464px;
height:464px;
}
</style>
### Updated PHP Code with jQuery Slider Integration
1. **Update the `render()` function to include navigation buttons and a year bar**.
2. **Add jQuery code for the slider functionality**.
Here's the complete code:
<?php
use ElementorWidget_Base;
use ElementorControls_Manager;
use ElementorRepeater;
use ElementorPlugin;
class Elementor_Timeline_Widget extends Widget_Base
{
public function get_name()
{
return 'rosemeier_timeline';
}
public function get_title()
{
return esc_html__('Timeline', 'rosemeier');
}
public function get_icon()
{
return 'eicon-time-line';
}
public function get_custom_help_url()
{
return 'https://docs.abart-digital.com';
}
public function get_categories()
{
return ['general'];
}
public function get_keywords()
{
return ['timeline', 'slider'];
}
public function get_script_depends()
{
return ['jquery'];
}
protected function register_controls()
{
$this->start_controls_section(
'section_timelines',
[
'label' => __('Timelines', 'rosemeier'),
]
);
$repeater = new ElementorRepeater();
$repeater->add_control(
'timeline_title',
[
'label' => __('Title', 'rosemeier'),
'type' => ElementorControls_Manager::TEXT,
'default' => __('Timeline Title', 'rosemeier'),
'label_block' => true,
]
);
$repeater->add_control(
'timeline_year',
[
'label' => __('Year', 'rosemeier'),
'type' => ElementorControls_Manager::NUMBER,
'default' => 2024,
'label_block' => true,
]
);
$repeater->add_control(
'timeline_desc',
[
'label' => __('Description', 'rosemeier'),
'type' => ElementorControls_Manager::WYSIWYG,
'default' => __('Timeline Description', 'rosemeier'),
'show_label' => false,
]
);
$repeater->add_control(
'timeline_image',
[
'label' => __('Choose Image', 'rosemeier'),
'type' => ElementorControls_Manager::MEDIA,
'default' => [
'url' => ElementorUtils::get_placeholder_image_src(),
],
]
);
$this->add_control(
'rose_timelines',
[
'label' => __('Timelines', 'rosemeier'),
'type' => ElementorControls_Manager::REPEATER,
'fields' => $repeater->get_controls(),
'default' => [
['timeline_title' => __('Timeline #1', 'rosemeier')],
['timeline_title' => __('Timeline #2', 'rosemeier')],
],
'title_field' => '{{{ timeline_title }}}',
]
);
$this->end_controls_section();
}
protected function render()
{
$settings = $this->get_settings_for_display();
if (isset($settings['rose_timelines']) && count($settings['rose_timelines']) > 0) {
?>
<style>
.timeline-slider {
display: flex;
overflow: hidden;
position: relative;
}
.timeline-slide {
min-width: 100%;
transition: transform 0.5s ease-in-out;
}
.timeline_navigation {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.timeline_year_bar {
display: flex;
justify-content: center;
margin-top: 10px;
gap: 10px;
}
.timeline_year_bar span {
cursor: pointer;
}
.active-year {
font-weight: bold;
text-decoration: underline;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<div class="timeline_navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<div class="timeline_year_bar">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
}
}
function updateYearBar() {
$('.timeline_year_bar span').removeClass('active-year');
$('.timeline_year_bar span').eq(currentIndex).addClass('active-year');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
$('.timeline_year_bar span').click(function () {
const index = $(this).data('slide');
showSlide(index);
});
showSlide(currentIndex);
});
</script>
<?php
}
}
}
### Explanation
1. **HTML & PHP Structure**:
– A `.timeline-slider` container holds individual `.timeline-slide` items.
– Navigation buttons (`Previous` and `Next`) allow users to scroll through the slides.
– A `.timeline_year_bar` with clickable years for direct navigation.
2. **CSS Styles**:
– Added styles for `.timeline-slider`, `.timeline-slide`, and navigation buttons.
– Made sure slides take up the full width for the slider effect.
3. **jQuery Functionality**:
– Uses `.css('transform')` to slide through the items.
– Listens to clicks on navigation buttons and year bar.
– Highlights the current year in the year bar.
This setup should give you a fully functional slider with a previous/next button and a year bar that updates according to the current slide.
### Solution: Adjust the JavaScript and CSS
Let's adjust the JavaScript to ensure that the slides display correctly when navigating, and update the CSS to avoid any hidden content issues.
#### Updated JavaScript and CSS:
<style>
.timeline-slider {
display: flex;
transition: transform 0.5s ease-in-out;
overflow: hidden;
}
.timeline-slide {
flex-shrink: 0;
width: 100%;
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
.timeline-slide.active {
opacity: 1;
}
.timeline_navigation {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.timeline_year_bar {
display: flex;
justify-content: center;
margin-top: 10px;
gap: 10px;
}
.timeline_year_bar span {
cursor: pointer;
}
.active-year {
font-weight: bold;
text-decoration: underline;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide <?php echo $index === 0 ? 'active' : ''; ?>">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<div class="timeline_navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<div class="timeline_year_bar">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
slides.removeClass('active');
slides.eq(index).addClass('active');
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
}
}
function updateYearBar() {
$('.timeline_year_bar span').removeClass('active-year');
$('.timeline_year_bar span').eq(currentIndex).addClass('active-year');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
$('.timeline_year_bar span').click(function () {
const index = $(this).data('slide');
showSlide(index);
});
// Initialize the first slide
showSlide(currentIndex);
});
</script>
### Explanation of Fixes:
1. **CSS**:
– Added an `active` class to handle the visibility of slides (`opacity: 1;`) and defaulted non-active slides to `opacity: 0;`.
– Ensured that slides are fully visible and occupy 100% width of the container.
2. **JavaScript**:
– Updated the `showSlide` function to add/remove the `active` class based on the current slide index.
– Added `.css('transform')` to transition the slider smoothly while changing slides.
– Included a direct update to the `.active-year` class for the year bar.
### How It Works:
– The `active` class controls which slide is currently visible.
– The `translateX` CSS transform is used for sliding animations.
– Clicking the "Next" and "Previous" buttons or any year in the bar triggers the slide change.
This updated approach ensures that all slides show up correctly when you navigate through them.
### Simplified Solution:
1. We'll use only the `transform` property for sliding without relying on `opacity`.
2. Ensure each slide occupies full width and moves correctly using CSS flexbox.
3. JavaScript will handle the navigation to display the correct slide.
### Updated Code:
<style>
.timeline-container {
max-width: 100%;
overflow: hidden;
position: relative;
}
.timeline-slider {
display: flex;
transition: transform 0.5s ease-in-out;
}
.timeline-slide {
min-width: 100%;
flex-shrink: 0;
box-sizing: border-box;
}
.timeline_section {
display: flex;
gap: 24px;
padding: 20px;
}
.timeline_image img {
width: 464px;
height: 464px;
object-fit: cover;
}
.timeline_navigation {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.timeline_year_bar {
display: flex;
justify-content: center;
margin-top: 20px;
gap: 10px;
}
.timeline_year_bar span {
cursor: pointer;
padding: 5px;
}
.active-year {
font-weight: bold;
text-decoration: underline;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<div class="timeline_navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<div class="timeline_year_bar">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
}
}
function updateYearBar() {
$('.timeline_year_bar span').removeClass('active-year');
$('.timeline_year_bar span').eq(currentIndex).addClass('active-year');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
$('.timeline_year_bar span').click(function () {
const index = $(this).data('slide');
showSlide(index);
});
// Initialize the first slide and year bar
showSlide(currentIndex);
});
</script>
### Explanation of Changes:
1. **CSS**:
– Ensured that `.timeline-slide` elements take up 100% of the container width.
– Used `transform: translateX()` for smooth horizontal sliding.
2. **JavaScript**:
– Simplified the logic to slide through the items using the `transform` property.
– Ensured the active year in the year bar is updated when navigating between slides.
– Added a check to prevent out-of-bound index errors.
### How to Use:
– The "Previous" and "Next" buttons allow users to navigate through the slides.
– Clicking on a year in the `.timeline_year_bar` navigates directly to the corresponding slide.
– The `.active-year` class highlights the current year in the year bar.
This version should fix the issue with slides not appearing when navigating between them. Let me know if this works for you!
### Solution:
Let's adjust the CSS to ensure that each slide takes up exactly 100% of the container's width, without showing parts of other slides.
### Updated CSS and JavaScript:
<style>
.timeline-container {
max-width: 100%;
overflow: hidden;
position: relative;
}
.timeline-slider {
display: flex;
transition: transform 0.5s ease-in-out;
width: 100%;
}
.timeline-slide {
min-width: 100%;
flex-shrink: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.timeline_section {
display: flex;
gap: 24px;
padding: 20px;
width: 100%;
}
.timeline_image img {
width: 100%;
max-width: 464px;
height: 464px;
object-fit: cover;
}
.timeline_navigation {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.timeline_year_bar {
display: flex;
justify-content: center;
margin-top: 20px;
gap: 10px;
}
.timeline_year_bar span {
cursor: pointer;
padding: 5px;
}
.active-year {
font-weight: bold;
text-decoration: underline;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<div class="timeline_navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<div class="timeline_year_bar">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
}
}
function updateYearBar() {
$('.timeline_year_bar span').removeClass('active-year');
$('.timeline_year_bar span').eq(currentIndex).addClass('active-year');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
$('.timeline_year_bar span').click(function () {
const index = $(this).data('slide');
showSlide(index);
});
// Initialize the first slide and year bar
showSlide(currentIndex);
});
</script>
### Key Changes:
1. **CSS Adjustments**:
– Set `min-width: 100%;` for `.timeline-slide` to ensure each slide takes the full width of the container.
– Added `object-fit: cover;` to the images to ensure they fit nicely within the defined size.
– Ensured that `.timeline-slider` uses `flex` without gaps between slides.
2. **JavaScript**:
– Simplified navigation logic remains the same, ensuring slides move 100% of their width with each transition.
This should solve the issue where parts of the next or previous slide were showing up. Now each slide should fully cover the container without overlapping content from adjacent slides.
Here's a refined version to fix this issue:
### Updated CSS and HTML:
<style>
.timeline-container {
max-width: 100%;
overflow: hidden;
position: relative;
}
.timeline-slider {
display: flex;
transition: transform 0.5s ease-in-out;
width: 100%;
}
.timeline-slide {
min-width: 100%;
flex-shrink: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
padding: 0; /* Ensure no padding to avoid overflow */
margin: 0; /* Ensure no margin to avoid overflow */
}
.timeline_section {
display: flex;
gap: 24px;
padding: 20px;
width: 100%;
box-sizing: border-box; /* Ensure content fits within slide */
}
.timeline_image img {
width: 100%;
max-width: 464px;
height: 464px;
object-fit: cover;
display: block; /* Ensure no extra space below the image */
}
.timeline_navigation {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.timeline_year_bar {
display: flex;
justify-content: center;
margin-top: 20px;
gap: 10px;
}
.timeline_year_bar span {
cursor: pointer;
padding: 5px;
}
.active-year {
font-weight: bold;
text-decoration: underline;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<div class="timeline_navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<div class="timeline_year_bar">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
}
}
function updateYearBar() {
$('.timeline_year_bar span').removeClass('active-year');
$('.timeline_year_bar span').eq(currentIndex).addClass('active-year');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
$('.timeline_year_bar span').click(function () {
const index = $(this).data('slide');
showSlide(index);
});
// Initialize the first slide and year bar
showSlide(currentIndex);
});
</script>
### Key Changes:
1. **Removed Margins and Padding**:
– Added `padding: 0;` and `margin: 0;` to `.timeline-slide` to prevent overflow.
– Ensured that `.timeline-slider` uses the full container width with no extra space.
2. **Ensured No Overflow**:
– Applied `box-sizing: border-box;` to ensure padding is included within the element's width and height.
– Set `display: block;` on images to avoid extra space below.
### Test and Verify:
– Ensure your browser cache is cleared to see the updated changes.
– The slider should now navigate smoothly without displaying parts of adjacent slides.
Let me know if this resolves the issue!
### Updated HTML, CSS, and JavaScript:
<style>
.timeline-container {
max-width: 100%;
overflow: hidden;
position: relative;
}
.timeline-slider {
display: flex;
transition: transform 0.5s ease-in-out;
width: 100%;
}
.timeline-slide {
min-width: 100%;
flex-shrink: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.timeline_section {
display: flex;
gap: 24px;
padding: 20px;
width: 100%;
box-sizing: border-box;
}
.timeline_image img {
width: 100%;
max-width: 464px;
height: 464px;
object-fit: cover;
display: block;
}
.timeline_navigation {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.timeline_year_bar {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
gap: 0;
width: 100%;
}
.timeline_year_bar span {
cursor: pointer;
padding: 5px 10px;
position: relative;
z-index: 2;
}
.timeline-progress {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
background-color: #ddd;
width: 100%;
z-index: 1;
}
.timeline-progress-fill {
height: 100%;
background-color: #007bff; /* Blue color for the active fill */
width: 0%;
transition: width 0.5s ease-in-out;
}
.active-year {
font-weight: bold;
color: #007bff;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<div class="timeline_navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<div class="timeline_year_bar">
<div class="timeline-progress">
<div class="timeline-progress-fill"></div>
</div>
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
const progressBarFill = $('.timeline-progress-fill');
const yearSpans = $('.timeline_year_bar span');
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
updateProgressBar();
}
}
function updateYearBar() {
yearSpans.removeClass('active-year');
yearSpans.eq(currentIndex).addClass('active-year');
}
function updateProgressBar() {
const progress = ((currentIndex + 1) / totalSlides) * 100;
progressBarFill.css('width', progress + '%');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
yearSpans.click(function () {
const index = $(this).data('slide');
showSlide(index);
});
// Initialize the first slide, year bar, and progress bar
showSlide(currentIndex);
});
</script>
### Explanation:
1. **CSS**:
– Added `.timeline-progress` for the progress bar background.
– Added `.timeline-progress-fill` for the filled part that will change based on the current slide.
2. **JavaScript**:
– Added `updateProgressBar()` function to dynamically fill the progress bar according to the current slide.
– Ensured that when navigating to a slide, both the year bar and progress bar update accordingly.
3. **HTML**:
– The year bar spans now include a progress bar line underneath, with the current year's position being highlighted.
This solution provides a visual indicator of progress through the timeline, with each year highlighted as you move through the slides.
### Updated HTML and CSS:
<style>
.timeline-container {
max-width: 100%;
overflow: hidden;
position: relative;
padding-right: 120px; /* Extra space for navigation buttons */
}
.timeline-slider {
display: flex;
transition: transform 0.5s ease-in-out;
width: 100%;
}
.timeline-slide {
min-width: 100%;
flex-shrink: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.timeline_section {
display: flex;
gap: 24px;
padding: 20px;
width: 100%;
box-sizing: border-box;
}
.timeline_image img {
width: 100%;
max-width: 464px;
height: 464px;
object-fit: cover;
display: block;
}
.timeline-navigation {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: 10px;
}
.timeline-navigation button {
background-color: #007bff;
color: #fff;
border: none;
padding: 10px;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s;
}
.timeline-navigation button:hover {
background-color: #0056b3;
}
.timeline_year_bar {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
gap: 0;
width: 100%;
}
.timeline_year_bar span {
cursor: pointer;
padding: 5px 10px;
position: relative;
z-index: 2;
}
.timeline-progress {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
background-color: #ddd;
width: 100%;
z-index: 1;
}
.timeline-progress-fill {
height: 100%;
background-color: #007bff;
width: 0%;
transition: width 0.5s ease-in-out;
}
.active-year {
font-weight: bold;
color: #007bff;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<div class="timeline-navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<div class="timeline_year_bar">
<div class="timeline-progress">
<div class="timeline-progress-fill"></div>
</div>
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
const progressBarFill = $('.timeline-progress-fill');
const yearSpans = $('.timeline_year_bar span');
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
updateProgressBar();
}
}
function updateYearBar() {
yearSpans.removeClass('active-year');
yearSpans.eq(currentIndex).addClass('active-year');
}
function updateProgressBar() {
const progress = ((currentIndex + 1) / totalSlides) * 100;
progressBarFill.css('width', progress + '%');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
yearSpans.click(function () {
const index = $(this).data('slide');
showSlide(index);
});
// Initialize the first slide, year bar, and progress bar
showSlide(currentIndex);
});
</script>
### Explanation:
1. **CSS Adjustments**:
– Added `.timeline-navigation` class to position the navigation buttons (`Next` and `Previous`) on the right side of the timeline.
– Used `position: absolute` to align buttons vertically at the middle right of the container.
2. **HTML Structure**:
– Placed the navigation buttons inside `.timeline-navigation` div, which is absolutely positioned to the right side.
3. **JavaScript**:
– No changes were required in the JavaScript, as the functionality remains the same.
This will align the "Next" and "Previous" buttons on the right side while maintaining the responsive design and functionality of your timeline slider.
### Updated HTML and CSS:
<style>
.timeline-container {
max-width: 100%;
overflow: hidden;
position: relative;
}
.timeline-slider {
display: flex;
transition: transform 0.5s ease-in-out;
width: 100%;
}
.timeline-slide {
min-width: 100%;
flex-shrink: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.timeline_section {
display: flex;
gap: 24px;
padding: 20px;
width: 100%;
box-sizing: border-box;
}
.timeline_image img {
width: 100%;
max-width: 464px;
height: 464px;
object-fit: cover;
display: block;
}
/* Updated Navigation Buttons */
.timeline-navigation {
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: 10px;
}
.timeline-navigation button {
background-color: #007bff;
color: #fff;
border: none;
padding: 10px;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s;
}
.timeline-navigation button:hover {
background-color: #0056b3;
}
.timeline_year_bar {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
width: 100%;
}
.timeline_year_bar span {
cursor: pointer;
padding: 5px 10px;
position: relative;
z-index: 2;
}
.timeline-progress {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
background-color: #ddd;
width: 100%;
z-index: 1;
}
.timeline-progress-fill {
height: 100%;
background-color: #007bff;
width: 0%;
transition: width 0.5s ease-in-out;
}
.active-year {
font-weight: bold;
color: #007bff;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<!-- Right Side Navigation Buttons -->
<div class="timeline-navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<div class="timeline_year_bar">
<div class="timeline-progress">
<div class="timeline-progress-fill"></div>
</div>
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
const progressBarFill = $('.timeline-progress-fill');
const yearSpans = $('.timeline_year_bar span');
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
updateProgressBar();
}
}
function updateYearBar() {
yearSpans.removeClass('active-year');
yearSpans.eq(currentIndex).addClass('active-year');
}
function updateProgressBar() {
const progress = ((currentIndex + 1) / totalSlides) * 100;
progressBarFill.css('width', progress + '%');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
yearSpans.click(function () {
const index = $(this).data('slide');
showSlide(index);
});
// Initialize the first slide, year bar, and progress bar
showSlide(currentIndex);
});
</script>
### Explanation:
1. **CSS Adjustments**:
– The `.timeline-navigation` class is updated to position the navigation buttons on the right side using `position: absolute`, `top: 50%`, and `right: 20px`.
– Added `transform: translateY(-50%)` to vertically center the buttons.
2. **JavaScript**:
– No changes were needed in the JavaScript as it already handles the slide navigation.
This should correctly position your "Next" and "Previous" buttons on the right side of the timeline, making it easier for users to navigate through your content.
### Updated HTML and CSS:
<style>
.timeline-container {
max-width: 100%;
overflow: hidden;
position: relative;
}
.timeline-slider {
display: flex;
transition: transform 0.5s ease-in-out;
width: 100%;
}
.timeline-slide {
min-width: 100%;
flex-shrink: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.timeline_section {
display: flex;
gap: 24px;
padding: 20px;
width: 100%;
box-sizing: border-box;
}
.timeline_image img {
width: 100%;
max-width: 464px;
height: 464px;
object-fit: cover;
display: block;
}
/* Navigation Buttons */
.timeline-navigation {
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: 10px;
}
.timeline-navigation button {
background-color: #007bff;
color: #fff;
border: none;
padding: 10px;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s;
}
.timeline-navigation button:hover {
background-color: #0056b3;
}
.timeline_year_bar_container {
position: relative;
margin-top: 30px;
width: 100%;
}
.timeline-progress {
position: relative;
height: 4px;
background-color: #ddd;
width: 100%;
z-index: 1;
}
.timeline-progress-fill {
height: 100%;
background-color: #007bff;
width: 0%;
transition: width 0.5s ease-in-out;
}
.timeline_year_bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10px;
padding: 0 10px;
}
.timeline_year_bar span {
cursor: pointer;
padding: 5px;
position: relative;
font-size: 14px;
color: #333;
transition: color 0.3s;
}
.timeline_year_bar span.active-year {
font-weight: bold;
color: #007bff;
}
</style>
<div class="timeline-container">
<div class="timeline-slider">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<div class="timeline-slide">
<div class="timeline_section">
<div class="timeline_content">
<div class="timeline_year">
<h1><?php echo esc_html($timeline['timeline_year']); ?></h1>
</div>
<div class="timeline_title">
<h4><?php echo esc_html($timeline['timeline_title']); ?></h4>
</div>
<div class="timeline_description">
<?php echo wp_kses_post($timeline['timeline_desc']); ?>
</div>
</div>
<div class="timeline_image">
<img src='<?php echo esc_url($timeline['timeline_image']['url']); ?>' class='img-fluid' />
</div>
</div>
</div>
<?php } ?>
</div>
<!-- Right Side Navigation Buttons -->
<div class="timeline-navigation">
<button class="prev-slide">Previous</button>
<button class="next-slide">Next</button>
</div>
<!-- Progress Bar and Years -->
<div class="timeline_year_bar_container">
<div class="timeline-progress">
<div class="timeline-progress-fill"></div>
</div>
<div class="timeline_year_bar">
<?php foreach ($settings['rose_timelines'] as $index => $timeline) { ?>
<span data-slide="<?php echo $index; ?>"><?php echo esc_html($timeline['timeline_year']); ?></span>
<?php } ?>
</div>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let currentIndex = 0;
const slides = $('.timeline-slide');
const totalSlides = slides.length;
const progressBarFill = $('.timeline-progress-fill');
const yearSpans = $('.timeline_year_bar span');
function showSlide(index) {
if (index >= 0 && index < totalSlides) {
$('.timeline-slider').css('transform', 'translateX(' + (-index * 100) + '%)');
currentIndex = index;
updateYearBar();
updateProgressBar();
}
}
function updateYearBar() {
yearSpans.removeClass('active-year');
yearSpans.eq(currentIndex).addClass('active-year');
}
function updateProgressBar() {
const progress = ((currentIndex + 1) / totalSlides) * 100;
progressBarFill.css('width', progress + '%');
}
$('.next-slide').click(function () {
if (currentIndex < totalSlides - 1) {
showSlide(currentIndex + 1);
}
});
$('.prev-slide').click(function () {
if (currentIndex > 0) {
showSlide(currentIndex - 1);
}
});
yearSpans.click(function () {
const index = $(this).data('slide');
showSlide(index);
});
// Initialize the first slide, year bar, and progress bar
showSlide(currentIndex);
});
</script>
### Explanation:
1. **CSS Adjustments**:
– Updated the `.timeline_year_bar_container` to include the progress bar and year labels.
– Positioned the years below the progress bar using `.timeline_year_bar`.
2. **HTML Structure**:
– The progress bar and year labels are now contained within `.timeline_year_bar_container`.
3. **JavaScript**:
– No changes were required in the JavaScript as it dynamically updates the years and progress bar based on the current slide.
This should display the years below the progress bar with a smooth transition effect, and the navigation buttons on the right side.