Code Monkey home page Code Monkey logo

timeline.js's Introduction

Timeline.js

This module draws a timeline diagram, using SVG to link entries.

Use

To use the timeline:

  • Include timeline.min.js and timeline.min.css in your document.
  • Optionally include timeline-dark.min.js to enable the default dark mode.
  • Add a <div> with id="diagram" to your HTML.
  • Add your timeline entries and events as <div> elements within div#diagram, with the appropriate data- attributes (see HTML below).
  • Instantiate a new Timeline in JS, and call the create() method on it.

Example

Here is an example showing the development of Linux Desktop Environments since the mid-1990s.

Entries are created using HTML data attributes, which determine their position and connections when the timeline is instantiated. Events can also be added, either to a particular entry or as a general event on the timeline.

<div id="diagram">
	<!--Timeline entries-->
	<div id="KDE" data-start="1996" data-become="Plasma" data-colour="#179af3">KDE</div>
	<div id="Plasma" data-start="2014" data-colour="#179af3">KDE Plasma</div>
	<div id="Trinity" data-start="2010" data-split="KDE" data-colour="#01306f">Trinity Desktop Environment</div>
	<div id="Budgie" data-start="2014" data-split="GNOME" data-row="2" data-colour="#6bca81">Budgie</div>
	<div id="GNOME" data-start="1997" data-row="3" data-colour="#000">GNOME</div>
	<div id="Cinnamon" data-start="2013" data-split="GNOME" data-colour="#dc682e">Cinnamon</div>
	<div id="MATE" data-start="2011" data-split="GNOME" data-colour="#9ddb60">MATE</div>
	<div id="XFCE" data-start="1997" data-colour="#00a8dd">XFCE</div>
	<div id="LXDE2" data-start="2013" data-split="LXDE" data-irregular="true" data-row="7" data-colour="#d1d1d1">LXDE</div>
	<div id="LXDE" data-start="2006" data-become="LXQT" data-row="8" data-colour="#d1d1d1">LXDE</div>
	<div id="LXQT" data-start="2013" data-row="8" data-colour="#0280b9">LXQT</div>
	<div id="Razor-qt" data-start="2010" data-merge="LXQT" data-row="9" data-end="2013" data-colour="#006c96">Razor-qt</div>
	<div id="Enlightenment" data-start="1997" data-colour="#fff078">Enlightenment</div>
	<div id="Moksha" data-start="2014" data-split="Enlightenment" data-colour="#5a860a">Moksha Desktop</div>
	
	<!--Events-->
	<div class="event" data-year="2004">X.org is founded as a fork of XFree86.</div>
	<div class="event" data-year="2008">The Wayland project was started.</div>
	<div class="event" data-year="2011" data-target="GNOME">Gnome 3.0 was released.</div>
	<div class="event" data-year="2008" data-target="KDE">KDE 4 was released.</div>
</div>
const example = new Timeline("diagram", { 
	yearStart: 1995
});
example.create();

This is rendered as below:

A timeline diagram showing the development of Linux Desktop Environments. Years are shown at intervals along the top and bottom, increasing from left to right. Entries (e.g. KDE, Gnome, XFCE) are depicted with a box, bordered with the entry's brand colour, from which a line extends to the right representing the length of its existence. Some entries split from or merge with others, represented by a connecting line.

Live examples

Javascript

The script is bundled as an ES6 module (dist/timeline.esm.js) or a UMD (dist/timeline.min.js), depending on your preferred development stack or build tools.

The Timeline class and configuration are documented below. Note that configuration is optional - any or none of the options can be passed in the config object. If specifying a config, you must also pass the container ID as the first parameter when creating the timeline.

Adding Entries

Entries can be defined either in your HTML using data attributes, or passed as an array of Javascript objects when instantiating Timeline.js.

Both methods can be combined, but any entry defined in JS that duplicates an existing id will be dropped and a warning sent in the console.

Each entry must have a unique ID, which must be a valid value for the HTML id attribute (See id on MDN for restrictions).

HTML

To define entries in your HTML, create an element within the container and define its properties with the data attributes in the table below.

By default, entries should be <div> elements and the container has the id #diagram, but both of these are configurable (see the Javscript configuration below).

Attribute Required Value Use
data-start Yes <number> A year The year the entry starts at in the timeline.
Note: If this is earlier than the start of the timeline itself, an arrow is added to indicate it pre-exists the period shown.
data-end No <number> A year The year the entry ends. If omitted, this will be determined either by other connections, or if there are none, it will continue to the end of the timeline.
data-row No <number> Note: The first row is '0'.
The row number this entry should appear in. This can be omitted, though automatic positioning is quite basic. It is recommended to use manual positioning or a combination of both for large or complex diagrams (see Entry Positioning below).
data-end-estimate No true or false Whether the end is an estimate. Estimated end times are shown with a dashed end to the line, instead of a point.
data-become No Another entry ID The entry 'becomes' another entry. I.e. another entry is the continuation of this entry, and it will be drawn on the same line. For example, use this when an entry changes its name.
data-split No Another entry ID If specified, the entry will be shown branching from the specified entry, at the year specified in 'data-start'.
data-merge No Another entry ID If specified, the entry will be connected to the specified entry, at the year specified in 'data-end'.
data-links No A space-separated list of entry IDs If specified, the entry is linked with a dashed line to each entry ID. Useful for looser associations between entries that should not be connected directly.
data-colour No A CSS colour value The colour of the border around the entry and connections from it.
data-irregular No true or false Set to true for entries that are 'irregular' or should not be unbroken from their start to end dates. If set to true, the entry will be drawn with a broken line.
data-group No A named group to which this entry belongs. This can be useful, for example, to keep entries that are not directly connected but have some shared property near each other in the diagram.

Javascript

Entries can also be added using an array of objects when creating the Timeline, using an optional parameter.

Each entry must have at least id, name and start properties. The name is the displayed name of the entry (determined by the inner text of the element when defining entries in HTML).

All attributes available as data attributes described above can be defined as object properties, with the omission of the data prefix and the object key named as it would be when converted from a data attribute to a property of the element's dataset. (See the MDN entry for this conversion).

For example:

const data = [
	{ id: "A", name: "First entry", start: 1950, end: 1960, merge: "B" },
	{ id: "B", name: "Second entry", start: 1955, end: 1981, endEstimate: true  },
	
	{ id: "Z", name: "Final entry", start: 1940 }
];

const example = new Timeline(
	"diagram",
	{}, //Default configuration
	data
);

example.create();

Adding Events

Two kinds of events can be added to the timeline:

  1. general events appearing on the date line at the top of the diagram;
  2. entry-specific events, appearing on an entry's own timeline.

These create information points that are expanded by hovering or touching. (See the example screenshot above or the live examples.) As with entries, they can be added either with HTML data attributes or in Javascript.

HTML

Events are added by creating a <div> with the class event and the required attributes.

Attribute Required Value Use
data-year Yes A year Determines where on the timeline the event appears.
data-target No An entry ID If defined, places the event on an entry's line instead of the top date line.
data-colour No A CSS colour value Defines the colour of the text of the event. For general events (no target entry) this also defines the colour of the information marker on the date line.

Javascript

As with entries, events can also be added using an array of objects in Javascript.

Each event must have at least year and content properties. The content provides the message shown for the event (determined by the inner text of the element when defining events in HTML).

In addition, if a valid entry id is provided in the target property, it will be displayed as an entry-specific event.

CSS Styling

The variables below are set in the included CSS. These are the default values, and can be over-ridden to customise the timeline's appearance.

--tl-colour-background: #fff;
--tl-colour-border: #ccc;
--tl-colour-stroke: #999;
--tl-colour-entry: #f2f2f2;
--tl-colour-text: #333;
--tl-colour-highlight: #FFF14D;
--tl-colour-background-feature: #fafafa;
--tl-colour-border-feature: #7a7a7a;
--tl-width-year: 50px;
--tl-width-box: 100px;
--tl-width-box-min: 40px;
--tl-height-box: 40px;
--tl-height-row: 50px;
--tl-padding: 5px;

Dark mode

If you want to include a dark mode, you can link the additional timeline-dark.min.css file in your HTML. This over-rides the above for users who have set a dark mode preference, as below.

--tl-colour-background: #222;
--tl-colour-border: #282828;
--tl-colour-stroke: #777777;
--tl-colour-entry: #555555;
--tl-colour-text: #eeeeee;
--tl-colour-highlight: #FFF14D;
--tl-colour-background-feature: #333333;
--tl-colour-border-feature: #7a7a7a;

Alternatively, add your own preferences within a prefers-color-scheme: dark media query.

Panning and Zooming

For large diagrams, Timeline can make use of @panzoom/panzoom to add panning and zooming to the diagram within a fixed container. Include @panzoom/panzoom in your dependencies (it is not bundled), and pass the panzoom function in the config when instantiating the timeline (see Javascript Options below).

Controls and searching

If Panzoom is active, controls can be added to find an entry and pan to it, and also to control the zoom.

Find an Entry

Include a form with the id "timeline-find" (by default - this is configurable) containing an input with the name "finder". The input will then provide an autocomplete list of the entries in the diagram, which, when selected, will trigger the diagram to pan to that entry and highlight it.

Zoom controls

Buttons can be added to control 'zoom in', 'zoom out' and 'reset zoom' with specified IDs. If not specified in the configuration, the zoom actions are attached to these IDs, if present in the document: 'timeline-zoom-in', 'timeline-zoom-out', 'timeline-zoom-reset'.

Finding on load with URL hash

If a URL hash is present on load and Panzoom is enabled, the timeline will pan to and highlight a given entry automatically if the hash is in the format #find-{id}.

Example

An example putting these together as a controls div within the diagram.

The provided classes will position the controls in a box in the bottom right corner of the timeline container.

<div class="controls">
	<form id="timeline-find">
			<input type="text" name="finder" 
				placeholder="Type to find an entry" aria-label="Find an entry" />
	</form>
	<div class="zoom-buttons" role="group" aria-label="Diagram Zoom Controls">
		<button id="timeline-zoom-out" type="button">Zoom Out</button>
		<button id="timeline-zoom-reset" type="button">Reset</button>
		<button id="timeline-zoom-in" type="button">Zoom In</button>
	</div>
</div>

Entry Positioning

The X axis position of each entry is manually set by specifing the 'data-start' attribute (note: If data-start is before the configured start of the timeline, it will be shown at the start with an arrow indicating it pre-exists the period shown). The extent of the entry along the timeline is determined either by the 'data-end' attribute, or extends to the end of the timeline.

Specifying the row manually for each entry is not required. However, only some basic tests are performed to choose a suitable row for each entry when it is not specified, so aside from simple examples, it is recommended to manually set 'data-row' on a proportion of entries and those with complex links to ensure a sensible layout.

The row is determined for each entry if it is omitted, in the order that they appear (either source-code order if added in HTML, or their array order if added via Javascript). A row is determined as follows:

  • Available space, starting from the centre of the diagram.
  • Connected entries (via 'data-becomes' attribute) must be on the same row.
  • Split and merge entries should aim to be as close to their linked entries as possible, depending on nearest available space.

Groups

If any groups have been specified, the same logic is applied, but to entries matching each group separately. The groups are then positioned on the diagram one after the other. Grouped and un-grouped entries can be mixed: any ungrouped entries will be positioned in an available space after all groups are completed.

Javascript Documentation

Timeline

The class representing the Timeline. This is the point of access to this tool. The simplest usage is to instantiate a new Timeline object, and then call the create() method.

Kind: global class

new Timeline([container], [config], [entries], [events])

Param Type Default Description
[container] string "diagram" The ID of the container element for the timeline.
[config] object All config for the timeline
[config.panzoom] function | null The Panzoom function to enable panning and zooming, or null to disable
[config.findForm] string "timeline-find" The ID of the find form
[config.zoomIn] string "timeline-zoom-in" The ID of the button to zoom in
[config.zoomOut] string "timeline-zoom-out" The ID of the button to zoom out
[config.zoomReset] string "timeline-zoom-reset" The ID of the button to reset the zoom level
[config.yearStart] number 1900 the starting year for the timeline
[config.yearEnd] number Current year + 1 the end year for the timeline
[config.strokeWidth] number 4 the width in px of the joining lines
[config.yearWidth] number 50 the width in px of diagram used for each year
[config.rowHeight] number 50 the height in px of each diagram row
[config.padding] number 5 the padding in px between rows
[config.boxWidth] number 100 the width in px of each entry
[config.guides] boolean true whether to draw striped guides at regular intervals in the timeline
[config.guideInterval] number 5 the interval in years between guides (ignored if 'guides' is false)
[config.entrySelector] string "div" the CSS selector used for entries
[entries] Array.<object> [] The Timeline entries as an array of objects
[events] Array.<object> [] Events as an array of objects

timeline.create()

Create the Timeline. This should be called after instantiation.

Kind: instance method of Timeline
Access: public

timeline.panToEntry(id)

If Panzoom is enabled, pan to the element with the given ID, and reset the zoom.

Kind: instance method of Timeline
Emits: timelineFind
Access: public

Param Type Description
id string The ID of a timeline entry

"timelineFind"

The timelineFind event is fired when panToEntry() is called. (Only applicable if Panzoom is enabled).

Kind: event emitted by Timeline
Access: public
Properties

Name Type Description
details object
details.id string the ID of the entry
details.name string the name of the entry

Licence

Copyright (C) 2021-23 Aonghus Storey

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

See the LICENCE file for details.

timeline.js's People

Contributors

aonrud avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.