diff --git a/JavaScript/horizontal_timeline.2.0.js b/JavaScript/horizontal_timeline.2.0.js index 707e49d..fe2829d 100644 --- a/JavaScript/horizontal_timeline.2.0.js +++ b/JavaScript/horizontal_timeline.2.0.js @@ -1,7 +1,7 @@ /* -------------------------------- Horizontal Timeline 2.0 - by Studocwho @ yCodeTech +by Studocwho @ yCodeTech Original Horizontal Timeline by CodyHouse @@ -38,6 +38,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk minimalFirstDateInterval: true, dateDisplay: "dateTime", // dateTime, date, time, dayMonth, monthYear, year + dateOrder: "normal", // normal, reverse autoplay: false, autoplaySpeed: 8, // Sec @@ -50,12 +51,12 @@ Docs at http://horizontal-timeline.ycodetech.co.uk useFontAwesomeIcons: true, useNavBtns: true, useScrollBtns: true, - - iconBaseClass: "fas fa-3x", + + iconBaseClass: "fas fa-3x", scrollLeft_iconClass: "fa-chevron-circle-left", - scrollRight_iconClass: "fa-chevron-circle-right", - prev_iconClass: "fa-arrow-circle-left", - next_iconClass: "fa-arrow-circle-right", + scrollRight_iconClass: "fa-chevron-circle-right", + prev_iconClass: "fa-arrow-circle-left", + next_iconClass: "fa-arrow-circle-right", pause_iconClass: "fa-pause-circle", play_iconClass: "fa-play-circle" }; @@ -73,9 +74,8 @@ Docs at http://horizontal-timeline.ycodetech.co.uk this._defaults = defaults; this._name = pluginName; + this.$element = $(element); - this.$element = $(element), - this.init(); } Timeline.prototype.init = function () { @@ -85,73 +85,101 @@ Docs at http://horizontal-timeline.ycodetech.co.uk var self = this, contentList = this.$element.find('li'); if(contentList.length == 0) this.$element.css('opacity', 1).html('

There are no events at this point in time.

Please add some content.

'); - - var url = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css"; - - // Function to load the file - // (url, type) - this._addFile(url, 'css'); - + if (this.settings.useFontAwesomeIcons == true) { + var url = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css"; + + // Function to load the file + // (url, type) + this._addFile(url, 'css'); + } this._create(); - timelineComponents = {}; - this._timelineComponents(timelineComponents); - - this.init.addIdsAndClasses = addIdsAndClasses; - this.init.addIdsAndClasses(); - - function addIdsAndClasses() { - //** Adding IDs and Classes **// - if (timelineComponents['eventsContentList'].length == 1) { - timelineComponents['eventsContentList'].first().attr('id', 'first'); - timelineComponents['timelineEvents'].first().addClass("first"); + // Wait about 300s to make sure the all elements are created properly. + // Otherwise the width of the timeline would report as bigger than it actually is. + window.setTimeout($.proxy(function(){ + timelineComponents = {}; + this._timelineComponents(timelineComponents); + + this.init.addIdsAndClasses = addIdsAndClasses; + this.init.addIdsAndClasses(this); + + function addIdsAndClasses(self) { + //** Adding IDs and Classes **// + if (timelineComponents['eventsContentList'].length == 1) { + timelineComponents['eventsContentList'].first().attr('id', 'first'); + timelineComponents['timelineEvents'].first().addClass("first"); + } + else { + // Adds id to the first and last li of the event-content list respectively. + timelineComponents['eventsContentList'] + .first().attr('id', 'first').end() + .last().attr('id', 'last'); + + // Adds class to the first and last timeline event dates respectively. + timelineComponents['timelineEvents'] + .first().addClass("first").end() + .last().addClass("last"); + } } - else { - // Adds id to the first and last li of the event-content list respectively. - timelineComponents['eventsContentList'] - .first().attr('id', 'first').end() - .last().attr('id', 'last'); - - // Adds class to the first and last timeline event dates respectively. - timelineComponents['timelineEvents'] - .first().addClass("first").end() - .last().addClass("last"); + //** Select the correct event **// + + // If any events-content has .selected class... + if (timelineComponents['eventsContentList'].hasClass('selected')) { + // Get date from data-date attribute + var date = timelineComponents['eventsContentSelected'].data('date'), + // Find the event date matching the data-date + selectedDate = timelineComponents['eventsWrapper'].find('a[data-date="'+date+'"]'); + + // Add .selected class to the matched element + selectedDate.addClass('selected'); + // Update all previous dates for styling. + this._updateOlderEvents(selectedDate); + } + // If no class found at all... + else { + // If dateOrder is normal (Ascending)... start from the left. + if (this.settings.dateOrder == "normal") { + // Add .selected class to the first event. + timelineComponents['eventsWrapper'].find('a.first').addClass('selected'); + + // Find the selected event + var selectedEvent = timelineComponents['eventsWrapper'].find('a.selected'), + // Get the selected event's date. + selectedDate = selectedEvent.data('date'); + + // Find the selected event's content using the date and add selected class to the content. + timelineComponents['eventsContent'].find('li[data-date="'+selectedDate+'"]').addClass('selected'); + } + // Else dateOrder is reverse (Descending)... start from the right. + else if (this.settings.dateOrder == "reverse") { + // Add .selected class to the last event. + timelineComponents['eventsWrapper'].find('a.last').addClass('selected'); + + // Find the selected event + var selectedEvent = timelineComponents['eventsWrapper'].find('a.selected'), + // Get the selected event's date. + selectedDate = selectedEvent.data('date'); + + // Find the selected event's content using the date and add selected class to the content. + timelineComponents['eventsContent'].find('li[data-date="'+selectedDate+'"]').addClass('selected'); + + this._updateOlderEvents(selectedEvent); + } } - } - //** Select the correct event **// - // If any events-content has .selected class... - if (timelineComponents['eventsContentList'].hasClass('selected')) { - // Get date from data-date attribute - var date = timelineComponents['eventsContentSelected'].data('date'), - // Find the event date matching the data-date - selectedDate = timelineComponents['eventsWrapper'].find('a[data-date="'+date+'"]'); - - // Add .selected class to the matched element - selectedDate.addClass('selected'); - // Update all previous dates for styling. - this._updateOlderEvents(selectedDate); - } - // If no class found at all... - else { - // Add .selected class to the first events-content and first event date respectively. - timelineComponents['eventsContent'] - .find('li#first').addClass('selected').end() - .siblings('.timeline').find('.events').find('a.first').addClass('selected'); - } - - - // Assign a left postion to the single events along the timeline - this._setDatePosition(timelineComponents); - // Assign a width to the timeline - var timelineTotalWidth = this._setTimelineWidth(timelineComponents); - // Set the filling line to the selected event - this._updateFilling(timelineComponents['eventsWrapper'] - .find('a.selected'), timelineComponents['fillingLine'], timelineTotalWidth); - // The timeline has been initialised - show it - this.$element.addClass('loaded'); - - this._setup(self, timelineComponents, timelineTotalWidth); + + // Assign a left postion to the single events along the timeline + this._setDatePosition(timelineComponents); + // Assign a width to the timeline + var timelineTotalWidth = this._setTimelineWidth(timelineComponents); + // Set the filling line to the selected event + this._updateFilling(timelineComponents['eventsWrapper'] + .find('a.selected'), timelineComponents['fillingLine'], timelineTotalWidth); + // The timeline has been initialised - show it + this.$element.addClass('loaded'); + + this._setup(self, timelineComponents, timelineTotalWidth); + }, this), 300); }; /* Dynamically creates the timeline according to the amount of events. */ Timeline.prototype._create = function () { @@ -180,7 +208,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk //** Create the timeline HTML **// // Create the timeline element. - this.$element.prepend($timelineWrapper) + this.$element.prepend($timelineWrapper); // Find the timeline element that was just created var $timeline = this.$element.find('.timeline'); @@ -213,7 +241,12 @@ Docs at http://horizontal-timeline.ycodetech.co.uk .find("#rightNav").append($nextButton).append($scrollRightButton); } // Otherwise, both button sets are disabled and we just need to add the timelineEventsWrapper. - else $timeline.append($timelineEventsWrapper); + else { + $timeline.append($timelineEventsWrapper); + // Add a 100% min-width to the events-wrapper if the buttons are disabled. + // Stops the timeline from disappearing due to apparent no width. + $timeline.find('.events-wrapper').css("min-width", "100%"); + } // Autoplay buttons // If autoplay is true, create the pause button @@ -227,39 +260,50 @@ Docs at http://horizontal-timeline.ycodetech.co.uk this._create.date(this, 'append'); // (instance, insertMethod (append, before, after [last 2 for addEvent method]), date to insert before/after [from addEvent method]) function createDate(self, insertMethod, arrangementDate) { + + // If dateOrder is normal (starting from the left). + if (self.settings.dateOrder == "normal") { + // Find the event content. + var $element = self.$element.children('.events-content').find('li'); + } + // Else if dateOrder is reverse (starting from the right). + else if (self.settings.dateOrder == "reverse") { + var $element = $(self.$element.children('.events-content').find('li').get().reverse()); + } + /* dateTime = the date and time */ if(self.settings.dateDisplay == "dateTime") { - self.$element.children('.events-content').find('li').each(function() { + $element.each(function() { self._create.eventDateDisplay(self, $(this), "dateTime", insertMethod, arrangementDate); }); } /* date = the date only */ else if (self.settings.dateDisplay == "date") { - self.$element.children('.events-content').find('li').each(function() { + $element.each(function() { self._create.eventDateDisplay(self, $(this), "date", insertMethod, arrangementDate); }); } /* time = the time only */ else if (self.settings.dateDisplay == "time") { - self.$element.children('.events-content').find('li').each(function() { + $element.each(function() { self._create.eventDateDisplay(self, $(this), "time", insertMethod, arrangementDate); }); } /* dayMonth = the day and monthName only */ else if (self.settings.dateDisplay == "dayMonth") { - self.$element.children('.events-content').find('li').each(function() { + $element.each(function() { self._create.eventDateDisplay(self, $(this), "dayMonth", insertMethod, arrangementDate); }); } /* monthYear = the monthName and year only */ else if (self.settings.dateDisplay == "monthYear") { - self.$element.children('.events-content').find('li').each(function() { + $element.each(function() { self._create.eventDateDisplay(self, $(this), "monthYear", insertMethod, arrangementDate); }); } /* year = the year only */ else if (self.settings.dateDisplay == "year") { - self.$element.children('.events-content').find('li').each(function() { + $element.each(function() { self._create.eventDateDisplay(self, $(this), "year", insertMethod, arrangementDate); }); } @@ -282,16 +326,13 @@ Docs at http://horizontal-timeline.ycodetech.co.uk yearDisplay = display == "year", // Find .events for the date display $eventDateDisplay = self.$element.find('.events'), - // Create an array of the months, with the index 0 = null, - // so that we can get the month by its corresponding index number. - months = [null, 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], - monthName = months, dateLink = '', // For use with the addEvent plublic method // Finds the event with the specific date. $arrangementEvent = $eventDateDisplay.find('a[data-date="'+ arrangementDate +'"]'); // Function to add the number suffix st, nd, rd, th (eg: 1st, 2nd, 3rd, 4th) + // Part of answer on StackOverflow: https://stackoverflow.com/a/15397495/2358222 function numSuffix(num) { if (num > 3 && num < 21) return 'th'; switch (num % 10) { @@ -301,6 +342,16 @@ Docs at http://horizontal-timeline.ycodetech.co.uk default: return "th"; } } + // Function to get the month name according to a number supplied. + // Answer on StackOverflow: https://stackoverflow.com/a/10996297/2358222 + function getMonthName(num) { + // Create an array of the months, with the index 0 = null, + // so that we can get the month by its corresponding index number. + var monthNames = [null, "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" ]; + return monthNames[num]; + } + var dateExists = $eventDateDisplay.children('a').map(function() { return $(this).data('date'); }).get(); @@ -356,16 +407,16 @@ Docs at http://horizontal-timeline.ycodetech.co.uk else $arrangementEvent.before(dateLink + time +''); } else if(dayMonthDisplay) { - if (insertMethod == 'append') $eventDateDisplay.append(dateLink + dayPart + numSuffix(dayPart) + '
' + monthName[monthPart]+''); + if (insertMethod == 'append') $eventDateDisplay.append(dateLink + dayPart + numSuffix(dayPart) + '
' + getMonthName(monthPart) +''); // For use with the addEvent method... creates new timeline events and places them where specified. - else if (insertMethod == 'after') $arrangementEvent.after(dateLink + dayPart + numSuffix(dayPart) + '
' + monthName[monthPart]+''); - else $arrangementEvent.before(dateLink + dayPart + numSuffix(dayPart) + '
' + monthName[monthPart]+''); + else if (insertMethod == 'after') $arrangementEvent.after(dateLink + dayPart + numSuffix(dayPart) + '
' + getMonthName(monthPart) +''); + else $arrangementEvent.before(dateLink + dayPart + numSuffix(dayPart) + '
' + getMonthName(monthPart) +''); } else if(monthYearDisplay) { - if (insertMethod == 'append') $eventDateDisplay.append(dateLink + monthName[monthPart] + '
' + yearPart +''); + if (insertMethod == 'append') $eventDateDisplay.append(dateLink + getMonthName(monthPart) + '
' + yearPart +''); // For use with the addEvent method... creates new timeline events and places them where specified. - else if (insertMethod == 'after') $arrangementEvent.after(dateLink + monthName[monthPart] + '
' + yearPart +''); - else $arrangementEvent.before(dateLink + monthName[monthPart] + '
' + yearPart +''); + else if (insertMethod == 'after') $arrangementEvent.after(dateLink + getMonthName(monthPart) + '
' + yearPart +''); + else $arrangementEvent.before(dateLink + getMonthName(monthPart) + '
' + yearPart +''); } else if(yearDisplay) { if (insertMethod == 'append') $eventDateDisplay.append(dateLink + yearPart +''); @@ -432,16 +483,16 @@ Docs at http://horizontal-timeline.ycodetech.co.uk else $arrangementEvent.before(dateLink + date +''); } else if(dayMonthDisplay) { - if (insertMethod == 'append') $eventDateDisplay.append(dateLink + dayPart + numSuffix(dayPart) + '
' + monthName[monthPart]+''); + if (insertMethod == 'append') $eventDateDisplay.append(dateLink + dayPart + numSuffix(dayPart) + '
' + getMonthName(monthPart) +''); // For use with the addEvent method... creates new timeline events and places them where specified. - else if (insertMethod == 'after') $arrangementEvent.after(dateLink + dayPart + numSuffix(dayPart) + '
' + monthName[monthPart]+''); - else $arrangementEvent.before(dateLink + dayPart + numSuffix(dayPart) + '
' + monthName[monthPart]+''); + else if (insertMethod == 'after') $arrangementEvent.after(dateLink + dayPart + numSuffix(dayPart) + '
' + getMonthName(monthPart) +''); + else $arrangementEvent.before(dateLink + dayPart + numSuffix(dayPart) + '
' + getMonthName(monthPart) +''); } else if(monthYearDisplay) { - if (insertMethod == 'append') $eventDateDisplay.append(dateLink + monthName[monthPart] + '
' + yearPart +''); + if (insertMethod == 'append') $eventDateDisplay.append(dateLink + getMonthName(monthPart) + '
' + yearPart +''); // For use with the addEvent method... creates new timeline events and places them where specified. - else if (insertMethod == 'after') $arrangementEvent.after(dateLink + monthName[monthPart] + '
' + yearPart +''); - else $arrangementEvent.before(dateLink + monthName[monthPart] + '
' + yearPart +''); + else if (insertMethod == 'after') $arrangementEvent.after(dateLink + getMonthName(monthPart) + '
' + yearPart +''); + else $arrangementEvent.before(dateLink + getMonthName(monthPart) + '
' + yearPart +''); } else if(yearDisplay) { if (insertMethod == 'append') $eventDateDisplay.append(dateLink + yearPart +''); @@ -520,6 +571,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk event.preventDefault(); var $this = $(event.target); + this._timelineComponents(timelineComponents); timelineTotalWidth = this._setTimelineWidth(timelineComponents); // If next button clicked, shows next content if($this.is('.next')) this._showNewContent(timelineComponents, timelineTotalWidth, 'next'); @@ -536,6 +588,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk event.preventDefault(); var $this = $(event.target); + this._timelineComponents(timelineComponents); // Remove selected class from all dates. this.$element.find('.events').find('a').removeClass('selected'); // Add class to the event date clicked. @@ -549,7 +602,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk // Change the event content to match the selected event. this._updateVisibleContent($this, timelineComponents['eventsContent']); // Translate (scroll) the timeline left or right according to the position of the targeted event date - this._updateTimelinePosition($this, timelineComponents); + this._updateTimelinePosition($this, timelineComponents, timelineTotalWidth); }, this)); //** Autoplay **// @@ -651,19 +704,26 @@ Docs at http://horizontal-timeline.ycodetech.co.uk //if percentTime is equal or greater than 100 if(percentTime >= 100){ - // If the current index is equal to the total number of events - if(current == this._setup.autoplay.countEvents()) { + // If dateOrder is normal AND the current index is equal to the total number of events + // OR dateOrder is reverse AND current index is equal to 1 ... + if((this.settings.dateOrder == "normal" && current == this._setup.autoplay.countEvents()) || (this.settings.dateOrder == "reverse" && current == 1)) { // Go back to the start of the cycle. this._showNewContent(timelineComponents, autoplayTimelineTotalWidth, 'start'); // Recalculate the current index to make sure it's reset back to 1 (the start). - current = timelineComponents['eventsWrapper'].find('.selected').index(); + current = timelineComponents['eventsWrapper'].find('.selected').index(); } else { - // Go to next event content. - this._showNewContent(timelineComponents, autoplayTimelineTotalWidth, 'next'); + // If dateOrder is normal. + if (this.settings.dateOrder == "normal") { + // Go to next event content. + this._showNewContent(timelineComponents, autoplayTimelineTotalWidth, 'next'); + } + // Else if dateOrder is reverse. + else if (this.settings.dateOrder == "reverse") { + // Go to next event content. + this._showNewContent(timelineComponents, autoplayTimelineTotalWidth, 'prev'); + } } - // Add 1 to the current index - current++; } } // End isPaused if statement } // End Interval function @@ -878,7 +938,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk // Find the targeted event date using the date selectedDate = timelineComponents['eventsWrapper'].find(eventDate), // Get the width value of the events (previously set) - timelineTotalWidth = timelineComponents['eventsWrapper'].width(); + timelineTotalWidth = this._setTimelineWidth(timelineComponents); // If a link is targetting the timeline it sits in (itself), then execute the function to translate the timeline if(targetSelf) translate_gotoTimeline(this); // If not, then use a smooth scroll and then execute the function afterwards. @@ -914,7 +974,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk pluginRef._updateVisibleContent(selectedDate, timelineComponents['eventsContent']); } // Translate (scroll) the timeline left or right according to the position of the targeted event date - pluginRef._updateTimelinePosition(selectedDate, timelineComponents); + pluginRef._updateTimelinePosition(selectedDate, timelineComponents, timelineTotalWidth); } // End translate_gotoTimeline() translate function } // End gotoTimeline function } // End if goToTimelineLink exists @@ -972,15 +1032,12 @@ Docs at http://horizontal-timeline.ycodetech.co.uk // Swipe right to go left (previous) swipeRight:$.proxy(function(event, direction, distance, duration, fingerCount) { // Show previous content on swipeRight - - this._setup.swipe(this, 'prev'); - //this._showNewContent(timelineComponents, this._setTimelineWidth(timelineComponents), 'prev'); + this._setup.swipe(this, 'prev'); }, this), // Swipe left to go right (next) swipeLeft:$.proxy(function(event, direction, distance, duration, fingerCount) { // Show next content on swipeLeft - this._setup.swipe(this, 'next'); - + this._setup.swipe(this, 'next'); }, this), // Swipe distance... 0 = any distance in px threshold:75, @@ -1066,26 +1123,18 @@ Docs at http://horizontal-timeline.ycodetech.co.uk Timeline.prototype.refresh = function () { this._timelineComponents(timelineComponents); + // Removes first and last id attributes of the event-content list. timelineComponents['eventsContent'] - // Removes first and last id attributes of the event-content list. .find('#first').removeAttr('id').end() .find('#last').removeAttr('id').end(); - // Adds id to the first li of the event-content list. - //.find('li').first().attr('id', 'first').end() - // Adds id to the last li of the event-content list. - //.last().attr('id', 'last'); - + + // Removes first and last classes from the timeline event date timelineComponents['eventsWrapper'] - // Removes first and last classes from the timeline event date .find('.first').removeClass('first').end() - .find('.last').removeClass('last').end(); - // Adds class to the first timeline event date. - //.find('a').first().addClass("first").end() - // Adds class to the last timeline event date. - //.last().addClass("last"); - - - this.init.addIdsAndClasses(); + .find('.last').removeClass('last').end(); + + // Adds classes and IDs. + this.init.addIdsAndClasses(this); this._setDatePosition(timelineComponents); timelineTotalWidth = this._setTimelineWidth(timelineComponents); @@ -1227,36 +1276,63 @@ Docs at http://horizontal-timeline.ycodetech.co.uk Timeline.prototype._showNewContent = function (timelineComponents, timelineTotalWidth, string) { // Show prev/next content // Find the .selected content - var visibleContent = timelineComponents['eventsContent'].find('.selected'), - // Find the prev/next content - newContent = (string == 'next') ? visibleContent.next() : visibleContent.prev(); - // If a prev/next content exists... - if (newContent.length > 0) { + var visibleContent = timelineComponents['eventsContent'].find('.selected'); + + // If dateOrder is normal... + if (this.settings.dateOrder == "normal") + // Find the prev/next content for detection later. + var newContent = (string == 'next') ? visibleContent.next() : visibleContent.prev(); + + // If dateOrder is reverse + else if (this.settings.dateOrder == "reverse") + // Find the prev/next content in reverse fore detection later. + var newContent = (string == 'next') ? visibleContent.prev() : visibleContent.next(); + + // If a prev/next content exists + // OR dateOrder is reverse AND string is start (for Autoplay)... + // This determines whether we can navigate prev or next. + if (newContent.length > 0 || (this.settings.dateOrder == "reverse" && string == 'start')) { // Find the .selected event var selectedDate = timelineComponents['eventsWrapper'].find('.selected'), newEvent; + // If start... (For Autoplay), find the first event - if(string == 'start') newEvent = timelineComponents['eventsWrapper'].find('.first'); + if(string == 'start') { + + // If the dateOrder is normal (starting from the left)... + if (this.settings.dateOrder == "normal") { + // Find the first event. + newEvent = timelineComponents['eventsWrapper'].find('.first'); + } + // Else if the dateOrder is reverse (starting from the right)... + else if (this.settings.dateOrder == "reverse") { + // Find the last event. + newEvent = timelineComponents['eventsWrapper'].find('.last'); + } + } // If next, find the next event from the current selected event - else if (string == 'next') newEvent = selectedDate.next('a'); + else if (string == 'next') + newEvent = selectedDate.next('a'); + // If prev, find the prev event from the current selected event - else if (string == 'prev') newEvent = selectedDate.prev('a'); + else if (string == 'prev') + newEvent = selectedDate.prev('a'); + this._updateVisibleContent(newEvent, timelineComponents['eventsContent']); newEvent.addClass('selected'); selectedDate.removeClass('selected'); this._updateFilling(newEvent, timelineComponents['fillingLine'], timelineTotalWidth); this._updateOlderEvents(newEvent); - this._updateTimelinePosition(newEvent, timelineComponents); + this._updateTimelinePosition(newEvent, timelineComponents, timelineTotalWidth); } } - Timeline.prototype._updateTimelinePosition = function (event, timelineComponents) { + Timeline.prototype._updateTimelinePosition = function (event, timelineComponents, timelineTotalWidth) { // Get the css left value of the targeted event date var eventLeft = Number(event.css('left').replace('px', '')), // Get the width value of the .events-wrapper - timelineWidth = timelineComponents['timelineWrapper'].width(), - // Get the width value of the events (previously set) - timelineTotalWidth = timelineComponents['eventsWrapper'].width(); + timelineWidth = timelineComponents['timelineWrapper'].width(); + this._translateTimeline(timelineComponents, - eventLeft + timelineWidth/2, timelineWidth - timelineTotalWidth); } @@ -1268,7 +1344,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk this._setTransformValue(timelineComponents['eventsWrapper'], 'translateX', value+'px'); // Disable the buttons if necessary - this._buttonDisable(timelineComponents, value, totalTranslateValue); + this._buttonStates(timelineComponents, value, totalTranslateValue); } Timeline.prototype._updateFilling = function (selectedEvent, filling, totalTranslateValue) { @@ -1298,7 +1374,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk timelineComponents['timelineEvents'].first().css({'left': '0px','padding-left': '10px'}); startingNum = 1; } - // i start at 1, meaning starts at 2nd date. + // When i starts at 1, it means starts at 2nd date. for (i = startingNum; i < timelineComponents['timelineEvents'].length; i++) { distnew = distprev + dateIntervals; timelineComponents['timelineEvents'].eq(i).css('left', distnew + 'px'); @@ -1314,15 +1390,17 @@ Docs at http://horizontal-timeline.ycodetech.co.uk // Get the css left value of the last event date, remove the px unit and add 100 to it. lastEventLeft = Number(timelineComponents['timelineEvents'].last().css('left').replace('px', '')) + 100; - // Set the timeline width - totalWidth = lastEventLeft; - - // Set a fail-safe, if totalWidth is less than the wrapperWidth then use the wrapperWidth as width. + // Set a fail-safe, if lastEventLeft is less than the wrapperWidth then use the wrapperWidth as totalWidth. // Stops the timeline width from being too small. - if (totalWidth < wrapperWidth) totalWidth = wrapperWidth; + if (lastEventLeft < wrapperWidth) { + totalWidth = wrapperWidth; + } + else { + totalWidth = lastEventLeft; + } timelineComponents['eventsWrapper'].css('width', totalWidth+'px'); - this._updateTimelinePosition(timelineComponents['eventsWrapper'].find('a.selected'), timelineComponents); + this._updateTimelinePosition(timelineComponents['eventsWrapper'].find('a.selected'), timelineComponents, totalWidth); return totalWidth; } @@ -1432,8 +1510,10 @@ Docs at http://horizontal-timeline.ycodetech.co.uk return window.getComputedStyle(this.element,':before').content.replace(/'/g, "").replace(/"/g, ""); } - // Function to add or remove disabled class to next button depending on whether the last item is selected or not - Timeline.prototype._buttonDisable = function (timelineComponents, translateValue, totalTranslateValue){ + //** Button States **// + + // Function to add or remove inactive class. + Timeline.prototype._buttonStates = function (timelineComponents, translateValue, totalTranslateValue){ var nextButton = timelineComponents['timelineNavigation'].find('.next'), prevButton = timelineComponents['timelineNavigation'].find('.prev'), @@ -1484,7 +1564,7 @@ Docs at http://horizontal-timeline.ycodetech.co.uk if (translateValue == totalTranslateValue) rightButton.addClass('inactive'); // If not, then enable the scroll right button else rightButton.removeClass('inactive'); - } // End buttonDisable() function + } // End _buttonStates() function // Function to add required js and css files dynamically // (CDN URL of the plugin, file type JS or CSS, callback function) @@ -1592,10 +1672,10 @@ Docs at http://horizontal-timeline.ycodetech.co.uk // e.g. $(element).defaultPluginName('functionName', arg1, arg2) $.fn[pluginName] = function ( options ) { var args = arguments, - windowWidth = $(window).width(), - dateExists = $(this).find('.events-content').find('li').map(function() { - return $(this).data('date'); - }).get(); + windowWidth = $(window).width(), + dateExists = $(this).find('.events-content').find('li').map(function() { + return $(this).data('date'); + }).get(); // Is the first parameter an object (options), or was omitted, // instantiate a new instance of the plugin. @@ -1610,7 +1690,12 @@ Docs at http://horizontal-timeline.ycodetech.co.uk // pass options to our plugin constructor, // and store the plugin instance // in the elements jQuery data object. - $.data(this, 'plugin_' + pluginName, {'originalEventsContent': $(this).find('.events-content').clone()[0], 'windowWidth': windowWidth, 'existingDates': dateExists, 'Timeline': new Timeline( this, options )}); + $.data(this, 'plugin_' + pluginName, { + 'originalEventsContent': $(this).find('.events-content').clone()[0], + 'windowWidth': windowWidth, + 'existingDates': dateExists, + 'Timeline': new Timeline(this, options) + }); } }); diff --git a/README.md b/README.md index 4c85261..be47e7d 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Version 2.0 adds functionality that has been previously requested for the origin - Added new options for the button icons. - Added new options to disable the buttons. - Added an option for custom date display text. + - Added an option, dateOrder, allowing the use of reversing the date display. For full documentation please check out the [Horizontal Timeline 2.0 website](http://horizontal-timeline.ycodetech.co.uk/) @@ -89,6 +90,7 @@ $('#example').horizontalTimeline({ minimalFirstDateInterval: true, dateDisplay: "dateTime", // dateTime, date, time, dayMonth, monthYear, year + dateOrder: "normal", // normal, reverse autoplay: false, autoplaySpeed: 8, // Sec diff --git a/To Do.md b/To Do.md new file mode 100644 index 0000000..327e5cb --- /dev/null +++ b/To Do.md @@ -0,0 +1,8 @@ +##### To do: + +- Add support for custom slide animations/transitions using Animate.css +- Implement a namespaced object data attribute to accomodate the data-date and possibly the custom animations. +- Add method to dynamically change existing dates and reposition them to reflect their new date order. +- ~~Add support for Right-to-Left.~~ (In the form of `dateOrder: reverse`.) +- ~~Rename the disableButton to reflect the docs name of Inactive Button States.~~ +- Rework Autoplay to allow multiple autoplaying timelines per page. diff --git a/css/horizontal_timeline.2.0.css b/css/horizontal_timeline.2.0.css index 412d782..bd907f1 100644 --- a/css/horizontal_timeline.2.0.css +++ b/css/horizontal_timeline.2.0.css @@ -10,11 +10,10 @@ Licensed under the MIT license Docs at http://horizontal-timeline.ycodetech.co.uk -------------------------------- */ -html, body { - /* Stop horizontal scrollbar from appearing/disappearing when the content slides across and changes. - Also fixes the fixed flexbox elements from moving along with the transforms.*/ - height: auto; - overflow: auto; +html, +body { + /* Stop horizontal scrollbar from appearing/disappearing when the content slides across and changes.*/ + overflow-x: hidden; } .horizontal-timeline { opacity: 0; @@ -43,7 +42,7 @@ html, body { /* Timeline */ .horizontal-timeline .timeline { position: relative; - height: 100px; + height: auto; margin: 0 auto; display: flex; -ms-flex-wrap: wrap; @@ -138,11 +137,11 @@ html, body { .timeline-navigation { position: relative; top: 3px; - -webkit-transform: translateY(-50%); - -moz-transform: translateY(-50%); - -ms-transform: translateY(-50%); - -o-transform: translateY(-50%); - transform: translateY(-50%); + -webkit-transform: translateY(50%); + -moz-transform: translateY(50%); + -ms-transform: translateY(50%); + -o-transform: translateY(50%); + transform: translateY(50%); z-index: 2; } .timeline-navigation#leftNav { @@ -170,7 +169,7 @@ html, body { /* Autoplay Pause/Play button */ .timeline-navigation#pausePlay { width: 100%; - top: 10px; + top: -10px; text-align: center; } /* Event content */ @@ -207,6 +206,9 @@ html, body { border-radius: 20px; opacity: 0; + font-size: 16pt; + text-align: center; + -webkit-touch-callout: none; /* iOS Safari */ -webkit-user-select: none; /* Safari */ -khtml-user-select: none; /* Konqueror HTML */