1/*jQuery(document).ready(function ($) { 2 3 4 (timelines.length > 0) && initTimeline(timelines); 5 6});*/ 7 8 9 eventsMinDistance = 300; 10 11 function initTimeline(timelines) { 12 timelines.each(function () { 13 var timeline = $(this), 14 timelineComponents = {}; 15 //cache timeline components 16 timelineComponents['timelineWrapper'] = timeline.find('.events-wrapper'); 17 timelineComponents['eventsWrapper'] = timelineComponents['timelineWrapper'].children('.events'); 18 timelineComponents['fillingLine'] = timelineComponents['eventsWrapper'].children('.filling-line'); 19 timelineComponents['timelineEvents'] = timelineComponents['eventsWrapper'].find('a'); 20 timelineComponents['timelineDates'] = parseDate(timelineComponents['timelineEvents']); 21 timelineComponents['eventsMinLapse'] = minLapse(timelineComponents['timelineDates']); 22 timelineComponents['timelineNavigation'] = timeline.find('.cd-timeline-navigation'); 23 timelineComponents['eventsContent'] = timeline.children('.events-content'); 24 25 //assign a left postion to the single events along the timeline 26 setDatePosition(timelineComponents, eventsMinDistance); 27 //assign a width to the timeline 28 var timelineTotWidth = setTimelineWidth(timelineComponents, eventsMinDistance); 29 //the timeline has been initialize - show it 30 timeline.addClass('loaded'); 31 32 //detect click on the next arrow 33 timelineComponents['timelineNavigation'].on('click', '.next', function (event) { 34 event.preventDefault(); 35 updateSlide(timelineComponents, timelineTotWidth, 'next'); 36 }); 37 //detect click on the prev arrow 38 timelineComponents['timelineNavigation'].on('click', '.prev', function (event) { 39 event.preventDefault(); 40 updateSlide(timelineComponents, timelineTotWidth, 'prev'); 41 }); 42 //detect click on the a single event - show new event content 43 timelineComponents['eventsWrapper'].on('click', 'a', function (event) { 44 //event.preventDefault(); 45 timelineComponents['timelineEvents'].removeClass('selected'); 46 $(this).addClass('selected'); 47 updateOlderEvents($(this)); 48 updateFilling($(this), timelineComponents['fillingLine'], timelineTotWidth); 49 updateVisibleContent($(this), timelineComponents['eventsContent']); 50 }); 51 52 //on swipe, show next/prev event content 53 timelineComponents['eventsContent'].on('swipeleft', function () { 54 var mq = checkMQ(); 55 (mq == 'mobile') && showNewContent(timelineComponents, timelineTotWidth, 'next'); 56 }); 57 timelineComponents['eventsContent'].on('swiperight', function () { 58 var mq = checkMQ(); 59 (mq == 'mobile') && showNewContent(timelineComponents, timelineTotWidth, 'prev'); 60 }); 61 62 //keyboard navigation 63 $(document).keyup(function (event) { 64 if (event.which == '37' && elementInViewport(timeline.get(0))) { 65 showNewContent(timelineComponents, timelineTotWidth, 'prev'); 66 } else if (event.which == '39' && elementInViewport(timeline.get(0))) { 67 showNewContent(timelineComponents, timelineTotWidth, 'next'); 68 } 69 }); 70 }); 71 } 72 73 function updateSlide(timelineComponents, timelineTotWidth, string) { 74 //retrieve translateX value of timelineComponents['eventsWrapper'] 75 var translateValue = getTranslateValue(timelineComponents['eventsWrapper']), 76 wrapperWidth = Number(timelineComponents['timelineWrapper'].css('width').replace('px', '')); 77 //translate the timeline to the left('next')/right('prev') 78 (string == 'next') 79 ? translateTimeline(timelineComponents, translateValue - wrapperW
79idth + eventsMinDistance, wrapperWidth - timelineTotWidth) 80 : translateTimeline(timelineComponents, translateValue + wrapperWidth - eventsMinDistance); 81 } 82 83 function showNewContent(timelineComponents, timelineTotWidth, string) { 84 //go from one event to the next/previous one 85 var visibleContent = timelineComponents['eventsContent'].find('.selected'), 86 newContent = (string == 'next') ? visibleContent.next() : visibleContent.prev(); 87 88 if (newContent.length > 0) { //if there's a next/prev event - show it 89 var selectedDate = timelineComponents['eventsWrapper'].find('.selected'), 90 newEvent = (string == 'next') ? selectedDate.parent('li').next('li').children('a') : selectedDate.parent('li').prev('li').children('a'); 91 92 updateFilling(newEvent, timelineComponents['fillingLine'], timelineTotWidth); 93 updateVisibleContent(newEvent, timelineComponents['eventsContent']); 94 newEvent.addClass('selected'); 95 selectedDate.removeClass('selected'); 96 updateOlderEvents(newEvent); 97 updateTimelinePosition(string, newEvent, timelineComponents); 98 } 99 } 100 101 function updateTimelinePosition(string, event, timelineComponents) { 102 //translate timeline to the left/right according to the position of the selected event 103 var eventStyle = window.getComputedStyle(event.get(0), null), 104 eventLeft = Number(eventStyle.getPropertyValue("left").replace('px', '')), 105 timelineWidth = Number(timelineComponents['timelineWrapper'].css('width').replace('px', '')), 106 timelineTotWidth = Number(timelineComponents['eventsWrapper'].css('width').replace('px', '')); 107 var timelineTranslate = getTranslateValue(timelineComponents['eventsWrapper']); 108 109 if ((string == 'next' && eventLeft > timelineWidth - timelineTranslate) || (string == 'prev' && eventLeft < -timelineTranslate)) { 110 translateTimeline(timelineComponents, -eventLeft + timelineWidth / 2, timelineWidth - timelineTotWidth); 111 } 112 } 113 114 function translateTimeline(timelineComponents, value, totWidth) { 115 var eventsWrapper = timelineComponents['eventsWrapper'].get(0); 116 value = (value > 0) ? 0 : value; //only negative translate value 117 value = (!(typeof totWidth === 'undefined') && value < totWidth) ? totWidth : value; //do not translate more than timeline width 118 setTransformValue(eventsWrapper, 'translateX', value + 'px'); 119 //update navigation arrows visibility 120 (value == 0) ? timelineComponents['timelineNavigation'].find('.prev').addClass('inactive') : timelineComponents['timelineNavigation'].find('.prev').removeClass('inactive'); 121 (value == totWidth) ? timelineComponents['timelineNavigation'].find('.next').addClass('inactive') : timelineComponents['timelineNavigation'].find('.next').removeClass('inactive'); 122 } 123 124 function updateFilling(selectedEvent, filling, totWidth) { 125 //change .filling-line length according to the selected event 126 var eventStyle = window.getComputedStyle(selectedEvent.get(0), null), 127 eventLeft = eventStyle.getPropertyValue("left"), 128 eventWidth = eventStyle.getPropertyValue("width"); 129 eventLeft = Number(eventLeft.replace('px', '')) + Number(eventWidth.replace('px', '')) / 2; 130 var scaleValue = eventLeft / totWidth; 131 setTransformValue(filling.get(0), 'scaleX', scaleValue); 132 } 133 134 function setDatePosition(timelineComponents, min) { 135 for (i = 0; i < timelineComponents['timelineDates'].length; i++) { 136 var distance = daydiff(timelineComponents['timelineDates'][0], timelineComponents['timelineDates'][i]), 137 distanceNorm = Math.round(distance / timelineComponents['eventsMinLapse']) + 0.5; 138 timelineComponents['timelineEvents'].eq(i).css('left', distanceNorm * min + 'px'); 139 } 140 } 141 142 function setTimelineWidth(timelineComponents, width) { 143 var timeSpan = daydiff(timelineComponents['timelineDates'][0], timelineComponents['timelineDates'][timelineComponents['timelineDates'].length - 1]), 144 timeSpanNorm = timeSpan / timelineComponents['eventsMinLapse'], 145 timeSpanNorm = Math.round(timeSpanNorm) + 4, 146 totalWidth = timeSpanNorm * width; 147 timelineComponents['eventsWrapper'].css('width', totalWidth + 'px'); 148 updateFilling(timelineComponents['eventsWrapper'].find('a.selected'), timelineComponents['fillingLine'], totalWidth);
149 updateTimelinePosition('next', timelineComponents['eventsWrapper'].find('a.selected'), timelineComponents); 150 151 return totalWidth; 152 } 153 154 function updateVisibleContent(event, eventsContent) { 155 var eventDate = event.data('date'), 156 visibleContent = eventsContent.find('.selected'), 157 selectedContent = eventsContent.find('[data-date="' + eventDate + '"]'), 158 selectedContentHeight = selectedContent.height(); 159 160 if (selectedContent.index() > visibleContent.index()) { 161 var classEnetering = 'selected enter-right', 162 classLeaving = 'leave-left'; 163 } else { 164 var classEnetering = 'selected enter-left', 165 classLeaving = 'leave-right'; 166 } 167 168 selectedContent.attr('class', classEnetering); 169 visibleContent.attr('class', classLeaving).one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function () { 170 visibleContent.removeClass('leave-right leave-left'); 171 selectedContent.removeClass('enter-left enter-right'); 172 }); 173 eventsContent.css('height', selectedContentHeight + 'px'); 174 } 175 176 function updateOlderEvents(event) { 177 event.parent('li').prevAll('li').children('a').addClass('older-event').end().end().nextAll('li').children('a').removeClass('older-event'); 178 } 179 180 function getTranslateValue(timeline) { 181 var timelineStyle = window.getComputedStyle(timeline.get(0), null), 182 timelineTranslate = timelineStyle.getPropertyValue("-webkit-transform") || 183 timelineStyle.getPropertyValue("-moz-transform") || 184 timelineStyle.getPropertyValue("-ms-transform") || 185 timelineStyle.getPropertyValue("-o-transform") || 186 timelineStyle.getPropertyValue("transform"); 187 188 if (timelineTranslate.indexOf('(') >= 0) { 189 var timelineTranslate = timelineTranslate.split('(')[1]; 190 timelineTranslate = timelineTranslate.split(')')[0]; 191 timelineTranslate = timelineTranslate.split(','); 192 var translateValue = timelineTranslate[4]; 193 } else { 194 var translateValue = 0; 195 } 196 197 return Number(translateValue); 198 } 199 200 function setTransformValue(element, property, value) { 201 element.style["-webkit-transform"] = property + "(" + value + ")"; 202 element.style["-moz-transform"] = property + "(" + value + ")"; 203 element.style["-ms-transform"] = property + "(" + value + ")"; 204 element.style["-o-transform"] = property + "(" + value + ")"; 205 element.style["transform"] = property + "(" + value + ")"; 206 } 207 208 //based on http://stackoverflow.com/questions/542938/how-do-i-get-the-number-of-days-between-two-dates-in-javascript 209 function parseDate(events) { 210 var dateArrays = []; 211 events.each(function () { 212 var singleDate = $(this), 213 dateComp = singleDate.data('date').split('T'); 214 if (dateComp.length > 1) { //both DD/MM/YEAR and time are provided 215 var dayComp = dateComp[0].split('/'), 216 timeComp = dateComp[1].split(':'); 217 } else if (dateComp[0].indexOf(':') >= 0) { //only time is provide 218 var dayComp = ["2000", "0", "0"], 219 timeComp = dateComp[0].split(':'); 220 } else { //only DD/MM/YEAR 221 var dayComp = dateComp[0].split('/'), 222 timeComp = ["0", "0"]; 223 } 224 var newDate = new Date(dayComp[2], dayComp[1] - 1, dayComp[0], timeComp[0], timeComp[1]); 225 dateArrays.push(newDate); 226 }); 227 return dateArrays; 228 } 229 230 function daydiff(first, second) { 231 return Math.round((second - first)); 232 } 233 234 function minLapse(dates) { 235 //determine the minimum distance among events 236 var dateDistances = []; 237 for (i = 1; i < dates.length; i++) { 238 var distance = daydiff(dates[i - 1], dates[i]); 239 dateDistances.push(distance); 240 } 241 return Math.min.apply(null, dateDistances); 242 } 243 244 /* 245 How to tell if a DOM element is visible in the current viewport? 246 http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport 247 */ 248 function elementInViewport(el) { 249 var top = el.offsetTop; 250 var left = el.offsetLeft; 251 var width = el.offsetWidth; 252 var height = el.offsetHeight; 253 254 while (el.offsetParent) { 255 el = el.offsetParent; 256 top += el.offsetTop; 257 left += el.offsetLeft; 258 } 259 260 return ( 261 top < (window.pageYOffset + window.innerHeight) && 262 left < (window.pageXOffset + window.innerWidth) && 263 (top + height) > window.pageYOffset && 264 (left + width) > window.pageXOffset 265 ); 266 } 267 268 function checkMQ() { 269 //check if mobile or desktop device 270 return window.getComputedStyle(document.querySelector('.cd-horizontal-timeline'), '::before').getPropertyValue('content').replace(/'/g, "").replace(/"/g, ""); 271 }
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.