Simple jQuery Timeline Plugin with Knockout and Moment.js

Simple jQuery Timeline Plugin with  Knockout and Moment.js
File Size: 63.2 KB
Views Total:
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   

An easy and lightweight jQuery plugin worked with Knockout library and moment.js for creating a simple vertical timeline on your web page. Click the arrow of a event will expand the event to display more information.

See also:

How to use it:

1. Create a container for your timeline.

<div class="grid">
<div class="left-timeline col-sand-left" data-bind=
        "template:{name:'event', foreach:leftEvents}"></div>
<div class="center-timeline col-sand-middle"></div>
<div class="right-timeline col-sand-right" data-bind=
        "template:{name:'event', foreach:rightEvents}"></div>
</div>

2. Add events to display on the timeline

<script id="event" type="text/html">
<div class="timeline-event" data-bind="style:{'top':top()+'px', 'height':height()+'px', 'borderLeftColor':color,'borderRightColor':color}, css:{'selected':selected},click:toggleSelected">
<figure>
<figcaption data-bind="text:title"></figcaption>
<h6><span data-bind="text:fromStart()"></span>
<small>to</small>
<span data-bind="text:fromEnd()"></span>
</h6>
<div data-bind="template:{name:template.name,data:template.context}"></div>
</figure>
</div>
</script>
<script type="text/html" id="your-event">
<p>
Your Content Goes Here.
</p>
</script>

3. Include the required stylesheet file to style the timeline.

<link href="src/stylesheets/app.css" rel="stylesheet">

4. Include the required javascript library files on the page.

<script src="src/vendor/moment.min.js"></script> 
<script src="src/vendor/knockout.js"></script> 
<script src="src/vendor/jquery.min.js"></script> 
<script src="src/vendor/jquery.scrollTo.min.js"></script> 

5. The javascript.

function get_random_color() {
    return '#' + (Math.random() * 0xFFFFFF << 0).toString(16);;
}


//Event to display on the timeline
function Event(title, start, end, template) {
    this.start = start;
    this.end = end;
    this.title = title;
    this.color = get_random_color();
    this.template = template;

    /*height and scale properties*/
    this.scale = ko.observable(1);
    this.height = ko.computed(function () {
        var days;
        if (!this.end) {
            days = moment().diff(this.start, "days");
        } else {
            days = this.end.diff(this.start, "days");
        }
        return days * this.scale();
    }, this);

    this.top = ko.computed(function () {
        var now = moment();
        if (!this.end) {
            return 0;
        }
        var diff = now.diff(this.end, 'days');
        return (diff * (this.scale()));

    }, this);

    /*time helpers*/
    this.fromEnd = function () {
        if (!this.end) {
            return "present"
        }
        return this.end.from(moment());
    };
    this.fromStart = function () {
        return this.start.from(moment());
    };
    /*selected*/
    this.selected = ko.observable(false);
    this.toggleSelected = function () {
        this.selected(!this.selected());
    };
}

//TODO: no overlapping event paradigm
//Left events
var leftEvents = [
    new Event("Pays the bills", moment("2012-12"), moment(), {
        name: 'your-event',
        context: {}
    }),
    new Event("Awesome Job", moment("2010-11"), moment("2012-12"), {
        name: 'your-event',
        context: {}
    }),
    new Event("Some cool place", moment("2009-01"), moment("2010-11"), {
        name: 'your-event',
        context: {}
    }),
    new Event("First Real Job", moment("2008-07"), moment("2009-01"), {
        name: 'your-event',
        context: {}
    }),
    new Event("The next place", moment("2006-10"), moment("2008-07"), {
        name: 'your-event',
        context: {}
    }),
    new Event("Some place", moment("2003-08"), moment("2006-10"), {
        name: 'your-event',
        context: {}
    }),
];

//right events
var rightEvents = [
    new Event("Grad School 2", moment("2010-12-17"), moment("2011-12-01"), {
        name: 'your-event',
        context: {}
    }),
    new Event("Grad School 1", moment("2008-08"), moment("2010-03"), {
        name: 'your-event',
        context: {}
    }),
    new Event("Uni 1", moment("2003-09"), moment("2005-09"), {
        name: 'your-event',
        context: {}
    })

];


//Timeline Viewmodel
function ViewModel() {
    this.title = "Your Name Here";
    this.subtitle = "Your Job Here";

    this.lastIndex = 0;
    this.leftEvents = ko.observableArray(leftEvents);
    this.rightEvents = ko.observableArray(rightEvents);
    this.currentScale = ko.observable(.75);
    this.currentScale.subscribe(this.updateEventsScale.bind(this));

    //any selected
    this.itemSelected = ko.computed(function () {
        var leftSelected = this.leftEvents().some(function (event) {
            return event.selected();
        });
        //return early
        if (leftSelected) {
            return leftSelected;
        }
        var rightSelected = this.rightEvents().some(function (event) {
            return event.selected();
        });

        return rightSelected;
    }, this);

    //combined and sorted items
    this.combinedSorted = ko.computed(function () {

        var combined = this.leftEvents().concat(this.rightEvents());

        //sort by computed top poisition
        combined.sort(function (a, b) {

            if (a.top() < b.top())
                return -1;
            if (a.top() > b.top())
                return 1;
            return 0;

        });

        return combined;

    }, this);

};

ViewModel.prototype.updateEventsScale = function (value) {
    this.leftEvents().forEach(function (event) {
        event.scale(value);
    });
    this.rightEvents().forEach(function (event) {
        event.scale(value);
    });
};
ViewModel.prototype.scrollNext = function () {

    if (this.lastIndex < this.combinedSorted().length - 1) {
        this.lastIndex++;
    }
    var top = this.combinedSorted()[this.lastIndex].top()

    $.scrollTo(top, 250);

};
ViewModel.prototype.scrollPrevious = function () {

    if (this.lastIndex > 0) {
        this.lastIndex--;
    }
    var top = this.combinedSorted()[this.lastIndex].top()

    $.scrollTo(top, 250);

};

//bind
var vm = new ViewModel();
ko.applyBindings(vm);

This awesome jQuery plugin is developed by bringking. For more Advanced Usages, please check the demo page or visit the official website.