UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,127 lines (940 loc) 53.2 kB
import './kendo.fx.js'; import './kendo.data.js'; import './kendo.draganddrop.js'; import './kendo.icons.js'; import './kendo.core.js'; import './kendo.licensing.js'; import '@progress/kendo-licensing'; import './kendo.data.odata.js'; import './kendo.data.xml.js'; import './kendo.userevents.js'; import './kendo.html.icon.js'; import './kendo.html.base.js'; import '@progress/kendo-svg-icons'; const __meta__ = { id: "timeline", name: "Timeline", category: "web", description: "The Kendo Timeline widget display events over time", depends: [ "userevents", "icons" ] }; (function($, undefined$1) { var kendo = window.kendo, ui = kendo.ui, Widget = ui.Widget, DataSource = kendo.data.DataSource, Transition = kendo.effects.Transition, keys = kendo.keys, isArray = Array.isArray, encode = kendo.htmlEncode, sanitizeLink = kendo.sanitizeLink, LEFT_PAGE = -1, CETER_PAGE = 0, RIGHT_PAGE = 1, VERTICAL = "vertical", TRANSITION_END = "transitionEnd", VIRTUAL_PAGE_COUNT = 3, VIRTUAL_PAGE_CLASS = "timeline-event", FLAGWRAPCLASS = "k-timeline-flag-wrap", TRACKITEMCLASS = "k-timeline-track-item", SCROLLABLEWRAPCLASS = "k-timeline-scrollable-wrap", TRACKITEM_NOTFLAG_SELECTOR = ".k-timeline-track-item:not(.k-timeline-flag-wrap)", NS = ".kendoTimeline", CHANGE = "change", DEFAULTHORIZONTALCARDTEMPLATE = (args) => { let titleField = args.titleField, subtitleField = args.subtitleField, descriptionField = args.descriptionField, imagesField = args.imagesField, actionsField = args.actionsField, altField = args.altField, data = args.data; return '<div class="k-card-inner">' + '<div class="k-card-header">' + (data[titleField] ? `<div class="k-card-title"><span class="k-event-title">${encode(data[titleField])}</span></div>` : '') + (data[subtitleField] ? `<div class="k-card-subtitle">${encode(data[subtitleField])}</div>` : '') + '</div>' + '<div class="k-card-body">' + '<div class="k-card-description">' + (data[descriptionField] ? `<p>${encode(data[descriptionField])}</p>` : '') + (data[imagesField] && data[imagesField].length > 0 ? `<img src="${encode(data[imagesField][0].src)}" ${data[altField] ? `alt="${encode(data[altField])}"` : ''} class="k-card-media" />` : '' ) + '</div>' + '</div>' + (data[actionsField] && data[actionsField].length > 0 ? '<div class="k-actions k-card-actions">' + data[actionsField].map(action => `<a class="k-button k-button-md k-rounded-md k-button-flat k-button-flat-primary" href="${action.url ? sanitizeLink(action.url) : "#"}">` + `<span class="k-button-text">${encode(action.text)}</span>` + '</a>' ).join('') + '</div>' : '') + '</div>'; }, DEFAULTVERTICALCARDTEMPLATE = (args) => { let titleField = args.titleField, subtitleField = args.subtitleField, descriptionField = args.descriptionField, imagesField = args.imagesField; args.navigatable; let collapsibleEvents = args.collapsibleEvents, actionsField = args.actionsField, altField = args.altField, data = args.data; return '<div class="k-card-inner">' + '<div class="k-card-header">' + '<div class="k-card-title">' + (data[titleField] ? `<span class="k-event-title">${encode(data[titleField])}</span>` : '') + (collapsibleEvents ? '<span class="k-event-collapse k-button k-button-md k-rounded-md k-button-flat k-button-flat-base k-icon-button">' + kendo.ui.icon({ icon: "chevron-right", iconClass: "k-button-icon" }) + '</span>' : '' ) + '</div>' + (data[subtitleField] ? `<div class="k-card-subtitle">${encode(data[subtitleField])}</div>` : '') + '</div>' + '<div class="k-card-body">' + '<div class="k-card-description">' + (data[descriptionField] ? `<p>${encode(data[descriptionField])}</p>` : '') + (data[imagesField] && data[imagesField].length > 0 ? `<img src="${encode(data[imagesField][0].src)}" ${data[altField] ? `alt="${encode(data[altField])}"` : ''} class="k-card-media" />` : '') + '</div>' + '</div>' + (data[actionsField] && data[actionsField].length > 0 ? '<div class="k-actions k-card-actions">' + data[actionsField].map(action => `<a class="k-button k-button-md k-rounded-md k-button-flat k-button-flat-primary" href="${action.url ? sanitizeLink(action.url) : "#"}">` + `<span class="k-button-text">${encode(action.text)}</span>` + '</a>' ).join('') + '</div>' : '') + '</div>'; }, HORIZONTALTRACKTEMPLATE = (args) => { args.itemTemplate; let dateField = args.dateField, dateFormat = args.dateFormat, showDateLabels = args.showDateLabels, data = args.data, year = 0; let result = ''; for (var i = 0; i < data.length; i++) { if (!(data[i][dateField] instanceof Date)) { continue; } let currentYear = data[i][dateField].getFullYear(); if (year != currentYear) { year = currentYear; result += '<li class="k-timeline-track-item k-timeline-flag-wrap">' + `<span class="k-timeline-flag">${year}</span>` + '</li>'; } result += '<li class="k-timeline-track-item" role="tab">' + '<div class="k-timeline-date-wrap">' + (showDateLabels ? `<span class="k-timeline-date">${kendo.toString(data[i][dateField], dateFormat)}</span>` : '') + '</div>' + '<span class="k-timeline-circle"></span>' + '</li>'; } return result; }, VERTICALEVENTSTEMPLATE = (args) => { let itemTemplate = args.itemTemplate, dateField = args.dateField, titleField = args.titleField, descriptionField = args.descriptionField, subtitleField = args.subtitleField, imagesField = args.imagesField, actionsField = args.actionsField, alterMode = args.alterMode, collapsibleEvents = args.collapsibleEvents, dateFormat = args.dateFormat, showDateLabels = args.showDateLabels, navigatable = args.navigatable, altField = args.altField, data = args.data, counter = 0, year = 0, reverse = false; let result = ''; for (var i = 0; i < data.length; i++) { if (!(data[i][dateField] instanceof Date)) { continue; } var currentYear = data[i][dateField].getFullYear(); if (currentYear != year) { year = currentYear; result += '<li class="k-timeline-flag-wrap">' + `<span class="k-timeline-flag">${year}</span>` + '</li>'; } reverse = counter % 2 === 0 && alterMode; result += `<li class="${reverse ? 'k-timeline-event k-reverse' : 'k-timeline-event'}" data-uid="${encode(data[i].uid)}">` + '<div class="k-timeline-date-wrap">' + (showDateLabels ? `<span id="${encode(data[i].uid)}-date" class="k-timeline-date">${kendo.toString(data[i][dateField], dateFormat)}</span>` : '') + '</div>' + '<span class="k-timeline-circle"></span>' + `<div class="${collapsibleEvents ? 'k-timeline-card k-collapsed' : 'k-timeline-card'}">` + `<div aria-expanded="false" class="k-card k-card-vertical k-card-with-callout" ${navigatable ? `aria-describedby="${encode(data[i].uid)}-date" tabindex="0" role="button" aria-live="polite" aria-atomic="true"` : ''} >` + `<span class="${reverse ? 'k-timeline-card-callout k-card-callout k-callout-e' : 'k-timeline-card-callout k-card-callout k-callout-w'}"></span>` + `${itemTemplate({ titleField: titleField, subtitleField: subtitleField, descriptionField: descriptionField, imagesField: imagesField, actionsField: actionsField, data: data[i], altField: altField, navigatable: navigatable, collapsibleEvents: collapsibleEvents })}` + '</div>' + '</div>' + '</li>'; counter ++; } return result; }, ARROWSHTML = '<button disabled tabindex="-1" aria-hidden="true" class="k-button k-button-md k-rounded-full k-button-solid k-button-solid-base k-icon-button k-timeline-arrow k-timeline-arrow-left k-disabled" title="previous">' + kendo.ui.icon({ icon: "caret-alt-left", iconClass: "k-button-icon" }) + '</button>' + '<button disabled tabindex="-1" aria-hidden="true" class="k-button k-button-md k-rounded-full k-button-solid k-button-solid-base k-icon-button k-timeline-arrow k-timeline-arrow-right k-disabled" title="next">' + kendo.ui.icon({ icon: "caret-alt-right", iconClass: "k-button-icon" }) + '</button>'; function className(name) { return "k-" + name; } function calculateTransform(element) { var matrix = element.css('transform'); var x; var values; if (matrix != "none" && matrix != "") { values = matrix.match(/-?[\d\.]+/g); x = values[4]; return (x / element.width() * 100); } else { return 0; } } function calculateOffset(element, parentElement) { return element.offset().left - parentElement.offset().left + element.width() / 2; } function applyCssStyles(element, property, value) { element.css(property, value); } var Page = kendo.Class.extend({ init: function(container) { this.cardContainer = $("<div class='k-card k-card-vertical k-card-with-callout' role='tabpanel'/>"); var cardWrapper = $("<div class='k-timeline-card'></div>").append(this.cardContainer); this.element = $("<li class='" + className(VIRTUAL_PAGE_CLASS) + "'></li>").append(cardWrapper); container.append(this.element); }, content: function(htmlContent, uid, label) { var callOut = $("<span class='k-timeline-card-callout k-card-callout k-callout-n'></span>"); this.cardContainer.html(htmlContent); this.cardContainer.prepend(callOut); this.element.attr("data-uid", uid); this.element.find(".k-card").attr({ role: "tabpanel", "aria-label": label }); }, position: function(position) { //position can be -1, 0, 1 this.element.css("transform", "translate3d(" + this.element.width() * position + "px, 0, 0)"); if (position === 0) { this.element.find(".k-card").attr("tabindex", 0); } else { this.element.find(".k-card").removeAttr("tabindex"); } }, setPageCallout: function(propery, value) { var element = this.element; var callOutElement = element.find(".k-timeline-card-callout"); callOutElement.css(propery, value); }, destroy: function() { var that = this; that.cardContainer = null; that.element.remove(); that.element = null; } }); var HorizontalPane = kendo.Observable.extend({ init: function(element, options) { var that = this; kendo.Observable.fn.init.call(this); this.element = element; var movable, transition, pages; movable = new kendo.ui.Movable(that.element); transition = new Transition({ axis: "x", movable: movable, onEnd: function() { that.trigger(TRANSITION_END); } }); pages = []; $.extend(that, { duration: options && options.duration || 1, movable: movable, transition: transition, pages: pages, eventTemplate: options.eventTemplate, eventHeight: options.eventHeight, dataFieldMappings: options.dataFieldMappings, dateFormat: options.dateFormat }); this.bind([TRANSITION_END], options); }, initPages: function() { var pages = this.pages, element = this.element, page; for (var i = 0; i < VIRTUAL_PAGE_COUNT; i++) { page = new Page(element); pages.push(page); } }, repositionPages: function() { var pages = this.pages; pages[0].position(LEFT_PAGE); pages[1].position(CETER_PAGE); pages[2].position(RIGHT_PAGE); }, setPageContent: function(page, data) { var template = typeof this.eventTemplate === Function ? this.eventTemplate : kendo.template(this.eventTemplate); var dataFieldMappings = this.dataFieldMappings; var label = kendo.toString(data.date, this.dateFormat); var html; html = template({ data: data, titleField: dataFieldMappings.title, subtitleField: dataFieldMappings.subtitle, descriptionField: dataFieldMappings.description, imagesField: dataFieldMappings.images, actionsField: dataFieldMappings.actions, altField: dataFieldMappings.altField }); page.content(html, data.uid, label); }, updatePage: function(isForward, data, calloutOffset) { var pages = this.pages; var page = isForward === null ? pages[1] : isForward ? pages[pages.length - 1] : pages[0]; this.setPageContent(page, data); page.setPageCallout("left", (calloutOffset / page.element.width()) * 100 + "%"); }, moveTo: function(offset) { this.movable.moveAxis("x", -offset); }, transitionTo: function(offset, ease) { this.transition.moveTo({ location: offset, duration: this.duration, ease: ease }); }, destroy: function() { var that = this; for (var index = 0; index < that.pages.length; index++) { that.pages[index].destroy(); } that.unbind(); that.movable = that.transition = that.dataFieldMappings = that.eventTemplate = that.duration = that.pages = null; } }); var Timeline = kendo.ui.Widget.extend({ init: function(element, options) { var that = this; var orientation = options.orientation || that.options.orientation; Widget.fn.init.call(this, element, options); this.element.addClass(orientation === VERTICAL ? "k-timeline k-timeline-vertical" : "k-timeline k-timeline-horizontal"); if (orientation != VERTICAL) { that._horizontal(); } else { that._vertical(); } this.element.on("click", ".k-card-actions", function(ev) { var action = $(ev.target); var dataItemUid = $(ev.target).closest(".k-timeline-event").data("uid"); var dataItem = that.dataSource.getByUid(dataItemUid); that.trigger("actionClick", { sender: that, element: action, dataItem: dataItem }); }); that.currentEventIndex = 0; that._forward = null; that._eventPage = 1; that._currentIndex = 0; that._firstIndexInView = 0; that._initDataFieldMappings(); that.setDataSource(options.dataSource); }, _horizontal: function() { var that = this; var element = this.element; var options = this.options; var trackWrap = $("<div />"); var trackEl = $("<div />"); var scrollableWrap = $("<ul role='tablist' tabindex='0' />"); var eventsWrap = $("<div />"); var eventsList = $("<ul />"); that._trackWrap = trackWrap; that._trackEl = trackEl; that._scrollableWrap = scrollableWrap; that._eventsWrap = eventsWrap; that._eventsList = eventsList; trackWrap.addClass("k-timeline-track-wrap"); trackEl.addClass("k-timeline-track"); scrollableWrap.addClass(SCROLLABLEWRAPCLASS); eventsWrap.addClass("k-timeline-events-list"); eventsList.addClass(SCROLLABLEWRAPCLASS); if (options.eventHeight) { eventsList.height(options.eventHeight); } trackEl.append(scrollableWrap); trackWrap.append(ARROWSHTML); trackWrap.append(trackEl); eventsWrap.append(eventsList); trackWrap.appendTo(element); eventsWrap.appendTo(element); }, _vertical: function() { var that = this; var options = this.options; var element = this.element; var eventsList = that._eventsList = $("<ul />"); var navigatable = options.navigatable; var collapsibleEvents = options.collapsibleEvents; that.element.append(eventsList); if (options.alternatingMode) { element.addClass("k-timeline-alternating"); } if (collapsibleEvents) { element.addClass("k-timeline-collapsible"); this.element.on("click", ".k-card-header", function() { var card = $(this).closest(".k-timeline-card"); var itemWrapper = card.parent(); var dataItem = that.dataSource.getByUid(itemWrapper.data("uid")); if (card.hasClass("k-collapsed")) { if (!that.trigger("expand", { sender: that, dataItem: dataItem })) { that.expand(itemWrapper); } } else { if (!that.trigger("collapse", { sender: that, dataItem: dataItem })) { that.collapse(itemWrapper); } } }); } if (navigatable) { if (collapsibleEvents) { this.element.on("keydown" + NS, that, function(e) { if (e.keyCode == keys.SPACEBAR || e.keyCode == keys.ENTER) { var target = $(e.target); var header = target.find(".k-card-header"); if (header.length) { e.preventDefault(); header.trigger("click"); } } }); } } }, _renderContentVertical: function(data) { var that = this; var options = that.options; var html; var itemTemplate; if (typeof options.eventTemplate === Function) { itemTemplate = options.eventTemplate; } else { itemTemplate = options.eventTemplate ? kendo.template(options.eventTemplate) : kendo.template(DEFAULTVERTICALCARDTEMPLATE, { useWithBlock: false }); } var template = kendo.template(VERTICALEVENTSTEMPLATE, { useWithBlock: false }); html = template({ data: data, dateField: options.dataDateField, titleField: options.dataTitleField, subtitleField: options.dataSubtitleField, descriptionField: options.dataDescriptionField, imagesField: options.dataImagesField, actionsField: options.dataActionsField, itemTemplate: itemTemplate, alterMode: options.alternatingMode, collapsibleEvents: options.collapsibleEvents, dateFormat: options.dateFormat, showDateLabels: options.showDateLabels, altField: options.dataImagesAltField, navigatable: options.navigatable }); this._eventsList.html(html); if (options.eventWidth) { that.element.find(".k-card").width(options.eventWidth); } }, _renderContentHorizontal: function(data) { var that = this; var options = that.options; var html; var itemTemplate; var dataFieldMappings = that._dataFieldMappings; if (typeof options.eventTemplate === Function) { itemTemplate = options.eventTemplate; } else { itemTemplate = options.eventTemplate ? kendo.template(options.eventTemplate) : kendo.template(DEFAULTHORIZONTALCARDTEMPLATE, { useWithBlock: false }); } var trackTemplate = kendo.template(HORIZONTALTRACKTEMPLATE, { useWithBlock: false }); html = trackTemplate({ data: data, itemTemplate: itemTemplate, dateFormat: options.dateFormat, dateField: options.dataDateField, showDateLabels: options.showDateLabels }); if (options.initialEventIndex) { that._trackWrap.append($(html).find("." + SCROLLABLEWRAPCLASS).css("transform", "translateX(-100%)").parent()); } else { that._scrollableWrap.html(html); } if (that.pane) { that.pane.destroy(); } that.pane = new HorizontalPane(that._eventsList, { transitionEnd: this._transitionEnd.bind(this), eventTemplate: itemTemplate, dataFieldMappings: dataFieldMappings, eventHeight: options.eventHeight, dateFormat: options.dateFormat }); }, _initDataFieldMappings: function() { var that = this; var options = that.options; that._dataFieldMappings = { "title": options.dataTitleField, "subtitle": options.dataSubtitleField, "date": options.dataDateField, "description": options.dataDescriptionField, "images": options.dataImagesField, "actions": options.dataActionsField, "altField": options.dataImagesAltField }; }, _transitionEnd: function() { if (this._forward) { this.pane.pages.push(this.pane.pages.shift());//forward } else { this.pane.pages.unshift(this.pane.pages.pop());//back } this._forward = null; this.pane.repositionPages(); this.pane.movable.moveAxis("x", 0); if (this.options.navigatable) { this._transition = null; this._eventsList.find(".k-card").removeAttr("id"); this.pane.pages[1].cardContainer.attr("id", this._cardId); this._setCurrent(this._currentBullet); } this._animationInProgress = false; }, _setCurrentEvent: function(event) { var that = this; var trackItem = $(event.currentTarget); var eventContainer; var dataItem = that.dataSource.view()[trackItem.parent().children(":not(.k-timeline-flag-wrap)").index(trackItem)]; eventContainer = that._forward ? that.pane.pages[2].element : that.pane.pages[0].element; if (!that.trigger("change", { eventContainer: eventContainer, dataItem: dataItem })) { that.open(trackItem); } }, open: function(element) { var that = this; var trackItem = $(element); var trackItemCircle = trackItem.find(".k-timeline-circle"); var trackItems = trackItem.parent().children(":not(.k-timeline-flag-wrap)"); var itemIndex = trackItems.index(trackItem); var forward; if (this.options.navigatable) { that._removeCurrent(); trackItems.attr("aria-selected", false); trackItem.attr("aria-selected", true); that._currentBullet = trackItem; //needed for screenreaders to announce at a later stage the item } var dataItem = that.dataSource.view()[itemIndex]; if (that.currentEventIndex === itemIndex) { return; } that._currentIndex = trackItem.index(); forward = that._forward = that.currentEventIndex < itemIndex; that.currentEventIndex = itemIndex; that.pane.updatePage(forward, dataItem, calculateOffset(trackItemCircle, that._trackWrap)); if (that._forward) { clearTimeout(that.navigateTimeOut); that.navigateTimeOut = setTimeout(function() { that.pane.transition.moveTo({ location: -that.pane.pages[2].element.width(), duration: 800, ease: Transition.easeOutExpo }); }, 200); } else { clearTimeout(that.navigateTimeOut); that.navigateTimeOut = setTimeout(function() { that.pane.transition.moveTo({ location: that.pane.pages[0].element.width(), duration: 800, ease: Transition.easeOutExpo }); }, 200); } that._repositionEvents(); }, _navigateToView: function(event) { var that = this; var delta = $(event.currentTarget).hasClass("k-timeline-arrow-right") ? 1 : -1; if (!that.trigger("navigate", { sender: that, action: delta > 0 ? "next" : "previous" }) && !that._animationInProgress) { that._animationInProgress = true; if (delta > 0) { that.next(); } else { that.previous(); } that._updateArrows(); } }, _enableDisableArrow: function(arrow, enable) { if (enable) { arrow.removeClass("k-disabled"); arrow.removeAttr("disabled"); arrow.attr("aria-hidden", false); } else { arrow.addClass("k-disabled"); arrow.attr("disabled", "disabled"); arrow.attr("aria-hidden", true); } }, _updateArrows: function() { var that = this; var arrows = that.element.find(".k-timeline-arrow"); var leftArrow = arrows.filter(".k-timeline-arrow-left"); var rightArrow = arrows.filter(".k-timeline-arrow-right"); this._enableDisableArrow(leftArrow, !that._validateNavigation(false)); this._enableDisableArrow(rightArrow, !that._validateNavigation(true)); }, _validateNavigation: function(next) { var that = this; var transform = that._end || 0; if (next) { return that._firstIndexInView + that.numOfEvents >= that.maxEvents; } else { return Math.abs(transform) <= 1; } }, next: function() { var that = this; var options = that.options; if (!that._validateNavigation(true) && options.orientation != VERTICAL) { that._forward = true; that._navigate(); } that._updateArrows(); }, _navigate: function() { var that = this; var firstEventInViewIndex; var firstEventInView; var dataItem; var forward = that._forward; var end = calculateTransform(this._trackWrap.find("." + SCROLLABLEWRAPCLASS)); var leftOffset = forward ? - $("." + SCROLLABLEWRAPCLASS).width() : $("." + SCROLLABLEWRAPCLASS).width(); var currentIndex = that._currentIndex; var currentPage; var firstIndexInView = that._firstIndexInView; end = forward ? end - 100 : end + 100; if (end >= 0) { end = 0; } that._end = end; that._tackItemWidth; currentPage = Math.floor(currentIndex / that.numOfEvents); if (forward) { if (that.numOfEvents === 1) { firstEventInViewIndex = firstIndexInView === 0 ? 1 : firstIndexInView; firstEventInView = this._trackWrap.find("." + TRACKITEMCLASS).eq(firstEventInViewIndex).nextAll(":not(." + FLAGWRAPCLASS + ")").first(); that._firstIndexInView = firstEventInView.index(); } else { firstEventInViewIndex = firstIndexInView + that.numOfEvents - 1; firstEventInView = this._trackWrap.find("." + TRACKITEMCLASS).eq(firstEventInViewIndex).nextAll(":not(." + FLAGWRAPCLASS + ")").first(); that._firstIndexInView = firstIndexInView + that.numOfEvents; } } else { if (that.numOfEvents === 1) { firstEventInViewIndex = firstIndexInView; firstEventInView = this._trackWrap.find("." + TRACKITEMCLASS).eq(firstEventInViewIndex).prevAll(":not(." + FLAGWRAPCLASS + ")").first(); that._firstIndexInView = firstEventInView.index(); } else { firstEventInViewIndex = firstIndexInView; firstEventInView = this._trackWrap.find("." + TRACKITEMCLASS).eq(firstEventInViewIndex).prevAll(":not(." + FLAGWRAPCLASS + ")").first(); firstEventInView = firstEventInView.length > 0 ? firstEventInView : this._trackWrap.find("." + TRACKITEMCLASS + ":not(." + FLAGWRAPCLASS + ")").first(); that._firstIndexInView = firstIndexInView - that.numOfEvents < 0 ? 0 : firstIndexInView - that.numOfEvents; } } dataItem = that.dataSource.view()[this._trackWrap.find(TRACKITEM_NOTFLAG_SELECTOR).index(firstEventInView)]; this._trackWrap.find("." + SCROLLABLEWRAPCLASS).css("transform", "translateX(" + end + "%)"); if (that._currentIndex != firstEventInView.index()) { that.currentEventIndex = this._trackWrap.find(TRACKITEM_NOTFLAG_SELECTOR).index(firstEventInView); that._currentIndex = firstEventInView.index(); that.pane.updatePage(that._forward, dataItem, (currentPage === 0 && !forward ? firstEventInView.find(".k-timeline-circle").offset().left + 15 : calculateOffset(firstEventInView.find(".k-timeline-circle"), that._trackWrap) + leftOffset)); clearTimeout(that.navigateTimeOut); that.navigateTimeOut = setTimeout(function() { if (forward && that.pane && that.pane.pages.length > 0) { that.pane.transition.moveTo({ location: - that.pane.pages[2].element.width(), duration: 800, ease: Transition.easeOutExpo }); } else { that.pane.transition.moveTo({ location: that.pane.pages[0].element.width(), duration: 800, ease: Transition.easeOutExpo }); } }, 200); } else { var scrollWrapElement = this._trackWrap.find("." + SCROLLABLEWRAPCLASS); var transitionEndHandler = function() { if (that.numOfEvents != 1) { var page = that.pane.pages[1]; var calloutOffset = calculateOffset(firstEventInView.find(".k-timeline-circle"), that._trackWrap); page.setPageCallout("left", (calloutOffset / page.element.width()) * 100 + "%"); } this._transition = null; scrollWrapElement.off('transitionend' + NS, transitionEndHandler); }; scrollWrapElement.on('transitionend' + NS, transitionEndHandler); } }, previous: function() { var that = this; var options = that.options; if (!that._validateNavigation(false) && options.orientation != VERTICAL) { that._forward = false; that._navigate(); } that._updateArrows(); }, expand: function(event) { var options = this.options, cardWrapper = $(event).find(".k-timeline-card"), cardElement = $(event).find(".k-card"), cardBody = $(event).find(".k-card-body"); if (!cardWrapper.hasClass("k-collapsed")) { return; } if (options.navigatable && options.collapsibleEvents) { cardElement.attr("aria-expanded", true); } cardWrapper.removeClass('k-collapsed'); kendo.fx(cardBody).expand("vertical").stop().play(); }, collapse: function(event) { var options = this.options, cardWrapper = $(event).find(".k-timeline-card"), cardElement = $(event).find(".k-card"), cardBody = $(event).find(".k-card-body"); if (cardWrapper.hasClass("k-collapsed")) { return; } if (options.navigatable && options.collapsibleEvents) { cardElement.attr("aria-expanded", false); } cardWrapper.addClass("k-collapsed"); kendo.fx(cardBody).expand("vertical").stop().reverse(); }, items: function() { return this.element.find("li[data-uid]"); }, _resizeHandler: function() { var that = this; clearTimeout(that.resizeTimeOut); that.resizeTimeOut = setTimeout(function() { that._redrawEvents(); that.pane.repositionPages(); }); }, redraw: function() { var options = this.options; if (options.orientation != VERTICAL) { this._redrawEvents(); this.pane.repositionPages(); } }, _redrawEvents: function() { var that = this; var numOfEvents = Math.floor(that.element.find("." + SCROLLABLEWRAPCLASS).width() / 150); var width; if (that.element.width() <= 480) { that.element.addClass("k-timeline-mobile"); width = 100; that.numOfEvents = 1; that._tackItemWidth = width; that.element.find("li." + TRACKITEMCLASS).css("flex", "1 0 " + width + "%"); that._repositionEvents(); } else { that.element.removeClass("k-timeline-mobile"); if (numOfEvents != that.numOfEvents) { that.numOfEvents = numOfEvents; width = 100 / numOfEvents; applyCssStyles(that.element.find("li." + TRACKITEMCLASS), "flex", "1 0 " + width + "%"); that._tackItemWidth = width; that._repositionEvents(); } } that._updateArrows(); }, _repositionEvents: function() { var that = this; var width = that._tackItemWidth; var page = that._forward === null ? that.pane.pages[1] : that._forward ? that.pane.pages[2] : that.pane.pages[0]; var trackWrapScrollableElement = this._trackWrap.find("." + SCROLLABLEWRAPCLASS); var end = calculateTransform(trackWrapScrollableElement); var calloutOffset; var offset; var leftOffset; var circleElement; if (that.numOfEvents === 1) { offset = that.currentEventIndex * width; } else { offset = that._currentIndex * width; } if (page) { if (that.numOfEvents === 1) { page.setPageCallout("left", "50%"); leftOffset = offset; applyCssStyles(trackWrapScrollableElement, "transform", "translateX(-" + leftOffset + "%)"); that._firstIndexInView = that._currentIndex; that._updateArrows(); return; } if (offset >= Math.abs(end) + 100) { leftOffset = Math.abs(end) + ((offset - (Math.abs(end) + 100)) + width); that._end = -leftOffset; applyCssStyles(trackWrapScrollableElement, "transform", "translateX(-" + leftOffset + "%)"); that._firstIndexInView = that._currentIndex - that.numOfEvents + 1; } else if (offset <= Math.abs(end)) { leftOffset = offset; that._end = -leftOffset; applyCssStyles(trackWrapScrollableElement, "transform", "translateX(-" + leftOffset + "%)"); that._firstIndexInView = that._currentIndex; } else { circleElement = trackWrapScrollableElement.find("li." + TRACKITEMCLASS).eq(that._currentIndex).find(".k-timeline-circle"); calloutOffset = calculateOffset(circleElement, that._trackWrap); page.setPageCallout("left", (calloutOffset / page.element.width()) * 100 + "%"); that._firstIndexInView = Math.round(Math.abs(end) / width); } var scrollWrapElement = this._trackWrap.find("." + SCROLLABLEWRAPCLASS); var transitionEndHandler = function() { if (that.numOfEvents != 1) { var page = that.pane.pages[1]; var eventElement = that._trackWrap.find("." + TRACKITEMCLASS).eq(that._currentIndex); var calloutOffset = calculateOffset(eventElement.find(".k-timeline-circle"), that._trackWrap); page.setPageCallout("left", (calloutOffset / page.element.width()) * 100 + "%"); } scrollWrapElement.off('transitionend' + NS, transitionEndHandler); }; scrollWrapElement.on('transitionend' + NS, transitionEndHandler); } that._updateArrows(); }, _initHorizontal: function() { var that = this; var firstEventElement = that._trackWrap.find(".k-timeline-circle").first(); var dataItem = that.dataSource.view()[0]; var navigatable = that.options.navigatable; var current; that.maxEvents = that._trackWrap.find("." + TRACKITEMCLASS).length; that._currentIndex = 1; that.pane.initPages(); that.pane.repositionPages(); that.pane.updatePage(that._forward, dataItem, calculateOffset(firstEventElement, that._trackWrap)); that._updateArrows(); that._resizeHandlerBound = that._resizeHandler.bind(that); kendo.jQuery(window).on("resize" + NS, that._resizeHandlerBound); that._trackWrap.on("click", TRACKITEM_NOTFLAG_SELECTOR, that._setCurrentEvent.bind(that)); that._trackWrap.on("click", ".k-timeline-arrow:not(.k-disabled)", that._navigateToView.bind(that)); if (navigatable) { that._trackWrap .find(".k-timeline-track-item.k-timeline-flag-wrap") .attr("role", "none") .attr("aria-hidden", true); that._trackWrap.find(TRACKITEM_NOTFLAG_SELECTOR) .attr("aria-selected", false) .first() .attr("aria-selected", true); that._cardId = kendo.guid(); that._scrollableWrap .on("focus" + NS, function() { that.pane.pages[1].cardContainer.attr("id", that._cardId); if (that._currentBullet) { that._currentBullet.addClass("k-focus"); } }) .on("focusout" + NS, function() { if (that._currentBullet) { that._currentBullet.removeClass("k-focus"); } }) .on("keydown" + NS, function(e) { var handled; var current = that._currentBullet; var itemOffset; var next; if (that._transition) { return; } if (e.keyCode == keys.LEFT) { handled = true; next = current.prevAll(TRACKITEM_NOTFLAG_SELECTOR).first(); if (next.length) { itemOffset = calculateOffset(next, that._trackWrap); if (itemOffset < 0 || itemOffset > next.parent().width()) { that._transition = true; that._removeCurrent(); that.previous(); that.open(next); } else { that._setCurrentEvent({ currentTarget: next }); } } } if (e.keyCode == keys.RIGHT) { handled = true; next = current.nextAll(TRACKITEM_NOTFLAG_SELECTOR).first(); if (next.length) { itemOffset = calculateOffset(next, that._trackWrap); if (itemOffset < 0 || itemOffset > next.parent().width()) { //itemOffset > 0 && itemOffset < parentWidth that._transition = true; that._removeCurrent(); that.next(); that.open(next); } else { that._setCurrentEvent({ currentTarget: next }); } } } if (handled) { //prevent scrolling while pressing the keys e.preventDefault(); } }); current = that._scrollableWrap.find("." + TRACKITEMCLASS).eq(that._currentIndex); that._setCurrent(current); current.removeClass("k-focus"); } }, _setCurrent: function(next) { if (!next) { return; } var id = kendo.guid(); var that = this; that._removeCurrent(); that._scrollableWrap.attr("aria-activedescendant", id); next.attr("id", id).addClass("k-focus"); next.siblings().removeAttr("aria-describedby"); if (next.attr("aria-selected") === "true") { next.attr("aria-describedby", that._cardId); that.pane.pages[1].cardContainer.attr("id", that._cardId); } that._currentBullet = next; }, _removeCurrent: function() { if (this._currentBullet) { this._currentBullet .removeClass("k-focus") .removeAttr("id") .removeAttr("aria-describedby"); } this._scrollableWrap.removeAttr("aria-activedescendant"); }, setDataSource: function(dataSource) { var that = this; var options = that.options; dataSource = isArray(dataSource) ? { data: dataSource } : dataSource; if (that.dataSource && that._refresh) { that.dataSource.unbind(CHANGE, that._refresh); } else { this._refresh = that.refresh.bind(that); } this.dataSource = DataSource.create(dataSource); if (this.dataSource._sort === undefined$1) { this.dataSource._sort = [{ field: options.dataDateField, dir: "asc" }]; } that.dataSource.bind(CHANGE, that._refresh); if (options.autoBind) { this.dataSource.fetch(); } }, refresh: function() { var that = this; var options = that.options; var data = this.dataSource.view(); if (options.orientation != VERTICAL) { that._trackWrap.empty().remove(); that.element.find('.k-timeline-events-list').remove(); that._horizontal();