init
This commit is contained in:
294
public/frontend/m_weben/js/main.js
Executable file
294
public/frontend/m_weben/js/main.js
Executable file
@@ -0,0 +1,294 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
var timelines = $('.cd-horizontal-timeline'),
|
||||
eventsMinDistance = 60
|
||||
|
||||
timelines.length > 0 && initTimeline(timelines)
|
||||
|
||||
function initTimeline(timelines) {
|
||||
timelines.each(function () {
|
||||
var timeline = $(this),
|
||||
timelineComponents = {}
|
||||
//cache timeline components
|
||||
timelineComponents['timelineWrapper'] = timeline.find('.events-wrapper')
|
||||
timelineComponents['eventsWrapper'] = timelineComponents['timelineWrapper'].children('.events')
|
||||
timelineComponents['fillingLine'] = timelineComponents['eventsWrapper'].children('.filling-line')
|
||||
timelineComponents['timelineEvents'] = timelineComponents['eventsWrapper'].find('a')
|
||||
timelineComponents['timelineDates'] = parseDate(timelineComponents['timelineEvents'])
|
||||
timelineComponents['eventsMinLapse'] = minLapse(timelineComponents['timelineDates'])
|
||||
timelineComponents['timelineNavigation'] = timeline.find('.cd-timeline-navigation')
|
||||
timelineComponents['eventsContent'] = timeline.children('.events-content')
|
||||
|
||||
//assign a left postion to the single events along the timeline
|
||||
setDatePosition(timelineComponents, eventsMinDistance)
|
||||
//assign a width to the timeline
|
||||
var timelineTotWidth = setTimelineWidth(timelineComponents, eventsMinDistance)
|
||||
//the timeline has been initialize - show it
|
||||
timeline.addClass('loaded')
|
||||
|
||||
//detect click on the next arrow
|
||||
timelineComponents['timelineNavigation'].on('click', '.next', function (event) {
|
||||
event.preventDefault()
|
||||
updateSlide(timelineComponents, timelineTotWidth, 'next')
|
||||
})
|
||||
//detect click on the prev arrow
|
||||
timelineComponents['timelineNavigation'].on('click', '.prev', function (event) {
|
||||
event.preventDefault()
|
||||
updateSlide(timelineComponents, timelineTotWidth, 'prev')
|
||||
})
|
||||
//detect click on the a single event - show new event content
|
||||
timelineComponents['eventsWrapper'].on('click', 'a', function (event) {
|
||||
event.preventDefault()
|
||||
timelineComponents['timelineEvents'].removeClass('selected')
|
||||
$(this).addClass('selected')
|
||||
updateOlderEvents($(this))
|
||||
updateFilling($(this), timelineComponents['fillingLine'], timelineTotWidth)
|
||||
updateVisibleContent($(this), timelineComponents['eventsContent'])
|
||||
})
|
||||
|
||||
//on swipe, show next/prev event content
|
||||
timelineComponents['eventsContent'].on('swipeleft', function () {
|
||||
var mq = checkMQ()
|
||||
mq == 'mobile' && showNewContent(timelineComponents, timelineTotWidth, 'next')
|
||||
})
|
||||
timelineComponents['eventsContent'].on('swiperight', function () {
|
||||
var mq = checkMQ()
|
||||
mq == 'mobile' && showNewContent(timelineComponents, timelineTotWidth, 'prev')
|
||||
})
|
||||
|
||||
//keyboard navigation
|
||||
$(document).keyup(function (event) {
|
||||
if (event.which == '37' && elementInViewport(timeline.get(0))) {
|
||||
showNewContent(timelineComponents, timelineTotWidth, 'prev')
|
||||
} else if (event.which == '39' && elementInViewport(timeline.get(0))) {
|
||||
showNewContent(timelineComponents, timelineTotWidth, 'next')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function updateSlide(timelineComponents, timelineTotWidth, string) {
|
||||
//retrieve translateX value of timelineComponents['eventsWrapper']
|
||||
var translateValue = getTranslateValue(timelineComponents['eventsWrapper']),
|
||||
wrapperWidth = Number(timelineComponents['timelineWrapper'].css('width').replace('px', ''))
|
||||
//translate the timeline to the left('next')/right('prev')
|
||||
string == 'next'
|
||||
? translateTimeline(timelineComponents, translateValue - wrapperWidth + eventsMinDistance, wrapperWidth - timelineTotWidth)
|
||||
: translateTimeline(timelineComponents, translateValue + wrapperWidth - eventsMinDistance)
|
||||
}
|
||||
|
||||
function showNewContent(timelineComponents, timelineTotWidth, string) {
|
||||
//go from one event to the next/previous one
|
||||
var visibleContent = timelineComponents['eventsContent'].find('.selected'),
|
||||
newContent = string == 'next' ? visibleContent.next() : visibleContent.prev()
|
||||
|
||||
if (newContent.length > 0) {
|
||||
//if there's a next/prev event - show it
|
||||
var selectedDate = timelineComponents['eventsWrapper'].find('.selected'),
|
||||
newEvent =
|
||||
string == 'next' ? selectedDate.parent('li').next('li').children('a') : selectedDate.parent('li').prev('li').children('a')
|
||||
|
||||
updateFilling(newEvent, timelineComponents['fillingLine'], timelineTotWidth)
|
||||
updateVisibleContent(newEvent, timelineComponents['eventsContent'])
|
||||
newEvent.addClass('selected')
|
||||
selectedDate.removeClass('selected')
|
||||
updateOlderEvents(newEvent)
|
||||
updateTimelinePosition(string, newEvent, timelineComponents)
|
||||
}
|
||||
}
|
||||
|
||||
function updateTimelinePosition(string, event, timelineComponents) {
|
||||
//translate timeline to the left/right according to the position of the selected event
|
||||
var eventStyle = window.getComputedStyle(event.get(0), null),
|
||||
eventLeft = Number(eventStyle.getPropertyValue('left').replace('px', '')),
|
||||
timelineWidth = Number(timelineComponents['timelineWrapper'].css('width').replace('px', '')),
|
||||
timelineTotWidth = Number(timelineComponents['eventsWrapper'].css('width').replace('px', ''))
|
||||
var timelineTranslate = getTranslateValue(timelineComponents['eventsWrapper'])
|
||||
|
||||
if ((string == 'next' && eventLeft > timelineWidth - timelineTranslate) || (string == 'prev' && eventLeft < -timelineTranslate)) {
|
||||
translateTimeline(timelineComponents, -eventLeft + timelineWidth / 2, timelineWidth - timelineTotWidth)
|
||||
}
|
||||
}
|
||||
|
||||
function translateTimeline(timelineComponents, value, totWidth) {
|
||||
var eventsWrapper = timelineComponents['eventsWrapper'].get(0)
|
||||
value = value > 0 ? 0 : value //only negative translate value
|
||||
value = !(typeof totWidth === 'undefined') && value < totWidth ? totWidth : value //do not translate more than timeline width
|
||||
setTransformValue(eventsWrapper, 'translateX', value + 'px')
|
||||
//update navigation arrows visibility
|
||||
value == 0
|
||||
? timelineComponents['timelineNavigation'].find('.prev').addClass('inactive')
|
||||
: timelineComponents['timelineNavigation'].find('.prev').removeClass('inactive')
|
||||
value == totWidth
|
||||
? timelineComponents['timelineNavigation'].find('.next').addClass('inactive')
|
||||
: timelineComponents['timelineNavigation'].find('.next').removeClass('inactive')
|
||||
}
|
||||
|
||||
function updateFilling(selectedEvent, filling, totWidth) {
|
||||
//change .filling-line length according to the selected event
|
||||
var eventStyle = window.getComputedStyle(selectedEvent.get(0), null),
|
||||
eventLeft = eventStyle.getPropertyValue('left'),
|
||||
eventWidth = eventStyle.getPropertyValue('width')
|
||||
eventLeft = Number(eventLeft.replace('px', '')) + Number(eventWidth.replace('px', '')) / 2
|
||||
var scaleValue = eventLeft / totWidth
|
||||
setTransformValue(filling.get(0), 'scaleX', scaleValue)
|
||||
}
|
||||
|
||||
function setDatePosition(timelineComponents, min) {
|
||||
for (i = 0; i < timelineComponents['timelineDates'].length; i++) {
|
||||
var distance = daydiff(timelineComponents['timelineDates'][0], timelineComponents['timelineDates'][i]),
|
||||
distanceNorm = Math.round(distance / timelineComponents['eventsMinLapse']) + 2
|
||||
timelineComponents['timelineEvents'].eq(i).css('left', distanceNorm * min + 'px')
|
||||
}
|
||||
}
|
||||
|
||||
function setTimelineWidth(timelineComponents, width) {
|
||||
var timeSpan = daydiff(
|
||||
timelineComponents['timelineDates'][0],
|
||||
timelineComponents['timelineDates'][timelineComponents['timelineDates'].length - 1]
|
||||
),
|
||||
timeSpanNorm = timeSpan / timelineComponents['eventsMinLapse'],
|
||||
timeSpanNorm = Math.round(timeSpanNorm) + 4,
|
||||
totalWidth = timeSpanNorm * width
|
||||
timelineComponents['eventsWrapper'].css('width', totalWidth + 'px')
|
||||
updateFilling(timelineComponents['eventsWrapper'].find('a.selected'), timelineComponents['fillingLine'], totalWidth)
|
||||
updateTimelinePosition('next', timelineComponents['eventsWrapper'].find('a.selected'), timelineComponents)
|
||||
|
||||
return totalWidth
|
||||
}
|
||||
|
||||
function updateVisibleContent(event, eventsContent) {
|
||||
var eventDate = event.data('date'),
|
||||
visibleContent = eventsContent.find('.selected'),
|
||||
selectedContent = eventsContent.find('[data-date="' + eventDate + '"]'),
|
||||
selectedContentHeight = selectedContent.height()
|
||||
|
||||
if (selectedContent.index() > visibleContent.index()) {
|
||||
var classEnetering = 'selected enter-right',
|
||||
classLeaving = 'leave-left'
|
||||
} else {
|
||||
var classEnetering = 'selected enter-left',
|
||||
classLeaving = 'leave-right'
|
||||
}
|
||||
|
||||
selectedContent.attr('class', classEnetering)
|
||||
visibleContent.attr('class', classLeaving).one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function () {
|
||||
visibleContent.removeClass('leave-right leave-left')
|
||||
selectedContent.removeClass('enter-left enter-right')
|
||||
})
|
||||
eventsContent.css('height', selectedContentHeight + 'px')
|
||||
}
|
||||
|
||||
function updateOlderEvents(event) {
|
||||
event
|
||||
.parent('li')
|
||||
.prevAll('li')
|
||||
.children('a')
|
||||
.addClass('older-event')
|
||||
.end()
|
||||
.end()
|
||||
.nextAll('li')
|
||||
.children('a')
|
||||
.removeClass('older-event')
|
||||
}
|
||||
|
||||
function getTranslateValue(timeline) {
|
||||
var timelineStyle = window.getComputedStyle(timeline.get(0), null),
|
||||
timelineTranslate =
|
||||
timelineStyle.getPropertyValue('-webkit-transform') ||
|
||||
timelineStyle.getPropertyValue('-moz-transform') ||
|
||||
timelineStyle.getPropertyValue('-ms-transform') ||
|
||||
timelineStyle.getPropertyValue('-o-transform') ||
|
||||
timelineStyle.getPropertyValue('transform')
|
||||
|
||||
if (timelineTranslate.indexOf('(') >= 0) {
|
||||
var timelineTranslate = timelineTranslate.split('(')[1]
|
||||
timelineTranslate = timelineTranslate.split(')')[0]
|
||||
timelineTranslate = timelineTranslate.split(',')
|
||||
var translateValue = timelineTranslate[4]
|
||||
} else {
|
||||
var translateValue = 0
|
||||
}
|
||||
|
||||
return Number(translateValue)
|
||||
}
|
||||
|
||||
function setTransformValue(element, property, value) {
|
||||
element.style['-webkit-transform'] = property + '(' + value + ')'
|
||||
element.style['-moz-transform'] = property + '(' + value + ')'
|
||||
element.style['-ms-transform'] = property + '(' + value + ')'
|
||||
element.style['-o-transform'] = property + '(' + value + ')'
|
||||
element.style['transform'] = property + '(' + value + ')'
|
||||
}
|
||||
|
||||
//based on http://stackoverflow.com/questions/542938/how-do-i-get-the-number-of-days-between-two-dates-in-javascript
|
||||
function parseDate(events) {
|
||||
var dateArrays = []
|
||||
events.each(function () {
|
||||
var singleDate = $(this),
|
||||
dateComp = singleDate.data('date').split('T')
|
||||
if (dateComp.length > 1) {
|
||||
//both DD/MM/YEAR and time are provided
|
||||
var dayComp = dateComp[0].split('/'),
|
||||
timeComp = dateComp[1].split(':')
|
||||
} else if (dateComp[0].indexOf(':') >= 0) {
|
||||
//only time is provide
|
||||
var dayComp = ['2000', '0', '0'],
|
||||
timeComp = dateComp[0].split(':')
|
||||
} else {
|
||||
//only DD/MM/YEAR
|
||||
var dayComp = dateComp[0].split('/'),
|
||||
timeComp = ['0', '0']
|
||||
}
|
||||
var newDate = new Date(dayComp[2], dayComp[1] - 1, dayComp[0], timeComp[0], timeComp[1])
|
||||
dateArrays.push(newDate)
|
||||
})
|
||||
return dateArrays
|
||||
}
|
||||
|
||||
function daydiff(first, second) {
|
||||
return Math.round(second - first)
|
||||
}
|
||||
|
||||
function minLapse(dates) {
|
||||
//determine the minimum distance among events
|
||||
var dateDistances = []
|
||||
for (i = 1; i < dates.length; i++) {
|
||||
var distance = daydiff(dates[i - 1], dates[i])
|
||||
dateDistances.push(distance)
|
||||
}
|
||||
return Math.min.apply(null, dateDistances)
|
||||
}
|
||||
|
||||
/*
|
||||
How to tell if a DOM element is visible in the current viewport?
|
||||
http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
|
||||
*/
|
||||
function elementInViewport(el) {
|
||||
var top = el.offsetTop
|
||||
var left = el.offsetLeft
|
||||
var width = el.offsetWidth
|
||||
var height = el.offsetHeight
|
||||
|
||||
while (el.offsetParent) {
|
||||
el = el.offsetParent
|
||||
top += el.offsetTop
|
||||
left += el.offsetLeft
|
||||
}
|
||||
|
||||
return (
|
||||
top < window.pageYOffset + window.innerHeight &&
|
||||
left < window.pageXOffset + window.innerWidth &&
|
||||
top + height > window.pageYOffset &&
|
||||
left + width > window.pageXOffset
|
||||
)
|
||||
}
|
||||
|
||||
function checkMQ() {
|
||||
//check if mobile or desktop device
|
||||
return window
|
||||
.getComputedStyle(document.querySelector('.cd-horizontal-timeline'), '::before')
|
||||
.getPropertyValue('content')
|
||||
.replace(/'/g, '')
|
||||
.replace(/"/g, '')
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user