Base solution for your next web application
Starts in:
01 DAYS
01 HRS
01 MIN
01 SEC
Open Closed

Horizontal timeline on Metronic 5 #4390


User avatar
0
Ricavir created

Hi,

While using Metronic 4 with angular and asp.net core, I've built a specific component for horizontal-timeline. It was working great. I've upgraded my project with latest aspnetzero version and with metronic 5. In metronic 5, it is not available in the demo templates.

I also noticed that you removed it from aspnetzero dashboard.

Do you know if this component will be available soon for metronic 5 ?

Is it possible to get the horizontal-timeline work again (with metronic 4 assets) and how will you do it ?

Any advice would be welcome :)


5 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Ricavir,

    We have spent a little time on migration the horizontal timeline from v4.x to v5.x and then decided to give up because it was going to hard.

    This is the timeline used <a class="postlink" href="https://github.com/CodyHouse/horizontal-timeline">https://github.com/CodyHouse/horizontal-timeline</a> and it seems like it's abandoned. We also couldn't find any other good option for horizontal timeline.

  • User Avatar
    0
    Ricavir created

    Hi @ismcagdas,

    I managed to make it work again. It was mainly css stuff to be reintegrated and adapted to Metronic 5.

    My horizontal-timeline component was not the same as yours. I completely wrap it in an angular component. I've also added missing css file for horizontal-timeline in angular.cli

    If you're interested, I can share it

    Cheers

  • User Avatar
    0
    alper created
    Support Team

    it would be great if you share it for the one's who may want to use it

  • User Avatar
    0
    Ricavir created

    Here it is :

    timeline.component.ts : wraps javascript for horizontal timeline

    import { Component, AfterViewInit, Injector, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
    import { AppComponentBase } from '@shared/common/app-component-base';
    import { TimelineItemDto } from '@shared/service-proxies/service-proxies';
    import * as moment from 'moment';
    
    @Component({
        selector: 'timeline',
        styles: ['./timeline.component.css'],
        templateUrl: './timeline.component.html',
        encapsulation: ViewEncapsulation.None
    })
    export class TimelineComponent extends AppComponentBase implements AfterViewInit {
         
        @Input()
        timelineItems: TimelineItemDto[];
        @Input()
        selectedItemId: number = 0;
    
        selectedItemIdAfterInit: number = 0;
    
        @Output()
        timelineItemClicked = new EventEmitter<TimelineItemDto>();
    
        constructor(
            injector: Injector
        ) {
            super(injector);
        }
    
        ngAfterViewInit(): void {        
            var timelines = $('.cd-horizontal-timeline');
            this.selectedItemIdAfterInit = this.selectedItemId;
            (timelines.length > 0 && this.timelineItems.length > 0) && initTimeline(timelines, this.timelineItems, this.selectedItemId);
        }
    
        timelineItemClick(item: TimelineItemDto) {
            this.timelineItemClicked.emit(item);
        }
    }
    
    
    function initTimeline(timelines, items, selectedItemId) {
        timelines.each(function () {
            var eventsMinDistance = $(this).data('spacing');
            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(items);
            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, selectedItemId);
            //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', eventsMinDistance);
            });
            //detect click on the prev arrow
            timelineComponents['timelineNavigation'].on('click', '.prev', function (event) {
                event.preventDefault();
                updateSlide(timelineComponents, timelineTotWidth, 'prev', eventsMinDistance);
            });
            //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');  
                this.selectedItemIdAfterInit = $(this).get(0).id;
                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, eventsMinDistance) {
        //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, undefined);
    }
    
    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).toString();
        var scaleValue = Number(eventLeft) / totWidth;
        setTransformValue(filling.get(0), 'scaleX', scaleValue);
    }
    
    function setDatePosition(timelineComponents, min) {
        for (var 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, selectedItemId) {
        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#' + selectedItemId), timelineComponents['fillingLine'], totalWidth);
        updateTimelinePosition('next', timelineComponents['eventsWrapper'].find('a#' + selectedItemId), timelineComponents);
    
        return totalWidth;
    }
    
    function updateVisibleContent(event, eventsContent) {
        var eventId = event[0].id,
            visibleContent = eventsContent.find('.selected'),
            selectedContent = eventsContent.find('li#' + eventId),
            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];
            var translateValue = timelineTranslate.split(',')[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 = [];
        for (var i = 0; i < events.length; i++) {       
            var dateComp = events[i].date.format("DD/MM/YYYY");
            var dayComp = dateComp.split('/');
            var 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 (var 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, "");
    }
    

    timeline.component.html :

    <div class="cd-horizontal-timeline mt-timeline-horizontal" data-spacing="60">
        <div class="timeline">
            <div class="events-wrapper">
                <div class="events">
                    <ol>
                        <li *ngFor="let timelineItem of timelineItems">
                            <a href="#0" id="{{timelineItem.id}}" class="border-after-red bg-after-red " [ngClass]="{'selected' : timelineItem.id===selectedItemId}">
                                <div>
                                    <i class="{{timelineItem.icon}}"></i>
                                </div>
                                <div>
                                    {{timelineItem.dateDisplay | date:'dd MMM'}}
                                </div>
                            </a>
                        </li>
                    </ol>
                    <span class="filling-line bg-red" aria-hidden="true"></span>
                </div>
                
            </div>
            
            <ul class="cd-timeline-navigation mt-ht-nav-icon">
                <li>
                    <a href="#0" class="prev btn btn-danger"> test
                        <i class="fa fa-chevron-left"></i>
                    </a>
                </li>
                <li>
                    <a href="#0" class="next btn btn-danger">
                        <i class="fa fa-chevron-right"></i>
                    </a>
                </li>
            </ul>
            
        </div>
        
        <div class="events-content">
            <ol>
                <li *ngFor="let timelineItem of timelineItems" [ngClass]="{'selected' : timelineItem.id===selectedItemId}" id="{{timelineItem.id}}">
                    <div class="mt-title">
                        <h2 class="mt-content-title"><i class="{{timelineItem.icon}}"></i> {{timelineItem.title}}</h2>
                    </div>
                    <div class="mt-author">                    
                        
                        <div class="mt-author-name">
                            <a class="font-blue-madison">{{timelineItem.creatorName}}</a>
                        </div>
                        <div class="mt-author-datetime font-grey-mint">{{timelineItem.dateDisplay | date:'short'}}</div>
                    </div>
                    <div class="mt-content border-grey-steel">         
                        <p>{{timelineItem.description}}</p>          
                        <a href="javascript:;" class="btn btn-primary" (click)="timelineItemClick(timelineItem)">{{timelineItem.buttonText}}</a>                    
                    </div>
                </li>                       
            </ol>
        </div>
        
    </div>
    

    and timeline.css to be added to angular.cli CSS imports

    /***
    Horizontal Timeline 
    ***/
    /* PLUGIN CSS */
    .cd-horizontal-timeline {
      opacity: 0;
      -webkit-transition: opacity 0.2s;
      -moz-transition: opacity 0.2s;
      transition: opacity 0.2s; }
    
    .cd-horizontal-timeline::before {
      /* never visible - this is used in jQuery to check the current MQ */
      content: 'mobile';
      display: none; }
    
    .cd-horizontal-timeline.loaded {
      /* show the timeline after events position has been set (using JavaScript) */
      opacity: 1; }
    
    .cd-horizontal-timeline .timeline {
      position: relative;
      height: 140px;
      width: 90%;
      max-width: 800px;
      margin: 0 auto; }
    
    .cd-horizontal-timeline .events-wrapper {
      position: relative;
      height: 100%;
      margin: 0 40px;
      overflow: hidden; }
    
    .cd-horizontal-timeline .events-wrapper::after, .cd-horizontal-timeline .events-wrapper::before {
      /* these are used to create a shadow effect at the sides of the timeline */
      content: '';
      position: absolute;
      z-index: 2;
      top: 0;
      height: 100%;
      width: 20px; }
    
    .cd-horizontal-timeline .events-wrapper::before {
      left: 0;
      background-image: -webkit-linear-gradient(left, #f8f8f8, rgba(248, 248, 248, 0));
      background-image: linear-gradient(to right, #f8f8f8, rgba(248, 248, 248, 0)); }
    
    .cd-horizontal-timeline .events-wrapper::after {
      right: 0;
      background-image: -webkit-linear-gradient(right, #f8f8f8, rgba(248, 248, 248, 0));
      background-image: linear-gradient(to left, #f8f8f8, rgba(248, 248, 248, 0)); }
    
    .cd-horizontal-timeline .events {
      /* this is the grey line/timeline */
      position: absolute;
      z-index: 1;
      left: 0;
      top: 69px;
      height: 2px;
      /* width will be set using JavaScript */
      background: #dfdfdf;
      -webkit-transition: -webkit-transform 0.4s;
      -moz-transition: -moz-transform 0.4s;
      transition: transform 0.4s; }
    
    .cd-horizontal-timeline .filling-line {
      /* this is used to create the green line filling the timeline */
      position: absolute;
      z-index: 1;
      left: 0;
      top: 0;
      height: 100%;
      width: 100%;
      background-color: #f4516c;
      -webkit-transform: scaleX(0);
      -moz-transform: scaleX(0);
      -ms-transform: scaleX(0);
      -o-transform: scaleX(0);
      transform: scaleX(0);
      -webkit-transform-origin: left center;
      -moz-transform-origin: left center;
      -ms-transform-origin: left center;
      -o-transform-origin: left center;
      transform-origin: left center;
      -webkit-transition: -webkit-transform 0.3s;
      -moz-transition: -moz-transform 0.3s;
      transition: transform 0.3s; }
    
    .cd-horizontal-timeline .events a {
      position: absolute;
      bottom: 0;
      z-index: 2;
      text-align: center;
      font-size: 1rem;
      padding-bottom: 15px;
      color: [#383838](https://support.aspnetzero.com/QA/Questions/383838);
      /* fix bug on Safari - text flickering while timeline translates */
      -webkit-transform: translateZ(0);
      -moz-transform: translateZ(0);
      -ms-transform: translateZ(0);
      -o-transform: translateZ(0);
      transform: translateZ(0); }
    
    .cd-horizontal-timeline .events a::after {
      /* this is used to create the event spot */
      content: '';
      position: absolute;
      left: 50%;
      right: auto;
      -webkit-transform: translateX(-50%);
      -moz-transform: translateX(-50%);
      -ms-transform: translateX(-50%);
      -o-transform: translateX(-50%);
      transform: translateX(-50%);
      bottom: -5px;
      height: 12px;
      width: 12px;
      border-radius: 50%;
      -webkit-transition: background-color 0.3s, border-color 0.3s;
      -moz-transition: background-color 0.3s, border-color 0.3s;
      transition: background-color 0.3s, border-color 0.3s; }
    
    .no-touch .cd-horizontal-timeline .events a:hover::after {
      background-color: #7b9d6f;
      border-color: #7b9d6f; }
    
    .cd-horizontal-timeline .events a.selected {
      pointer-events: none; }
    
    @media only screen and (min-width: 1100px) {
      .cd-horizontal-timeline::before {
        /* never visible - this is used in jQuery to check the current MQ */
        content: 'desktop'; } }
    
    .cd-timeline-navigation a {
      /* these are the left/right arrows to navigate the timeline */
      position: absolute;
      z-index: 1;
      top: 50%;
      bottom: auto;
      -webkit-transform: translateY(-50%);
      -moz-transform: translateY(-50%);
      -ms-transform: translateY(-50%);
      -o-transform: translateY(-50%);
      transform: translateY(-50%);
      height: 34px;
      width: 34px;
      border-radius: 50%;
      /* replace text with an icon */
      overflow: hidden;
      text-indent: 100%;
      white-space: nowrap;
      -webkit-transition: border-color 0.3s;
      -moz-transition: border-color 0.3s;
      transition: border-color 0.3s; }
    
    .cd-timeline-navigation a.prev {
      left: 0; }
    
    .cd-timeline-navigation a.next {
      right: 0; }
    
    .cd-timeline-navigation a.inactive {
      cursor: not-allowed; }
    
    .cd-timeline-navigation a.inactive::after {
      background-position: 0 -16px; }
    
    .cd-horizontal-timeline .events-content {
      position: relative;
      width: 100%;
      margin: 10px 0 0 0;
      overflow: hidden;
      -webkit-transition: height 0.4s;
      -moz-transition: height 0.4s;
      transition: height 0.4s; }
    
    .cd-horizontal-timeline .events-content > ol > li {
      position: absolute;
      z-index: 1;
      width: 100%;
      left: 0;
      top: 0;
      -webkit-transform: translateX(-100%);
      -moz-transform: translateX(-100%);
      -ms-transform: translateX(-100%);
      -o-transform: translateX(-100%);
      transform: translateX(-100%);
      padding: 0;
      opacity: 0;
      -webkit-animation-duration: 0.4s;
      -moz-animation-duration: 0.4s;
      animation-duration: 0.4s;
      -webkit-animation-timing-function: ease-in-out;
      -moz-animation-timing-function: ease-in-out;
      animation-timing-function: ease-in-out; }
    
    .cd-horizontal-timeline .events-content > ol > li.selected {
      /* visible event content */
      position: relative;
      z-index: 2;
      opacity: 1;
      -webkit-transform: translateX(0);
      -moz-transform: translateX(0);
      -ms-transform: translateX(0);
      -o-transform: translateX(0);
      transform: translateX(0); }
    
    .cd-horizontal-timeline .events-content > ol > li.enter-right, .cd-horizontal-timeline .events-content > ol > li.leave-right {
      -webkit-animation-name: cd-enter-right;
      -moz-animation-name: cd-enter-right;
      animation-name: cd-enter-right; }
    
    .cd-horizontal-timeline .events-content > ol > li.enter-left, .cd-horizontal-timeline .events-content > ol > li.leave-left {
      -webkit-animation-name: cd-enter-left;
      -moz-animation-name: cd-enter-left;
      animation-name: cd-enter-left; }
    
    .cd-horizontal-timeline .events-content > ol > li.leave-right, .cd-horizontal-timeline .events-content > ol > li.leave-left {
      -webkit-animation-direction: reverse;
      -moz-animation-direction: reverse;
      animation-direction: reverse; }
    
    .cd-horizontal-timeline .events-content > ol > li {
      margin: 0 auto; }
    
    .cd-horizontal-timeline .events-content em {
      display: block;
      font-style: italic;
      margin: 10px auto; }
    
    .cd-horizontal-timeline .events-content em::before {
      content: '- '; }
    
    @-webkit-keyframes cd-enter-right {
      0% {
        opacity: 0;
        -webkit-transform: translateX(100%); }
      100% {
        opacity: 1;
        -webkit-transform: translateX(0%); } }
    
    @-moz-keyframes cd-enter-right {
      0% {
        opacity: 0;
        -moz-transform: translateX(100%); }
      100% {
        opacity: 1;
        -moz-transform: translateX(0%); } }
    
    @keyframes cd-enter-right {
      0% {
        opacity: 0;
        -webkit-transform: translateX(100%);
        -moz-transform: translateX(100%);
        -ms-transform: translateX(100%);
        -o-transform: translateX(100%);
        transform: translateX(100%); }
      100% {
        opacity: 1;
        -webkit-transform: translateX(0%);
        -moz-transform: translateX(0%);
        -ms-transform: translateX(0%);
        -o-transform: translateX(0%);
        transform: translateX(0%); } }
    
    @-webkit-keyframes cd-enter-left {
      0% {
        opacity: 0;
        -webkit-transform: translateX(-100%); }
      100% {
        opacity: 1;
        -webkit-transform: translateX(0%); } }
    
    @-moz-keyframes cd-enter-left {
      0% {
        opacity: 0;
        -moz-transform: translateX(-100%); }
      100% {
        opacity: 1;
        -moz-transform: translateX(0%); } }
    
    @keyframes cd-enter-left {
      0% {
        opacity: 0;
        -webkit-transform: translateX(-100%);
        -moz-transform: translateX(-100%);
        -ms-transform: translateX(-100%);
        -o-transform: translateX(-100%);
        transform: translateX(-100%); }
      100% {
        opacity: 1;
        -webkit-transform: translateX(0%);
        -moz-transform: translateX(0%);
        -ms-transform: translateX(0%);
        -o-transform: translateX(0%);
        transform: translateX(0%); } }
    
    /* METRONIC EXTENDED CSS */
    .mt-timeline-horizontal {
      font-size: 14px; }
      .mt-timeline-horizontal ol, .mt-timeline-horizontal ul {
        list-style: none; }
      .mt-timeline-horizontal blockquote, .mt-timeline-horizontal q {
        quotes: none; }
      .mt-timeline-horizontal blockquote:before, .mt-timeline-horizontal blockquote:after,
      .mt-timeline-horizontal q:before, .mt-timeline-horizontal q:after {
        content: '';
        content: none; }
      .mt-timeline-horizontal table {
        border-collapse: collapse;
        border-spacing: 0; }
      .mt-timeline-horizontal .timeline {
        width: 100%;
        max-width: 100%; }
        .mt-timeline-horizontal .timeline:before {
          background: transparent; }
        .mt-timeline-horizontal .timeline .events-wrapper .events a:after {
          background-color: #fff;
          border: 2px solid; }
        .mt-timeline-horizontal .timeline .events-wrapper .events a.selected:after {
          background-color: #fff !important; }
        .mt-timeline-horizontal .timeline .events-wrapper .events a:hover, .mt-timeline-horizontal .timeline .events-wrapper .events a:focus {
          text-decoration: none; }
        .mt-timeline-horizontal .timeline .events-wrapper:before, .mt-timeline-horizontal .timeline .events-wrapper:after {
          background-image: none; }
        .mt-timeline-horizontal .timeline .mt-ht-nav-icon li a {
          border-radius: 50% !important; }
          .mt-timeline-horizontal .timeline .mt-ht-nav-icon li a i {
            position: absolute;
            top: 50%;
            left: 8px;
            transform: translateX(50%) translateY(-50%);
            width: 10px; }
        .mt-timeline-horizontal .timeline .mt-ht-nav-icon li:first-child a i {
          left: 5px; }
        .mt-timeline-horizontal .timeline.mt-timeline-square .events a:after {
          border-radius: 0 !important; }
        .mt-timeline-horizontal .timeline.mt-timeline-square .mt-ht-nav-icon li a {
          border-radius: 0 !important; }
      .mt-timeline-horizontal .events-content ol {
        padding: 0; }
        .mt-timeline-horizontal .events-content ol li .mt-title {
          margin-top: 15px;
          float: left;
          width: 60%; }
          .mt-timeline-horizontal .events-content ol li .mt-title h2 {
            margin: 0;
            opacity: 0.8 ;
            filter: alpha(opacity=80) ;
            font-size: 18px;
            font-weight: 600; }
        .mt-timeline-horizontal .events-content ol li .mt-author {
          float: right;
          position: relative;
          text-align: right;
          width: 40%; }
          .mt-timeline-horizontal .events-content ol li .mt-author > .mt-avatar {
            float: right;
            margin-left: 15px; }
          .mt-timeline-horizontal .events-content ol li .mt-author > .mt-author-name {
            margin-top: 5px; }
            .mt-timeline-horizontal .events-content ol li .mt-author > .mt-author-name a {
              opacity: 0.9 ;
              filter: alpha(opacity=90) ;
              font-size: 15px;
              font-weight: 600; }
              .mt-timeline-horizontal .events-content ol li .mt-author > .mt-author-name a:hover, .mt-timeline-horizontal .events-content ol li .mt-author > .mt-author-name a:focus {
                text-decoration: none; }
          .mt-timeline-horizontal .events-content ol li .mt-author > .mt-author-datetime {
            font-size: 13px; }
          .mt-timeline-horizontal .events-content ol li .mt-author > .mt-avatar {
            width: 50px;
            height: 50px;
            border-radius: 50% !important;
            overflow: hidden; }
            .mt-timeline-horizontal .events-content ol li .mt-author > .mt-avatar > img {
              width: 100%;
              height: auto; }
        .mt-timeline-horizontal .events-content ol li .mt-content {
          margin-top: 20px;
          padding-top: 20px;
          border-top: 1px solid;
          clear: both;
          line-height: 1.7em; }
          .mt-timeline-horizontal .events-content ol li .mt-content > p {
            opacity: 0.7 ;
            filter: alpha(opacity=70) ; }
          .mt-timeline-horizontal .events-content ol li .mt-content img.pull-left {
            margin: 0 15px 15px 0; }
          .mt-timeline-horizontal .events-content ol li .mt-content img.pull-right {
            margin: 0 0 15px 15px; }
          .mt-timeline-horizontal .events-content ol li .mt-content .btn-group .dropdown-menu {
            margin-right: 5px; }
    
    @media (max-width: 480px) {
      .mt-timeline-horizontal .events-content ol li .mt-title {
        width: 100%; }
      .mt-timeline-horizontal .events-content ol li .mt-author {
        width: 100%;
        margin-top: 15px;
        text-align: left; }
        .mt-timeline-horizontal .events-content ol li .mt-author > .mt-avatar {
          float: left;
          margin-right: 15px;
          margin-left: 0; }
        .mt-timeline-horizontal .events-content ol li .mt-author > .mt-author-name {
          margin-top: 10px; }
      .mt-timeline-horizontal .btn.pull-right {
        float: none !important;
        margin: 0 !important; } }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Thanks a lot @Ricavir :),

    I have created an issue for this <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero-core/issues/697">https://github.com/aspnetzero/aspnet-ze ... issues/697</a>.