// Vertical Class
class CtlVertical {
constructor() {
this.prevScrollComplete = true;
this.swiperInitId = new Array();
this.ctlWrapper = jQuery('.cool-timeline-wrapper.ctl-vertical-wrapper');
if (this.ctlWrapper.length > 0) {
this.storyLoop();
}
if (this.ctlWrapper.hasClass('ctl-compact-wrapper')) {
this.compactLayoutInit();
}
}
// Function to delay execution asynchronously
delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// line filling call back function
VrLineFillCallback = async () => {
await this.delay(200);
jQuery('.ctl-vertical-wrapper').each((index, element) => {
const parentWrp = jQuery(element);
this.CtlVrLineFilling(parentWrp);
});
};
// Vertical Line filling
CtlVrLineFilling = (element) => {
const parentWrp = element;
const timelineYear = parentWrp.find('.ctl-year');
const lineFilling = parentWrp.data('line-filling');
const Stories = parentWrp.find('.ctl-story');
let rect = '';
let ctlTop = '';
let height = '';
let centerLine = '';
if (lineFilling && Stories.length > 0) {
const outerDiv = parentWrp.hasClass('compact-wrapper')
? parentWrp.find('.clt-compact-cont')
: parentWrp.find('.ctl-timeline-container');
const outerHeight = outerDiv.outerHeight();
rect = outerDiv[0].getBoundingClientRect();
const shortcodePrview = window.parent.jQuery('#ctl_preview');
if (shortcodePrview.length > 0) {
height = shortcodePrview.height() / 2;
} else {
height = jQuery(window).height() / 2;
}
centerLine = parentWrp.find('.ctl-inner-line');
ctlTop = rect.top < 0 ? Math.abs(rect.top) : -Math.abs(rect.top);
const lineInnerHeight = ctlTop + height;
const centerLineHeight = centerLine.height();
const topScroll = jQuery(window).scrollTop() + height + 10;
centerLine.height(
lineInnerHeight <= outerHeight ? lineInnerHeight : outerHeight
);
timelineYear.each((index, year) => {
const yearPosition = jQuery(year).offset().top;
const yearHeight = jQuery(year).height() / 1.5;
jQuery(year).toggleClass(
'innerViewPort',
topScroll >= yearPosition + yearHeight
);
});
if (!jQuery(Stories[0])?.hasClass('ctl-story-no-icon')) {
Stories.each((index, wrp) => {
const icons = wrp.classList.contains('ctl-story-dot-icon')
? '.ctl-icondot'
: '.ctl-icon';
const iconsSize=jQuery(wrp).find(icons).width();
const iconPosition = (jQuery(wrp).find(icons).offset().top + iconsSize / 2);
jQuery(wrp).toggleClass(
'innerViewPort',
topScroll >= iconPosition
);
});
}
if (
lineInnerHeight >= outerHeight &&
centerLineHeight < outerHeight
) {
centerLine.height(outerHeight);
}
const centerLineElement = parentWrp.find('.center-line');
parentWrp.toggleClass('ctl-start-fill', lineInnerHeight > 0);
centerLineElement.toggleClass(
'BeforeViewPort',
lineInnerHeight > 0
);
centerLineElement.toggleClass(
'AfterViewPort',
lineInnerHeight >= outerHeight
);
parentWrp.toggleClass(
'ctl-end-fill',
lineInnerHeight >= outerHeight
);
}
};
// Year Navigation
ctlYearNavigation = (element) => {
const selector = jQuery(element);
const navBarEnable = selector.data('nav');
const wrpId = selector[0].id;
const postId = Number(wrpId.replace(/\D/g, ''));
const yearEntry = selector.find('.scrollable-section');
if (yearEntry.length > 0 && navBarEnable === 'show') {
if (!selector.find('.ctl-navigation-bar').length) {
const navPosition = selector.data('nav-pos');
const navBar = ``;
jQuery(navBar).prependTo(`#${wrpId}`);
const listAll = jQuery(
'
'
);
selector.find('.ctl-navigation-bar').append(listAll);
}
const navigationBar = selector.find('.ctl-navigation-bar');
navigationBar.addClass('ctl-out-viewport');
const navigator = selector.find('.ctl-year-container');
navigator.each((i, labelWrp) => {
this.CtlNavLiElement(i, wrpId, labelWrp);
});
this.yearNavHandleScroll({ data: selector });
jQuery(window).on('scroll', selector, this.yearNavHandleScroll);
this.ctlYearScrollAnimation();
}
};
// Year Navigation Scroll Handler
yearNavHandleScroll = async (event) => {
const selector = event.data;
const TimelineStories = selector.find('.ctl-story');
const compact = selector.hasClass('ctl-compact-wrapper');
const laststory = TimelineStories[TimelineStories.length - 1];
const rootElement = document.documentElement;
const viewport = jQuery(window).height() / 3;
const timelineWrapperPosition = selector.offset().top;
const laststoryDiv = jQuery(laststory);
const navigationBar = selector.find('.ctl-navigation-bar');
const mainNavLinks = navigationBar.find('ul li a');
let previousEl = null;
if (laststoryDiv.length > 0) {
const timelineBottom = laststoryDiv.offset().top +
laststoryDiv.height() -
rootElement.scrollTop;
const timelineTop = timelineWrapperPosition - rootElement.scrollTop;
navigationBar.toggleClass(
'ctl-in-viewport',
timelineTop < viewport
);
navigationBar.toggleClass(
'ctl-out-viewport',
timelineTop >= viewport || timelineBottom < viewport
);
const extraspace = compact ? 70 : 400;
const fromTop = window.scrollY + extraspace;
mainNavLinks.each(function () {
const hash = this.hash;
if (!jQuery(hash).length) {
return false;
}
const section = jQuery(hash).offset().top;
if (section <= fromTop) {
if (previousEl !== null) {
previousEl
.removeClass('current')
.parent()
.removeClass('current');
}
jQuery(this)
.addClass('current')
.parent()
.addClass('current');
}
if (section >= fromTop) {
jQuery(this)
.removeClass('current')
.parent()
.removeClass('current');
}
previousEl = jQuery(this);
});
}
};
// Creat Nav Elements
CtlNavLiElement = (index, wrpId, labelWrp) => {
const postId = Number(wrpId.replace(/\D/g, ''));
const YeraLabel = jQuery(labelWrp).data('section-title');
const uniqueID = `${postId}-${YeraLabel}`;
const scrollbarID = `ctl-scrollar-${uniqueID}`;
jQuery(labelWrp).attr('id', scrollbarID);
const listEl = jQuery(
`${YeraLabel}`
);
if (index === 0) {
listEl.addClass('current');
}
const ulList = jQuery(`#ctl-navigation-bar-${postId}`).find('ul');
ulList.append(listEl);
};
// Year Navigation Scroll Animation
ctlYearScrollAnimation = () => {
jQuery(document).on(
'click',
'.ctl-vertical-wrapper .ctl-navigation-bar ul li',
(e) => {
if (this.prevScrollComplete) {
this.prevScrollComplete = false;
e.preventDefault();
const targetElement = jQuery(e.currentTarget)
.find('a')
.attr('href');
if (targetElement.length) {
const targetTopPosition =
jQuery(targetElement).offset().top - 40;
jQuery('html, body').animate(
{
scrollTop: targetTopPosition,
},
500,
() => {
this.prevScrollComplete = true;
}
);
}
}
}
);
};
// Aos animation
CtlStoryAos = (wrapperId) => {
// enabled animation on page scroll
const parentWrp = jQuery(`#${wrapperId}`);
const timelineContainer = parentWrp.find('.ctl-timeline-container');
const animation = timelineContainer.attr('data-animation');
let prevHeight = jQuery(`#${wrapperId}`).height();
const parentWrpAosCls =
!parentWrp.hasClass('ctl-compact-wrapper') &&
parentWrp.hasClass('ctl-design-6');
// addded empty data aos attribute on element for before init the AOS
if (animation !== 'none') {
timelineContainer.find('.ctl-story').each((index, story) => {
if (parentWrpAosCls) {
story.dataset.aos = '';
} else {
jQuery(story)
.find(
'.ctl-icon, .ctl-content, .ctl-labels, .ctl-icondot'
)
.each((_index, element) => {
element.dataset.aos = '';
});
}
});
// You can also pass an optional settings object
// below listed default settings
// init aos animation
AOS.init({
// Global settings:
disable: 'mobile',
startEvent: 'DOMContentLoaded',
offset: 75,
delay: 0,
duration: 750,
easing: 'ease-in-out-sine',
mirror: true,
});
// Added animation value in aos attribute on element
timelineContainer.find('.ctl-story').each((index, story) => {
// story.dataset.aos = animation;
if (parentWrpAosCls) {
story.dataset.aos = animation;
} else {
jQuery(story)
.find(
'.ctl-icon, .ctl-content, .ctl-labels, .ctl-icondot'
)
.each((_index, element) => {
element.dataset.aos = animation;
});
}
});
setTimeout(() => {
AOS.refresh();
}, 500);
}
jQuery(window).scroll(() => {
const currentHeight = jQuery(`#${wrapperId}`).height();
if (prevHeight !== currentHeight) {
setTimeout(function () {
AOS.refresh();
}, 500);
prevHeight = currentHeight;
}
});
};
// Compact layout initialize function
ctlCompactMasonry = (grids, animation, reloadItems) => {
let grid = '';
let leftReminder = 0;
let rightReminder = 0;
if (reloadItems) {
grid = grids.masonry('reloadItems');
} else {
grid = grids.masonry({
itemSelector: '.ctl-story',
initLayout: false,
});
}
// layout images after they are loaded
grid.imagesLoaded().progress(() => {
grid.masonry('layout');
});
grid.one('layoutComplete', () => {
let leftPos = 0;
let topPosDiff;
grid.find('.ctl-story').each((index, element) => {
leftPos = jQuery(element).position().left;
if (leftPos <= 0) {
const extraCls = (leftReminder % 2) === 0 ? 'ctl-left-odd' : 'ctl-left-even';
const prevCls = extraCls === 'ctl-left-odd' ? 'ctl-left-even' : 'ctl-left-odd';
jQuery(element)
.removeClass('ctl-story-right')
.removeClass('ctl-right-even')
.removeClass('ctl-right-odd')
.removeClass(prevCls)
.addClass('ctl-story-left')
.addClass(extraCls);
leftReminder++;
} else {
const extraCls = (rightReminder % 2) === 0 ? 'ctl-right-odd' : 'ctl-right-even';
const prevCls = extraCls === 'ctl-right-odd' ? 'ctl-right-even' : 'ctl-right-odd';
jQuery(element)
.removeClass('ctl-story-left')
.removeClass('ctl-left-odd')
.removeClass('ctl-left-even')
.removeClass(prevCls)
.addClass('ctl-story-right')
.addClass(extraCls);
rightReminder++;
}
topPosDiff =
jQuery(element).position().top -
jQuery(element).prev().position().top;
if (topPosDiff < 40) {
jQuery(element)
.removeClass('ctl-compact-up')
.addClass('ctl-compact-down');
jQuery(element)
.prev()
.removeClass('ctl-compact-down')
.addClass('ctl-compact-up');
}
});
jQuery('.ctl-icon').addClass('showit');
jQuery('.ctl-title').addClass('showit-after');
if (animation !== 'none') {
AOS.refreshHard();
}
});
};
// Static Svg Icons
CtlStaticSvgIcons = (icon) => {
const iconsArr = {
chevronLeft: ``,
chevronRight: ``
};
const data = undefined !== iconsArr[icon] ? iconsArr[icon] : '';
return data;
};
// Each timeline loop
storyLoop = () => {
this.ctlWrapper.each((index, element) => {
const container = jQuery(element).find(
'.ctl-timeline-container'
);
const totalStory = container.find('.ctl-story').length;
const parentWrp = jQuery(element);
const timelineContainer = parentWrp.find('.ctl-timeline-container')[0];
const animation = jQuery(timelineContainer).attr('data-animation');
// eslint-disable-next-line no-unused-expressions
totalStory === 0 &&
jQuery(element).addClass('ctl-content-empty');
if (animation !== 'none' && animation !== undefined) {
this.CtlStoryAos(parentWrp[0].id, animation);
}
// Line filling run after page load
this.CtlVrLineFilling(parentWrp);
// Line filling update after page scroll
jQuery(window).on('scroll', parentWrp, (el) => {
this.CtlVrLineFilling(el.data);
const mediaSlides = jQuery(parentWrp).find('.ctl-story .ctp-story-slider.swiper-initialized');
mediaSlides.each((index, element) => {
const swiper = element.swiper;
const id = swiper.slidesEl.id;
if (!this.swiperInitId.includes(id)) {
this.swiperInitId.push(id);
swiper.on('slideChange', () => {
this.VrLineFillCallback();
});
}
});;
});
this.ctlYearNavigation(element);
});
};
// Compact Layout call
compactLayoutInit() {
const initializeCompactMasonry = () => {
const wrapper = jQuery(
'.ctl-compact-wrapper .ctl-timeline-container'
);
const animation = wrapper.data('animation');
this.ctlCompactMasonry(wrapper, animation);
}
jQuery(document).ready(initializeCompactMasonry);
jQuery(window).on('load', function () {
setTimeout(initializeCompactMasonry, 200);
});
jQuery(window).on('resize', initializeCompactMasonry);
}
}
(function () {
new CtlVertical();
})(jQuery);